diff --git a/.github/codecov.yml b/.github/codecov.yml index f0deaa1dd..f0c2e9c4a 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -12,8 +12,10 @@ flag_management: - type: project target: auto threshold: 1% + informational: true - type: patch target: 90% + informational: true comment: layout: "header, diff, flags, components, files" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 448db0698..6c0c1ae0d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,10 +1,11 @@ name: CI -on: +"on": push: branches: [main] tags: ["v*"] pull_request: + workflow_dispatch: jobs: check-types: @@ -53,11 +54,17 @@ jobs: bun run coverage:reports - name: Upload coverage - run: cd contracts && bun run coverage:upload + run: | + if [ -z "$CC_TOKEN" ]; then + echo "CODECOV_TOKEN is not configured; skipping coverage upload." + exit 0 + fi + cd contracts && bun run coverage:upload env: CC_TOKEN: ${{ secrets.CODECOV_TOKEN }} CC_GIT_SERVICE: github - CC_SHA: ${{ github.sha }} + CC_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + CC_PR: ${{ github.event_name == 'pull_request' && github.event.pull_request.number || '' }} hardhat-tests: name: Hardhat Tests @@ -80,14 +87,20 @@ jobs: bun run coverage:reports - name: Upload coverage - run: cd contracts && bun run coverage:upload + run: | + if [ -z "$CC_TOKEN" ]; then + echo "CODECOV_TOKEN is not configured; skipping coverage upload." + exit 0 + fi + cd contracts && bun run coverage:upload env: CC_TOKEN: ${{ secrets.CODECOV_TOKEN }} CC_GIT_SERVICE: github - CC_SHA: ${{ github.sha }} + CC_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + CC_PR: ${{ github.event_name == 'pull_request' && github.event.pull_request.number || '' }} lint: - name: Lint + name: Lint and Format runs-on: ubuntu-latest steps: # setup @@ -97,10 +110,13 @@ jobs: - name: Lint run: bun --filter contracts lint + - name: Format + run: bun --filter contracts format:check + publish-docker: name: Publish Docker Image - if: github.ref == 'refs/heads/main' - needs: [check-types, forge-tests, hardhat-tests, lint] + if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.ref_type == 'branch') + needs: [check-types, e2e-tests, forge-tests, hardhat-tests, lint] runs-on: ubuntu-latest permissions: contents: read @@ -126,15 +142,33 @@ jobs: - name: Get branch name and short SHA for tagging id: branch + env: + EVENT_NAME: ${{ github.event_name }} + HEAD_REF: ${{ github.head_ref }} + REF_NAME: ${{ github.ref_name }} + GITHUB_SHA_VALUE: ${{ github.sha }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - echo "name=${{ github.head_ref }}" >> $GITHUB_OUTPUT - SHORT_SHA=$(echo "${{ github.event.pull_request.head.sha }}" | cut -c1-7) + if [ "$EVENT_NAME" = "pull_request" ]; then + BRANCH_NAME="$HEAD_REF" + SOURCE_SHA="$PR_HEAD_SHA" else - echo "name=${{ github.ref_name }}" >> $GITHUB_OUTPUT - SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) + BRANCH_NAME="$REF_NAME" + SOURCE_SHA="$GITHUB_SHA_VALUE" fi - echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT + + SHORT_SHA=$(printf '%s' "$SOURCE_SHA" | cut -c1-7) + DOCKER_TAG=$(printf '%s' "$BRANCH_NAME" | sed -E 's/[^A-Za-z0-9_.-]+/-/g; s/^[.-]+//; s/[.-]+$//') + + if [ -z "$DOCKER_TAG" ]; then + DOCKER_TAG="branch" + fi + + DOCKER_TAG=$(printf '%s' "$DOCKER_TAG" | cut -c1-128) + DOCKER_TAG_PREFIX=$(printf '%s' "$DOCKER_TAG" | cut -c1-120) + + echo "tag=$DOCKER_TAG" >> "$GITHUB_OUTPUT" + echo "sha_tag=$DOCKER_TAG_PREFIX-$SHORT_SHA" >> "$GITHUB_OUTPUT" - name: Extract metadata for Docker id: meta @@ -142,8 +176,9 @@ jobs: with: images: ghcr.io/${{ github.repository }} tags: | - type=raw,value=${{ steps.branch.outputs.name }}-${{ steps.branch.outputs.short_sha }} - type=raw,value=latest,enable=${{ github.ref_name == github.event.repository.default_branch }} + type=raw,value=${{ steps.branch.outputs.sha_tag }} + type=raw,value=${{ steps.branch.outputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' && github.ref_type == 'branch' && github.ref != 'refs/heads/main' }} + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} type=ref,event=tag - name: Build and push Docker image diff --git a/.gitignore b/.gitignore index 71c02e01e..19a7dd93e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,10 @@ .env node_modules/ +.solgrid_cache/ .DS_Store .claude/settings.local.json .devdocs/ - -# for now -deployments/ -!deployments/testnet-*.json -!deployments/mainnet-*.json \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index f94768fde..ea5b712ee 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "contracts/lib/unruggable-gateways"] path = contracts/lib/unruggable-gateways url = https://github.com/unruggable-labs/unruggable-gateways +[submodule "contracts/lib/solady"] + path = contracts/lib/solady + url = https://github.com/vectorized/solady diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100755 index 4389e7411..000000000 --- a/.prettierrc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "tabWidth": 2, - "printWidth": 80, - "trailingComma": "all", - "plugins": ["prettier-plugin-solidity"], - "overrides": [ - { - "files": "*.sol", - "options": { - "tabWidth": 4, - "printWidth": 100 - } - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json index b60cbc17f..deb9e56f2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,14 +2,34 @@ "solidity.packageDefaultDependenciesContractsDirectory": "./contracts/src", "solidity.packageDefaultDependenciesDirectory": "./contracts/lib", "solidity.compileUsingRemoteVersion": "v0.8.25+commit.b61c2a91", - "solidity.solhintPackageDirectory": "./node_modules/solhint", - "solidity.formatter": "prettier", + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true + }, + "[javascriptreact]": { + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true + }, + "[jsonc]": { + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true + }, "[solidity]": { - "editor.defaultFormatter": "JuanBlanco.solidity", + "editor.formatOnSave": false + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true + }, + "[typescriptreact]": { + "editor.defaultFormatter": "biomejs.biome", "editor.formatOnSave": true }, "editor.formatOnSave": true, - "prettier.configPath": "./.prettierrc.json", "search.exclude": { "**/node_modules": true, "**/cache": true, diff --git a/CLAUDE.md b/AGENTS.md similarity index 78% rename from CLAUDE.md rename to AGENTS.md index fe6106021..8b17bfa09 100644 --- a/CLAUDE.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ - When running tests they should be run from the contracts/ subfolder. - See package.json for the test commands. -- When testing for event emission never use vm.expectEmit, always use vm.recordLogs and actually check the logs properly. +- When testing for event emission, always check logs properly. Use either `vm.recordLogs` with explicit log assertions, or `vm.expectEmit` paired with an `emit Event(...)` expectation before the call under test. - Do not use --via-ir when compiling contracts and tests. If there are Solidity stack too deep errors then fix them through code refactoring. - When doing vm.prank and vm.expectRevert together for a call, always place the vm.expectRevert call before the vm.prank call. @@ -37,4 +37,8 @@ Do what has been asked; nothing more, nothing less. NEVER create files unless they're absolutely necessary for achieving your goal. ALWAYS prefer editing an existing file to creating a new one. NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User. -- when writing tests that involve constants already defined in the source (e.g contracts/src/registry/libraries/RegistryRolesLib.sol) use those defined constants directly instead of hardcoding their values in the tests. \ No newline at end of file +- when writing tests that involve constants already defined in the source (e.g contracts/src/registry/libraries/RegistryRolesLib.sol) use those defined constants directly instead of hardcoding their values in the tests. + +# Documentation + +The `contracts/docs/` folder contains operational documentation for scripts and tools. When making changes to code that is covered by documentation in `contracts/docs/`, the corresponding documentation MUST be kept up-to-date alongside the code changes. diff --git a/Dockerfile b/Dockerfile index bad552a6d..9187aa625 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,8 +28,6 @@ COPY package.json bun.lock ./ # Copy the package.json for each workspace. COPY contracts/package.json ./contracts/ -COPY solhint-plugins/package.json ./solhint-plugins/ - # Copy patches for post script execution #COPY /patches ./patches diff --git a/biome.json b/biome.json new file mode 100644 index 000000000..67d0d5bfe --- /dev/null +++ b/biome.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.4.11/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": true + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 80 + }, + "linter": { + "enabled": false + }, + "assist": { + "enabled": false + }, + "javascript": { + "formatter": { + "quoteStyle": "double", + "trailingCommas": "all" + } + } +} diff --git a/bun.lock b/bun.lock index 2424f7e94..a67116dcd 100644 --- a/bun.lock +++ b/bun.lock @@ -1,9 +1,11 @@ { "lockfileVersion": 1, + "configVersion": 1, "workspaces": { "": { "name": "contracts-v2", "devDependencies": { + "@biomejs/biome": "^2.4.11", "husky": "^9.1.7", "typescript": "^5.8.3", }, @@ -11,18 +13,20 @@ "contracts": { "name": "contracts", "dependencies": { - "@ensdomains/hardhat-chai-matchers-viem": "^0.1.14", + "@ensdomains/hardhat-chai-matchers-viem": "^0.1.16", + "@nomicfoundation/hardhat-keystore": "3.0.5", "@nomicfoundation/hardhat-network-helpers": "3.0.0", "@nomicfoundation/hardhat-viem": "3.0.0", - "@rocketh/deploy": "0.14.0", - "@rocketh/read-execute": "0.14.0", - "@rocketh/viem": "0.14.0", + "@rocketh/deploy": "0.19.1", + "@rocketh/node": "0.19.3", + "@rocketh/read-execute": "0.19.0", + "@rocketh/viem": "0.19.0", "commander": "^14.0.1", "dns-packet": "^5.6.1", - "hardhat": "3.0.1", - "hardhat-deploy": "2.0.0-next.41", + "hardhat": "3.1.12", + "hardhat-deploy": "2.0.3", "prool": "^0.0.24", - "rocketh": "0.14.5", + "rocketh": "0.19.3", "viem": "^2.31.6", "yoctocolors": "^2.1.2", }, @@ -30,16 +34,13 @@ "@ensdomains/address-encoder": "^1.1.3", "@nomicfoundation/edr": "0.12.0-next.4", "@nomicfoundation/hardhat-foundry": "^1.2.0", - "@rocketh/proxy": "0.14.0", - "@rocketh/verifier": "0.14.4", + "@rocketh/proxy": "0.19.3", + "@rocketh/verifier": "0.19.3", "@types/bun": "^1.3.2", + "abitype": "^1.2.3", "chai": "^5.1.1", "ethers": "^6.15.0", - "prettier": "^3.5.3", - "prettier-plugin-solidity": "2.0.0", - "solhint": "6.0.0", - "solhint-plugin-contracts-v2": "workspace:*", - "solhint-plugin-prettier": "^0.1.0", + "solgrid": "0.0.16", "ts-node": "^10.9.2", "vite-tsconfig-paths": "^5.1.4", "vitest": "3.1.3", @@ -48,9 +49,10 @@ "typescript": "^5.8.3", }, }, - "solhint-plugins": { - "name": "solhint-plugin-contracts-v2", - }, + }, + "patchedDependencies": { + "rocketh@0.19.3": "patches/rocketh@0.19.3.patch", + "@rocketh/node@0.19.3": "patches/@rocketh-node@0.19.3.patch", }, "overrides": { "esbuild": "0.25.11", @@ -58,11 +60,23 @@ "packages": { "@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.10.1", "", {}, "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw=="], - "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], + "@biomejs/biome": ["@biomejs/biome@2.4.15", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.15", "@biomejs/cli-darwin-x64": "2.4.15", "@biomejs/cli-linux-arm64": "2.4.15", "@biomejs/cli-linux-arm64-musl": "2.4.15", "@biomejs/cli-linux-x64": "2.4.15", "@biomejs/cli-linux-x64-musl": "2.4.15", "@biomejs/cli-win32-arm64": "2.4.15", "@biomejs/cli-win32-x64": "2.4.15" }, "bin": { "biome": "bin/biome" } }, "sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.15", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rF3PPqLq1yoST79zaQbDjVJwsuIeci/O+9bgNmC5QpgOqz6aqYuzA4abyAGx+mgyiDXn4A049xAN8gijbuR1Qg=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.15", "", { "os": "darwin", "cpu": "x64" }, "sha512-/5KHXYMfSJs1fNXiX30xFtI8JcCFV6zaVVLxOa0M2sfqBKHkpQhRTv94yxQWxeTY2lzo2OuTlNvPC+hDQt2wcQ=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-owaAMZD/T4LrD0ELNCk0Km3qrRHuM0X6EAyVE1FSqGY0rbLoiDLrO4Us2tllm6cAeB2Ioa9C2C08NZPdr8+0Ug=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZPcxznxm0pogHBLZhYntyR3sR+MrZjqJIKEr7ZqVen0Rl+P/4upVmfYXjftizi9RoqZntg33fv/1fbdhbYXpEQ=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.15", "", { "os": "linux", "cpu": "x64" }, "sha512-0jj7THz12GbUOLmMibktK6DZjqz2zV64KFxyBtcFTKPiiOIY0a7vns1elpO1dERvxpsZ5ik0oFfz0oGwFde1+g=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.15", "", { "os": "linux", "cpu": "x64" }, "sha512-CNq/9W38SYSH023lfcQ4KKU8K0YX8T//FZUhcgtMMRABDojx5XsMV7jlweAvGSl389wJQB29Qo6Zb/a+jdvt+w=="], - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.15", "", { "os": "win32", "cpu": "arm64" }, "sha512-ouhkYdlhp/1GghEJPdWwD/Vi3gQ1nFxuSpMolWsbq3Lsq3QUR4jl6UdhhscdCugKU5vOEuMiJhvKj66O0OCq+w=="], - "@bytecodealliance/preview2-shim": ["@bytecodealliance/preview2-shim@0.17.2", "", {}, "sha512-mNm/lblgES8UkVle8rGImXOz4TtL3eU3inHay/7TVchkKrb/lgcVvTK0+VAw8p5zQ0rgQsXm1j5dOlAAd+MeoA=="], + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.15", "", { "os": "win32", "cpu": "x64" }, "sha512-zBrGq5mx5wwpnow4+2BxUvleDM+GNd4sLbPaMapsSLQLD0NGRCquqPBTgN+7XkUteHvj7M+BstuI8tmnV7+HgQ=="], "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], @@ -122,8 +136,6 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="], - "@humanwhocodes/momoa": ["@humanwhocodes/momoa@2.0.4", "", {}, "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA=="], - "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], @@ -134,7 +146,7 @@ "@leichtgewicht/ip-codec": ["@leichtgewicht/ip-codec@2.0.5", "", {}, "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="], - "@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="], + "@noble/ciphers": ["@noble/ciphers@1.2.1", "", {}, "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA=="], "@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="], @@ -156,19 +168,21 @@ "@nomicfoundation/edr-win32-x64-msvc": ["@nomicfoundation/edr-win32-x64-msvc@0.12.0-next.4", "", {}, "sha512-OPpVYE7F4FuTKPdt8z0nrx/KZd7vHeNAjd4KAlzi+/X6imVHFX3sArVd0cdbw/oijINrvxgL/S6SrgbvSgASTA=="], - "@nomicfoundation/hardhat-errors": ["@nomicfoundation/hardhat-errors@3.0.6", "", { "dependencies": { "@nomicfoundation/hardhat-utils": "^3.0.1" } }, "sha512-3x+OVdZv7Rgy3z6os9pB6kiHLxs6q0PCXHRu+WLZflr44PG9zW+7V9o+ehrUqmmivlHcIFr3Qh4M2wZVuoCYww=="], + "@nomicfoundation/hardhat-errors": ["@nomicfoundation/hardhat-errors@3.0.13", "", { "dependencies": { "@nomicfoundation/hardhat-utils": "^4.1.2" } }, "sha512-h0nWNzKbmP6XhINMgSUfGixevzksT8BQPK08KNnsr/8kQORAeYzsv6bf0CLUD8mZfmBEP45m4QMlNP6xcoc0Ow=="], + + "@nomicfoundation/hardhat-foundry": ["@nomicfoundation/hardhat-foundry@1.2.1", "", { "dependencies": { "picocolors": "^1.1.0" }, "peerDependencies": { "hardhat": "^2.26.0" } }, "sha512-pH1KeyI0sysgi7I7uQKPLXWl895EkuS6V41rSi820Ipqp/FScIwDh27RbevgC9zJ4ufSsSz34njm9cvRMGMNVA=="], - "@nomicfoundation/hardhat-foundry": ["@nomicfoundation/hardhat-foundry@1.2.0", "", { "dependencies": { "picocolors": "^1.1.0" }, "peerDependencies": { "hardhat": "^2.26.0" } }, "sha512-2AJQLcWnUk/iQqHDVnyOadASKFQKF1PhNtt1cONEQqzUPK+fqME1IbP+EKu+RkZTRcyc4xqUMaB0sutglKRITg=="], + "@nomicfoundation/hardhat-keystore": ["@nomicfoundation/hardhat-keystore@3.0.5", "", { "dependencies": { "@noble/ciphers": "1.2.1", "@noble/hashes": "1.7.1", "@nomicfoundation/hardhat-errors": "^3.0.7", "@nomicfoundation/hardhat-utils": "^4.0.0", "@nomicfoundation/hardhat-zod-utils": "^3.0.2", "chalk": "^5.3.0", "debug": "^4.3.2", "zod": "^3.23.8" }, "peerDependencies": { "hardhat": "^3.0.0" } }, "sha512-jxihFx7r9ekcGmxRVbeDxFJcE3P9cmOHObKxX4ORyBR4b/AKiaqKiktirvsF5MXKJSuQbbp/+wmaqfQDB3LyeA=="], "@nomicfoundation/hardhat-network-helpers": ["@nomicfoundation/hardhat-network-helpers@3.0.0", "", { "dependencies": { "@nomicfoundation/hardhat-errors": "^3.0.0", "@nomicfoundation/hardhat-utils": "^3.0.0" }, "peerDependencies": { "hardhat": "^3.0.0" } }, "sha512-Nemas5cEaHyb4QoK40+USMxHMhIr4csRhpJFzm1T9I0/Wd1szw9kG412ubjUJxgm82ofyJGH3i5NKu7QgprmVg=="], - "@nomicfoundation/hardhat-utils": ["@nomicfoundation/hardhat-utils@3.0.6", "", { "dependencies": { "@streamparser/json-node": "^0.0.22", "debug": "^4.3.2", "env-paths": "^2.2.0", "ethereum-cryptography": "^2.2.1", "fast-equals": "^5.4.0", "json-stream-stringify": "^3.1.6", "rfdc": "^1.3.1", "undici": "^6.16.1" } }, "sha512-AD/LPNdjXNFRrZcaAAewgJpdnHpPppZxo5p+x6wGMm5Hz4B3+oLf/LUzVn8qb4DDy9RE2c24l2F8vmL/w6ZuXg=="], + "@nomicfoundation/hardhat-utils": ["@nomicfoundation/hardhat-utils@4.1.2", "", { "dependencies": { "@streamparser/json-node": "^0.0.22", "env-paths": "^2.2.0", "ethereum-cryptography": "^2.2.1", "fast-equals": "^5.4.0", "json-stream-stringify": "^3.1.6", "rfdc": "^1.3.1", "undici": "^6.16.1" } }, "sha512-jUQfbyIoTLHmSua+BMhIqUIk7uDwL2bhTtJgfwRoVooM3TTvm5rIdRK+eNkvZcZR/wAL/SBQOq/r9yOekj4Unw=="], - "@nomicfoundation/hardhat-viem": ["@nomicfoundation/hardhat-viem@3.0.0", "", { "dependencies": { "@nomicfoundation/hardhat-errors": "^3.0.0", "@nomicfoundation/hardhat-utils": "^3.0.0" }, "peerDependencies": { "hardhat": "^3.0.0", "viem": "^2.30.0" } }, "sha512-4QHBfTgJuo1O8vK9AO2AQYKsIp9yg06aF9C+WydDr2XS7VLJYh3g3gZdszLbSD9eHWsuviN688VKbcmfIZNWvQ=="], + "@nomicfoundation/hardhat-vendored": ["@nomicfoundation/hardhat-vendored@3.0.4", "", {}, "sha512-RO8Otj1FvRvxJmXzkxh1vTwK/+cqSVPYLqY6RrWkmzHEEcxnAwAFsBYdW7xyTEyW/pVbSSNd2gs3aoGdGZaoNA=="], - "@nomicfoundation/hardhat-zod-utils": ["@nomicfoundation/hardhat-zod-utils@3.0.1", "", { "dependencies": { "@nomicfoundation/hardhat-errors": "^3.0.0", "@nomicfoundation/hardhat-utils": "^3.0.2" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-I6/pyYiS9p2lLkzQuedr1ScMocH+ew8l233xTi+LP92gjEiviJDxselpkzgU01MUM0t6BPpfP8yMO958LDEJVg=="], + "@nomicfoundation/hardhat-viem": ["@nomicfoundation/hardhat-viem@3.0.0", "", { "dependencies": { "@nomicfoundation/hardhat-errors": "^3.0.0", "@nomicfoundation/hardhat-utils": "^3.0.0" }, "peerDependencies": { "hardhat": "^3.0.0", "viem": "^2.30.0" } }, "sha512-4QHBfTgJuo1O8vK9AO2AQYKsIp9yg06aF9C+WydDr2XS7VLJYh3g3gZdszLbSD9eHWsuviN688VKbcmfIZNWvQ=="], - "@nomicfoundation/slang": ["@nomicfoundation/slang@1.1.0", "", { "dependencies": { "@bytecodealliance/preview2-shim": "0.17.2" } }, "sha512-g2BofMUq1qCP22L/ksOftScrCxjdHTxgg8ch5PYon2zfSSKGCMwE4TgIC64CuorMcSsvCmqNNFEWR/fwFcMeTw=="], + "@nomicfoundation/hardhat-zod-utils": ["@nomicfoundation/hardhat-zod-utils@3.0.5", "", { "dependencies": { "@nomicfoundation/hardhat-errors": "^3.0.13", "@nomicfoundation/hardhat-utils": "^4.1.2" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-A1G9Jcizf/vYcGMtqkf+st94zBPTDB+bXXlojOMu77gmBZYbywY0k7hdRM2B4uJY+8nM0oe0sNVGVkARITXdcw=="], "@nomicfoundation/solidity-analyzer": ["@nomicfoundation/solidity-analyzer@0.1.2", "", { "optionalDependencies": { "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.2", "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.2", "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.2", "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.2", "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.2", "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.2", "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.2" } }, "sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA=="], @@ -186,73 +200,69 @@ "@nomicfoundation/solidity-analyzer-win32-x64-msvc": ["@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2", "", {}, "sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA=="], - "@pnpm/config.env-replace": ["@pnpm/config.env-replace@1.1.0", "", {}, "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w=="], + "@rocketh/core": ["@rocketh/core@0.19.0", "", { "dependencies": { "abitype": "^1.2.3", "eip-1193": "^0.6.5", "named-logs": "^0.4.1", "viem": "^2.45.1" } }, "sha512-pCauA7HP/5k0uyTgjOYApJGcNuVx61+o6AuvFUIR3DIaWyKgmSHB3oTmTe1CHZBWWBUurDf9SIYyAFS2qhTWJQ=="], - "@pnpm/network.ca-file": ["@pnpm/network.ca-file@1.0.2", "", { "dependencies": { "graceful-fs": "4.2.10" } }, "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA=="], + "@rocketh/deploy": ["@rocketh/deploy@0.19.1", "", { "dependencies": { "@rocketh/core": "0.19.0", "abitype": "^1.2.3", "eip-1193": "^0.6.5", "named-logs": "^0.4.1", "viem": "^2.45.1" } }, "sha512-Lob1B70E2Xvo/KqbGgtGjYRTISkY3FeS8eakQ1qagKEx0g6Mz982o+F0f6lYUsuQEmov2REog2dVkTVsr/ZfAA=="], - "@pnpm/npm-conf": ["@pnpm/npm-conf@3.0.2", "", { "dependencies": { "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", "config-chain": "^1.1.11" } }, "sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA=="], + "@rocketh/node": ["@rocketh/node@0.19.3", "", { "dependencies": { "@rocketh/core": "0.19.0", "@types/prompts": "^2.4.9", "change-case": "^5.4.4", "commander": "^14.0.3", "eip-1193": "^0.6.5", "ldenv": "^0.3.16", "named-logs": "^0.4.1", "named-logs-console": "^0.5.1", "prompts": "^2.4.2", "tsx": "^4.21.0", "viem": "^2.45.1" }, "peerDependencies": { "rocketh": "0.19.3" }, "bin": { "rocketh": "dist/cli.js" } }, "sha512-toGhmd2h3g5N3a+glhBP/Tpitbay+yVPmQ89TXN2Q6/mvHoL6KCUjcglxdnS1yV0nzJvp7XxIpvKIvIigXhTZw=="], - "@prettier/sync": ["@prettier/sync@0.3.0", "", { "peerDependencies": { "prettier": "^3.0.0" } }, "sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw=="], + "@rocketh/proxy": ["@rocketh/proxy@0.19.3", "", { "dependencies": { "@rocketh/core": "0.19.0", "@rocketh/deploy": "0.19.1", "@rocketh/read-execute": "0.19.0", "abitype": "^1.2.3", "eip-1193": "^0.6.5", "named-logs": "^0.4.1", "viem": "^2.45.1" } }, "sha512-IUosFjPiT4o5PG1dpS6XLjcjHEB1CTr1S+j3qS81WQqyQcTXHbzGrQC6mpIV6P4zCZ7D4LNm/944Mny3udmFzA=="], - "@rocketh/deploy": ["@rocketh/deploy@0.14.0", "", { "dependencies": { "named-logs": "^0.3.2", "viem": "^2.23.12" } }, "sha512-4uBIpKchoTZ9QSxyTYYT137+nI0beOlqkh10NWwNgBrQXPpFc51pDB2cDZkgzJpJ5Bzn5hL6klaEsVfPxmAvSA=="], + "@rocketh/read-execute": ["@rocketh/read-execute@0.19.0", "", { "dependencies": { "@rocketh/core": "0.19.0", "abitype": "^1.2.3", "eip-1193": "^0.6.5", "named-logs": "^0.4.1", "viem": "^2.45.1" } }, "sha512-nnaOOpvoZy58FYD+Olwcbco+EBk7ngokQ/VMKdSMk1FJ/KpXHfrplH3x5Q6zDymlF/stXdQfSpzPRMbI/ZZpSA=="], - "@rocketh/proxy": ["@rocketh/proxy@0.14.0", "", { "dependencies": { "@rocketh/deploy": "0.14.0", "@rocketh/read-execute": "0.14.0", "named-logs": "^0.3.2", "viem": "^2.23.12" } }, "sha512-Dhj9/U/45NuCGCWoOOYPwQiMxA0bfHPnD8GOCwXOMJpXDJDpWDK6wPN/EyuOaG2rpmvy9JkpFf34y0rXBL9isQ=="], + "@rocketh/verifier": ["@rocketh/verifier@0.19.3", "", { "dependencies": { "@rocketh/core": "0.19.0", "@types/fs-extra": "^11.0.4", "@types/qs": "^6.14.0", "chalk": "5.6.2", "commander": "^14.0.3", "fs-extra": "^11.3.3", "ldenv": "^0.3.16", "neoqs": "^6.13.0" }, "peerDependencies": { "@rocketh/node": "0.19.3" }, "bin": { "rocketh-verify": "dist/cli.js" } }, "sha512-XpyC9C7Fuz8OljatcDI2RcTSW3itdrOL+l16sanbpDyRNYWEGyruLlYYZjQ6rndXUUQgE7kxOOme8Yo9Q0QbDw=="], - "@rocketh/read-execute": ["@rocketh/read-execute@0.14.0", "", { "dependencies": { "named-logs": "^0.3.2", "viem": "^2.23.12" } }, "sha512-+QhG2I34kg36FklCVotZdKp5UuNlq+AfnKka75wVJigdAn3+RSheYf9yhofT8tIGa4dv6p4LE5eett2HOmfENQ=="], + "@rocketh/viem": ["@rocketh/viem@0.19.0", "", { "dependencies": { "@rocketh/core": "0.19.0", "abitype": "^1.2.3", "eip-1193": "^0.6.5", "named-logs": "^0.4.1" }, "peerDependencies": { "viem": "^2.45.0" } }, "sha512-qKvxwLAzBSOcIEVoKBcHUDOjoG+sIt1zvkmkmuAxPu91+TuDZDm5sZj5FJqcn2cQal2BjjydgPLZfsa7KCi18w=="], - "@rocketh/verifier": ["@rocketh/verifier@0.14.4", "", { "dependencies": { "@types/fs-extra": "^11.0.4", "@types/qs": "^6.9.18", "chalk": "5.4.1", "commander": "^13.1.0", "fs-extra": "^11.3.0", "ldenv": "^0.3.12", "neoqs": "^6.13.0" }, "peerDependencies": { "rocketh": "0.14.4" }, "bin": { "rocketh-verify": "dist/cli.js" } }, "sha512-nfxigIPC3zXZ6ajJhxEYJ7zkm0nn3kNHRryY1HPOlhnAjwTwzELLzDP2YFutvhwRcaEGcQz5vIeQJEVAaFG4zw=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.4", "", { "os": "android", "cpu": "arm" }, "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ=="], - "@rocketh/viem": ["@rocketh/viem@0.14.0", "", { "dependencies": { "named-logs": "^0.3.2" }, "peerDependencies": { "viem": "^2.23.12" } }, "sha512-1RRVpCgPJrPQEIs9OUyVBzCzXNbhIME+HFJBLdYI4y4ol94otqcaTnoXC91bRLmTPb60fvfssKV4p8gK9pyUQw=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.4", "", { "os": "android", "cpu": "arm64" }, "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.1", "", { "os": "android", "cpu": "arm" }, "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.57.1", "", { "os": "android", "cpu": "arm64" }, "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.57.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.57.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.57.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.4", "", { "os": "linux", "cpu": "arm" }, "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.57.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.4", "", { "os": "linux", "cpu": "arm" }, "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q=="], + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg=="], - "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw=="], + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA=="], - "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.4", "", { "os": "linux", "cpu": "x64" }, "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.57.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg=="], + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.4", "", { "os": "none", "cpu": "arm64" }, "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg=="], - "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.57.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.57.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.57.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ=="], + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.4", "", { "os": "win32", "cpu": "x64" }, "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.57.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew=="], - - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ=="], - - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA=="], + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.4", "", { "os": "win32", "cpu": "x64" }, "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw=="], "@scure/base": ["@scure/base@1.2.6", "", {}, "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg=="], @@ -264,18 +274,20 @@ "@sentry/core": ["@sentry/core@9.47.1", "", {}, "sha512-KX62+qIt4xgy8eHKHiikfhz2p5fOciXd0Cl+dNzhgPFq8klq4MGMNaf148GB3M/vBqP4nw/eFvRMAayFCgdRQw=="], - "@sindresorhus/is": ["@sindresorhus/is@5.6.0", "", {}, "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g=="], - "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], - "@solidity-parser/parser": ["@solidity-parser/parser@0.20.2", "", {}, "sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA=="], + "@solgrid/cli-darwin-arm64": ["@solgrid/cli-darwin-arm64@0.0.16", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Hi9sRcd3NOzS4hUmrovY2GGn+kpmfKuCdyNS0gNtAeTrr+rirJvJOgORD4Yj4xhHhoZPt8RNLUclurqSKFoIsg=="], + + "@solgrid/cli-linux-arm64": ["@solgrid/cli-linux-arm64@0.0.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-kc+Js4INos48nC0L82WM6WUHNxF5W8txHsdWcyz3tjEHupBlZhXSZk88G4djLcUYYd8ZPyltOSKboT0PEmY+/A=="], + + "@solgrid/cli-linux-x64": ["@solgrid/cli-linux-x64@0.0.16", "", { "os": "linux", "cpu": "x64" }, "sha512-TZS70lZCEfmtXZqViU9jidgjIwU70sqfqIp88M8CAJ2LP0Zq0fy3iWOSRUbshP3aXmATboC34npY+pBUD6rbAQ=="], + + "@solgrid/cli-win32-x64": ["@solgrid/cli-win32-x64@0.0.16", "", { "os": "win32", "cpu": "x64" }, "sha512-YenZKkeAFu/ntvBhgPrWwHT+Wfkrd28QVJSToN5125YmCX2DidlaJzHuu/AOXv/QvGP4/zgnvldK5HNe+nlblw=="], "@streamparser/json": ["@streamparser/json@0.0.22", "", {}, "sha512-b6gTSBjJ8G8SuO3Gbbj+zXbVx8NSs1EbpbMKpzGLWMdkR+98McH9bEjSz3+0mPJf68c5nxa3CrJHp5EQNXM6zQ=="], "@streamparser/json-node": ["@streamparser/json-node@0.0.22", "", { "dependencies": { "@streamparser/json": "^0.0.22" } }, "sha512-sJT2ptNRwqB1lIsQrQlCoWk5rF4tif9wDh+7yluAGijJamAhrHGYpFB/Zg3hJeceoZypi74ftXk8DHzwYpbZSg=="], - "@szmarczak/http-timer": ["@szmarczak/http-timer@5.0.1", "", { "dependencies": { "defer-to-connect": "^2.0.1" } }, "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw=="], - "@tsconfig/node10": ["@tsconfig/node10@1.0.12", "", {}, "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ=="], "@tsconfig/node12": ["@tsconfig/node12@1.0.11", "", {}, "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="], @@ -284,27 +296,19 @@ "@tsconfig/node16": ["@tsconfig/node16@1.0.4", "", {}, "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="], - "@types/bun": ["@types/bun@1.3.8", "", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="], - - "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - "@types/figlet": ["@types/figlet@1.7.0", "", {}, "sha512-KwrT7p/8Eo3Op/HBSIwGXOsTZKYiM9NpWRBJ5sVjWP/SmlS+oxxRvJht/FNAtliJvja44N3ul1yATgohnVBV0Q=="], - "@types/fs-extra": ["@types/fs-extra@11.0.4", "", { "dependencies": { "@types/jsonfile": "*", "@types/node": "*" } }, "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ=="], - "@types/http-cache-semantics": ["@types/http-cache-semantics@4.2.0", "", {}, "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q=="], - "@types/jsonfile": ["@types/jsonfile@6.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ=="], - "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@22.7.5", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ=="], "@types/prompts": ["@types/prompts@2.4.9", "", { "dependencies": { "@types/node": "*", "kleur": "^3.0.3" } }, "sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA=="], - "@types/qs": ["@types/qs@6.14.0", "", {}, "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ=="], + "@types/qs": ["@types/qs@6.15.1", "", {}, "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw=="], "@vitest/expect": ["@vitest/expect@3.1.3", "", { "dependencies": { "@vitest/spy": "3.1.3", "@vitest/utils": "3.1.3", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg=="], @@ -320,90 +324,52 @@ "@vitest/utils": ["@vitest/utils@3.1.3", "", { "dependencies": { "@vitest/pretty-format": "3.1.3", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" } }, "sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg=="], - "abitype": ["abitype@1.2.3", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg=="], + "abitype": ["abitype@1.2.4", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-dpKH+N27vRjarMVTFFkeY445VTKftzGWpL0FiT7xmVmzQRKazZexzC5uHG0f6XKsVLAuUlndnbGau6lRejClxg=="], - "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], + "acorn-walk": ["acorn-walk@8.3.5", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw=="], "adm-zip": ["adm-zip@0.4.16", "", {}, "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg=="], "aes-js": ["aes-js@4.0.0-beta.5", "", {}, "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q=="], - "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - - "ajv-errors": ["ajv-errors@1.0.1", "", { "peerDependencies": { "ajv": ">=5.0.0" } }, "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ=="], - "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - - "antlr4": ["antlr4@4.13.2", "", {}, "sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg=="], - "arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="], - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], - "ast-parents": ["ast-parents@0.0.1", "", {}, "sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA=="], - - "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="], - - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - - "better-ajv-errors": ["better-ajv-errors@2.0.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@humanwhocodes/momoa": "^2.0.4", "chalk": "^4.1.2", "jsonpointer": "^5.0.1", "leven": "^3.1.0 < 4" }, "peerDependencies": { "ajv": "4.11.8 - 8" } }, "sha512-t1vxUP+vYKsaYi/BbKo2K98nEAZmfi4sjwvmRT8aOPDzPJeAtLurfoIDazVkLILxO4K+Sw4YrLYnBQ46l6pePg=="], - - "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - - "bun-types": ["bun-types@1.3.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], + "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], - "cacheable-lookup": ["cacheable-lookup@7.0.0", "", {}, "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w=="], - - "cacheable-request": ["cacheable-request@10.2.14", "", { "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" } }, "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ=="], - - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], - "chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="], + "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="], - "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], - - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], - "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], - "config-chain": ["config-chain@1.1.13", "", { "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" } }, "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ=="], - "contracts": ["contracts@workspace:contracts"], - "cosmiconfig": ["cosmiconfig@8.3.6", "", { "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0", "path-type": "^4.0.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA=="], - "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], - "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], - "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], - - "defer-to-connect": ["defer-to-connect@2.0.1", "", {}, "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="], - "diff": ["diff@4.0.4", "", {}, "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ=="], "dns-packet": ["dns-packet@5.6.1", "", { "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" } }, "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw=="], @@ -412,16 +378,14 @@ "dotenv-expand": ["dotenv-expand@10.0.0", "", {}, "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A=="], - "eip-1193-jsonrpc-provider": ["eip-1193-jsonrpc-provider@0.4.3", "", { "dependencies": { "named-logs": "^0.3.2", "promise-throttle": "^1.1.2" } }, "sha512-xcrz22ArOqvbXt4LHOeV5JooL8jTt/sv8WIH7MLQTn8z7fQwRDDzUECgIwZaX1Irpn/HIZGiu6YZwIoRVfPEow=="], + "eip-1193": ["eip-1193@0.6.5", "", {}, "sha512-KXCSdjFLIT5/06rMD2pMqoAZhZcTg4EofiCI70ovIOy8L/6twGJFE+RtW89S/hMFKDoNEGJ/WK8jQv7CpuGDgg=="], - "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "eip-1193-jsonrpc-provider": ["eip-1193-jsonrpc-provider@0.4.3", "", { "dependencies": { "named-logs": "^0.3.2", "promise-throttle": "^1.1.2" } }, "sha512-xcrz22ArOqvbXt4LHOeV5JooL8jTt/sv8WIH7MLQTn8z7fQwRDDzUECgIwZaX1Irpn/HIZGiu6YZwIoRVfPEow=="], "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], - "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], - "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], "esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="], @@ -432,82 +396,42 @@ "ethers": ["ethers@6.16.0", "", { "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" } }, "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A=="], - "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], "execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="], "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], - "fast-equals": ["fast-equals@5.4.0", "", {}, "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw=="], - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - - "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], - "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - "figlet": ["figlet@1.10.0", "", { "dependencies": { "commander": "^14.0.0" }, "bin": { "figlet": "bin/index.js" } }, "sha512-aktIwEZZ6Gp9AWdMXW4YCi0J2Ahuxo67fNJRUIWD81w8pQ0t9TS8FFpbl27ChlTLF06VkwjDesZSzEVzN75rzA=="], - "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], - "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], + "follow-redirects": ["follow-redirects@1.16.0", "", {}, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="], - "form-data-encoder": ["form-data-encoder@2.1.4", "", {}, "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw=="], - - "fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="], - - "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + "fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="], "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "get-port": ["get-port@7.1.0", "", {}, "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw=="], + "get-port": ["get-port@7.2.0", "", {}, "sha512-afP4W205ONCuMoPBqcR6PSXnzX35KTcJygfJfcp+QY+uwm3p20p1YczWXhlICIzGMCxYBQcySEcOgsJcrkyobg=="], "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], - "get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="], - - "glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="], - "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], - "got": ["got@12.6.1", "", { "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" } }, "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ=="], - "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - "hardhat": ["hardhat@3.0.1", "", { "dependencies": { "@nomicfoundation/edr": "0.12.0-next.4", "@nomicfoundation/hardhat-errors": "^3.0.0", "@nomicfoundation/hardhat-utils": "^3.0.0", "@nomicfoundation/hardhat-zod-utils": "^3.0.0", "@nomicfoundation/solidity-analyzer": "^0.1.1", "@sentry/core": "^9.4.0", "adm-zip": "^0.4.16", "chalk": "^5.3.0", "debug": "^4.3.2", "enquirer": "^2.3.0", "ethereum-cryptography": "^2.2.1", "micro-eth-signer": "^0.14.0", "p-map": "^7.0.2", "resolve.exports": "^2.0.3", "semver": "^7.6.3", "tsx": "^4.19.3", "ws": "^8.18.0", "zod": "^3.23.8" }, "bin": { "hardhat": "dist/src/cli.js" } }, "sha512-IronMout14GKbg8RTbW2b5HAkcztCBLs9ZldssUoDiM2rXyf6LBOS126/dFPntclILeT7ik3uGpWcoJ+2DtXpg=="], - - "hardhat-deploy": ["hardhat-deploy@2.0.0-next.41", "", { "dependencies": { "@nomicfoundation/hardhat-zod-utils": "3.0.0", "@types/debug": "^4.1.12", "debug": "^4.4.1", "slash": "^5.1.0", "zod": "^4.1.5" }, "peerDependencies": { "hardhat": "^3.0.0", "rocketh": "^0.14.4" } }, "sha512-27s7uA5gBjTmoOQyRvYdGQpvbScdJPLqd5giHVi6iOtzgyKoLkfw35k/8r1EdWdf93xkNtK01SpvAUtsP9Lo5w=="], + "hardhat": ["hardhat@3.1.12", "", { "dependencies": { "@nomicfoundation/edr": "0.12.0-next.28", "@nomicfoundation/hardhat-errors": "^3.0.8", "@nomicfoundation/hardhat-utils": "^4.0.1", "@nomicfoundation/hardhat-vendored": "^3.0.1", "@nomicfoundation/hardhat-zod-utils": "^3.0.3", "@nomicfoundation/solidity-analyzer": "^0.1.1", "@sentry/core": "^9.4.0", "adm-zip": "^0.4.16", "chalk": "^5.3.0", "chokidar": "^4.0.3", "debug": "^4.3.2", "enquirer": "^2.3.0", "ethereum-cryptography": "^2.2.1", "micro-eth-signer": "^0.14.0", "p-map": "^7.0.2", "resolve.exports": "^2.0.3", "semver": "^7.6.3", "tsx": "^4.19.3", "ws": "^8.18.0", "zod": "^3.23.8" }, "bin": { "hardhat": "dist/src/cli.js" } }, "sha512-/3TrZV4ViCIKgy2K5XwPS5xla2v4xjxYA2Ms1pi/0t+1GQQ1dWQpKJhDjKBc02UWYiWihIZFAv9RS30anyhqpQ=="], - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - - "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], + "hardhat-deploy": ["hardhat-deploy@2.0.3", "", { "dependencies": { "@nomicfoundation/hardhat-zod-utils": "^3.0.1", "commander": "^14.0.3", "named-logs": "^0.4.1", "named-logs-console": "^0.5.1", "zod": "^3.25.76" }, "peerDependencies": { "@rocketh/node": "^0.19.3", "hardhat": "^3.1.8", "rocketh": "^0.19.3" }, "bin": { "hardhat-deploy": "dist/cli.js" } }, "sha512-XejiG82KaixTLSWCAjkStT0lpv4+Vk+bT/5bXGeW6uQLdh9ks+xPbBDbh9R9/bkmTBMq5EcZcX4+8DIlXJgVaQ=="], "http-proxy": ["http-proxy@1.18.1", "", { "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ=="], - "http2-wrapper": ["http2-wrapper@2.2.1", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" } }, "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ=="], - "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="], "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], - "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - - "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], - - "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], - - "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - - "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], - - "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], - - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], "is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], @@ -518,42 +442,16 @@ "isows": ["isows@1.0.7", "", { "peerDependencies": { "ws": "*" } }, "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg=="], - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], - - "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], - - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "json-stream-stringify": ["json-stream-stringify@3.1.6", "", {}, "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog=="], - "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], - - "jsonpointer": ["jsonpointer@5.0.1", "", {}, "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ=="], - - "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + "jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], - "latest-version": ["latest-version@7.0.0", "", { "dependencies": { "package-json": "^8.1.0" } }, "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg=="], - "ldenv": ["ldenv@0.3.16", "", { "dependencies": { "dotenv": "^16.0.3", "dotenv-expand": "^10.0.0" }, "bin": { "ldenv": "dist/cli.cjs" } }, "sha512-ShaNPPzgUi+iGj9bsQ0TPRm6MuOcPpc1NklL0/IzJsvB0OdHwWoPhmeTVR5z0oC3zzLebrojozo/nt8d2XTZbQ=="], - "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], - - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], - - "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], - - "lodash.truncate": ["lodash.truncate@4.4.2", "", {}, "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw=="], - "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], - "lowercase-keys": ["lowercase-keys@3.0.0", "", {}, "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ=="], - "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], "make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="], @@ -562,13 +460,7 @@ "micro-packed": ["micro-packed@0.7.3", "", { "dependencies": { "@scure/base": "~1.2.5" } }, "sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg=="], - "mimic-response": ["mimic-response@4.0.0", "", {}, "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg=="], - - "minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="], @@ -576,55 +468,33 @@ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "named-logs": ["named-logs@0.3.2", "", {}, "sha512-rpgShWrH6NakMKUDK32Pn/FZyPl7QoQRleMekHKkbrExXDymb2wNm3/BUbdTG5f3v7Qa17imVkSWHOfNFhDIPw=="], + "named-logs": ["named-logs@0.4.1", "", {}, "sha512-CHLNCYsSBTC+xVbdA2nTWWfW+c3hyQKCOfl7MzgKtO6/VoP4nXQ1o1Ji2ExY/P0v7QljOGH338fOF6rYJCoK0Q=="], - "named-logs-console": ["named-logs-console@0.3.1", "", { "dependencies": { "named-logs": "^0.2.2" } }, "sha512-qExLlmkSSrI/57Juvc94c0zlldI5IvreilyFeg7KfxMGGotTVER6xfk+KB7DZ5m18GYnFZn77z2kyigtcn2zHA=="], + "named-logs-console": ["named-logs-console@0.5.1", "", { "dependencies": { "named-logs": "^0.4.1" } }, "sha512-GL2mfmVO7vcOTIl9QRczOBq6aaXsVfehXTU150cIFscRbVMbNYivhDzRgLadPC5pK+URCHmnEn5jWo+LZ7GkHQ=="], - "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="], "neoqs": ["neoqs@6.13.0", "", {}, "sha512-IysBpjrEG9qiUb/IT6XrXSz2ASzBxLebp4s8/GBm7STYC315vMNqH0aWdRR+f7KvXK4aRlLcf5r2Z6dOTxQSrQ=="], - "normalize-url": ["normalize-url@8.1.1", "", {}, "sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ=="], - "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], - - "ox": ["ox@0.11.3", "", { "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" }, "optionalPeers": ["typescript"] }, "sha512-1bWYGk/xZel3xro3l8WGg6eq4YEKlaqvyMtVhfMFpbJzK2F6rj4EDRtqDCWVEJMkzcmEi9uW2QxsqELokOlarw=="], - - "p-cancelable": ["p-cancelable@3.0.0", "", {}, "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw=="], + "ox": ["ox@https://pkg.pr.new/ox@386a3439fe1ce76d237930f8c6e6bb493746069a", { "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" }, "optionalPeers": ["typescript"] }, "sha512-OHHm9re1yVjiMN66GZ2JSGuqmvJPrk40zh3PIS/3I6prZLbt6U/zKlgW18eIIkO0Y/ZyySKr6D/4mUXjBmky1g=="], "p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="], - "package-json": ["package-json@8.1.1", "", { "dependencies": { "got": "^12.1.0", "registry-auth-token": "^5.0.1", "registry-url": "^6.0.0", "semver": "^7.3.7" } }, "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA=="], - - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - - "parse-json": ["parse-json@5.2.0", "", { "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" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], - "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], - "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - - "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], - - "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], - "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], - - "prettier-linter-helpers": ["prettier-linter-helpers@1.0.1", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg=="], - - "prettier-plugin-solidity": ["prettier-plugin-solidity@2.0.0", "", { "dependencies": { "@nomicfoundation/slang": "1.1.0", "@solidity-parser/parser": "^0.20.1", "semver": "^7.7.1" }, "peerDependencies": { "prettier": ">=3.0.0" } }, "sha512-tis3SwLSrYKDzzRFle48fjPM4GQKBtkVBUajAkt4b75/cc6zojFP7qjz6fDxKfup+34q0jKeSM3QeP9flJFXWw=="], + "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="], "pretty-ms": ["pretty-ms@9.3.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ=="], @@ -634,39 +504,19 @@ "prool": ["prool@0.0.24", "", { "dependencies": { "change-case": "5.4.4", "eventemitter3": "^5.0.1", "execa": "^9.1.0", "get-port": "^7.1.0", "http-proxy": "^1.18.1", "tar": "7.2.0" }, "peerDependencies": { "@pimlico/alto": "*" }, "optionalPeers": ["@pimlico/alto"] }, "sha512-L0EGUF5vK1XAQtceaiwfGxf0LGeJwurUizzc3i6JESsUyMROzGxTSMSBiajF8AoQaDYWIX2s1m00sC36CATrvQ=="], - "proto-list": ["proto-list@1.2.4", "", {}, "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="], - - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - - "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="], - - "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], - - "registry-auth-token": ["registry-auth-token@5.1.1", "", { "dependencies": { "@pnpm/npm-conf": "^3.0.2" } }, "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q=="], - - "registry-url": ["registry-url@6.0.1", "", { "dependencies": { "rc": "1.2.8" } }, "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q=="], - - "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="], - "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="], - - "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], - - "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], - "resolve.exports": ["resolve.exports@2.0.3", "", {}, "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A=="], - "responselike": ["responselike@3.0.0", "", { "dependencies": { "lowercase-keys": "^3.0.0" } }, "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg=="], - "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - "rocketh": ["rocketh@0.14.5", "", { "dependencies": { "@types/figlet": "^1.7.0", "@types/prompts": "^2.4.9", "commander": "^13.1.0", "eip-1193-jsonrpc-provider": "^0.4.3", "ethers": "^6.13.5", "figlet": "^1.8.0", "ldenv": "^0.3.12", "named-logs": "^0.3.2", "named-logs-console": "^0.3.1", "prompts": "^2.4.2", "tsx": "^4.19.3", "viem": "^2.23.12" }, "bin": { "rocketh": "dist/cli.js" } }, "sha512-gSdIFtGKXwkFOyya+uoh9TJuy1dzJ4svV4VyQ4OIbwI5nOH7adiio4gG6LDA0FNOozl/AZE8NnxO8vWqcSr6Zw=="], + "rocketh": ["rocketh@0.19.3", "", { "dependencies": { "@rocketh/core": "0.19.0", "abitype": "^1.2.3", "change-case": "^5.4.4", "eip-1193": "^0.6.5", "eip-1193-jsonrpc-provider": "^0.4.3", "ldenv": "^0.3.16", "named-logs": "^0.4.1" } }, "sha512-OWLU/YOCMYYtdMNNfOdCqUTK8kn0ps6K0BxPKNN3nFW+7RXR9Vn0Nn/arSZVwBAk3/ksAWTNNJBOSabSEmgfLA=="], - "rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="], + "rollup": ["rollup@4.60.4", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.4", "@rollup/rollup-android-arm64": "4.60.4", "@rollup/rollup-darwin-arm64": "4.60.4", "@rollup/rollup-darwin-x64": "4.60.4", "@rollup/rollup-freebsd-arm64": "4.60.4", "@rollup/rollup-freebsd-x64": "4.60.4", "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", "@rollup/rollup-linux-arm-musleabihf": "4.60.4", "@rollup/rollup-linux-arm64-gnu": "4.60.4", "@rollup/rollup-linux-arm64-musl": "4.60.4", "@rollup/rollup-linux-loong64-gnu": "4.60.4", "@rollup/rollup-linux-loong64-musl": "4.60.4", "@rollup/rollup-linux-ppc64-gnu": "4.60.4", "@rollup/rollup-linux-ppc64-musl": "4.60.4", "@rollup/rollup-linux-riscv64-gnu": "4.60.4", "@rollup/rollup-linux-riscv64-musl": "4.60.4", "@rollup/rollup-linux-s390x-gnu": "4.60.4", "@rollup/rollup-linux-x64-gnu": "4.60.4", "@rollup/rollup-linux-x64-musl": "4.60.4", "@rollup/rollup-openbsd-x64": "4.60.4", "@rollup/rollup-openharmony-arm64": "4.60.4", "@rollup/rollup-win32-arm64-msvc": "4.60.4", "@rollup/rollup-win32-ia32-msvc": "4.60.4", "@rollup/rollup-win32-x64-gnu": "4.60.4", "@rollup/rollup-win32-x64-msvc": "4.60.4", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g=="], - "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + "semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], @@ -678,15 +528,7 @@ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], - "slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], - - "slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="], - - "solhint": ["solhint@6.0.0", "", { "dependencies": { "@solidity-parser/parser": "^0.20.0", "ajv": "^6.12.6", "ajv-errors": "^1.0.1", "antlr4": "^4.13.1-patch-1", "ast-parents": "^0.0.1", "better-ajv-errors": "^2.0.2", "chalk": "^4.1.2", "commander": "^10.0.0", "cosmiconfig": "^8.0.0", "fast-diff": "^1.2.0", "fs-extra": "^11.1.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" }, "optionalDependencies": { "prettier": "^2.8.3" }, "bin": { "solhint": "solhint.js" } }, "sha512-PQGfwFqfeYdebi2tEG1fhVfMjqSzbW3Noz+LYf8UusKe5nkikCghdgEjYQPcGfFZj4snlVyJQt//AaxkubOtVQ=="], - - "solhint-plugin-contracts-v2": ["solhint-plugin-contracts-v2@workspace:solhint-plugins"], - - "solhint-plugin-prettier": ["solhint-plugin-prettier@0.1.0", "", { "dependencies": { "@prettier/sync": "^0.3.0", "prettier-linter-helpers": "^1.0.0" }, "peerDependencies": { "prettier": "^3.0.0", "prettier-plugin-solidity": "^1.0.0" } }, "sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw=="], + "solgrid": ["solgrid@0.0.16", "", { "optionalDependencies": { "@solgrid/cli-darwin-arm64": "0.0.16", "@solgrid/cli-linux-arm64": "0.0.16", "@solgrid/cli-linux-x64": "0.0.16", "@solgrid/cli-win32-x64": "0.0.16" }, "bin": { "solgrid": "bin/solgrid.js" } }, "sha512-dnXHeQ4+wLlYhNQCNeHJ6UYUIKZ2hIPA1oUsyeNsXZyU+l6b7TJSyneJetUMaMf2zhqMyXoldsqaUUEK9kTpSw=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], @@ -694,27 +536,17 @@ "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="], - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], - "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], - - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - - "table": ["table@6.9.0", "", { "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" } }, "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A=="], - "tar": ["tar@7.2.0", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.0", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w=="], - "text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="], - "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], - "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], @@ -728,11 +560,11 @@ "tslib": ["tslib@2.7.0", "", {}, "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="], - "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="], + "tsx": ["tsx@4.22.3", "", { "dependencies": { "esbuild": "~0.28.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], - "undici": ["undici@6.23.0", "", {}, "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g=="], + "undici": ["undici@6.26.0", "", {}, "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A=="], "undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], @@ -740,13 +572,11 @@ "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - "v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="], - "viem": ["viem@2.45.2", "", { "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.3", "ws": "8.18.3" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-GXPMmj0ukqFNL87sgpsZBy4CjGvsFQk42/EUdsn8dv3ZWtL4ukDXNCM0nME2hU0IcuS29CuUbrwbZN6iWxAipw=="], + "viem": ["viem@2.51.0", "", { "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": "https://pkg.pr.new/ox@386a3439fe1ce76d237930f8c6e6bb493746069a", "ws": "8.20.1" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-8C0Ca+eEapXE29vHMUW59NqKENl1X4s9P6xSNC9Nvw6EvAeAhn/LNUlgztk6TOw7KN1Gzz5a/n9Wv4okUfmY9g=="], - "vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], + "vite": ["vite@6.4.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ=="], "vite-node": ["vite-node@3.1.3", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA=="], @@ -758,8 +588,6 @@ "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - "ws": ["ws@8.17.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ=="], "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], @@ -770,19 +598,19 @@ "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "@pnpm/network.ca-file/graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="], + "@nomicfoundation/hardhat-keystore/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], + + "@nomicfoundation/hardhat-network-helpers/@nomicfoundation/hardhat-utils": ["@nomicfoundation/hardhat-utils@3.0.6", "", { "dependencies": { "@streamparser/json-node": "^0.0.22", "debug": "^4.3.2", "env-paths": "^2.2.0", "ethereum-cryptography": "^2.2.1", "fast-equals": "^5.4.0", "json-stream-stringify": "^3.1.6", "rfdc": "^1.3.1", "undici": "^6.16.1" } }, "sha512-AD/LPNdjXNFRrZcaAAewgJpdnHpPppZxo5p+x6wGMm5Hz4B3+oLf/LUzVn8qb4DDy9RE2c24l2F8vmL/w6ZuXg=="], - "@rocketh/verifier/commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], + "@nomicfoundation/hardhat-viem/@nomicfoundation/hardhat-utils": ["@nomicfoundation/hardhat-utils@3.0.6", "", { "dependencies": { "@streamparser/json-node": "^0.0.22", "debug": "^4.3.2", "env-paths": "^2.2.0", "ethereum-cryptography": "^2.2.1", "fast-equals": "^5.4.0", "json-stream-stringify": "^3.1.6", "rfdc": "^1.3.1", "undici": "^6.16.1" } }, "sha512-AD/LPNdjXNFRrZcaAAewgJpdnHpPppZxo5p+x6wGMm5Hz4B3+oLf/LUzVn8qb4DDy9RE2c24l2F8vmL/w6ZuXg=="], "@vitest/snapshot/@vitest/pretty-format": ["@vitest/pretty-format@3.1.3", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA=="], "@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.1.3", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA=="], - "better-ajv-errors/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "eip-1193-jsonrpc-provider/named-logs": ["named-logs@0.3.2", "", {}, "sha512-rpgShWrH6NakMKUDK32Pn/FZyPl7QoQRleMekHKkbrExXDymb2wNm3/BUbdTG5f3v7Qa17imVkSWHOfNFhDIPw=="], - "cacheable-request/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], - - "decompress-response/mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + "estree-walker/@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], "ethereum-cryptography/@noble/curves": ["@noble/curves@1.4.2", "", { "dependencies": { "@noble/hashes": "1.4.0" } }, "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw=="], @@ -796,44 +624,46 @@ "ethers/@noble/hashes": ["@noble/hashes@1.3.2", "", {}, "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="], - "got/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], - - "hardhat/ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], + "hardhat/@nomicfoundation/edr": ["@nomicfoundation/edr@0.12.0-next.28", "", { "dependencies": { "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.28", "@nomicfoundation/edr-darwin-x64": "0.12.0-next.28", "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.28", "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.28", "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.28", "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.28", "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.28" } }, "sha512-DOW5VFGIZWpuB6Llx+5ewn9HingN7uV/6nI3ecB3pZ4qc5OnwxnfG/KatYS6Fq3J55SuWMSxgDMHHA0kAVTFHQ=="], - "hardhat-deploy/@nomicfoundation/hardhat-zod-utils": ["@nomicfoundation/hardhat-zod-utils@3.0.0", "", { "dependencies": { "@nomicfoundation/hardhat-utils": "^3.0.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-xAi+45+V82pZZ9QGDEiii0wp+SXXH/8hS7/pk7S0gOG6h29gPuE42yek8wh3Ff0M+DrsB/RKZjcezmdwH5a6mQ=="], - - "hardhat-deploy/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], + "hardhat/ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], "http-proxy/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], "micro-eth-signer/@noble/curves": ["@noble/curves@1.8.2", "", { "dependencies": { "@noble/hashes": "1.7.2" } }, "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g=="], - "micro-eth-signer/@noble/hashes": ["@noble/hashes@1.7.2", "", {}, "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ=="], - - "named-logs-console/named-logs": ["named-logs@0.2.4", "", {}, "sha512-QHlcLpK2Ij+u7ZYDYgaYkTIlC/NcOwEnFdqbY+PF9ewAMUjvBwRVUyqBUtVaJ3V2YKVy2HiloAgLUdOEVRRyBA=="], + "micro-eth-signer/@noble/hashes": ["@noble/hashes@1.7.1", "", {}, "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ=="], "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], "ox/@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.1", "", {}, "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ=="], - "rocketh/commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], + "ox/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="], - "solhint/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "ox/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], - "solhint/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + "viem/abitype": ["abitype@1.2.3", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg=="], - "solhint/prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="], - - "table/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], - - "viem/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], + "viem/ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="], "ethereum-cryptography/@scure/bip32/@scure/base": ["@scure/base@1.1.9", "", {}, "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg=="], "ethereum-cryptography/@scure/bip39/@scure/base": ["@scure/base@1.1.9", "", {}, "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg=="], - "hardhat-deploy/@nomicfoundation/hardhat-zod-utils/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "hardhat/@nomicfoundation/edr/@nomicfoundation/edr-darwin-arm64": ["@nomicfoundation/edr-darwin-arm64@0.12.0-next.28", "", {}, "sha512-fJsQ8enlgp4Sky98jHcAFXXmb3EYNoYlwtGlmfoYjDsIeL74a2lozNzyo55CtduHD/sugffjtyF0nDyxZEdwMg=="], + + "hardhat/@nomicfoundation/edr/@nomicfoundation/edr-darwin-x64": ["@nomicfoundation/edr-darwin-x64@0.12.0-next.28", "", {}, "sha512-QST3PPJPejfRJhxThR5CoCxQAfIty0n8k40JtI+wLwKGCDT86JRKkJ3AaXPM1a72nUqMYoQK+gzQyA11zZGd4Q=="], + + "hardhat/@nomicfoundation/edr/@nomicfoundation/edr-linux-arm64-gnu": ["@nomicfoundation/edr-linux-arm64-gnu@0.12.0-next.28", "", {}, "sha512-sj4p6jeQfkiePxn1goZFZzz7V0SVFfZDH6ngPileQcAoFBWHKqi17UOG4IZ4NFpjYmDCcdrUWDNRbxC7OhgEqQ=="], + + "hardhat/@nomicfoundation/edr/@nomicfoundation/edr-linux-arm64-musl": ["@nomicfoundation/edr-linux-arm64-musl@0.12.0-next.28", "", {}, "sha512-d0hV02jMTozPEqRF3PO65Xi6/RqN5EywU5KaiDMcO+8b0nk+pJZ6VdcugRgv3lMMJbM/sP3LDFQn2eoOhalp7w=="], + + "hardhat/@nomicfoundation/edr/@nomicfoundation/edr-linux-x64-gnu": ["@nomicfoundation/edr-linux-x64-gnu@0.12.0-next.28", "", {}, "sha512-x3z4xbmCtSyZZg9MOhHcw1DOscngj50KK+6ZG0HKkGEbZ7WvDB9BnmRFEWo1rvIM+gqIcZvUBJbpLIdkA/BQYw=="], + + "hardhat/@nomicfoundation/edr/@nomicfoundation/edr-linux-x64-musl": ["@nomicfoundation/edr-linux-x64-musl@0.12.0-next.28", "", {}, "sha512-CKGcvP7enTo7gTXVxQiR8txPDOTNqS+wPLPkKXFzQBuVJ0FDj8eKIMRlZaw3Wbcd8QObaAKmKH7KzHVO5zzXmQ=="], + + "hardhat/@nomicfoundation/edr/@nomicfoundation/edr-win32-x64-msvc": ["@nomicfoundation/edr-win32-x64-msvc@0.12.0-next.28", "", {}, "sha512-QAzb9dZGwOU7Ee2N96dvdSLiUMmjlPVxgLqTKsQbkibcBZ9I+Zs8TGisGUZsDccrbUcR4wDv8S9tD1EM9fEs/g=="], - "table/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + "micro-eth-signer/@noble/curves/@noble/hashes": ["@noble/hashes@1.7.2", "", {}, "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ=="], } } diff --git a/contracts/.gitignore b/contracts/.gitignore index c34f3a098..06888bcc3 100644 --- a/contracts/.gitignore +++ b/contracts/.gitignore @@ -1,5 +1,6 @@ # Compiler files cache/ +.solgrid_cache/ out/ # Ignores development broadcast logs @@ -7,9 +8,6 @@ out/ /broadcast/*/31337/ /broadcast/**/dry-run/ -# Docs -docs/ - # Dotenv file .env @@ -25,6 +23,19 @@ lcov.info generated/ -deployments/devnet-local/ - +# Deployment records: track real deploys (live namespaces + dated archives) by +# default; ignore only the local rehearsal/runtime namespaces so editors do not +# dim the committed sets and throwaway runs stay out of the repo. +deployments/*-fork/ +deployments/*-clean-*/ +deployments/v1/* +!deployments/v1/sepolia/ + +# pre-migration +preMigration.log +preMigration-checkpoint.json +preMigration-errors.log csv-data/ + +# Dev scratch (analysis writeups, local rehearsal logs) +.dev/ diff --git a/contracts/.prettierrc.json b/contracts/.prettierrc.json deleted file mode 100644 index bbf6b58df..000000000 --- a/contracts/.prettierrc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "tabWidth": 2, - "printWidth": 80, - "trailingComma": "all", - "plugins": ["prettier-plugin-solidity"], - "overrides": [ - { - "files": "*.sol", - "options": { - "tabWidth": 4, - "printWidth": 100 - } - } - ] -} \ No newline at end of file diff --git a/contracts/.solhint.json b/contracts/.solhint.json deleted file mode 100644 index 2887ed33e..000000000 --- a/contracts/.solhint.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "extends": "solhint:recommended", - "plugins": ["prettier", "contracts-v2"], - "rules": { - "prettier/prettier": "error", - "compiler-version": ["error", ">=0.8.13"], - "no-unused-import": "error", - "no-global-import": "error", - "use-natspec": [ - "off", - { - "title": { - "enabled": true, - "ignore": {} - }, - "author": { - "enabled": true, - "ignore": {} - }, - "notice": { - "enabled": true, - "ignore": {} - }, - "param": { - "enabled": true, - "ignore": {} - }, - "return": { - "enabled": true, - "ignore": {} - } - } - ], - "duplicated-imports": "error", - "const-name-snakecase": "error", - "contract-name-capwords": "error", - "func-name-mixedcase": "warn", - "func-visibility": [ - "warn", - { - "ignoreConstructors": true - } - ], - "immutable-vars-naming": [ - "error", - { - "immutablesAsConstants": true - } - ], - "modifier-name-mixedcase": "error", - "named-parameters-mapping": "error", - "private-vars-leading-underscore": [ - "error", - { - "strict": true - } - ], - "imports-on-top": "error", - "imports-order": "off", - "import-path-check": "off", - "visibility-modifier-order": "error", - "contracts-v2/ordering": "error", - "contracts-v2/import-order-separation": [ - "error", - { - "importOrder": ["^forge-std/", "^@?\\w", "^\\.\\./", "^\\./"] - } - ], - "contracts-v2/selector-tags": "error", - "contracts-v2/natspec-triple-slash": "error" - } -} diff --git a/contracts/README.md b/contracts/README.md index 1e9b9fb4c..1ffba8179 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -77,7 +77,7 @@ Technical details: - Normal roles are stored in the lower 128 bits of the `uint256` role bitmap. The corresponding admin roles are stored in the upper 128 bits. For a given role its admin role is found by calculating `role << 128`. -- For a given resource, a **maximum of 15 assigness** can have a given role in that resource. +- For a given resource, a **maximum of 15 assignees** can have a given role in that resource. - Assigning a role via the external methods (`grantRole`, `revokeRole`, etc) requires the caller to hold the corresponding admin role for that role. @@ -85,7 +85,7 @@ Technical details: - Admin roles can, however, be revoked from oneself. -=**Permission Inheritance**: When checking permissions for a resource, EAC combines (via bitwise OR) the roles from: +**Permission Inheritance**: When checking permissions for a resource, EAC combines (via bitwise OR) the roles from: - The specific resource (e.g., your name's permissions) - The root resource (root-level permissions) @@ -98,15 +98,22 @@ In registry contracts, EAC is used with these specific behaviors: **Registry-Specific Roles**: From [`RegistryRolesLib.sol`](src/registry/libraries/RegistryRolesLib.sol): -| Role | Bit Position | Admin Bit Position | Description | -| ------------------------- | ------------ | ------------------ | ---------------------------------------------------------------------- | -| `ROLE_REGISTRAR` | 0 | 128 | Can register new names (root-only) | -| `ROLE_RENEW` | 4 | 132 | Can renew name registrations | -| `ROLE_SET_SUBREGISTRY` | 8 | 136 | Can change subregistry addresses | -| `ROLE_SET_RESOLVER` | 12 | 140 | Can change the resolver address | -| `ROLE_CAN_TRANSFER_ADMIN` | - | 144 | Auto-granted to new name owner. Revoking this creates a soulbound NFT. | +| Role | Bit | Admin Bit | Scope | Description | +| ------------------------- | ---- | --------- | ------------- | ---------------------------------------------------------------------- | +| `ROLE_REGISTRAR` | 0 | 128 | Root-only | Register and reserve new names | +| `ROLE_REGISTER_RESERVED` | 4 | 132 | Root-only | Promote reserved name to registered | +| `ROLE_SET_PARENT` | 8 | 136 | Root-only | Set parent registry | +| `ROLE_UNREGISTER` | 12 | 140 | Root or token | Unregister names | +| `ROLE_RENEW` | 16 | 144 | Root or token | Extend name expiry | +| `ROLE_SET_SUBREGISTRY` | 20 | 148 | Root or token | Change child registry | +| `ROLE_SET_RESOLVER` | 24 | 152 | Root or token | Change resolver address | +| `ROLE_CAN_TRANSFER_ADMIN` | 28\* | 156 | Root or token | Admin-only. Auto-granted to name owner. Revoke to make soulbound. | +| `ROLE_CAN_NAME` | 120 | 248 | Root-only | Name contract | +| `ROLE_UPGRADE` | 124 | 252 | Root-only | UUPS proxy upgrades. WrapperRegistry targets must also be DAO-approved | -**Note**: `ROLE_REGISTRAR` is a root-only role since creating new subnames has no logical resource-specific equivalent (the resource doesn't exist yet). +\*`ROLE_CAN_TRANSFER_ADMIN` has no base role; it is admin-only (upper 128 bits). + +**Note**: Root-only roles have no resource-specific equivalent (e.g. `ROLE_REGISTRAR` — the resource doesn't exist until the name is created). **Admin Role Capabilities** @@ -120,22 +127,29 @@ In registry contracts, EAC is used with these specific behaviors: - Existing **roles** delegated to other accounts remain intact unless explicitly revoked - Example: If Alice granted Bob `ROLE_SET_RESOLVER` and transfers the name to Charlie, Charlie becomes the new admin but Bob keeps his resolver permission -#### Usage Examples +#### Static Deployment Permissions -```solidity -// Grant a base role for a specific name -registry.grantRoles(tokenId, ROLE_SET_RESOLVER, alice); +Roles granted during core deployment. -// Grant multiple roles at once -uint256 roles = ROLE_SET_RESOLVER | ROLE_SET_SUBREGISTRY; -registry.grantRoles(tokenId, roles, operator); +| Contract | Scope | Target | REGISTRAR | REGISTER_RESERVED | SET_PARENT | UNREGISTER | RENEW | SET_SUBREGISTRY | SET_RESOLVER | CAN_TRANSFER_ADMIN | CAN_NAME | UPGRADE | +| --------------- | -------- | ----------------------------- | --------- | ----------------- | ---------- | ---------- | ----- | --------------- | ------------ | ------------------ | -------- | ------- | +| RootRegistry | Root | Deployer | AR | AR | AR | | AR | | | | AR | | +| RootRegistry | .eth | Deployer | | | | | | | AR | AR | | | +| RootRegistry | .reverse | Deployer | | | | AR | AR | AR | AR | AR | | | +| ETHRegistry | Root | Deployer | A | A | AR | | A | | | | AR | | +| ETHRegistry | Root | `ETHRegistrar` | R | | | | R | | | | | | +| ETHRegistry | Root | `BatchRegistrar` | R | | | | R | | | | | | +| ETHRegistry | Root | `UnlockedMigrationController` | | R | | | | | | | | | +| ETHRegistry | Root | `LockedMigrationController` | | R | | | | | | | | | +| ReverseRegistry | Root | Deployer | AR | AR | AR | AR | AR | AR | AR | AR | AR | AR | -// Set global permissions (requires registry owner) -registry.grantRoles(ROOT_RESOURCE, ROLE_SET_RESOLVER, admin); +Legend: A = admin only, R = regular only, AR = admin and regular -// Check permissions -registry.hasRoles(tokenId, ROLE_SET_RESOLVER, alice); -``` +_`ETHRegistrar`, `ETHRenewerV1`, and `ApprovedUpgradeGate` use `Ownable`, not `EnhancedAccessControl`. Implementation contracts (`PermissionedResolverImpl`, `UserRegistryImpl`, `WrapperRegistryImpl`) grant `ROLE_CAN_NAME | ROLE_CAN_NAME_ADMIN` roles at deployment; proxies receive roles via `initialize()` when created._ + +_Under the phased migration deploy (the `deferV2Registrar` tag, always set by `phase deploy-v2` — see [docs/migration.md](docs/migration.md#phase-1-deploy-v2-contracts)), the `ETHRegistrar` grant of `REGISTRAR | RENEW` is skipped at deploy time and instead performed in [phase 6](docs/migration.md#phase-6-enable-the-v2-controller)._ + +_The token for `eth` is registered to the deployer; `reverse` and `addr.reverse` are reserved._ #### Creating Emancipated Names @@ -145,7 +159,7 @@ You can create the equivalent of Name Wrapper "emancipated" names by: 2. Locking the subregistry into the parent registry 3. Result: Parent registry owner cannot interfere with subname operations -#### Example Usage +#### Usage Examples ```solidity import {RegistryRolesLib} from "./libraries/RegistryRolesLib.sol"; @@ -165,6 +179,9 @@ uint256 operatorRoles = RegistryRolesLib.ROLE_SET_RESOLVER | RegistryRolesLib.ROLE_SET_SUBREGISTRY; registry.grantRoles(tokenId, operatorRoles, operator); +// Grant a role at the registry root (applies to every name; requires the root admin role) +registry.grantRootRoles(RegistryRolesLib.ROLE_SET_RESOLVER, admin); + // Check if user has required permissions bool canSetResolver = registry.hasRoles( tokenId, @@ -192,15 +209,45 @@ Standard interface all registries must implement: ```solidity interface IRegistry is IERC1155Singleton { - event NameRegistered(uint256 indexed tokenId, bytes32 indexed labelHash, string label, address owner, uint64 expiry, address indexed sender); - event NameReserved(uint256 indexed tokenId, bytes32 indexed labelHash, string label, uint64 expiry, address indexed sender); + event NameRegistered( + uint256 indexed tokenId, + bytes32 indexed labelHash, + string label, + address owner, + uint64 expiry, + address indexed sender + ); + event NameReserved( + uint256 indexed tokenId, + bytes32 indexed labelHash, + string label, + uint64 expiry, + address indexed sender + ); event NameUnregistered(uint256 indexed tokenId, address indexed sender); - event ExpiryUpdated(uint256 indexed tokenId, uint64 newExpiry, address indexed sender); - event SubregistryUpdated(uint256 indexed tokenId, IRegistry subregistry, address indexed sender); - event ResolverUpdated(uint256 indexed tokenId, address resolver, address indexed sender); - event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId); - - function getSubregistry(string calldata label) external view returns (IRegistry); + event ExpiryUpdated( + uint256 indexed tokenId, + uint64 newExpiry, + address indexed sender + ); + event SubregistryUpdated( + uint256 indexed tokenId, + IRegistry subregistry, + address indexed sender + ); + event ResolverUpdated( + uint256 indexed tokenId, + address resolver, + address indexed sender + ); + event TokenRegenerated( + uint256 indexed oldTokenId, + uint256 indexed newTokenId + ); + + function getSubregistry( + string calldata label + ) external view returns (IRegistry); function getResolver(string calldata label) external view returns (address); } ``` @@ -228,11 +275,11 @@ Feature-complete registry with role-based access control: ```solidity struct Entry { - uint32 eacVersionId; // Version counter for access control changes (incremented on permission updates) - uint32 tokenVersionId; // Version counter for token regeneration (incremented on burn/remint) - IRegistry subregistry; // Registry contract for subdomains under this name - uint64 expiry; // Timestamp when the name expires (0 = never expires) - address resolver; // Resolver contract for name resolution data + uint32 eacVersionId; // Version counter for access control changes (incremented on permission updates) + uint32 tokenVersionId; // Version counter for token regeneration (incremented on burn/remint) + IRegistry subregistry; // Registry contract for subdomains under this name + uint64 expiry; // Timestamp when the name expires (0 = never expires) + address resolver; // Resolver contract for name resolution data } ``` @@ -255,6 +302,13 @@ Modified ERC1155 allowing only one token per ID: - `LockedMigrationController`: Handles ENSv1 → ENSv2 migration for locked names - `UnlockedMigrationController`: Handles ENSv1 → ENSv2 migration for unlocked names +Scripts for running the migration end-to-end: + +- [Phased migration](docs/migration.md) — the phase-by-phase workflow that runs the v1 → v2 cutover: phase definitions, the `bun run migration` operator CLI, the Hardhat `migration` tasks, and the fork/clean-testnet rehearsals. +- [Pre-migration](docs/premigration.md) — seed v1 registrations into the v2 registry as _reserved_ entries, via `BatchRegistrar`. +- [Prepare migration](docs/prepareMigration.md) — swap registry roles from `BatchRegistrar` to `ETHRegistrar` and the two migration controllers once pre-migration is complete. +- [Universal Resolver structure](docs/universalResolver.md) — the proxy chain used to cut universal resolution over from v1 to v2, and the phased deploy scripts that manage it. + ### Resolution #### `UniversalResolverV2` - One-Stop Resolution @@ -268,6 +322,8 @@ Single contract for resolving any ENS name: - Wildcard resolution - Batch resolution +On live networks, clients reach it through a chain of upgradable proxies that manages the v1 → v2 cutover — see [Universal Resolver structure](docs/universalResolver.md). + **Example**: ```solidity @@ -279,6 +335,15 @@ Single contract for resolving any ENS name: address resolved = abi.decode(result, (address)); ``` +## Deployed Addresses + +Generated contract address tables, regenerated automatically at the end of `phase deploy-v2` (or on demand with `bun run docs:addresses`): + +- [Sepolia](docs/addresses/sepolia.md) +- [Mainnet](docs/addresses/mainnet.md) + +> **Operational note (Sepolia, temporary):** the intermediate URP `0x6d80F2172CFdEc5730fE683860C33d26fC42e6F1` has been repointed from the current fresh deployment (`deployments/sepolia`) back to the previous deployment's `UniversalResolverV2` `0x2f8a180604c42457cb56c7c4f708748ff1f91df1` (`deployments/sepolia-official-v1-20260525-r2`), so the public entrypoint `0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe` again resolves v1 names. This is a temporary measure at the team's request until the fresh deployment's v1 mirror is wired up; to revert, run `phase upgrade-managed-urp --network sepolia --deployment-network sepolia` (the current stack). + ## Getting started ### Installation @@ -326,6 +391,7 @@ Or run specific test suites: bun run test:hardhat # Run Hardhat tests bun run test:forge # Run Forge tests bun run test:hardhat test/Ens.t.ts # specific Hardhat test +bun run test:e2e # end-to-end tests ``` ## Running the Devnet @@ -342,6 +408,17 @@ bun run devnet # runs w/last build This will start a local chain at http://localhost:8545 (Chain ID: 31337) +To populate the devnet with test names (registrations, subnames, aliases, renewals, etc.): + +```sh +bun run devnet --testNames +``` + +This runs `testNames()` which creates 17 names in various states. For details on the test data and the events emitted, see: + +- [Indexing Test Names](../docs/indexing-test-names.md) — what each test name does and which events it emits +- [Indexing ENSv2 Events](../docs/indexing-ensv2-events.md) — full reference of all ENSv2 contract events + ### Using Docker Compose 1. Make sure you have Docker and Docker Compose installed diff --git a/contracts/deploy/00_ContractNamer.ts b/contracts/deploy/00_ContractNamer.ts new file mode 100755 index 000000000..8ee517515 --- /dev/null +++ b/contracts/deploy/00_ContractNamer.ts @@ -0,0 +1,23 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ deployViaProxy, namedAccounts: { deployer, owner } }) => { + await deployViaProxy( + "ContractNamer", + { + account: deployer, + artifact: artifacts.ContractNamer, + }, + { + proxyContract: "UUPS", + execute: { + methodName: "initialize", + args: [owner], + }, + }, + ); + }, + { + tags: ["ContractNamer", "v2"], + }, +); diff --git a/contracts/deploy/00_DNSSECGatewayProvider.ts b/contracts/deploy/00_DNSSECGatewayProvider.ts index 64bfe8e5a..98ab5c623 100755 --- a/contracts/deploy/00_DNSSECGatewayProvider.ts +++ b/contracts/deploy/00_DNSSECGatewayProvider.ts @@ -1,14 +1,14 @@ import { artifacts, execute } from "@rocketh"; export default execute( - async ({ deploy, namedAccounts: { deployer } }) => { + async ({ deploy, namedAccounts: { deployer, owner } }) => { await deploy("DNSSECGatewayProvider", { account: deployer, artifact: artifacts.GatewayProvider, - args: [deployer, ["https://dnssec-oracle.ens.domains/"]], + args: [owner, ["https://dnssec-oracle.ens.domains/"]], }); }, { - tags: ["DNSSECGatewayProvider", "l1"], + tags: ["DNSSECGatewayProvider", "v2"], }, ); diff --git a/contracts/deploy/00_DNSTXTResolver.ts b/contracts/deploy/00_DNSTXTResolver.ts index 0a927c65f..aa55216d1 100644 --- a/contracts/deploy/00_DNSTXTResolver.ts +++ b/contracts/deploy/00_DNSTXTResolver.ts @@ -1,13 +1,18 @@ import { artifacts, execute } from "@rocketh"; export default execute( - async ({ deploy, namedAccounts: { deployer } }) => { + async ({ get, deploy, namedAccounts: { deployer } }) => { + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + await deploy("DNSTXTResolver", { account: deployer, artifact: artifacts.DNSTXTResolver, + args: [contractNamer.address], }); }, { - tags: ["DNSTXTResolver", "l1"], + tags: ["DNSTXTResolver", "v2"], + dependencies: ["ContractNamer"], }, ); diff --git a/contracts/deploy/00_ENSV1Resolver.ts b/contracts/deploy/00_ENSV1Resolver.ts index 496b75f46..b1bd0cd69 100644 --- a/contracts/deploy/00_ENSV1Resolver.ts +++ b/contracts/deploy/00_ENSV1Resolver.ts @@ -1,22 +1,31 @@ import { artifacts, execute } from "@rocketh"; export default execute( - async ({ get, deploy, namedAccounts: { deployer } }) => { - const ensRegistryV1 = - get<(typeof artifacts.ENSRegistry)["abi"]>("ENSRegistry"); - - const batchGatewayProvider = get<(typeof artifacts.GatewayProvider)["abi"]>( + async ({ get, getV1, deploy, namedAccounts: { deployer } }) => { + const batchGatewayProvider = await getV1< + (typeof artifacts.GatewayProvider)["abi"] + >( "BatchGatewayProvider", ); + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + const ensRegistry = + await getV1<(typeof artifacts.ENSRegistry)["abi"]>("ENSRegistry"); + await deploy("ENSV1Resolver", { account: deployer, artifact: artifacts.ENSV1Resolver, - args: [ensRegistryV1.address, batchGatewayProvider.address], + args: [ + batchGatewayProvider.address, + contractNamer.address, + ensRegistry.address, + ], }); }, { - tags: ["ENSV1Resolver", "l1"], - dependencies: ["ENSRegistry", "BatchGatewayProvider"], + tags: ["ENSV1Resolver", "migration:phase1:deploy-v2", "v2"], + dependencies: ["BatchGatewayProvider", "ContractNamer", "ENSRegistry"], }, ); diff --git a/contracts/deploy/00_ENSV2Resolver.ts b/contracts/deploy/00_ENSV2Resolver.ts index 8d0053639..de913d477 100755 --- a/contracts/deploy/00_ENSV2Resolver.ts +++ b/contracts/deploy/00_ENSV2Resolver.ts @@ -1,22 +1,90 @@ import { artifacts, execute } from "@rocketh"; +import { getAddress, namehash, zeroAddress } from "viem"; export default execute( - async ({ get, deploy, namedAccounts: { deployer } }) => { + async ({ + get, + getOrNull, + getV1, + deploy, + execute: write, + read, + namedAccounts: { deployer, owner, v1Owner }, + }) => { + const batchGatewayProvider = await getV1< + (typeof artifacts.GatewayProvider)["abi"] + >( + "BatchGatewayProvider", + ); + + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + const rootRegistry = get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); - const batchGatewayProvider = get<(typeof artifacts.GatewayProvider)["abi"]>( - "BatchGatewayProvider", - ); + const ensRegistry = + await getV1<(typeof artifacts.ENSRegistry)["abi"]>("ENSRegistry"); - await deploy("ENSV2Resolver", { + const registrarSecurityController = await getV1< + (typeof artifacts.RegistrarSecurityController)["abi"] + >("RegistrarSecurityController").catch(() => null); + + console.log("Deploying ENSV2Resolver"); + console.log(" - Getting ENSv1 .eth resolver"); + const currentResolver = await read(ensRegistry, { + functionName: "resolver", + args: [namehash("eth")], + }); + const ethResolver = getAddress(currentResolver) === getAddress(zeroAddress) + ? await getV1<(typeof artifacts.OwnedResolver)["abi"]>("OwnedResolver") + .then((deployment) => deployment.address) + .catch(() => currentResolver) + : currentResolver; + console.log(` - Got: ${ethResolver}`); + + const existingEnsV2Resolver = getOrNull< + (typeof artifacts.ENSV2Resolver)["abi"] + >("ENSV2Resolver"); + const ensV2Resolver = existingEnsV2Resolver ?? await deploy("ENSV2Resolver", { account: deployer, artifact: artifacts.ENSV2Resolver, - args: [rootRegistry.address, batchGatewayProvider.address], + args: [ + batchGatewayProvider.address, + contractNamer.address, + rootRegistry.address, + ethResolver, + ], }); + + if (getAddress(currentResolver) === getAddress(ensV2Resolver.address)) return; + + console.log(" - Setting ENSv1 .eth resolver to ENSV2Resolver"); + if (registrarSecurityController) { + await write(registrarSecurityController, { + account: v1Owner ?? owner, + functionName: "setRegistrarResolver", + args: [ensV2Resolver.address], + }); + } else { + const baseRegistrar = await getV1< + (typeof artifacts.BaseRegistrarImplementation)["abi"] + >("BaseRegistrarImplementation"); + await write(baseRegistrar, { + account: v1Owner ?? owner, + functionName: "setResolver", + args: [ensV2Resolver.address], + }); + } }, { - tags: ["ENSV2Resolver", "l1"], - dependencies: ["RootRegistry", "BatchGatewayProvider"], + tags: ["ENSV2Resolver", "migration:phase1:deploy-v2", "v2"], + dependencies: [ + "BatchGatewayProvider", + "ContractNamer", + "RootRegistry", + "EthOwnedResolver", // BaseRegistrarImplementation:setup => eventually setup as OwnedResolver + "RegistrarSecurityController", + ], }, ); diff --git a/contracts/deploy/00_ETHReverseRegistrar.ts b/contracts/deploy/00_ETHReverseRegistrar.ts deleted file mode 100644 index f51802b34..000000000 --- a/contracts/deploy/00_ETHReverseRegistrar.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { artifacts, execute } from "@rocketh"; - -export default execute( - async ({ deploy, namedAccounts: { deployer } }) => { - // create a new registrar for "addr.reverse" - await deploy("ETHReverseRegistrar", { - account: deployer, - artifact: artifacts.L2ReverseRegistrar, - args: [60n], - }); - }, - { - tags: ["ETHReverseRegistrar", "l1"], - }, -); diff --git a/contracts/deploy/00_HCAFactory.ts b/contracts/deploy/00_HCAFactory.ts deleted file mode 100644 index f0eb8accc..000000000 --- a/contracts/deploy/00_HCAFactory.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { artifacts, execute } from "@rocketh"; - -export default execute( - async ({ deploy, namedAccounts: { deployer } }) => { - // TODO: deploy the actual HCAFactory - await deploy("HCAFactory", { - account: deployer, - artifact: artifacts.MockHCAFactoryBasic, - args: [], - }); - }, - { - tags: ["HCAFactory", "l1"], - }, -); diff --git a/contracts/deploy/02_MockTokens.ts b/contracts/deploy/00_MockTokens.ts similarity index 51% rename from contracts/deploy/02_MockTokens.ts rename to contracts/deploy/00_MockTokens.ts index b861bcf45..b9a8824e7 100644 --- a/contracts/deploy/02_MockTokens.ts +++ b/contracts/deploy/00_MockTokens.ts @@ -1,26 +1,26 @@ import { artifacts, execute } from "@rocketh"; export default execute( - async ({ deploy, get, namedAccounts: { deployer } }) => { - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); + async ({ deploy, namedAccounts: { deployer }, tags }) => { + // Free-mint mock payment tokens must never ship to mainnet; the price + // oracle wires real tokens there instead. + if (tags.hasDao) return; const MockERC20 = artifacts["test/mocks/MockERC20.sol/MockERC20"]; await deploy("MockUSDC", { account: deployer, artifact: MockERC20, - args: ["USDC", 6, hcaFactory.address], + args: ["USDC", 6], }); await deploy("MockDAI", { account: deployer, artifact: MockERC20, - args: ["DAI", 18, hcaFactory.address], + args: ["DAI", 18], }); }, { - tags: ["MockTokens", "l1"], - dependencies: ["HCAFactory"], + tags: ["MockTokens", "migration:phase1:deploy-v2", "v2"], }, ); diff --git a/contracts/deploy/00_RootRegistry.ts b/contracts/deploy/00_RootRegistry.ts index e581e642b..280a19dac 100644 --- a/contracts/deploy/00_RootRegistry.ts +++ b/contracts/deploy/00_RootRegistry.ts @@ -1,23 +1,30 @@ import { artifacts, execute } from "@rocketh"; -import { ROLES } from "../script/deploy-constants.js"; +import { DEPLOYMENT_ROLES, ROLES } from "../script/deploy-constants.js"; export default execute( - async ({ deploy, get, namedAccounts: { deployer } }) => { - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); + async ({ + deploy, + get, + execute: write, + namedAccounts: { deployer, owner }, + }) => { + const labelStore = get<(typeof artifacts.ILabelStore)["abi"]>("LabelStore"); - const registryMetadata = get< - (typeof artifacts.SimpleRegistryMetadata)["abi"] - >("SimpleRegistryMetadata"); - - await deploy("RootRegistry", { + const rootRegistry = await deploy("RootRegistry", { account: deployer, artifact: artifacts.PermissionedRegistry, - args: [hcaFactory.address, registryMetadata.address, deployer, ROLES.ALL], + args: [labelStore.address, deployer, DEPLOYMENT_ROLES.ROOT_REGISTRY_ROOT], + }); + + console.log(" - Granting CAN_NAME to owner"); + await write(rootRegistry, { + functionName: "grantRootRoles", + args: [ROLES.REGISTRY.CAN_NAME, owner], + account: deployer, }); }, { - tags: ["RootRegistry", "l1"], - dependencies: ["HCAFactory", "RegistryMetadata"], + tags: ["RootRegistry", "migration:phase1:deploy-v2", "v2"], + dependencies: ["LabelStore"], }, ); diff --git a/contracts/deploy/00_VerifiableFactory.ts b/contracts/deploy/00_VerifiableFactory.ts index 03cbcfb24..3a5169a7b 100644 --- a/contracts/deploy/00_VerifiableFactory.ts +++ b/contracts/deploy/00_VerifiableFactory.ts @@ -8,6 +8,6 @@ export default execute( }); }, { - tags: ["VerifiableFactory", "l1"], + tags: ["VerifiableFactory", "migration:phase1:deploy-v2", "v2"], }, ); diff --git a/contracts/deploy/01_DNSAliasResolver.ts b/contracts/deploy/01_DNSAliasResolver.ts index 7961ac9ec..bd8b0a330 100755 --- a/contracts/deploy/01_DNSAliasResolver.ts +++ b/contracts/deploy/01_DNSAliasResolver.ts @@ -1,22 +1,31 @@ import { artifacts, execute } from "@rocketh"; export default execute( - async ({ deploy, get, namedAccounts: { deployer } }) => { + async ({ deploy, get, getV1, namedAccounts: { deployer } }) => { const rootRegistry = get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); - const batchGatewayProvider = get<(typeof artifacts.GatewayProvider)["abi"]>( + const batchGatewayProvider = await getV1< + (typeof artifacts.GatewayProvider)["abi"] + >( "BatchGatewayProvider", ); + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + const dnsAliasResolver = await deploy("DNSAliasResolver", { account: deployer, artifact: artifacts.DNSAliasResolver, - args: [rootRegistry.address, batchGatewayProvider.address], + args: [ + rootRegistry.address, + batchGatewayProvider.address, + contractNamer.address, + ], }); }, { - tags: ["DNSAliasResolver", "l1"], - dependencies: ["RootRegistry", "BatchGatewayProvider"], + tags: ["DNSAliasResolver", "v2"], + dependencies: ["RootRegistry", "BatchGatewayProvider", "ContractNamer"], }, ); diff --git a/contracts/deploy/01_DNSTLDResolver.ts b/contracts/deploy/01_DNSTLDResolver.ts index bd4bdbf9e..c88c9d636 100755 --- a/contracts/deploy/01_DNSTLDResolver.ts +++ b/contracts/deploy/01_DNSTLDResolver.ts @@ -1,106 +1,106 @@ import { artifacts, execute } from "@rocketh"; -import { zeroAddress } from "viem"; -import { dnsEncodeName } from "../test/utils/utils.js"; -import { MAX_EXPIRY } from "../script/deploy-constants.js"; - -async function fetchPublicSuffixes() { - const res = await fetch( - "https://publicsuffix.org/list/public_suffix_list.dat", - { headers: { Connection: "close" } }, - ); - if (!res.ok) throw new Error(`expected suffixes: ${res.status}`); - return (await res.text()) - .split("\n") - .map((x) => x.trim()) - .filter((x) => x && !x.startsWith("//")); -} +import { + fetchPublicSuffixes, + filterAvailableSuffixes, + registerSuffixesViaBatchRegistrar, +} from "../script/publicSuffixes.js"; export default execute( async ({ deploy, execute: write, get, + getV1, read, namedAccounts: { deployer }, - network, + tags, }) => { - const ensRegistryV1 = - get<(typeof artifacts.ENSRegistry)["abi"]>("ENSRegistry"); + const ensRegistry = + await getV1<(typeof artifacts.ENSRegistry)["abi"]>("ENSRegistry"); - const dnsTLDResolverV1 = get<(typeof artifacts.OffchainDNSResolver)["abi"]>( - "OffchainDNSResolver", - ); + const dnsTLDResolverV1 = await getV1< + (typeof artifacts.OffchainDNSResolver)["abi"] + >("OffchainDNSResolver"); - const publicSuffixList = get< + const publicSuffixList = await getV1< (typeof artifacts.SimplePublicSuffixList)["abi"] >("SimplePublicSuffixList"); const rootRegistry = get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); - const dnssecOracle = get<(typeof artifacts.DNSSEC)["abi"]>("DNSSECImpl"); + const dnssecOracle = + await getV1<(typeof artifacts.DNSSECImpl)["abi"]>("DNSSECImpl"); - const batchGatewayProvider = get<(typeof artifacts.GatewayProvider)["abi"]>( - "BatchGatewayProvider", - ); + const batchGatewayProvider = await getV1< + (typeof artifacts.GatewayProvider)["abi"] + >("BatchGatewayProvider"); const dnssecGatewayProvider = get< (typeof artifacts.GatewayProvider)["abi"] >("DNSSECGatewayProvider"); + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + const dnsTLDResolver = await deploy("DNSTLDResolver", { account: deployer, artifact: artifacts.DNSTLDResolver, args: [ - ensRegistryV1.address, + ensRegistry.address, dnsTLDResolverV1.address, rootRegistry.address, dnssecOracle.address, dnssecGatewayProvider.address, batchGatewayProvider.address, + contractNamer.address, ], }); - let suffixes = network.tags.local + const candidates = tags.local ? ["com", "org", "net", "xyz"] : await fetchPublicSuffixes(); - suffixes = ( - await Promise.all( - suffixes.map((suffix) => - read(publicSuffixList, { - functionName: "isPublicSuffix", - args: [dnsEncodeName(suffix)], - }).then((pub) => (pub ? suffix : "")), - ), - ) - ).filter(Boolean); + const suffixes = await filterAvailableSuffixes({ + read, + publicSuffixList, + rootRegistry, + candidates, + }); - // TODO: this create 1000+ transactions - // batching is a mess in rocketh - // anvil batching appears broken (only mines 1-2 tx) - for (const suffix of suffixes) { - await write(rootRegistry, { - account: deployer, - functionName: "register", - args: [ - suffix, - deployer, // TODO: ownership - zeroAddress, - dnsTLDResolver.address, - 0n, // TODO: roles - MAX_EXPIRY, - ], - }); + if (suffixes.length === 0) { + console.warn(" - No suffixes found"); + return; } + + const batchRegistrar = await deploy("RootBatchRegistrar", { + account: deployer, + artifact: artifacts.BatchRegistrar, + args: [rootRegistry.address, deployer], + }); + + await registerSuffixesViaBatchRegistrar({ + write, + account: deployer, + rootRegistry, + batchRegistrar, + resolver: dnsTLDResolver.address, + suffixes, + }); }, { - tags: ["DNSTLDResolver", "l1"], + tags: ["DNSTLDResolver", "v2"], dependencies: [ "RootRegistry", - "OffchainDNSResolver", // "ENSRegistry" + "DNSSECImpl" + "ENSRegistry", + "DNSSECImpl", + "OffchainDNSResolver", "SimplePublicSuffixList", "BatchGatewayProvider", "DNSSECGatewayProvider", + "ContractNamer", + // Run the v1 root-TLD mirror first so it claims root TLDs for v1 fallback; + // this resolver then registers only the remaining (non-root) public suffixes. + "DNSV1MirrorTLDs", ], }, ); diff --git a/contracts/deploy/01_DNSV1MirrorTLDs.ts b/contracts/deploy/01_DNSV1MirrorTLDs.ts new file mode 100644 index 000000000..34c2f3fde --- /dev/null +++ b/contracts/deploy/01_DNSV1MirrorTLDs.ts @@ -0,0 +1,76 @@ +import { artifacts, execute } from "@rocketh"; +import { + fetchPublicSuffixes, + filterAvailableSuffixes, + registerSuffixesViaBatchRegistrar, +} from "../script/publicSuffixes.js"; + +function rootTLDs(suffixes: string[]) { + return suffixes.filter( + (suffix) => + !suffix.startsWith("!") && + !suffix.startsWith("*.") && + !suffix.includes("."), + ); +} + +export default execute( + async ({ + deploy, + execute: write, + get, + getV1, + read, + namedAccounts: { deployer }, + tags, + }) => { + const publicSuffixList = await getV1< + (typeof artifacts.SimplePublicSuffixList)["abi"] + >("SimplePublicSuffixList"); + + const rootRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); + + const ensV1Resolver = + get<(typeof artifacts.ENSV1Resolver)["abi"]>("ENSV1Resolver"); + + if (tags["clean-testnet"]) { + console.warn(" - Skipping v1 mirror TLD registration on clean-testnet"); + return; + } + + const candidates = tags.local + ? ["com", "org", "net", "xyz"] + : rootTLDs(await fetchPublicSuffixes()); + const suffixes = await filterAvailableSuffixes({ + read, + publicSuffixList, + rootRegistry, + candidates, + }); + + if (suffixes.length === 0) { + console.warn(" - No suffixes found"); + return; + } + + const batchRegistrar = await deploy("DNSV1MirrorRootBatchRegistrar", { + account: deployer, + artifact: artifacts.BatchRegistrar, + args: [rootRegistry.address, deployer], + }); + + await registerSuffixesViaBatchRegistrar({ + write, + account: deployer, + rootRegistry, + batchRegistrar, + resolver: ensV1Resolver.address, + suffixes, + }); + }, + { + tags: ["DNSV1MirrorTLDs", "migration:phase1:deploy-v2"], + dependencies: ["RootRegistry", "ENSV1Resolver", "SimplePublicSuffixList"], + }, +); diff --git a/contracts/deploy/01_ETHRegistry.ts b/contracts/deploy/01_ETHRegistry.ts index 103d9de94..393cdd6f0 100644 --- a/contracts/deploy/01_ETHRegistry.ts +++ b/contracts/deploy/01_ETHRegistry.ts @@ -1,34 +1,77 @@ import { artifacts, execute } from "@rocketh"; -import { zeroAddress } from "viem"; -import { MAX_EXPIRY, ROLES } from "../script/deploy-constants.js"; +import { isAddressEqual, labelhash, zeroAddress } from "viem"; +import { + MAX_EXPIRY, + DEPLOYMENT_ROLES, + ROLES, +} from "../script/deploy-constants.js"; -// TODO: ownership export default execute( - async ({ deploy, execute: write, get, namedAccounts: { deployer } }) => { + async ({ + deploy, + execute: write, + get, + read, + namedAccounts: { deployer, owner }, + }) => { const rootRegistry = get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); - - const registryMetadata = get< - (typeof artifacts.SimpleRegistryMetadata)["abi"] - >("SimpleRegistryMetadata"); + const labelStore = get<(typeof artifacts.ILabelStore)["abi"]>("LabelStore"); + console.log("Deploying ETHRegistry"); const ethRegistry = await deploy("ETHRegistry", { account: deployer, artifact: artifacts.PermissionedRegistry, - args: [hcaFactory.address, registryMetadata.address, deployer, ROLES.ALL], + args: [labelStore.address, deployer, DEPLOYMENT_ROLES.ETH_REGISTRY_ROOT], + }); + + const currentStatus = await read(rootRegistry, { + functionName: "getStatus", + args: [BigInt(labelhash("eth"))], }); - await write(rootRegistry, { + if (currentStatus === 0) { + console.log(" - Registering in parent"); + await write(rootRegistry, { + account: deployer, + functionName: "register", + args: [ + "eth", + deployer, + ethRegistry.address, + zeroAddress, + DEPLOYMENT_ROLES.ETH_TOKEN, + MAX_EXPIRY, + ], + }); + } + + const [currentParent, currentLabel] = await read(ethRegistry, { + functionName: "getParent", + }); + + if ( + !isAddressEqual(currentParent, rootRegistry.address) || + currentLabel !== "eth" + ) { + console.log(" - Setting canonical parent"); + await write(ethRegistry, { + account: deployer, + functionName: "setParent", + args: [rootRegistry.address, "eth"], + }); + } + + console.log(" - Granting CAN_NAME to owner"); + await write(ethRegistry, { + functionName: "grantRootRoles", + args: [ROLES.REGISTRY.CAN_NAME, owner], account: deployer, - functionName: "register", - args: ["eth", deployer, ethRegistry.address, zeroAddress, 0n, MAX_EXPIRY], }); }, { - tags: ["ETHRegistry", "l1"], - dependencies: ["RootRegistry", "HCAFactory", "RegistryMetadata"], + tags: ["ETHRegistry", "migration:phase1:deploy-v2", "v2"], + dependencies: ["RootRegistry", "LabelStore"], }, ); diff --git a/contracts/deploy/01_Graveyard.ts b/contracts/deploy/01_Graveyard.ts new file mode 100755 index 000000000..2d532cd85 --- /dev/null +++ b/contracts/deploy/01_Graveyard.ts @@ -0,0 +1,21 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ get, getV1, deploy, namedAccounts: { deployer } }) => { + const nameWrapper = + await getV1<(typeof artifacts.NameWrapper)["abi"]>("NameWrapper"); + + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + await deploy("Graveyard", { + account: deployer, + artifact: artifacts.Graveyard, + args: [nameWrapper.address, contractNamer.address], + }); + }, + { + tags: ["Graveyard", "v2"], + dependencies: ["NameWrapper", "ContractNamer"], + }, +); diff --git a/contracts/deploy/01_LabelStore.ts b/contracts/deploy/01_LabelStore.ts new file mode 100755 index 000000000..f0a3ee2e1 --- /dev/null +++ b/contracts/deploy/01_LabelStore.ts @@ -0,0 +1,18 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ get, deploy, namedAccounts: { deployer } }) => { + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + await deploy("LabelStore", { + account: deployer, + artifact: artifacts.LabelStore, + args: [contractNamer.address], + }); + }, + { + tags: ["LabelStore", "v2"], + dependencies: ["ContractNamer"], + }, +); diff --git a/contracts/deploy/01_PermissionedResolverImpl.ts b/contracts/deploy/01_PermissionedResolverImpl.ts index 85309a19a..b8f10faa9 100755 --- a/contracts/deploy/01_PermissionedResolverImpl.ts +++ b/contracts/deploy/01_PermissionedResolverImpl.ts @@ -1,18 +1,14 @@ import { artifacts, execute } from "@rocketh"; export default execute( - async ({ deploy, get, namedAccounts: { deployer } }) => { - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); - + async ({ deploy, get, namedAccounts: { deployer, owner } }) => { await deploy("PermissionedResolverImpl", { account: deployer, artifact: artifacts["PermissionedResolver"], - args: [hcaFactory.address], + args: [owner], }); }, { - tags: ["PermissionedResolverImpl", "l1"], - dependencies: ["HCAFactory"], + tags: ["PermissionedResolverImpl", "migration:phase1:deploy-v2", "v2"], }, ); diff --git a/contracts/deploy/01_PublicResolverSet.ts b/contracts/deploy/01_PublicResolverSet.ts new file mode 100755 index 000000000..d3d437cdb --- /dev/null +++ b/contracts/deploy/01_PublicResolverSet.ts @@ -0,0 +1,55 @@ +import { artifacts, execute } from "@rocketh"; +import type { Address } from "viem"; + +export default execute( + async ({ + deploy, + execute: write, + get, + getV1, + read, + namedAccounts: { deployer, owner }, + name, + }) => { + const publicResolverSet = await deploy("PublicResolverSet", { + account: deployer, + artifact: artifacts.PermissionedAddressSet, + args: [owner], + }); + + const publicResolverV1 = + await getV1<(typeof artifacts.PublicResolver)["abi"]>("PublicResolver"); + + // The wrapper-aware v1 public resolvers whose locked names should be + // re-pointed at the new v2 PublicResolver during migration. On mainnet these + // are the historical PublicResolverV3/V4 deployments; elsewhere the single + // resolved v1 PublicResolver covers the local/test deployment. + const wrapperAwarePublicResolvers: Address[] = + name === "mainnet" + ? [ + "0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63", // PublicResolverV3: https://etherscan.io/address/0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63 + "0xF29100983E058B709F3D539b0c765937B804AC15", // PublicResolverV4: https://etherscan.io/address/0xF29100983E058B709F3D539b0c765937B804AC15 + ] + : [publicResolverV1.address]; + for (const addr of wrapperAwarePublicResolvers) { + const approved = await read(publicResolverSet, { + functionName: "includes", + args: [addr], + }); + if (approved) continue; + + await write(publicResolverSet, { + account: owner, + functionName: "approve", + args: [addr, true], + }); + } + + console.log("Wrapper-aware PublicResolvers:"); + console.table(wrapperAwarePublicResolvers); + }, + { + tags: ["PublicResolverSet", "v2"], + dependencies: ["PublicResolver"], + }, +); diff --git a/contracts/deploy/01_PublicResolverV2.ts b/contracts/deploy/01_PublicResolverV2.ts new file mode 100755 index 000000000..cb20be5f5 --- /dev/null +++ b/contracts/deploy/01_PublicResolverV2.ts @@ -0,0 +1,24 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ deploy, get, getV1, namedAccounts: { deployer } }) => { + const nameWrapper = + await getV1<(typeof artifacts.NameWrapper)["abi"]>("NameWrapper"); + + const rootRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); + + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + await deploy("PublicResolverV2", { + account: deployer, + artifact: artifacts.PublicResolverV2, + args: [nameWrapper.address, rootRegistry.address, contractNamer.address], + }); + }, + { + tags: ["PublicResolverV2", "v2"], + dependencies: ["NameWrapper", "RootRegistry", "ContractNamer"], + }, +); diff --git a/contracts/deploy/01_RegistryMetadata.ts b/contracts/deploy/01_RegistryMetadata.ts deleted file mode 100644 index 97a8224dc..000000000 --- a/contracts/deploy/01_RegistryMetadata.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { artifacts, execute } from "@rocketh"; - -export default execute( - async ({ deploy, get, namedAccounts: { deployer } }) => { - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); - - await deploy("SimpleRegistryMetadata", { - account: deployer, - artifact: artifacts.SimpleRegistryMetadata, - args: [hcaFactory.address], - }); - }, - { tags: ["RegistryMetadata", "l1"], dependencies: ["HCAFactory"] }, -); diff --git a/contracts/deploy/01_ReverseMirror.ts b/contracts/deploy/01_ReverseMirror.ts new file mode 100644 index 000000000..84938c26f --- /dev/null +++ b/contracts/deploy/01_ReverseMirror.ts @@ -0,0 +1,31 @@ +import { artifacts, execute } from "@rocketh"; +import { zeroAddress } from "viem"; +import { DEPLOYMENT_ROLES, MAX_EXPIRY } from "../script/deploy-constants.js"; + +// TODO: ownership +export default execute( + async ({ execute: write, get, namedAccounts: { deployer, owner } }) => { + const rootRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); + + const ensV1Resolver = + get<(typeof artifacts.ENSV1Resolver)["abi"]>("ENSV1Resolver"); + + await write(rootRegistry, { + account: deployer, + functionName: "register", + args: [ + "reverse", + owner, + zeroAddress, + ensV1Resolver.address, + DEPLOYMENT_ROLES.REVERSE_REGISTRY_ROOT, + MAX_EXPIRY, + ], + }); + }, + { + tags: ["ReverseMirror", "v2"], + dependencies: ["RootRegistry", "ENSV1Resolver"], + }, +); diff --git a/contracts/deploy/01_ReverseRegistry.ts b/contracts/deploy/01_ReverseRegistry.ts deleted file mode 100644 index 41b83ebe0..000000000 --- a/contracts/deploy/01_ReverseRegistry.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { artifacts, execute } from "@rocketh"; -import { MAX_EXPIRY, ROLES } from "../script/deploy-constants.js"; - -// TODO: ownership -export default execute( - async ({ deploy, execute: write, get, namedAccounts: { deployer } }) => { - const defaultReverseResolverV1 = get< - (typeof artifacts.DefaultReverseResolver)["abi"] - >("DefaultReverseResolver"); - - const rootRegistry = - get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); - - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); - - const registryMetadata = get< - (typeof artifacts.SimpleRegistryMetadata)["abi"] - >("SimpleRegistryMetadata"); - - // create "reverse" registry - const reverseRegistry = await deploy("ReverseRegistry", { - account: deployer, - artifact: artifacts.PermissionedRegistry, - args: [ - hcaFactory.address, - registryMetadata.address, - deployer, - ROLES.ALL, - ], - }); - - // register "reverse" with default resolver - await write(rootRegistry, { - account: deployer, - functionName: "register", - args: [ - "reverse", - deployer, - reverseRegistry.address, - defaultReverseResolverV1.address, - 0n, - MAX_EXPIRY, - ], - }); - }, - { - tags: ["ReverseRegistry", "l1"], - dependencies: [ - "DefaultReverseResolver", - "RootRegistry", - "HCAFactory", - "SimpleRegistryMetadata", - ], - }, -); diff --git a/contracts/deploy/01_StandardRentPriceOracle.ts b/contracts/deploy/01_StandardRentPriceOracle.ts new file mode 100644 index 000000000..fa5802a95 --- /dev/null +++ b/contracts/deploy/01_StandardRentPriceOracle.ts @@ -0,0 +1,157 @@ +import { artifacts, execute } from "@rocketh"; +import { + SEC_PER_YEAR, + PRICE_SCALE, + PRICE_DECIMALS, + BASE_RATE_PER_CP, + DISCOUNT_POINTS, + DISCOUNT_DENOMINATOR, + PREMIUM_PRICE_INITIAL, + PREMIUM_HALVING_PERIOD, + PREMIUM_PERIOD, + SEPOLIA_USDC, + MAINNET_USDC, + MAINNET_DAI, +} from "../script/deploy-constants.js"; + +type MockERC20 = + (typeof artifacts)["test/mocks/MockERC20.sol/MockERC20"]["abi"]; + +export default execute( + async ({ + deploy, + execute: write, + read, + get, + getOrNull, + namedAccounts: { deployer, owner }, + tags, + }) => { + const mockTokenArtifact = artifacts["test/mocks/MockERC20.sol/MockERC20"]; + // Mainnet whitelists the real payment tokens; the free-mint mocks are only + // deployed (and only accepted) on test/dev networks. The ERC20 metadata + // reads below (symbol/decimals) work against the real tokens too. + const paymentTokens = tags.hasDao + ? [ + { address: MAINNET_USDC, abi: mockTokenArtifact.abi }, + { address: MAINNET_DAI, abi: mockTokenArtifact.abi }, + ] + : [ + get("MockUSDC"), + get("MockDAI"), + ...(tags.sepolia || tags["clean-testnet"] + ? [{ address: SEPOLIA_USDC, abi: mockTokenArtifact.abi }] + : []), + ]; + + const baseRates = BASE_RATE_PER_CP.flatMap((rate, i) => { + const yearly = Number(rate * SEC_PER_YEAR) / Number(PRICE_SCALE); + return rate ? { cp: 1 + i, rate, yearly } : []; + }).reverse(); + + const paymentFactors = await Promise.all( + paymentTokens.map(async (x) => { + const [symbol, decimalsResult] = await Promise.all([ + read(x, { functionName: "symbol" }), + read(x, { functionName: "decimals" }), + ]); + const decimals = Number(decimalsResult); + return { + MockERC20: symbol, + paymentToken: x.address, + decimals, + Δ: decimals - PRICE_DECIMALS, + numer: 10n ** BigInt(Math.max(decimals - PRICE_DECIMALS, 0)), + denom: 10n ** BigInt(Math.max(PRICE_DECIMALS - decimals, 0)), + }; + }), + ); + + console.table(paymentFactors); + + console.table( + baseRates.map((x) => ({ ...x, yearly: x.yearly.toFixed(2) })), + ); + + const standardRentPriceOracle = + getOrNull( + "StandardRentPriceOracle", + ) ?? + (await deploy("StandardRentPriceOracle", { + account: deployer, + artifact: artifacts.StandardRentPriceOracle, + args: [ + owner, + BASE_RATE_PER_CP, + DISCOUNT_POINTS, + DISCOUNT_DENOMINATOR, + PREMIUM_PRICE_INITIAL, + PREMIUM_HALVING_PERIOD, + PREMIUM_PERIOD, + paymentFactors, + ], + })); + + for (const paymentFactor of paymentFactors) { + const [numer, denom] = (await read(standardRentPriceOracle, { + functionName: "getPaymentTokenRatio", + args: [paymentFactor.paymentToken], + })) as [bigint, bigint]; + if (numer === paymentFactor.numer && denom === paymentFactor.denom) { + continue; + } + await write(standardRentPriceOracle, { + account: owner, + functionName: "updatePaymentToken", + args: [ + paymentFactor.paymentToken, + paymentFactor.numer, + paymentFactor.denom, + ], + }); + } + + const denom = 100000n; + const durations = [ + ...new Set([ + ...DISCOUNT_POINTS.map((x) => x.duration), + ...Array.from({ length: 10 }, (_, yr) => BigInt(yr + 1) * SEC_PER_YEAR), + ...[25n, 100n].map((yr) => yr * SEC_PER_YEAR), + ]), + ].sort((a, b) => Number(a - b)); + const numers = await Promise.all( + durations.map((t) => + read(standardRentPriceOracle, { + functionName: "applyDiscount", + args: [denom, t - 1n], + }), + ), + ); + console.table( + await Promise.all( + durations.map(async (t, i) => { + const years = Number(t) / Number(SEC_PER_YEAR); + const ratio = Number(numers[i]) / Number(denom); + return { + years: `<${years.toFixed(2)}`, + discount: `${(100 * (1 - ratio)).toFixed(2)}%`, + ...Object.fromEntries( + baseRates.flatMap((x) => { + const perYear = + (ratio * Number(x.rate * SEC_PER_YEAR)) / Number(PRICE_SCALE); + return [ + [`${x.cp}cp/yr`, `${perYear.toFixed(2)}`], + [`${x.cp}cp`, `${(perYear * years).toFixed(2)}`], + ]; + }), + ), + }; + }), + ), + ); + }, + { + tags: ["StandardRentPriceOracle", "migration:phase1:deploy-v2", "v2"], + dependencies: ["MockTokens"], + }, +); diff --git a/contracts/deploy/01_UserRegistryImpl.ts b/contracts/deploy/01_UserRegistryImpl.ts index f793649d4..58a94b0a8 100644 --- a/contracts/deploy/01_UserRegistryImpl.ts +++ b/contracts/deploy/01_UserRegistryImpl.ts @@ -1,22 +1,17 @@ import { artifacts, execute } from "@rocketh"; export default execute( - async ({ deploy, get, namedAccounts: { deployer } }) => { - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); - - const registryMetadata = get< - (typeof artifacts.SimpleRegistryMetadata)["abi"] - >("SimpleRegistryMetadata"); + async ({ deploy, get, namedAccounts: { deployer, owner } }) => { + const labelStore = get<(typeof artifacts.ILabelStore)["abi"]>("LabelStore"); await deploy("UserRegistryImpl", { account: deployer, artifact: artifacts.UserRegistry, - args: [hcaFactory.address, registryMetadata.address], + args: [labelStore.address, owner], }); }, { - tags: ["UserRegistryImpl", "l1"], - dependencies: ["HCAFactory", "RegistryMetadata"], + tags: ["UserRegistryImpl", "migration:phase1:deploy-v2", "v2"], + dependencies: ["LabelStore"], }, ); diff --git a/contracts/deploy/02_DefaultReverseRegistrarAdapter.ts b/contracts/deploy/02_DefaultReverseRegistrarAdapter.ts new file mode 100644 index 000000000..1b298bc42 --- /dev/null +++ b/contracts/deploy/02_DefaultReverseRegistrarAdapter.ts @@ -0,0 +1,45 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ + deploy, + execute: write, + get, + getV1, + read, + namedAccounts: { deployer, owner, v1Owner }, + }) => { + const defaultReverseRegistrar = await getV1< + (typeof artifacts.DefaultReverseRegistrar)["abi"] + >("DefaultReverseRegistrar"); + + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + const adapter = await deploy("DefaultReverseRegistrarAdapter", { + account: deployer, + artifact: artifacts.DefaultReverseRegistrarAdapter, + args: [defaultReverseRegistrar.address, contractNamer.address], + }); + + const adapterIsDefaultController = await read(defaultReverseRegistrar, { + functionName: "controllers", + args: [adapter.address], + }); + + if (!adapterIsDefaultController) { + // The v1 DefaultReverseRegistrar is owned by the v1 owner, not the v2 + // admin, so route the controller grant through v1Owner (honouring the + // deferred v1-owner transaction flow, which only captures v1Owner sends). + await write(defaultReverseRegistrar, { + account: v1Owner ?? owner, + functionName: "setController", + args: [adapter.address, true], + }); + } + }, + { + tags: ["DefaultReverseRegistrarAdapter", "migration:phase1:deploy-v2", "v2"], + dependencies: ["ContractNamer"], + }, +); diff --git a/contracts/deploy/02_ETHReverseResolver.ts b/contracts/deploy/02_ETHReverseResolver.ts deleted file mode 100644 index 8176669e3..000000000 --- a/contracts/deploy/02_ETHReverseResolver.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { artifacts, execute } from "@rocketh"; -import { MAX_EXPIRY } from "../script/deploy-constants.js"; -import { zeroAddress } from "viem"; - -// TODO: ownership -export default execute( - async ({ deploy, execute: write, get, namedAccounts: { deployer } }) => { - const ensRegistryV1 = - get<(typeof artifacts.ENSRegistry)["abi"]>("ENSRegistry"); - - const defaultReverseRegistrarV1 = get< - (typeof artifacts.DefaultReverseRegistrar)["abi"] - >("DefaultReverseRegistrar"); - - const reverseRegistry = - get<(typeof artifacts.PermissionedRegistry)["abi"]>("ReverseRegistry"); - - const ethReverseRegistrar = get< - (typeof artifacts.StandaloneReverseRegistrar)["abi"] - >("ETHReverseRegistrar"); - - // create resolver for "addr.reverse" - const ethReverseResolver = await deploy("ETHReverseResolver", { - account: deployer, - artifact: artifacts.ETHReverseResolver, - args: [ - ensRegistryV1.address, - ethReverseRegistrar.address, - defaultReverseRegistrarV1.address, - ], - }); - - // register "addr.reverse" - await write(reverseRegistry, { - account: deployer, - functionName: "register", - args: [ - "addr", - deployer, - zeroAddress, - ethReverseResolver.address, - 0n, - MAX_EXPIRY, - ], - }); - }, - { - tags: ["ETHReverseResolver", "l1"], - dependencies: [ - "ENSRegistry", - "ReverseRegistry", // "RootRegistry" - "DefaultReverseRegistrar", - "ETHReverseRegistrar", - ], - }, -); diff --git a/contracts/deploy/02_ReverseRegistrarAdapter.ts b/contracts/deploy/02_ReverseRegistrarAdapter.ts new file mode 100644 index 000000000..0cd54dbb3 --- /dev/null +++ b/contracts/deploy/02_ReverseRegistrarAdapter.ts @@ -0,0 +1,46 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ + deploy, + execute: write, + get, + getV1, + read, + namedAccounts: { deployer, owner, v1Owner }, + }) => { + const reverseRegistrar = + await getV1<(typeof artifacts.ReverseRegistrar)["abi"]>( + "ReverseRegistrar", + ); + + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + const adapter = await deploy("ReverseRegistrarAdapter", { + account: deployer, + artifact: artifacts.ReverseRegistrarAdapter, + args: [reverseRegistrar.address, contractNamer.address], + }); + + const adapterIsReverseController = await read(reverseRegistrar, { + functionName: "controllers", + args: [adapter.address], + }); + + if (!adapterIsReverseController) { + // The v1 ReverseRegistrar is owned by the v1 owner, not the v2 admin, so + // route the controller grant through v1Owner (honouring the deferred + // v1-owner transaction flow, which only captures v1Owner sends). + await write(reverseRegistrar, { + account: v1Owner ?? owner, + functionName: "setController", + args: [adapter.address, true], + }); + } + }, + { + tags: ["ReverseRegistrarAdapter", "migration:phase1:deploy-v2", "v2"], + dependencies: ["ContractNamer"], + }, +); diff --git a/contracts/deploy/02_StandardRentPriceOracle.ts b/contracts/deploy/02_StandardRentPriceOracle.ts deleted file mode 100644 index 060080c07..000000000 --- a/contracts/deploy/02_StandardRentPriceOracle.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { artifacts, execute } from "@rocketh"; - -export default execute( - async ({ deploy, read, get, namedAccounts: { deployer, owner } }) => { - const ethRegistry = - get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); - - type MockERC20 = - (typeof artifacts)["test/mocks/MockERC20.sol/MockERC20"]["abi"]; - const mockUSDC = get("MockUSDC"); - const mockDAI = get("MockDAI"); - const paymentTokens = [mockUSDC, mockDAI]; - - // see: StandardPricing.sol - const SEC_PER_YEAR = 31_557_600n; - const SEC_PER_DAY = 86400n; - const PRICE_DECIMALS = 12; - const PRICE_SCALE = 10n ** BigInt(PRICE_DECIMALS); - const PREMIUM_PRICE_INITIAL = PRICE_SCALE * 100_000_000n; - const PREMIUM_HALVING_PERIOD = SEC_PER_DAY; - const PREMIUM_PERIOD = SEC_PER_DAY * 21n; - - const baseRatePerCp = [ - 0n, - 0n, - PRICE_SCALE * 640n, - PRICE_SCALE * 160n, - PRICE_SCALE * 5n, - ].map((x) => (x + SEC_PER_YEAR - 1n) / SEC_PER_YEAR); - - const DISCOUNT_SCALE = (1n << 128n) - 1n; // type(uint128).max - function discountRatio(numer: bigint, denom: bigint) { - return (DISCOUNT_SCALE * numer + denom - 1n) / denom; - } - const discountPoints: [bigint, bigint][] = [ - [SEC_PER_YEAR, 0n], - [SEC_PER_YEAR, discountRatio(1n, 10n)], // 10% - [SEC_PER_YEAR, discountRatio(2n, 10n)], - [SEC_PER_YEAR * 2n, discountRatio(2875n, 10000n)], - [SEC_PER_YEAR * 5n, discountRatio(325n, 1000n)], - [SEC_PER_YEAR * 15n, discountRatio(1n, 3n)], - ]; - - const paymentFactors = await Promise.all( - paymentTokens.map(async (x) => { - const [symbol, decimals] = await Promise.all([ - read(x, { functionName: "symbol" }), - read(x, { functionName: "decimals" }), - ]); - return { - MockERC20: symbol, - decimals, - token: x.address, - numer: 10n ** BigInt(Math.max(decimals - PRICE_DECIMALS, 0)), - denom: 10n ** BigInt(Math.max(PRICE_DECIMALS - decimals, 0)), - }; - }), - ); - - console.table(paymentFactors); - - console.table( - baseRatePerCp.flatMap((rate, i) => { - const yearly = ( - Number(rate * SEC_PER_YEAR) / Number(PRICE_SCALE) - ).toFixed(2); - return rate ? { cp: 1 + i, rate, yearly } : []; - }), - ); - - console.table( - discountPoints.map((_, i, v) => { - const sum = v.slice(0, i + 1).reduce((a, x) => a + x[0], 0n); - const acc = v.slice(0, i + 1).reduce((a, x) => a + x[0] * x[1], 0n); - return { - years: (Number(sum) / Number(SEC_PER_YEAR)).toFixed(2), - discount: `${((100 * Number(acc / sum)) / Number(DISCOUNT_SCALE)).toFixed(2)}%`, - }; - }), - ); - - await deploy("StandardRentPriceOracle", { - account: deployer, - artifact: artifacts.StandardRentPriceOracle, - args: [ - owner, - ethRegistry.address, - baseRatePerCp, - discountPoints.map(([t, value]) => ({ t, value })), - PREMIUM_PRICE_INITIAL, - PREMIUM_HALVING_PERIOD, - PREMIUM_PERIOD, - paymentFactors, - ], - }); - }, - { - tags: ["StandardRentPriceOracle", "l1"], - dependencies: ["MockTokens", "ETHRegistry"], - }, -); diff --git a/contracts/deploy/02_UnlockedMigrationController.ts b/contracts/deploy/02_UnlockedMigrationController.ts new file mode 100755 index 000000000..0cb0457d9 --- /dev/null +++ b/contracts/deploy/02_UnlockedMigrationController.ts @@ -0,0 +1,42 @@ +import { artifacts, execute } from "@rocketh"; +import { DEPLOYMENT_ROLES } from "../script/deploy-constants.js"; + +export default execute( + async ({ deploy, execute: write, get, getV1, namedAccounts: { deployer } }) => { + const nameWrapper = + await getV1<(typeof artifacts.NameWrapper)["abi"]>("NameWrapper"); + + const graveyard = get<(typeof artifacts.Graveyard)["abi"]>("Graveyard"); + + const ethRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); + + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + const migrationController = await deploy("UnlockedMigrationController", { + account: deployer, + artifact: artifacts.UnlockedMigrationController, + args: [ + nameWrapper.address, + graveyard.address, + ethRegistry.address, + contractNamer.address, + ], + }); + + // see: UnlockedMigrationController.t.sol + await write(ethRegistry, { + account: deployer, + functionName: "grantRootRoles", + args: [ + DEPLOYMENT_ROLES.MIGRATION_CONTROLLER_ROOT, + migrationController.address, + ], + }); + }, + { + tags: ["UnlockedMigrationController", "migration:phase1:deploy-v2", "v2"], + dependencies: ["NameWrapper", "Graveyard", "ETHRegistry", "ContractNamer"], + }, +); diff --git a/contracts/deploy/03_ApprovedUpgradeGate.ts b/contracts/deploy/03_ApprovedUpgradeGate.ts new file mode 100644 index 000000000..1e882ca00 --- /dev/null +++ b/contracts/deploy/03_ApprovedUpgradeGate.ts @@ -0,0 +1,14 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ deploy, namedAccounts: { deployer, owner } }) => { + await deploy("ApprovedUpgradeGate", { + account: deployer, + artifact: artifacts.ApprovedUpgradeGate, + args: [owner], + }); + }, + { + tags: ["ApprovedUpgradeGate", "v2"], + }, +); diff --git a/contracts/deploy/03_ETHRegistrar.ts b/contracts/deploy/03_ETHRegistrar.ts index 8ea87c6e9..182ae5f9a 100644 --- a/contracts/deploy/03_ETHRegistrar.ts +++ b/contracts/deploy/03_ETHRegistrar.ts @@ -1,5 +1,11 @@ import { artifacts, execute } from "@rocketh"; -import { ROLES } from "../script/deploy-constants.js"; +import { + DEPLOYMENT_ROLES, + GRACE_PERIOD_V2, + MIN_COMMITMENT_AGE, + MAX_COMMITMENT_AGE, + MIN_REGISTER_DURATION, +} from "../script/deploy-constants.js"; export default execute( async ({ @@ -7,10 +13,8 @@ export default execute( execute: write, get, namedAccounts: { deployer, owner }, + tags, }) => { - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); - const ethRegistry = get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); @@ -18,34 +22,34 @@ export default execute( "StandardRentPriceOracle", ); - const beneficiary = owner || deployer; - - const SEC_PER_DAY = 86400n; const ethRegistrar = await deploy("ETHRegistrar", { account: deployer, artifact: artifacts.ETHRegistrar, args: [ + owner, ethRegistry.address, - hcaFactory.address, - beneficiary, - 60n, // minCommitmentAge - SEC_PER_DAY, // maxCommitmentAge - 28n * SEC_PER_DAY, // minRegistrationDuration + owner, // TODO: beneficiary, rentPriceOracle.address, + GRACE_PERIOD_V2, + MIN_COMMITMENT_AGE, + MAX_COMMITMENT_AGE, + MIN_REGISTER_DURATION, ], }); - await write(ethRegistry, { - functionName: "grantRootRoles", - args: [ - ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW, - ethRegistrar.address, - ], - account: deployer, - }); + if (!tags.deferV2Registrar) { + await write(ethRegistry, { + functionName: "grantRootRoles", + args: [ + DEPLOYMENT_ROLES.ETH_REGISTRAR_ROOT, + ethRegistrar.address, + ], + account: deployer, + }); + } }, { - tags: ["ETHRegistrar", "l1"], - dependencies: ["HCAFactory", "ETHRegistry", "StandardRentPriceOracle"], + tags: ["ETHRegistrar", "migration:phase1:deploy-v2", "v2"], + dependencies: ["ETHRegistry", "StandardRentPriceOracle"], }, ); diff --git a/contracts/deploy/03_ETHRenewerV1.ts b/contracts/deploy/03_ETHRenewerV1.ts new file mode 100755 index 000000000..4691e19d1 --- /dev/null +++ b/contracts/deploy/03_ETHRenewerV1.ts @@ -0,0 +1,60 @@ +import { artifacts, execute } from "@rocketh"; +import { + DEPLOYMENT_ROLES, + GRACE_PERIOD_V2, + PREMIGRATION_BONUS_PERIOD, +} from "../script/deploy-constants.js"; + +export default execute( + async ({ + deploy, + execute: write, + get, + getV1, + namedAccounts: { deployer, owner }, + }) => { + const ethRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); + + const rentPriceOracle = get<(typeof artifacts.IRentPriceOracle)["abi"]>( + "StandardRentPriceOracle", + ); + + const nameWrapper = + await getV1<(typeof artifacts.NameWrapper)["abi"]>("NameWrapper"); + + const wrappedController = await getV1< + (typeof artifacts.IWrappedETHRegistrarController)["abi"] + >("WrappedETHRegistrarController"); + + const ethRenewerV1 = await deploy("ETHRenewerV1", { + account: deployer, + artifact: artifacts.ETHRenewerV1, + args: [ + owner, + ethRegistry.address, + owner, // TODO: beneficiary, + rentPriceOracle.address, + GRACE_PERIOD_V2, + PREMIGRATION_BONUS_PERIOD, + nameWrapper.address, + wrappedController.address, + ], + }); + + await write(ethRegistry, { + functionName: "grantRootRoles", + args: [DEPLOYMENT_ROLES.ETH_RENEWER_V1_ROOT, ethRenewerV1.address], + account: deployer, + }); + }, + { + tags: ["ETHRenewerV1", "migration:phase1:deploy-v2", "v2"], + dependencies: [ + "ETHRegistry", + "StandardRentPriceOracle", + "NameWrapper", + "WrappedETHRegistrarController", + ], + }, +); diff --git a/contracts/deploy/03_WrapperRegistryImpl.ts b/contracts/deploy/03_WrapperRegistryImpl.ts index b8f7d248b..e0e8f615e 100644 --- a/contracts/deploy/03_WrapperRegistryImpl.ts +++ b/contracts/deploy/03_WrapperRegistryImpl.ts @@ -1,16 +1,11 @@ import { artifacts, execute } from "@rocketh"; export default execute( - async ({ deploy, get, namedAccounts: { deployer } }) => { - const nameWrapperV1 = - get<(typeof artifacts.NameWrapper)["abi"]>("NameWrapper"); + async ({ deploy, get, getV1, namedAccounts: { deployer, owner } }) => { + const nameWrapper = + await getV1<(typeof artifacts.NameWrapper)["abi"]>("NameWrapper"); - const hcaFactory = - get<(typeof artifacts.MockHCAFactoryBasic)["abi"]>("HCAFactory"); - - const registryMetadata = get< - (typeof artifacts.SimpleRegistryMetadata)["abi"] - >("SimpleRegistryMetadata"); + const graveyard = get<(typeof artifacts.Graveyard)["abi"]>("Graveyard"); const verifiableFactory = get<(typeof artifacts.VerifiableFactory)["abi"]>("VerifiableFactory"); @@ -18,26 +13,45 @@ export default execute( const ensV1Resolver = get<(typeof artifacts.ENSV1Resolver)["abi"]>("ENSV1Resolver"); + const labelStore = get<(typeof artifacts.ILabelStore)["abi"]>("LabelStore"); + + const approvedUpgradeGate = get< + (typeof artifacts.ApprovedUpgradeGate)["abi"] + >("ApprovedUpgradeGate"); + + const publicResolverSet = + get<(typeof artifacts.IAddressSet)["abi"]>("PublicResolverSet"); + + const publicResolverV2 = + get<(typeof artifacts.PublicResolverV2)["abi"]>("PublicResolverV2"); + await deploy("WrapperRegistryImpl", { account: deployer, artifact: artifacts.WrapperRegistry, args: [ - nameWrapperV1.address, + nameWrapper.address, + graveyard.address, verifiableFactory.address, - hcaFactory.address, - registryMetadata.address, ensV1Resolver.address, + approvedUpgradeGate.address, + labelStore.address, + publicResolverSet.address, + publicResolverV2.address, + owner, ], }); }, { - tags: ["WrapperRegistryImpl", "l1"], + tags: ["WrapperRegistryImpl", "migration:phase1:deploy-v2", "v2"], dependencies: [ "NameWrapper", - "HCAFactory", - "SimpleRegistryMetadata", + "Graveyard", "VerifiableFactory", "ENSV1Resolver", + "ApprovedUpgradeGate", + "LabelStore", + "PublicResolverSet", + "PublicResolverV2", ], }, ); diff --git a/contracts/deploy/04_BatchRegistrar.ts b/contracts/deploy/04_BatchRegistrar.ts new file mode 100644 index 000000000..5391a8880 --- /dev/null +++ b/contracts/deploy/04_BatchRegistrar.ts @@ -0,0 +1,25 @@ +import { artifacts, execute } from "@rocketh"; +import { DEPLOYMENT_ROLES } from "../script/deploy-constants.js"; + +export default execute( + async ({ deploy, execute: write, get, namedAccounts: { deployer } }) => { + const ethRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); + + const batchRegistrar = await deploy("BatchRegistrar", { + account: deployer, + artifact: artifacts.BatchRegistrar, + args: [ethRegistry.address, deployer], + }); + + await write(ethRegistry, { + account: deployer, + functionName: "grantRootRoles", + args: [DEPLOYMENT_ROLES.ETH_REGISTRAR_ROOT, batchRegistrar.address], + }); + }, + { + tags: ["BatchRegistrar", "migration:phase1:deploy-v2", "v2"], + dependencies: ["ETHRegistry"], + }, +); diff --git a/contracts/deploy/04_LockedMigrationController.ts b/contracts/deploy/04_LockedMigrationController.ts new file mode 100755 index 000000000..9b86e0d20 --- /dev/null +++ b/contracts/deploy/04_LockedMigrationController.ts @@ -0,0 +1,67 @@ +import { artifacts, execute } from "@rocketh"; +import { DEPLOYMENT_ROLES } from "../script/deploy-constants.js"; + +export default execute( + async ({ deploy, execute: write, get, getV1, namedAccounts: { deployer } }) => { + const nameWrapper = + await getV1<(typeof artifacts.NameWrapper)["abi"]>("NameWrapper"); + + const graveyard = get<(typeof artifacts.Graveyard)["abi"]>("Graveyard"); + + const ethRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); + + const verifiableFactory = + get<(typeof artifacts.VerifiableFactory)["abi"]>("VerifiableFactory"); + + const wrapperRegistryImpl = + get<(typeof artifacts.WrapperRegistry)["abi"]>("WrapperRegistryImpl"); + + const publicResolverSet = + get<(typeof artifacts.IAddressSet)["abi"]>("PublicResolverSet"); + + const publicResolverV2 = + get<(typeof artifacts.PublicResolverV2)["abi"]>("PublicResolverV2"); + + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + const migrationController = await deploy("LockedMigrationController", { + account: deployer, + artifact: artifacts.LockedMigrationController, + args: [ + nameWrapper.address, + graveyard.address, + ethRegistry.address, + verifiableFactory.address, + wrapperRegistryImpl.address, + publicResolverSet.address, + publicResolverV2.address, + contractNamer.address, + ], + }); + + // see: LockedMigrationController.t.sol + await write(ethRegistry, { + account: deployer, + functionName: "grantRootRoles", + args: [ + DEPLOYMENT_ROLES.MIGRATION_CONTROLLER_ROOT, + migrationController.address, + ], + }); + }, + { + tags: ["LockedMigrationController", "migration:phase1:deploy-v2", "v2"], + dependencies: [ + "NameWrapper", + "Graveyard", + "ETHRegistry", + "VerifiableFactory", + "WrapperRegistryImpl", + "PublicResolverSet", + "PublicResolverV2", + "ContractNamer", + ], + }, +); diff --git a/contracts/deploy/05_MigrationHelper.ts b/contracts/deploy/05_MigrationHelper.ts new file mode 100755 index 000000000..9e4c049b9 --- /dev/null +++ b/contracts/deploy/05_MigrationHelper.ts @@ -0,0 +1,39 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ deploy, get, namedAccounts: { deployer } }) => { + const rootRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); + + const unlockedMigrationController = get< + (typeof artifacts.UnlockedMigrationController)["abi"] + >("UnlockedMigrationController"); + + const lockedMigrationController = get< + (typeof artifacts.LockedMigrationController)["abi"] + >("LockedMigrationController"); + + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + await deploy("MigrationHelper", { + account: deployer, + artifact: artifacts.MigrationHelper, + args: [ + rootRegistry.address, + unlockedMigrationController.address, + lockedMigrationController.address, + contractNamer.address, + ], + }); + }, + { + tags: ["MigrationHelper", "migration:phase1:deploy-v2", "v2"], + dependencies: [ + "RootRegistry", + "UnlockedMigrationController", + "LockedMigrationController", + "ContractNamer", + ], + }, +); diff --git a/contracts/deploy/testnet/00_FastETHRegistrar.ts b/contracts/deploy/testnet/00_FastETHRegistrar.ts new file mode 100644 index 000000000..3b97dfcdc --- /dev/null +++ b/contracts/deploy/testnet/00_FastETHRegistrar.ts @@ -0,0 +1,51 @@ +import { artifacts, execute } from "@rocketh"; +import { + DEPLOYMENT_ROLES, + GRACE_PERIOD_V2, + MIN_REGISTER_DURATION, +} from "../../script/deploy-constants.js"; + +export default execute( + async ({ + deploy, + execute: write, + get, + namedAccounts: { deployer, owner }, + network, + }) => { + if (network.chain.id === 1) return; + + const ethRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); + + const rentPriceOracle = get<(typeof artifacts.IRentPriceOracle)["abi"]>( + "StandardRentPriceOracle", + ); + + const SEC_PER_DAY = 86400n; + const ethRegistrar = await deploy("FastETHRegistrar", { + account: deployer, + artifact: artifacts.ETHRegistrar, + args: [ + owner, + ethRegistry.address, + owner, // beneficiary + rentPriceOracle.address, + GRACE_PERIOD_V2, + 0n, // minCommitmentAge + SEC_PER_DAY, // maxCommitmentAge + MIN_REGISTER_DURATION, + ], + }); + + await write(ethRegistry, { + functionName: "grantRootRoles", + args: [DEPLOYMENT_ROLES.ETH_REGISTRAR_ROOT, ethRegistrar.address], + account: deployer, + }); + }, + { + tags: ["FastETHRegistrar", "v2", "testnet"], + dependencies: ["ETHRegistry", "StandardRentPriceOracle"], + }, +); diff --git a/contracts/deploy/testnet/00_MockPremigrator.ts b/contracts/deploy/testnet/00_MockPremigrator.ts new file mode 100644 index 000000000..632cc2a6d --- /dev/null +++ b/contracts/deploy/testnet/00_MockPremigrator.ts @@ -0,0 +1,47 @@ +import { artifacts, execute } from "@rocketh"; +import { ROLES } from "../../script/deploy-constants.js"; + +const MOCK_PREMIGRATOR_ROLE_BITMAP = + ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW; + +export default execute( + async ({ + deploy, + execute: write, + get, + namedAccounts: { deployer }, + network, + read, + tags, + }) => { + // only on testnet + if (network.chain.id === 1) return; + // only for dev (fresh) deployments + if (!tags.dev) return; + + const ethRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); + + const mockPremigrator = await deploy("MockPremigrator", { + account: deployer, + artifact: artifacts.MockPremigrator, + args: [ethRegistry.address], + }); + + const hasPremigrationRoles = await read(ethRegistry, { + functionName: "hasRootRoles", + args: [MOCK_PREMIGRATOR_ROLE_BITMAP, mockPremigrator.address], + }); + if (!hasPremigrationRoles) { + await write(ethRegistry, { + account: deployer, + functionName: "grantRootRoles", + args: [MOCK_PREMIGRATOR_ROLE_BITMAP, mockPremigrator.address], + }); + } + }, + { + tags: ["MockPremigrator", "testnet"], + dependencies: ["ETHRegistry"], + }, +); diff --git a/contracts/deploy/testnet/00_setup_oracle.ts b/contracts/deploy/testnet/00_setup_oracle.ts new file mode 100644 index 000000000..a36050eed --- /dev/null +++ b/contracts/deploy/testnet/00_setup_oracle.ts @@ -0,0 +1,53 @@ +import { artifacts, execute } from "@rocketh"; +import { + SEPOLIA_USDC, + STANDARD_RENT_PRICE_ORACLE_PRICE_DECIMALS, +} from "../../script/deploy-constants.js"; + +const SEPOLIA_CHAIN_ID = 11155111; +const PRICE_DECIMALS = STANDARD_RENT_PRICE_ORACLE_PRICE_DECIMALS; +const SEPOLIA_USDC_DECIMALS = 6n; +const SEPOLIA_USDC_NUMER = + 10n ** + (SEPOLIA_USDC_DECIMALS > PRICE_DECIMALS + ? SEPOLIA_USDC_DECIMALS - PRICE_DECIMALS + : 0n); +const SEPOLIA_USDC_DENOM = + 10n ** + (PRICE_DECIMALS > SEPOLIA_USDC_DECIMALS + ? PRICE_DECIMALS - SEPOLIA_USDC_DECIMALS + : 0n); + +export default execute( + async ({ + execute: write, + get, + read, + namedAccounts: { deployer, owner }, + network, + }) => { + if (network.chain.id !== SEPOLIA_CHAIN_ID) return; + + const oracle = get<(typeof artifacts.StandardRentPriceOracle)["abi"]>( + "StandardRentPriceOracle", + ); + const oracleOwner = owner || deployer; + + const oracleHasSepoliaUsdc = await read(oracle, { + functionName: "isPaymentToken", + args: [SEPOLIA_USDC], + }); + + if (!oracleHasSepoliaUsdc) { + await write(oracle, { + account: oracleOwner, + functionName: "updatePaymentToken", + args: [SEPOLIA_USDC, SEPOLIA_USDC_NUMER, SEPOLIA_USDC_DENOM], + }); + } + }, + { + tags: ["oracle:setup", "testnet", "v2"], + dependencies: ["StandardRentPriceOracle"], + }, +); diff --git a/contracts/deploy/testnet/01_TestnetV1PremigrationRegistrar.ts b/contracts/deploy/testnet/01_TestnetV1PremigrationRegistrar.ts new file mode 100644 index 000000000..1c547c7ef --- /dev/null +++ b/contracts/deploy/testnet/01_TestnetV1PremigrationRegistrar.ts @@ -0,0 +1,132 @@ +import { artifacts, execute } from "@rocketh"; +import { zeroAddress } from "viem"; +import { ROLES } from "../../script/deploy-constants.js"; + +const PREMIGRATION_ROLE_BITMAP = + ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW; + +export default execute( + async ({ + deploy, + execute: write, + get, + getV1, + namedAccounts: { deployer, owner, v1Owner }, + network, + read, + tags, + }) => { + if ( + network.chain.id === 1 || + (!tags.tenderly && !tags["testnet-premigration-registrar"]) + ) + return; + + const baseRegistrar = await getV1< + (typeof artifacts.BaseRegistrarImplementation)["abi"] + >("BaseRegistrarImplementation"); + const ensRegistry = + await getV1<(typeof artifacts.ENSRegistry)["abi"]>("ENSRegistry"); + const reverseRegistrar = + await getV1<(typeof artifacts.ReverseRegistrar)["abi"]>( + "ReverseRegistrar", + ); + const defaultReverseRegistrar = await getV1< + (typeof artifacts.DefaultReverseRegistrar)["abi"] + >("DefaultReverseRegistrar"); + + const ethRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("ETHRegistry"); + const ensV1Resolver = + get<(typeof artifacts.ENSV1Resolver)["abi"]>("ENSV1Resolver"); + + const registrar = await deploy("TestnetV1PremigrationRegistrar", { + account: deployer, + artifact: artifacts.TestnetV1PremigrationRegistrar, + args: [ + baseRegistrar.address, + ensRegistry.address, + reverseRegistrar.address, + defaultReverseRegistrar.address, + ethRegistry.address, + zeroAddress, + ensV1Resolver.address, + ], + }); + + const hasPremigrationRoles = await read(ethRegistry, { + functionName: "hasRootRoles", + args: [PREMIGRATION_ROLE_BITMAP, registrar.address], + }); + if (!hasPremigrationRoles) { + await write(ethRegistry, { + account: deployer, + functionName: "grantRootRoles", + args: [PREMIGRATION_ROLE_BITMAP, registrar.address], + }); + } + + // register() calls BASE.register(), so the registrar must also be an + // ENSv1 registrar controller; that grant is a v1-owner transaction + // (deferred on phased deploys via deferV1OwnerTransactions) + const isV1Controller = await read(baseRegistrar, { + functionName: "controllers", + args: [registrar.address], + }); + if (!isV1Controller) { + console.log(" - Adding as ENSv1 registrar controller"); + const registrarSecurityController = await getV1< + (typeof artifacts.RegistrarSecurityController)["abi"] + >("RegistrarSecurityController").catch(() => null); + if (registrarSecurityController) { + await write(registrarSecurityController, { + account: v1Owner ?? owner, + functionName: "addRegistrarController", + args: [registrar.address], + }); + } else { + await write(baseRegistrar, { + account: v1Owner ?? owner, + functionName: "addController", + args: [registrar.address], + }); + } + } + + // register() sets reverse records on behalf of the registrant, so the registrar + // must also be a controller of the reverse registrars; these are v1-owner + // transactions (deferred on phased deploys via deferV1OwnerTransactions) + const isReverseController = await read(reverseRegistrar, { + functionName: "controllers", + args: [registrar.address], + }); + if (!isReverseController) { + await write(reverseRegistrar, { + account: v1Owner ?? owner, + functionName: "setController", + args: [registrar.address, true], + }); + } + + const isDefaultReverseController = await read(defaultReverseRegistrar, { + functionName: "controllers", + args: [registrar.address], + }); + if (!isDefaultReverseController) { + await write(defaultReverseRegistrar, { + account: v1Owner ?? owner, + functionName: "setController", + args: [registrar.address, true], + }); + } + }, + { + tags: [ + "TestnetV1PremigrationRegistrar", + "migration:phase1:deploy-v2", + "migration:testnet:v1-premigration-registrar", + "testnet", + ], + dependencies: ["ETHRegistry", "ENSV1Resolver"], + }, +); diff --git a/contracts/deploy/universalResolver/00_UniversalResolver.ts b/contracts/deploy/universalResolver/00_UniversalResolver.ts deleted file mode 100644 index e87162df8..000000000 --- a/contracts/deploy/universalResolver/00_UniversalResolver.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { artifacts, execute } from "@rocketh"; - -export default execute( - async ({ deploy, get, namedAccounts: { deployer } }) => { - const rootRegistry = - get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); - - const batchGatewayProvider = get<(typeof artifacts.GatewayProvider)["abi"]>( - "BatchGatewayProvider", - ); - - await deploy("UniversalResolverV2", { - account: deployer, - artifact: artifacts.UniversalResolverV2, - args: [rootRegistry.address, batchGatewayProvider.address], - }); - }, - { - tags: ["UniversalResolverV2", "l1"], - dependencies: ["RootRegistry", "BatchGatewayProvider"], - }, -); diff --git a/contracts/deploy/universalResolver/00_deploy_UniversalResolver.ts b/contracts/deploy/universalResolver/00_deploy_UniversalResolver.ts new file mode 100644 index 000000000..2371884da --- /dev/null +++ b/contracts/deploy/universalResolver/00_deploy_UniversalResolver.ts @@ -0,0 +1,73 @@ +import { artifacts, execute } from "@rocketh"; + +import { + isDeployedTopProxy, + knownProxyNetworkName, + loadKnownTopProxyDeployment, +} from "../../script/universalResolverDeployUtils.js"; + +export default execute( + async ({ + deploy, + getV1, + getOrNull, + save, + namedAccounts: { deployer, owner }, + name, + tags, + }) => { + if (tags.local) return true; + + // A clean-testnet run builds a self-owned stack from scratch (including its + // own v1), so it deploys its own top URP it can administer. + if (tags["clean-testnet"]) { + const v1UniversalResolver = + await getV1<(typeof artifacts.UniversalResolver)["abi"]>( + "UniversalResolver", + ); + await deploy("UpgradableUniversalResolverProxy", { + account: deployer, + artifact: artifacts.UpgradableUniversalResolverProxy, + args: [owner, v1UniversalResolver.address], + }); + return true; + } + + // Otherwise the top URP is a pre-existing, long-lived deployment: adopt the + // canonical address for the network. Deploying a fresh top URP is no longer + // supported here — the migration reuses the existing one. + const currentDeployment = getOrNull< + typeof artifacts.UpgradableUniversalResolverProxy.abi + >("UpgradableUniversalResolverProxy"); + const currentTopProxyDeployment = + currentDeployment && isDeployedTopProxy(currentDeployment) + ? currentDeployment + : null; + const knownProxyNetwork = knownProxyNetworkName(tags, name); + const knownTopProxyDeployment = + await loadKnownTopProxyDeployment(knownProxyNetwork); + const topProxyDeployment = + currentTopProxyDeployment ?? knownTopProxyDeployment; + + if (!topProxyDeployment) { + throw new Error( + `No known top URP for network "${knownProxyNetwork}". A pre-existing top URP is required; deploying a fresh top URP is not supported (re-add the create3 deploy to bootstrap a new network).`, + ); + } + + if (!currentTopProxyDeployment) { + await save("UpgradableUniversalResolverProxy", topProxyDeployment); + } + return true; + }, + { + id: "universal-resolver:deploy-universal-resolver:v1", + tags: [ + "UniversalResolverMigration", + "migration:phase1:deploy-v2", + "UniversalResolver", + "UpgradableUniversalResolverProxy", + "v2", + ], + }, +); diff --git a/contracts/deploy/universalResolver/01_UpgradableUniversalResolverProxy.ts b/contracts/deploy/universalResolver/01_UpgradableUniversalResolverProxy.ts deleted file mode 100644 index 90069cd19..000000000 --- a/contracts/deploy/universalResolver/01_UpgradableUniversalResolverProxy.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { artifacts, execute } from "@rocketh"; -import { readFile } from "fs/promises"; -import { resolve } from "path"; -import type { Abi, Deployment } from "rocketh"; - -const __dirname = new URL(".", import.meta.url).pathname; -const deploymentsPath = resolve( - __dirname, - "../../lib/ens-contracts/deployments", -); - -export default execute( - async ({ - deploy, - get, - namedAccounts: { deployer, owner }, - network, - config, - }) => { - if (network.tags.local) { - const universalResolver = - get<(typeof artifacts.UniversalResolverV2)["abi"]>( - "UniversalResolverV2", - ); - await deploy("UpgradableUniversalResolverProxy", { - account: deployer, - artifact: artifacts.UpgradableUniversalResolverProxy, - args: [owner, universalResolver.address], - }); - return; - } - - const v1UniversalResolverDeployment = await readFile( - resolve(deploymentsPath, `${config.network.name}/UniversalResolver.json`), - "utf-8", - ); - const v1UniversalResolverDeploymentJson = JSON.parse( - v1UniversalResolverDeployment, - ) as Deployment; - - await deploy("UpgradableUniversalResolverProxy", { - account: deployer, - artifact: artifacts.UpgradableUniversalResolverProxy, - args: [owner, v1UniversalResolverDeploymentJson.address], - }); - }, - { tags: ["UpgradableUniversalResolverProxy", "l1", "UniversalResolverV2"] }, -); diff --git a/contracts/deploy/universalResolver/01_setup_UniversalResolverToV1.ts b/contracts/deploy/universalResolver/01_setup_UniversalResolverToV1.ts new file mode 100644 index 000000000..b7563d1d5 --- /dev/null +++ b/contracts/deploy/universalResolver/01_setup_UniversalResolverToV1.ts @@ -0,0 +1,74 @@ +import { artifacts, execute } from "@rocketh"; +import { getAddress, zeroAddress } from "viem"; + +import { + externalTopProxyOwnerLabel, + logUpgradeCalldata, + setProxyImplementationIfNeeded, +} from "../../script/universalResolverDeployUtils.js"; + +export default execute( + async ({ + get, + getV1, + execute: write, + read, + namedAccounts: { owner }, + tags, + }) => { + if (tags.local) return true; + + const topUrp = get< + typeof artifacts.UpgradableUniversalResolverProxy.abi + >("UpgradableUniversalResolverProxy"); + + // Only a freshly bootstrapped top URP with an unset implementation needs + // initializing to v1. An adopted top URP already serves either v1 or the + // intermediate URP and must never be re-pointed here. + const currentImplementation = (await read(topUrp, { + functionName: "implementation", + })) as `0x${string}`; + if (getAddress(currentImplementation) !== getAddress(zeroAddress)) { + console.log( + `UniversalResolver implementation: already ${currentImplementation}`, + ); + return true; + } + + const v1UniversalResolver = + await getV1<(typeof artifacts.UniversalResolver)["abi"]>( + "UniversalResolver", + ); + + const ownerLabel = externalTopProxyOwnerLabel(tags); + if (ownerLabel) { + logUpgradeCalldata( + "Set UniversalResolver implementation to v1 UniversalResolver", + topUrp.address, + v1UniversalResolver.address, + ownerLabel, + ); + return true; + } + + await setProxyImplementationIfNeeded({ + read, + write, + deployment: topUrp, + implementation: v1UniversalResolver.address, + account: owner, + label: "UniversalResolver implementation", + }); + return true; + }, + { + id: "universal-resolver:set-universal-resolver-to-v1:v1", + tags: [ + "UniversalResolverMigration", + "migration:phase1:deploy-v2", + "UniversalResolverV1", + "v2", + ], + dependencies: ["UniversalResolver"], + }, +); diff --git a/contracts/deploy/universalResolver/02_deploy_ManagedUniversalResolverProxy.ts b/contracts/deploy/universalResolver/02_deploy_ManagedUniversalResolverProxy.ts new file mode 100644 index 000000000..365a4ba26 --- /dev/null +++ b/contracts/deploy/universalResolver/02_deploy_ManagedUniversalResolverProxy.ts @@ -0,0 +1,78 @@ +import { artifacts, execute } from "@rocketh"; +import { getAddress, zeroAddress } from "viem"; + +import { + knownProxyNetworkName, + loadKnownIntermediateUrpDeployment, +} from "../../script/universalResolverDeployUtils.js"; + +export default execute( + async ({ + deploy, + get, + getV1, + getOrNull, + save, + read, + namedAccounts: { deployer, urManager }, + name, + tags, + }) => { + if (tags.local) return true; + + if ( + getOrNull( + "ManagedUniversalResolverProxy", + ) + ) + return true; + + // Reuse a long-lived intermediate URP when one already fronts the top URP on + // this network. A fresh v2 deployment then only re-points this proxy at the + // new implementation, leaving the externally-administered top URP untouched. + const knownIntermediate = await loadKnownIntermediateUrpDeployment( + knownProxyNetworkName(tags, name), + ); + if (knownIntermediate) { + await save("ManagedUniversalResolverProxy", knownIntermediate); + return true; + } + + // No pre-existing intermediate URP: deploy one seeded with whatever the top + // proxy currently serves so that later switching the top proxy onto it is + // transparent for resolution. Fall back to the v1 UniversalResolver only when + // the top proxy implementation is unset. + const topProxy = + get( + "UpgradableUniversalResolverProxy", + ); + const topImplementation = (await read(topProxy, { + functionName: "implementation", + })) as `0x${string}`; + const seedImplementation = + getAddress(topImplementation) !== getAddress(zeroAddress) + ? topImplementation + : ( + await getV1<(typeof artifacts.UniversalResolver)["abi"]>( + "UniversalResolver", + ) + ).address; + + await deploy("ManagedUniversalResolverProxy", { + account: deployer, + artifact: artifacts.UpgradableUniversalResolverProxy, + args: [urManager ?? deployer, seedImplementation], + }); + return true; + }, + { + id: "universal-resolver:deploy-managed-urp:v1", + tags: [ + "UniversalResolverMigration", + "migration:phase1:deploy-v2", + "ManagedUniversalResolverProxy", + "v2", + ], + dependencies: ["UniversalResolverV1"], + }, +); diff --git a/contracts/deploy/universalResolver/03_setup_UniversalResolverToManaged.ts b/contracts/deploy/universalResolver/03_setup_UniversalResolverToManaged.ts new file mode 100644 index 000000000..acf2bef57 --- /dev/null +++ b/contracts/deploy/universalResolver/03_setup_UniversalResolverToManaged.ts @@ -0,0 +1,70 @@ +import { artifacts, execute } from "@rocketh"; +import { getAddress } from "viem"; + +import { + externalTopProxyOwnerLabel, + logUpgradeCalldata, + setProxyImplementationIfNeeded, +} from "../../script/universalResolverDeployUtils.js"; + +export default execute( + async ({ + get, + execute: write, + read, + namedAccounts: { owner }, + tags, + }) => { + if (tags.local) return true; + + const topUrp = get< + typeof artifacts.UpgradableUniversalResolverProxy.abi + >("UpgradableUniversalResolverProxy"); + const managedUrp = get< + typeof artifacts.UpgradableUniversalResolverProxy.abi + >("ManagedUniversalResolverProxy"); + + // When the top URP already fronts the intermediate URP (the reuse flow), the + // switch is already done — never re-point the externally-administered top URP. + const currentImplementation = (await read(topUrp, { + functionName: "implementation", + })) as `0x${string}`; + if (getAddress(currentImplementation) === getAddress(managedUrp.address)) { + console.log( + `UniversalResolver implementation: already ${managedUrp.address} (intermediate URP)`, + ); + return true; + } + + const ownerLabel = externalTopProxyOwnerLabel(tags); + if (ownerLabel) { + logUpgradeCalldata( + "Set UniversalResolver implementation to ManagedUniversalResolverProxy", + topUrp.address, + managedUrp.address, + ownerLabel, + ); + return true; + } + + await setProxyImplementationIfNeeded({ + read, + write, + deployment: topUrp, + implementation: managedUrp.address, + account: owner, + label: "UniversalResolver implementation", + }); + return true; + }, + { + id: "universal-resolver:set-universal-resolver-to-managed:v1", + tags: [ + "UniversalResolverMigration", + "migration:phase5:switch-urp-to-managed", + "UniversalResolverManaged", + "v2", + ], + dependencies: ["ManagedUniversalResolverProxy"], + }, +); diff --git a/contracts/deploy/universalResolver/04_deploy_UniversalResolverImplementation.ts b/contracts/deploy/universalResolver/04_deploy_UniversalResolverImplementation.ts new file mode 100644 index 000000000..cb9565ccd --- /dev/null +++ b/contracts/deploy/universalResolver/04_deploy_UniversalResolverImplementation.ts @@ -0,0 +1,41 @@ +import { artifacts, execute } from "@rocketh"; + +export default execute( + async ({ deploy, get, getV1, namedAccounts: { deployer } }) => { + const rootRegistry = + get<(typeof artifacts.PermissionedRegistry)["abi"]>("RootRegistry"); + const batchGatewayProvider = + await getV1<(typeof artifacts.GatewayProvider)["abi"]>( + "BatchGatewayProvider", + ); + const contractNamer = + get<(typeof artifacts.IContractNamer)["abi"]>("ContractNamer"); + + await deploy("UniversalResolverV2", { + account: deployer, + artifact: artifacts.UniversalResolverV2, + args: [ + rootRegistry.address, + batchGatewayProvider.address, + contractNamer.address, + ], + }); + return true; + }, + { + id: "universal-resolver:deploy-universal-resolver-implementation:v1", + tags: [ + "UniversalResolverMigration", + "migration:phase1:deploy-v2", + "UniversalResolverImplementation", + "UniversalResolverV2", + "v2", + ], + dependencies: [ + "RootRegistry", + "BatchGatewayProvider", + "ContractNamer", + "ManagedUniversalResolverProxy", + ], + }, +); diff --git a/contracts/deploy/universalResolver/05_setup_ManagedUniversalResolverProxyToUniversalResolverImplementation.ts b/contracts/deploy/universalResolver/05_setup_ManagedUniversalResolverProxyToUniversalResolverImplementation.ts new file mode 100644 index 000000000..4bfd67c7f --- /dev/null +++ b/contracts/deploy/universalResolver/05_setup_ManagedUniversalResolverProxyToUniversalResolverImplementation.ts @@ -0,0 +1,59 @@ +import { artifacts, execute } from "@rocketh"; + +import { + logUpgradeCalldata, + setProxyImplementationIfNeeded, +} from "../../script/universalResolverDeployUtils.js"; + +export default execute( + async ({ + get, + execute: write, + read, + namedAccounts: { deployer, urManager }, + tags, + }) => { + if (tags.local) return true; + + const managedUrp = + get<(typeof artifacts.UpgradableUniversalResolverProxy)["abi"]>( + "ManagedUniversalResolverProxy", + ); + const universalResolverV2 = + get<(typeof artifacts.UniversalResolverV2)["abi"]>( + "UniversalResolverV2", + ); + + if (tags.hasDao) { + logUpgradeCalldata( + "Set ManagedUniversalResolverProxy implementation to UniversalResolverImplementation", + managedUrp.address, + universalResolverV2.address, + ); + return true; + } + + await setProxyImplementationIfNeeded({ + read, + write, + deployment: managedUrp, + implementation: universalResolverV2.address, + account: urManager ?? deployer, + label: "ManagedUniversalResolverProxy implementation", + }); + return true; + }, + { + id: "universal-resolver:set-managed-urp-to-universal-resolver-implementation:v1", + tags: [ + "UniversalResolverMigration", + "migration:phase6:upgrade-managed-urp", + "ManagedUniversalResolverProxyToUniversalResolverImplementation", + "v2", + ], + dependencies: [ + "UniversalResolverImplementation", + "ManagedUniversalResolverProxy", + ], + }, +); diff --git a/contracts/deploy/universalResolver/06_setup_UniversalResolverToUniversalResolverImplementation.ts b/contracts/deploy/universalResolver/06_setup_UniversalResolverToUniversalResolverImplementation.ts new file mode 100644 index 000000000..3ce6047d3 --- /dev/null +++ b/contracts/deploy/universalResolver/06_setup_UniversalResolverToUniversalResolverImplementation.ts @@ -0,0 +1,59 @@ +import { artifacts, execute } from "@rocketh"; + +import { + externalTopProxyOwnerLabel, + logUpgradeCalldata, + setProxyImplementationIfNeeded, +} from "../../script/universalResolverDeployUtils.js"; + +export default execute( + async ({ + get, + execute: write, + read, + namedAccounts: { owner }, + tags, + }) => { + if (tags.local) return true; + + const topUrp = + get<(typeof artifacts.UpgradableUniversalResolverProxy)["abi"]>( + "UpgradableUniversalResolverProxy", + ); + const universalResolverV2 = + get<(typeof artifacts.UniversalResolverV2)["abi"]>( + "UniversalResolverV2", + ); + + const ownerLabel = externalTopProxyOwnerLabel(tags); + if (ownerLabel) { + logUpgradeCalldata( + "Set UniversalResolver implementation to UniversalResolverImplementation", + topUrp.address, + universalResolverV2.address, + ownerLabel, + ); + return true; + } + + await setProxyImplementationIfNeeded({ + read, + write, + deployment: topUrp, + implementation: universalResolverV2.address, + account: owner, + label: "UniversalResolver implementation", + }); + return true; + }, + { + id: "universal-resolver:set-universal-resolver-to-universal-resolver-implementation:v1", + tags: [ + "UniversalResolverMigration", + "migration:post-cutover:direct-urp-to-v2", + "UniversalResolverToUniversalResolverImplementation", + "v2", + ], + dependencies: ["ManagedUniversalResolverProxyToUniversalResolverImplementation"], + }, +); diff --git a/contracts/deployments/README.md b/contracts/deployments/README.md new file mode 100644 index 000000000..c7e2fcd98 --- /dev/null +++ b/contracts/deployments/README.md @@ -0,0 +1,128 @@ +# Deployments + +Deployment artifacts written and read by [rocketh](https://github.com/wighawag/rocketh) +through the migration tooling ([`script/migration.ts`](../script/migration.ts), +[`docs/migration.md`](../docs/migration.md)). Each contract a deploy script +produces is recorded here as JSON so later runs and the phase commands can resolve +on-chain addresses without re-deploying. + +## Layout + +Artifacts are grouped into **namespaces**, one directory per deployment set: + +``` +deployments/ + README.md # this file + / # a single deployment set (v2 contracts) + .chain # { chainId, genesisHash } the set was deployed against + .migrations.json # rocketh's record of completed deploy scripts (id → unix-epoch-seconds) + .deployment.json # { environment, chainId, deployedAt } — when this set was first deployed + .json # one file per deployed contract (address, abi, bytecode, receipt, …) + v1/ + / # local v1-reference overrides (searched before the bundled set) + .chainId # chain id of the referenced v1 set + .json +``` + +The `.chain`, `.migrations.json`, and `.deployment.json` dotfiles are metadata; +rocketh loads only `.migrations.json` and the `.json` artifacts and +ignores every other dotfile, so `.deployment.json` is never mistaken for a +contract. `.deployment.json` is written once, on the first deploy into a +namespace, so its `deployedAt` records the original deployment time and survives +idempotent re-runs. + +A namespace is addressed by two inputs on every migration command: + +- `--deployments-dir ` — the root (defaults to this `deployments/` directory). +- `--deployment-network ` — the namespace subdirectory. Defaults to the + migration network name (`sepolia` / `mainnet`), i.e. `deployments/sepolia/`. + +v1 references resolve independently via `--v1-deployments-dir` +(default `deployments/v1`, then the bundled `lib/ens-contracts/deployments`) and +`--v1-deployment-network` (default: the network name). The two roots are searched +in order and the first match wins, so `deployments/v1//` acts as a **local +override layer**: the bundled ens-contracts deployment supplies the canonical v1 +contracts, and anything dropped under `deployments/v1/` takes precedence or adds a +contract the bundled set omits. + +## Namespace naming and `sepolia-official-v1-20260525-r2` + +`sepolia-official-v1-20260525-r2` is the existing **v2** deployment on Sepolia +(chain `11155111`) — the name encodes that it was built against the official v1 +references, dated `2026-05-25`, revision `r2`. Despite `v1` in the name its +contents are the v2 set (`ETHRegistry`, `ENSV2Resolver`, `ETHRegistrar`, +`UpgradableUniversalResolverProxy`, the migration controllers, …). + +The date/revision suffix is deliberate: **a previous deployment is kept as a +standalone, immutable record** rather than being overwritten, and rocketh always +gets a clean folder to deploy into (see below). This folder was named by hand; +`phase deploy-v2` now produces the same shape automatically, archiving the prior +set to `--r`. + +Because this namespace is not the default (`sepolia`), routine commands and the +`fork full` rehearsal do not load it unless you pass +`--deployment-network sepolia-official-v1-20260525-r2`. + +## Re-deploying: fresh by default, `--resume` to continue + +`phase deploy-v2` deploys fresh by default — it archives the current namespace out +of the way and deploys into a clean one: + +```bash +bun run migration -- phase deploy-v2 --network sepolia +``` + +- The existing `deployments//` is renamed to `deployments/--r`, + where the date is the archived deployment's `deployedAt` (from `.deployment.json`, + falling back to the latest `.migrations.json` timestamp) and `` auto-increments + if a same-date archive already exists. +- A fresh deployment is then written into `deployments//` and a new + `.deployment.json` is stamped. + +This works identically for `--network mainnet` (the namespace defaults to the +network name). Manually moving or clearing the namespace directory first is +equivalent; the default archive just automates it with a dated name. + +Phase 1 sends many transactions and can be interrupted partway. Re-run with +`--resume` to continue into the **existing** namespace instead of archiving: + +```bash +bun run migration -- phase deploy-v2 --network sepolia --resume +``` + +rocketh is idempotent against the namespace folder — a deploy script that finds an +artifact of the same name **reuses it instead of redeploying** (scripts guard with +`getOrNull(name) ?? deploy(name, …)`, and `.migrations.json` lets the runner skip +scripts that already completed) — so `--resume` reloads the contracts already +deployed and sends only the not-yet-deployed ones. + +The persistent `UpgradableUniversalResolverProxy` entry point +(`0xeEeE…EeEe`) is fixed by constant and is never re-deployed; a fresh run +re-points it at the newly deployed managed URP during phase 7. The previous +namespace's contracts remain on-chain but become orphaned once the entry point +is cut over. + +## Saving artifacts + +The rehearsal (`fork full`) does not persist artifacts unless `--save-deployments` +is passed, so a fork run leaves `deployments/` untouched by default. `phase +deploy-v2` always persists its deployment into the chosen `--deployment-network` +(both a fresh run and a `--resume`). + +## Git tracking + +`.gitignore` tracks real deployment namespaces by default and ignores only the +local rehearsal/runtime ones, so committed sets are not dimmed by editors while +throwaway runs stay out of the repository: + +``` +deployments/*-fork/ # fork full --save-deployments rehearsal namespaces +deployments/*-clean-*/ # clean-testnet runtime namespaces +deployments/v1/* # v1 references are ignored … +!deployments/v1/sepolia/ # … except the tracked sepolia v1 references +``` + +A live namespace (`deployments/sepolia/`) and dated archives +(`deployments/sepolia--r/`) are therefore committed automatically — +no allow-list entry needed. To deliberately keep a namespace local-only, name it +with a `-fork` / `-clean-` suffix or add a matching ignore line. diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/.chain b/contracts/deployments/sepolia-official-v1-20260525-r2/.chain new file mode 100644 index 000000000..58f80a4ab --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/.chain @@ -0,0 +1 @@ +{"chainId":"11155111","genesisHash":"0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/.migrations.json b/contracts/deployments/sepolia-official-v1-20260525-r2/.migrations.json new file mode 100644 index 000000000..307ca6172 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/.migrations.json @@ -0,0 +1 @@ +{"universal-resolver:deploy-universal-resolver:v1":1779749053,"universal-resolver:set-universal-resolver-to-v1:v1":1779749053,"universal-resolver:deploy-managed-urp:v1":1779749066,"universal-resolver:deploy-universal-resolver-implementation:v1":1779749078} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ApprovedUpgradeGate.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ApprovedUpgradeGate.json new file mode 100644 index 000000000..5f059eb00 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ApprovedUpgradeGate.json @@ -0,0 +1,285 @@ +{ + "address": "0x2c83019d86ff3be9cc269687215f4731158a8b6f", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ImplementationApprovalChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "approvedImplementations", + "outputs": [ + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setImplementationApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "ApprovedUpgradeGate", + "sourceName": "src/registry/ApprovedUpgradeGate.sol", + "bytecode": "0x6080604052348015600e575f5ffd5b506040516103f43803806103f4833981016040819052602b9160b4565b806001600160a01b038116605857604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b605f816065565b505060df565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121560c3575f5ffd5b81516001600160a01b038116811460d8575f5ffd5b9392505050565b610308806100ec5f395ff3fe608060405234801561000f575f5ffd5b5060043610610064575f3560e01c806396b78cbe1161004d57806396b78cbe14610091578063e537b27b146100c3578063f2fde38b146100d6575f5ffd5b8063715018a6146100685780638da5cb5b14610072575b5f5ffd5b6100706100e9565b005b5f546040516001600160a01b0390911681526020015b60405180910390f35b6100b361009f366004610279565b60016020525f908152604090205460ff1681565b6040519015158152602001610088565b6100706100d1366004610299565b6100fc565b6100706100e4366004610279565b610157565b6100f16101b2565b6100fa5f6101f7565b565b6101046101b2565b6001600160a01b0382165f81815260016020526040808220805460ff191685151590811790915590519092917fdf2de8f46c1295aaa5eaaea8c458190346b99f2dd813bd0a543dff50c0c4106e91a35050565b61015f6101b2565b6001600160a01b0381166101a6576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6101af816101f7565b50565b5f546001600160a01b031633146100fa576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240161019d565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80356001600160a01b0381168114610274575f5ffd5b919050565b5f60208284031215610289575f5ffd5b6102928261025e565b9392505050565b5f5f604083850312156102aa575f5ffd5b6102b38361025e565b9150602083013580151581146102c7575f5ffd5b80915050925092905056fea264697066735822122003566dfbf6b0b3adae039409f095b4b6838cc2ff5db26841393de2de3233c7c664736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610064575f3560e01c806396b78cbe1161004d57806396b78cbe14610091578063e537b27b146100c3578063f2fde38b146100d6575f5ffd5b8063715018a6146100685780638da5cb5b14610072575b5f5ffd5b6100706100e9565b005b5f546040516001600160a01b0390911681526020015b60405180910390f35b6100b361009f366004610279565b60016020525f908152604090205460ff1681565b6040519015158152602001610088565b6100706100d1366004610299565b6100fc565b6100706100e4366004610279565b610157565b6100f16101b2565b6100fa5f6101f7565b565b6101046101b2565b6001600160a01b0382165f81815260016020526040808220805460ff191685151590811790915590519092917fdf2de8f46c1295aaa5eaaea8c458190346b99f2dd813bd0a543dff50c0c4106e91a35050565b61015f6101b2565b6001600160a01b0381166101a6576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6101af816101f7565b50565b5f546001600160a01b031633146100fa576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240161019d565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80356001600160a01b0381168114610274575f5ffd5b919050565b5f60208284031215610289575f5ffd5b6102928261025e565b9392505050565b5f5f604083850312156102aa575f5ffd5b6102b38361025e565b9150602083013580151581146102c7575f5ffd5b80915050925092905056fea264697066735822122003566dfbf6b0b3adae039409f095b4b6838cc2ff5db26841393de2de3233c7c664736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/src/registry/ApprovedUpgradeGate.sol", + "devdoc": { + "errors": { + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "events": { + "ImplementationApprovalChanged(address,bool)": { + "params": { + "approved": "Whether upgrades to the implementation are approved.", + "implementation": "The implementation address." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "owner_": "The address that controls implementation approvals." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setImplementationApproval(address,bool)": { + "params": { + "approved": "Whether upgrades to the implementation are approved.", + "implementation": "The implementation address." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "155200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "approvedImplementations(address)": "2528", + "owner()": "2311", + "renounceOwnership()": "infinite", + "setImplementationApproval(address,bool)": "28397", + "transferOwnership(address)": "28358" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ImplementationApprovalChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"approvedImplementations\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setImplementationApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"ImplementationApprovalChanged(address,bool)\":{\"params\":{\"approved\":\"Whether upgrades to the implementation are approved.\",\"implementation\":\"The implementation address.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"owner_\":\"The address that controls implementation approvals.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setImplementationApproval(address,bool)\":{\"params\":{\"approved\":\"Whether upgrades to the implementation are approved.\",\"implementation\":\"The implementation address.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"events\":{\"ImplementationApprovalChanged(address,bool)\":{\"notice\":\"Approval status changed for an implementation.\"}},\"kind\":\"user\",\"methods\":{\"approvedImplementations(address)\":{\"notice\":\"Returns whether an implementation may be used as an upgrade target.\"},\"setImplementationApproval(address,bool)\":{\"notice\":\"Set whether an implementation may be used as an upgrade target.\"}},\"notice\":\"Allowlist for approved implementation upgrade targets.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/ApprovedUpgradeGate.sol\":\"ApprovedUpgradeGate\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/src/registry/ApprovedUpgradeGate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/// @notice Allowlist for approved implementation upgrade targets.\\ncontract ApprovedUpgradeGate is Ownable {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Returns whether an implementation may be used as an upgrade target.\\n mapping(address implementation => bool approved) public approvedImplementations;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Approval status changed for an implementation.\\n /// @param implementation The implementation address.\\n /// @param approved Whether upgrades to the implementation are approved.\\n event ImplementationApprovalChanged(address indexed implementation, bool indexed approved);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ The address that controls implementation approvals.\\n constructor(address owner_) Ownable(owner_) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Set whether an implementation may be used as an upgrade target.\\n /// @param implementation The implementation address.\\n /// @param approved Whether upgrades to the implementation are approved.\\n function setImplementationApproval(address implementation, bool approved) external onlyOwner {\\n approvedImplementations[implementation] = approved;\\n emit ImplementationApprovalChanged(implementation, approved);\\n }\\n}\\n\",\"keccak256\":\"0xecaf823f2344fb8336d18f889905de806299edfa6424796a24ce584eeda1eb2f\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 34237, + "contract": "project/src/registry/ApprovedUpgradeGate.sol:ApprovedUpgradeGate", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 66552, + "contract": "project/src/registry/ApprovedUpgradeGate.sol:ApprovedUpgradeGate", + "label": "approvedImplementations", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + }, + "userdoc": { + "events": { + "ImplementationApprovalChanged(address,bool)": { + "notice": "Approval status changed for an implementation." + } + }, + "kind": "user", + "methods": { + "approvedImplementations(address)": { + "notice": "Returns whether an implementation may be used as an upgrade target." + }, + "setImplementationApproval(address,bool)": { + "notice": "Set whether an implementation may be used as an upgrade target." + } + }, + "notice": "Allowlist for approved implementation upgrade targets.", + "version": 1 + }, + "argsData": "0x000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80", + "transaction": { + "hash": "0xce89ff1ce8dd34a9b1f8e63072e168c476efabd16f834483ec6f40864e85cc14", + "nonce": "0x1e96", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x7283cdd0f6b2fd7554ea8eb49b0462706865861be4514487a3e4787f7388c73f", + "blockNumber": "0xa6a80b", + "transactionIndex": "0x40" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/BatchRegistrar.json b/contracts/deployments/sepolia-official-v1-20260525-r2/BatchRegistrar.json new file mode 100644 index 000000000..a924e3b56 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/BatchRegistrar.json @@ -0,0 +1,282 @@ +{ + "address": "0xb39c2da7143dffa4a097970887fa6f1d17c1d60f", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry_", + "type": "address" + }, + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InputLengthMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "string[]", + "name": "labels", + "type": "string[]" + }, + { + "internalType": "uint64[]", + "name": "expires", + "type": "uint64[]" + } + ], + "name": "batchRegister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "BatchRegistrar", + "sourceName": "src/registrar/BatchRegistrar.sol", + "bytecode": "0x60a060405234801561000f575f5ffd5b506040516109e53803806109e583398101604081905261002e916100de565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006581610078565b50506001600160a01b0316608052610116565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146100db575f5ffd5b50565b5f5f604083850312156100ef575f5ffd5b82516100fa816100c7565b602084015190925061010b816100c7565b809150509250929050565b6080516108a36101425f395f818160820152818161013901528181610240015261038a01526108a35ff3fe608060405234801561000f575f5ffd5b5060043610610064575f3560e01c8063715018a61161004d578063715018a6146100c05780638da5cb5b146100c8578063f2fde38b146100d8575f5ffd5b8063087be49f14610068578063475007081461007d575b5f5ffd5b61007b6100763660046105ea565b6100eb565b005b6100a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61007b610469565b5f546001600160a01b03166100a4565b61007b6100e636600461067e565b61047c565b6100f36104d7565b82811461012c576040517faaad13f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b83811015610460575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286101c688888681811061017b5761017b6106a0565b905060200281019061018d91906106b4565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061051c92505050565b6040518263ffffffff1660e01b81526004016101e491815260200190565b60a060405180830381865afa1580156101ff573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610735565b90505f81516002811115610239576102396107c3565b03610324577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f3e64387878581811061027f5761027f6106a0565b905060200281019061029191906106b4565b5f8c8c5f8b8b8b8181106102a7576102a76106a0565b90506020020160208101906102bc91906107d7565b6040518863ffffffff1660e01b81526004016102de97969594939291906107f2565b6020604051808303815f875af11580156102fa573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610856565b50610457565b600181516002811115610339576103396107c3565b1480156103835750806020015167ffffffffffffffff16848484818110610362576103626106a0565b905060200201602081019061037791906107d7565b67ffffffffffffffff16115b15610457577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635569f33d82606001518686868181106103ce576103ce6106a0565b90506020020160208101906103e391906107d7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925267ffffffffffffffff1660248201526044015f604051808303815f87803b158015610440575f5ffd5b505af1158015610452573d5f5f3e3d5ffd5b505050505b5060010161012e565b50505050505050565b6104716104d7565b61047a5f610527565b565b6104846104d7565b6001600160a01b0381166104cb576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d481610527565b50565b5f546001600160a01b0316331461047a576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104c2565b805160209091012090565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146104d4575f5ffd5b5f5f83601f8401126105b2575f5ffd5b50813567ffffffffffffffff8111156105c9575f5ffd5b6020830191508360208260051b85010111156105e3575f5ffd5b9250929050565b5f5f5f5f5f5f608087890312156105ff575f5ffd5b863561060a8161058e565b9550602087013561061a8161058e565b9450604087013567ffffffffffffffff811115610635575f5ffd5b61064189828a016105a2565b909550935050606087013567ffffffffffffffff811115610660575f5ffd5b61066c89828a016105a2565b979a9699509497509295939492505050565b5f6020828403121561068e575f5ffd5b81356106998161058e565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e198436030181126106c9575f5ffd5b83018035915067ffffffffffffffff8211156106e3575f5ffd5b6020019150368190038213156105e3575f5ffd5b805160038110610705575f5ffd5b919050565b67ffffffffffffffff811681146104d4575f5ffd5b80516107058161070a565b80516107058161058e565b5f60a0828403128015610746575f5ffd5b5060405160a0810167ffffffffffffffff8111828210171561077657634e487b7160e01b5f52604160045260245ffd5b604052610782836106f7565b81526107906020840161071f565b60208201526107a16040840161072a565b6040820152606083810151908201526080928301519281019290925250919050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156107e7575f5ffd5b81356106998161070a565b60c081528660c0820152868860e08301375f60e08883018101919091526001600160a01b0396871660208301529486166040820152929094166060830152608082015267ffffffffffffffff90921660a0830152601f909201601f19160101919050565b5f60208284031215610866575f5ffd5b505191905056fea2646970667358221220634a2efe5cac7c21eb3b64088dd3aa06d978ce9f20c62d54ca652ad4a858f0bf64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610064575f3560e01c8063715018a61161004d578063715018a6146100c05780638da5cb5b146100c8578063f2fde38b146100d8575f5ffd5b8063087be49f14610068578063475007081461007d575b5f5ffd5b61007b6100763660046105ea565b6100eb565b005b6100a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61007b610469565b5f546001600160a01b03166100a4565b61007b6100e636600461067e565b61047c565b6100f36104d7565b82811461012c576040517faaad13f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b83811015610460575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286101c688888681811061017b5761017b6106a0565b905060200281019061018d91906106b4565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061051c92505050565b6040518263ffffffff1660e01b81526004016101e491815260200190565b60a060405180830381865afa1580156101ff573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610735565b90505f81516002811115610239576102396107c3565b03610324577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f3e64387878581811061027f5761027f6106a0565b905060200281019061029191906106b4565b5f8c8c5f8b8b8b8181106102a7576102a76106a0565b90506020020160208101906102bc91906107d7565b6040518863ffffffff1660e01b81526004016102de97969594939291906107f2565b6020604051808303815f875af11580156102fa573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610856565b50610457565b600181516002811115610339576103396107c3565b1480156103835750806020015167ffffffffffffffff16848484818110610362576103626106a0565b905060200201602081019061037791906107d7565b67ffffffffffffffff16115b15610457577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635569f33d82606001518686868181106103ce576103ce6106a0565b90506020020160208101906103e391906107d7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925267ffffffffffffffff1660248201526044015f604051808303815f87803b158015610440575f5ffd5b505af1158015610452573d5f5f3e3d5ffd5b505050505b5060010161012e565b50505050505050565b6104716104d7565b61047a5f610527565b565b6104846104d7565b6001600160a01b0381166104cb576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d481610527565b50565b5f546001600160a01b0316331461047a576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104c2565b805160209091012090565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146104d4575f5ffd5b5f5f83601f8401126105b2575f5ffd5b50813567ffffffffffffffff8111156105c9575f5ffd5b6020830191508360208260051b85010111156105e3575f5ffd5b9250929050565b5f5f5f5f5f5f608087890312156105ff575f5ffd5b863561060a8161058e565b9550602087013561061a8161058e565b9450604087013567ffffffffffffffff811115610635575f5ffd5b61064189828a016105a2565b909550935050606087013567ffffffffffffffff811115610660575f5ffd5b61066c89828a016105a2565b979a9699509497509295939492505050565b5f6020828403121561068e575f5ffd5b81356106998161058e565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e198436030181126106c9575f5ffd5b83018035915067ffffffffffffffff8211156106e3575f5ffd5b6020019150368190038213156105e3575f5ffd5b805160038110610705575f5ffd5b919050565b67ffffffffffffffff811681146104d4575f5ffd5b80516107058161070a565b80516107058161058e565b5f60a0828403128015610746575f5ffd5b5060405160a0810167ffffffffffffffff8111828210171561077657634e487b7160e01b5f52604160045260245ffd5b604052610782836106f7565b81526107906020840161071f565b60208201526107a16040840161072a565b6040820152606083810151908201526080928301519281019290925250919050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156107e7575f5ffd5b81356106998161070a565b60c081528660c0820152868860e08301375f60e08883018101919091526001600160a01b0396871660208301529486166040820152929094166060830152608082015267ffffffffffffffff90921660a0830152601f909201601f19160101919050565b5f60208284031215610866575f5ffd5b505191905056fea2646970667358221220634a2efe5cac7c21eb3b64088dd3aa06d978ce9f20c62d54ca652ad4a858f0bf64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "63803": [ + { + "length": 32, + "start": 130 + }, + { + "length": 32, + "start": 313 + }, + { + "length": 32, + "start": 576 + }, + { + "length": 32, + "start": 906 + } + ] + }, + "inputSourceName": "project/src/registrar/BatchRegistrar.sol", + "devdoc": { + "errors": { + "InputLengthMismatch()": [ + { + "details": "Error selector: `0xaaad13f7`" + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "kind": "dev", + "methods": { + "batchRegister(address,address,string[],uint64[])": { + "params": { + "expires": "Array of expiry timestamps corresponding to each label", + "labels": "Array of labels to reserve or renew", + "registry": "The registry for all names", + "resolver": "The resolver for all names" + } + }, + "constructor": { + "params": { + "ethRegistry_": "The ETH registry to use for batch registration.", + "owner_": "The owner of the contract." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "title": "BatchRegistrar", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "442200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ETH_REGISTRY()": "infinite", + "batchRegister(address,address,string[],uint64[])": "infinite", + "owner()": "2339", + "renounceOwnership()": "infinite", + "transferOwnership(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InputLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"labels\",\"type\":\"string[]\"},{\"internalType\":\"uint64[]\",\"name\":\"expires\",\"type\":\"uint64[]\"}],\"name\":\"batchRegister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InputLengthMismatch()\":[{\"details\":\"Error selector: `0xaaad13f7`\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"kind\":\"dev\",\"methods\":{\"batchRegister(address,address,string[],uint64[])\":{\"params\":{\"expires\":\"Array of expiry timestamps corresponding to each label\",\"labels\":\"Array of labels to reserve or renew\",\"registry\":\"The registry for all names\",\"resolver\":\"The resolver for all names\"}},\"constructor\":{\"params\":{\"ethRegistry_\":\"The ETH registry to use for batch registration.\",\"owner_\":\"The owner of the contract.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"BatchRegistrar\",\"version\":1},\"userdoc\":{\"errors\":{\"InputLengthMismatch()\":[{\"notice\":\"Thrown when batch registration inputs have different lengths.\"}]},\"kind\":\"user\",\"methods\":{\"ETH_REGISTRY()\":{\"notice\":\"The ETH registry to use for batch registration.\"},\"batchRegister(address,address,string[],uint64[])\":{\"notice\":\"Batch reserve or renew names for pre-migration\"}},\"notice\":\"Simple batch registration contract for pre-migration of ENS names. Only the owner can invoke batch registration.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/BatchRegistrar.sol\":\"BatchRegistrar\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registrar/BatchRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\n/// @title BatchRegistrar\\n/// @notice Simple batch registration contract for pre-migration of ENS names.\\n/// Only the owner can invoke batch registration.\\ncontract BatchRegistrar is Ownable {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ETH registry to use for batch registration.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Thrown when batch registration inputs have different lengths.\\n /// @dev Error selector: `0xaaad13f7`\\n error InputLengthMismatch();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param ethRegistry_ The ETH registry to use for batch registration.\\n /// @param owner_ The owner of the contract.\\n constructor(IPermissionedRegistry ethRegistry_, address owner_) Ownable(owner_) {\\n ETH_REGISTRY = ethRegistry_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Batch reserve or renew names for pre-migration\\n /// @param registry The registry for all names\\n /// @param resolver The resolver for all names\\n /// @param labels Array of labels to reserve or renew\\n /// @param expires Array of expiry timestamps corresponding to each label\\n function batchRegister(\\n IRegistry registry,\\n address resolver,\\n string[] calldata labels,\\n uint64[] calldata expires\\n )\\n external\\n onlyOwner\\n {\\n if (labels.length != expires.length) {\\n revert InputLengthMismatch();\\n }\\n\\n for (uint256 i = 0; i < labels.length; i++) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(labels[i]));\\n\\n if (state.status == IPermissionedRegistry.Status.AVAILABLE) {\\n ETH_REGISTRY.register(labels[i], address(0), registry, resolver, 0, expires[i]);\\n } else if (\\n state.status == IPermissionedRegistry.Status.RESERVED && expires[i] > state.expiry\\n ) {\\n ETH_REGISTRY.renew(state.tokenId, expires[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x500267938ff1c4abbf7fcb0155e65759a672e0d12c16217290e1c38fca25d6fd\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 34237, + "contract": "project/src/registrar/BatchRegistrar.sol:BatchRegistrar", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + }, + "userdoc": { + "errors": { + "InputLengthMismatch()": [ + { + "notice": "Thrown when batch registration inputs have different lengths." + } + ] + }, + "kind": "user", + "methods": { + "ETH_REGISTRY()": { + "notice": "The ETH registry to use for batch registration." + }, + "batchRegister(address,address,string[],uint64[])": { + "notice": "Batch reserve or renew names for pre-migration" + } + }, + "notice": "Simple batch registration contract for pre-migration of ENS names. Only the owner can invoke batch registration.", + "version": 1 + }, + "argsData": "0x000000000000000000000000dedb92913a25abe1f7bcdd85d8a344a43b398b67000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80", + "transaction": { + "hash": "0xaecad1b82115501b61cb60edd83bc192848a6cbc655fca21ed8fc179b441b348", + "nonce": "0x1e9b", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xd7ce8dc51617181b46c9332ea29fa54927e18d1efa0b2bacc07eafd84f5de82a", + "blockNumber": "0xa6a810", + "transactionIndex": "0x44" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer.json new file mode 100644 index 000000000..0317c65f6 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer.json @@ -0,0 +1,465 @@ +{ + "address": "0xfc8bf9234969d6b85729b756fa9e14bb84a06754", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + } + ], + "contractName": "ContractNamer", + "sourceName": "src/utils/ContractNamer.sol", + "bytecode": "0x60a060405230608052348015610013575f5ffd5b5061001c610021565b6100d3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100715760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d05780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b608051610c8e6100f95f395f81816104de01528181610507015261068a0152610c8e5ff3fe608060405260043610610093575f3560e01c8063715018a611610066578063ad3cb1cc1161004c578063ad3cb1cc1461017b578063c4d66de8146101d0578063f2fde38b146101ef575f5ffd5b8063715018a6146101215780638da5cb5b14610135575f5ffd5b806301ffc9a7146100975780634f1ef286146100cb57806352d1902d146100e05780636f3ff72614610102575b5f5ffd5b3480156100a2575f5ffd5b506100b66100b1366004610a92565b61020e565b60405190151581526020015b60405180910390f35b6100de6100d9366004610b19565b6102a6565b005b3480156100eb575f5ffd5b506100f46102c5565b6040519081526020016100c2565b34801561010d575f5ffd5b506100b661011c366004610bdd565b6102f3565b34801561012c575f5ffd5b506100de61033f565b348015610140575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020016100c2565b348015610186575f5ffd5b506101c36040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c29190610bf6565b3480156101db575f5ffd5b506100de6101ea366004610bdd565b610352565b3480156101fa575f5ffd5b506100de610209366004610bdd565b610478565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f6f3ff7260000000000000000000000000000000000000000000000000000000014806102a057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6102ae6104d3565b6102b78261058a565b6102c18282610592565b5050565b5f6102ce61067f565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f816001600160a01b031661032f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161492915050565b6103476106c8565b6103505f61073c565b565b5f61035b6107b9565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156103875750825b90505f8267ffffffffffffffff1660011480156103a35750303b155b9050811580156103b1575080155b156103e8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561041c57845468ff00000000000000001916680100000000000000001785555b610425866107e1565b831561047057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6104806106c8565b6001600160a01b0381166104c7576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d08161073c565b50565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061056c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156103505760405163703e46dd60e11b815260040160405180910390fd5b6104d06106c8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105ec575060408051601f3d908101601f191682019092526105e991810190610c2b565b60015b61061457604051634c9c8ce360e01b81526001600160a01b03831660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610670576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016104be565b61067a83836107f2565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103505760405163703e46dd60e11b815260040160405180910390fd5b336106fa7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610350576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104be565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102a0565b6107e9610847565b6104d081610885565b6107fb8261088d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561083f5761067a8282610910565b6102c1610982565b61084f6109ba565b610350576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610480610847565b806001600160a01b03163b5f036108c257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f5f846001600160a01b03168460405161092c9190610c42565b5f60405180830381855af49150503d805f8114610964576040519150601f19603f3d011682016040523d82523d5f602084013e610969565b606091505b50915091506109798583836109d8565b95945050505050565b3415610350576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6109c36107b9565b5468010000000000000000900460ff16919050565b6060826109ed576109e882610a50565b610a49565b8151158015610a0457506001600160a01b0384163b155b15610a46576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016104be565b50805b9392505050565b805115610a605780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610aa2575f5ffd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a49575f5ffd5b80356001600160a01b0381168114610ae7575f5ffd5b919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f60408385031215610b2a575f5ffd5b610b3383610ad1565b9150602083013567ffffffffffffffff811115610b4e575f5ffd5b8301601f81018513610b5e575f5ffd5b803567ffffffffffffffff811115610b7857610b78610aec565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610ba757610ba7610aec565b604052818152828201602001871015610bbe575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f60208284031215610bed575f5ffd5b610a4982610ad1565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610c3b575f5ffd5b5051919050565b5f82518060208501845e5f92019182525091905056fea26469706673582212204e422766ce5b88ad718a0bff7905c3a04cfae01af85ec46e205355b54064127b64736f6c634300081b0033", + "deployedBytecode": "0x608060405260043610610093575f3560e01c8063715018a611610066578063ad3cb1cc1161004c578063ad3cb1cc1461017b578063c4d66de8146101d0578063f2fde38b146101ef575f5ffd5b8063715018a6146101215780638da5cb5b14610135575f5ffd5b806301ffc9a7146100975780634f1ef286146100cb57806352d1902d146100e05780636f3ff72614610102575b5f5ffd5b3480156100a2575f5ffd5b506100b66100b1366004610a92565b61020e565b60405190151581526020015b60405180910390f35b6100de6100d9366004610b19565b6102a6565b005b3480156100eb575f5ffd5b506100f46102c5565b6040519081526020016100c2565b34801561010d575f5ffd5b506100b661011c366004610bdd565b6102f3565b34801561012c575f5ffd5b506100de61033f565b348015610140575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020016100c2565b348015610186575f5ffd5b506101c36040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c29190610bf6565b3480156101db575f5ffd5b506100de6101ea366004610bdd565b610352565b3480156101fa575f5ffd5b506100de610209366004610bdd565b610478565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f6f3ff7260000000000000000000000000000000000000000000000000000000014806102a057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6102ae6104d3565b6102b78261058a565b6102c18282610592565b5050565b5f6102ce61067f565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f816001600160a01b031661032f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161492915050565b6103476106c8565b6103505f61073c565b565b5f61035b6107b9565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156103875750825b90505f8267ffffffffffffffff1660011480156103a35750303b155b9050811580156103b1575080155b156103e8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561041c57845468ff00000000000000001916680100000000000000001785555b610425866107e1565b831561047057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6104806106c8565b6001600160a01b0381166104c7576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d08161073c565b50565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061056c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156103505760405163703e46dd60e11b815260040160405180910390fd5b6104d06106c8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105ec575060408051601f3d908101601f191682019092526105e991810190610c2b565b60015b61061457604051634c9c8ce360e01b81526001600160a01b03831660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610670576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016104be565b61067a83836107f2565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103505760405163703e46dd60e11b815260040160405180910390fd5b336106fa7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610350576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104be565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102a0565b6107e9610847565b6104d081610885565b6107fb8261088d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561083f5761067a8282610910565b6102c1610982565b61084f6109ba565b610350576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610480610847565b806001600160a01b03163b5f036108c257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f5f846001600160a01b03168460405161092c9190610c42565b5f60405180830381855af49150503d805f8114610964576040519150601f19603f3d011682016040523d82523d5f602084013e610969565b606091505b50915091506109798583836109d8565b95945050505050565b3415610350576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6109c36107b9565b5468010000000000000000900460ff16919050565b6060826109ed576109e882610a50565b610a49565b8151158015610a0457506001600160a01b0384163b155b15610a46576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016104be565b50805b9392505050565b805115610a605780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610aa2575f5ffd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a49575f5ffd5b80356001600160a01b0381168114610ae7575f5ffd5b919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f60408385031215610b2a575f5ffd5b610b3383610ad1565b9150602083013567ffffffffffffffff811115610b4e575f5ffd5b8301601f81018513610b5e575f5ffd5b803567ffffffffffffffff811115610b7857610b78610aec565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610ba757610ba7610aec565b604052818152828201602001871015610bbe575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f60208284031215610bed575f5ffd5b610a4982610ad1565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610c3b575f5ffd5b5051919050565b5f82518060208501845e5f92019182525091905056fea26469706673582212204e422766ce5b88ad718a0bff7905c3a04cfae01af85ec46e205355b54064127b64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ] + }, + "events": { + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "initialize(address)": { + "params": { + "owner_": "The contract owner." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "642800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "UPGRADE_INTERFACE_VERSION()": "infinite", + "initialize(address)": "infinite", + "isContractNamer(address)": "2609", + "owner()": "2345", + "proxiableUUID()": "infinite", + "renounceOwnership()": "infinite", + "supportsInterface(bytes4)": "367", + "transferOwnership(address)": "28419", + "upgradeToAndCall(address,bytes)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}]},\"events\":{\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"initialize(address)\":{\"params\":{\"owner_\":\"The contract owner.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(address)\":{\"notice\":\"Initialize the contract.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"}},\"notice\":\"Shared `IContractNamer` instance.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/utils/ContractNamer.sol\":\"ContractNamer\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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 OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\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 * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\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 Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\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 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\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 _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\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 // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\\n *\\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\\n */\\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\\n return INITIALIZABLE_STORAGE;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n bytes32 slot = _initializableStorageSlot();\\n assembly {\\n $.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IERC1822Proxiable} from \\\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\\\";\\nimport {Initializable} from \\\"./Initializable.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 */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\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 _checkNotDelegated();\\n _;\\n }\\n\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\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 * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {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 onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: 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\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\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 ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\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 ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.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 the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\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 ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\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 * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, bytes memory returndata) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n _revert(returndata);\\n }\\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 or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) 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 assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/ContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @notice Shared `IContractNamer` instance.\\ncontract ContractNamer is ERC165, OwnableUpgradeable, UUPSUpgradeable, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /// @notice Initialize the contract.\\n /// @param owner_ The contract owner.\\n function initialize(address owner_) external initializer {\\n __Ownable_init(owner_);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return owner() == namer;\\n }\\n\\n /// @dev Allow owner to upgrade.\\n function _authorizeUpgrade(address) internal override onlyOwner {}\\n}\\n\",\"keccak256\":\"0x69dc17485dba9a662c0c577677eb9a06dcfbe1cdb0bc8471f23ae8fc6fcf856f\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": { + "initialize(address)": { + "notice": "Initialize the contract." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + } + }, + "notice": "Shared `IContractNamer` instance.", + "version": 1 + }, + "solcInput": "{\n \"language\": \"Solidity\",\n \"sources\": {\n \"solc_0.8/openzeppelin/access/Ownable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 (address initialOwner) {\\n _transferOwnership(initialOwner);\\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 _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\"\n },\n \"solc_0.8/openzeppelin/utils/Context.sol\": {\n \"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\"\n },\n \"solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./TransparentUpgradeableProxy.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\n\\n/**\\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\\n */\\ncontract ProxyAdmin is Ownable {\\n\\n constructor (address initialOwner) Ownable(initialOwner) {}\\n\\n /**\\n * @dev Returns the current implementation of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"implementation()\\\")) == 0x5c60da1b\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"5c60da1b\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Returns the current admin of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"admin()\\\")) == 0xf851a440\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"f851a440\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Changes the admin of `proxy` to `newAdmin`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the current admin of `proxy`.\\n */\\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\\n proxy.changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\\n proxy.upgradeTo(implementation);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgradeAndCall(\\n TransparentUpgradeableProxy proxy,\\n address implementation,\\n bytes memory data\\n ) public payable virtual onlyOwner {\\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\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\"\n },\n \"solc_0.8/openzeppelin/proxy/Proxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 overriden 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 internall 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 overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 virtual 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(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\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\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\": {\n \"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\"\n },\n \"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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\"\n },\n \"solc_0.8/openzeppelin/utils/Address.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 functionCall(target, data, \\\"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 require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason 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 // 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\\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}\\n\"\n },\n \"solc_0.8/openzeppelin/utils/StorageSlot.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 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 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 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 assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\"\n },\n \"solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract OptimizedTransparentUpgradeableProxy is ERC1967Proxy {\\n address internal immutable _ADMIN;\\n\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _ADMIN = admin_;\\n\\n // still store it to work with EIP-1967\\n bytes32 slot = _ADMIN_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, admin_)\\n }\\n emit AdminChanged(address(0), admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n\\n function _getAdmin() internal view virtual override returns (address) {\\n return _ADMIN;\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/utils/UUPSUpgradeable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 that the this implementation remains valid after 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\"\n },\n \"solc_0.8/openzeppelin/proxy/utils/Initializable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.0;\\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 * 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 initialize the implementation contract, you can either invoke the\\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() initializer {}\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool 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 Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\\n // contract may have been reentered.\\n require(_initializing ? _isConstructor() : !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} modifier, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n function _isConstructor() private view returns (bool) {\\n return !Address.isContract(address(this));\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/UpgradeableBeacon.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\\n * implementation contract, which is where they will delegate all function calls.\\n *\\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\\n */\\ncontract UpgradeableBeacon is IBeacon, Ownable {\\n address private _implementation;\\n\\n /**\\n * @dev Emitted when the implementation returned by the beacon is changed.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\\n * beacon.\\n */\\n\\n constructor(address implementation_, address initialOwner) Ownable(initialOwner) {\\n _setImplementation(implementation_);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function implementation() public view virtual override returns (address) {\\n return _implementation;\\n }\\n\\n /**\\n * @dev Upgrades the beacon to a new implementation.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * Requirements:\\n *\\n * - msg.sender must be the owner of the contract.\\n * - `newImplementation` must be a contract.\\n */\\n function upgradeTo(address newImplementation) public virtual onlyOwner {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Sets the implementation contract address for this beacon\\n *\\n * Requirements:\\n *\\n * - `newImplementation` must be a contract.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"UpgradeableBeacon: implementation is not a contract\\\");\\n _implementation = newImplementation;\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/BeaconProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"../ERC1967/ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.\\n *\\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\\n * conflict with the storage layout of the implementation behind the proxy.\\n *\\n * _Available since v3.4._\\n */\\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the proxy with `beacon`.\\n *\\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\\n * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity\\n * constructor.\\n *\\n * Requirements:\\n *\\n * - `beacon` must be a contract with the interface {IBeacon}.\\n */\\n constructor(address beacon, bytes memory data) payable {\\n assert(_BEACON_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.beacon\\\")) - 1));\\n _upgradeBeaconToAndCall(beacon, data, false);\\n }\\n\\n /**\\n * @dev Returns the current beacon address.\\n */\\n function _beacon() internal view virtual returns (address) {\\n return _getBeacon();\\n }\\n\\n /**\\n * @dev Returns the current implementation address of the associated beacon.\\n */\\n function _implementation() internal view virtual override returns (address) {\\n return IBeacon(_getBeacon()).implementation();\\n }\\n\\n /**\\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\\n *\\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\\n *\\n * Requirements:\\n *\\n * - `beacon` must be a contract.\\n * - The implementation returned by `beacon` must be a contract.\\n */\\n function _setBeacon(address beacon, bytes memory data) internal virtual {\\n _upgradeBeaconToAndCall(beacon, data, false);\\n }\\n}\\n\"\n }\n },\n \"settings\": {\n \"optimizer\": {\n \"enabled\": true,\n \"runs\": 999999\n },\n \"outputSelection\": {\n \"*\": {\n \"*\": [\n \"abi\",\n \"evm.bytecode\",\n \"evm.deployedBytecode\",\n \"evm.methodIdentifiers\",\n \"metadata\",\n \"devdoc\",\n \"userdoc\",\n \"storageLayout\",\n \"evm.gasEstimates\"\n ],\n \"\": [\n \"ast\"\n ]\n }\n },\n \"metadata\": {\n \"useLiteralContent\": true\n }\n }\n}", + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "argsData": "0x0000000000000000000000002f11596dd12361a13e4d8a48a2e31fad170b0a3400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f8000000000000000000000000000000000000000000000000000000000", + "transaction": { + "hash": "0xcf2aeb70331178ce8c2b304d32e67a54d935cb8f101456697601623011cb2b5b", + "nonce": "0x1e49", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xdc2342dcf0c17e01413593e979ca4f1ae811eb9ef8b328a7824338a2aa7508d0", + "blockNumber": "0xa6a7bb", + "transactionIndex": "0x3b" + }, + "immutableReferences": { + "28949": [ + { + "length": 32, + "start": 1246 + }, + { + "length": 32, + "start": 1287 + }, + { + "length": 32, + "start": 1674 + } + ] + }, + "inputSourceName": "project/src/utils/ContractNamer.sol" +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer_Implementation.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer_Implementation.json new file mode 100644 index 000000000..98a1bc842 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer_Implementation.json @@ -0,0 +1,436 @@ +{ + "address": "0x2f11596dd12361a13e4d8a48a2e31fad170b0a34", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "contractName": "ContractNamer", + "sourceName": "src/utils/ContractNamer.sol", + "bytecode": "0x60a060405230608052348015610013575f5ffd5b5061001c610021565b6100d3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100715760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d05780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b608051610c8e6100f95f395f81816104de01528181610507015261068a0152610c8e5ff3fe608060405260043610610093575f3560e01c8063715018a611610066578063ad3cb1cc1161004c578063ad3cb1cc1461017b578063c4d66de8146101d0578063f2fde38b146101ef575f5ffd5b8063715018a6146101215780638da5cb5b14610135575f5ffd5b806301ffc9a7146100975780634f1ef286146100cb57806352d1902d146100e05780636f3ff72614610102575b5f5ffd5b3480156100a2575f5ffd5b506100b66100b1366004610a92565b61020e565b60405190151581526020015b60405180910390f35b6100de6100d9366004610b19565b6102a6565b005b3480156100eb575f5ffd5b506100f46102c5565b6040519081526020016100c2565b34801561010d575f5ffd5b506100b661011c366004610bdd565b6102f3565b34801561012c575f5ffd5b506100de61033f565b348015610140575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020016100c2565b348015610186575f5ffd5b506101c36040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c29190610bf6565b3480156101db575f5ffd5b506100de6101ea366004610bdd565b610352565b3480156101fa575f5ffd5b506100de610209366004610bdd565b610478565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f6f3ff7260000000000000000000000000000000000000000000000000000000014806102a057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6102ae6104d3565b6102b78261058a565b6102c18282610592565b5050565b5f6102ce61067f565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f816001600160a01b031661032f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161492915050565b6103476106c8565b6103505f61073c565b565b5f61035b6107b9565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156103875750825b90505f8267ffffffffffffffff1660011480156103a35750303b155b9050811580156103b1575080155b156103e8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561041c57845468ff00000000000000001916680100000000000000001785555b610425866107e1565b831561047057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6104806106c8565b6001600160a01b0381166104c7576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d08161073c565b50565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061056c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156103505760405163703e46dd60e11b815260040160405180910390fd5b6104d06106c8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105ec575060408051601f3d908101601f191682019092526105e991810190610c2b565b60015b61061457604051634c9c8ce360e01b81526001600160a01b03831660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610670576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016104be565b61067a83836107f2565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103505760405163703e46dd60e11b815260040160405180910390fd5b336106fa7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610350576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104be565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102a0565b6107e9610847565b6104d081610885565b6107fb8261088d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561083f5761067a8282610910565b6102c1610982565b61084f6109ba565b610350576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610480610847565b806001600160a01b03163b5f036108c257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f5f846001600160a01b03168460405161092c9190610c42565b5f60405180830381855af49150503d805f8114610964576040519150601f19603f3d011682016040523d82523d5f602084013e610969565b606091505b50915091506109798583836109d8565b95945050505050565b3415610350576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6109c36107b9565b5468010000000000000000900460ff16919050565b6060826109ed576109e882610a50565b610a49565b8151158015610a0457506001600160a01b0384163b155b15610a46576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016104be565b50805b9392505050565b805115610a605780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610aa2575f5ffd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a49575f5ffd5b80356001600160a01b0381168114610ae7575f5ffd5b919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f60408385031215610b2a575f5ffd5b610b3383610ad1565b9150602083013567ffffffffffffffff811115610b4e575f5ffd5b8301601f81018513610b5e575f5ffd5b803567ffffffffffffffff811115610b7857610b78610aec565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610ba757610ba7610aec565b604052818152828201602001871015610bbe575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f60208284031215610bed575f5ffd5b610a4982610ad1565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610c3b575f5ffd5b5051919050565b5f82518060208501845e5f92019182525091905056fea26469706673582212204e422766ce5b88ad718a0bff7905c3a04cfae01af85ec46e205355b54064127b64736f6c634300081b0033", + "deployedBytecode": "0x608060405260043610610093575f3560e01c8063715018a611610066578063ad3cb1cc1161004c578063ad3cb1cc1461017b578063c4d66de8146101d0578063f2fde38b146101ef575f5ffd5b8063715018a6146101215780638da5cb5b14610135575f5ffd5b806301ffc9a7146100975780634f1ef286146100cb57806352d1902d146100e05780636f3ff72614610102575b5f5ffd5b3480156100a2575f5ffd5b506100b66100b1366004610a92565b61020e565b60405190151581526020015b60405180910390f35b6100de6100d9366004610b19565b6102a6565b005b3480156100eb575f5ffd5b506100f46102c5565b6040519081526020016100c2565b34801561010d575f5ffd5b506100b661011c366004610bdd565b6102f3565b34801561012c575f5ffd5b506100de61033f565b348015610140575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020016100c2565b348015610186575f5ffd5b506101c36040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c29190610bf6565b3480156101db575f5ffd5b506100de6101ea366004610bdd565b610352565b3480156101fa575f5ffd5b506100de610209366004610bdd565b610478565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f6f3ff7260000000000000000000000000000000000000000000000000000000014806102a057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6102ae6104d3565b6102b78261058a565b6102c18282610592565b5050565b5f6102ce61067f565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f816001600160a01b031661032f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161492915050565b6103476106c8565b6103505f61073c565b565b5f61035b6107b9565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156103875750825b90505f8267ffffffffffffffff1660011480156103a35750303b155b9050811580156103b1575080155b156103e8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561041c57845468ff00000000000000001916680100000000000000001785555b610425866107e1565b831561047057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6104806106c8565b6001600160a01b0381166104c7576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d08161073c565b50565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061056c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156103505760405163703e46dd60e11b815260040160405180910390fd5b6104d06106c8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105ec575060408051601f3d908101601f191682019092526105e991810190610c2b565b60015b61061457604051634c9c8ce360e01b81526001600160a01b03831660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610670576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016104be565b61067a83836107f2565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103505760405163703e46dd60e11b815260040160405180910390fd5b336106fa7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610350576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104be565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102a0565b6107e9610847565b6104d081610885565b6107fb8261088d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561083f5761067a8282610910565b6102c1610982565b61084f6109ba565b610350576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610480610847565b806001600160a01b03163b5f036108c257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f5f846001600160a01b03168460405161092c9190610c42565b5f60405180830381855af49150503d805f8114610964576040519150601f19603f3d011682016040523d82523d5f602084013e610969565b606091505b50915091506109798583836109d8565b95945050505050565b3415610350576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6109c36107b9565b5468010000000000000000900460ff16919050565b6060826109ed576109e882610a50565b610a49565b8151158015610a0457506001600160a01b0384163b155b15610a46576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016104be565b50805b9392505050565b805115610a605780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610aa2575f5ffd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a49575f5ffd5b80356001600160a01b0381168114610ae7575f5ffd5b919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f60408385031215610b2a575f5ffd5b610b3383610ad1565b9150602083013567ffffffffffffffff811115610b4e575f5ffd5b8301601f81018513610b5e575f5ffd5b803567ffffffffffffffff811115610b7857610b78610aec565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610ba757610ba7610aec565b604052818152828201602001871015610bbe575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f60208284031215610bed575f5ffd5b610a4982610ad1565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610c3b575f5ffd5b5051919050565b5f82518060208501845e5f92019182525091905056fea26469706673582212204e422766ce5b88ad718a0bff7905c3a04cfae01af85ec46e205355b54064127b64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "28949": [ + { + "length": 32, + "start": 1246 + }, + { + "length": 32, + "start": 1287 + }, + { + "length": 32, + "start": 1674 + } + ] + }, + "inputSourceName": "project/src/utils/ContractNamer.sol", + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ] + }, + "events": { + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "initialize(address)": { + "params": { + "owner_": "The contract owner." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "642800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "UPGRADE_INTERFACE_VERSION()": "infinite", + "initialize(address)": "infinite", + "isContractNamer(address)": "2609", + "owner()": "2345", + "proxiableUUID()": "infinite", + "renounceOwnership()": "infinite", + "supportsInterface(bytes4)": "367", + "transferOwnership(address)": "28419", + "upgradeToAndCall(address,bytes)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}]},\"events\":{\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"initialize(address)\":{\"params\":{\"owner_\":\"The contract owner.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(address)\":{\"notice\":\"Initialize the contract.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"}},\"notice\":\"Shared `IContractNamer` instance.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/utils/ContractNamer.sol\":\"ContractNamer\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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 OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\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 * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\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 Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\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 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\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 _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\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 // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\\n *\\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\\n */\\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\\n return INITIALIZABLE_STORAGE;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n bytes32 slot = _initializableStorageSlot();\\n assembly {\\n $.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IERC1822Proxiable} from \\\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\\\";\\nimport {Initializable} from \\\"./Initializable.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 */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\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 _checkNotDelegated();\\n _;\\n }\\n\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\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 * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {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 onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: 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\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\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 ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\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 ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.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 the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\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 ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\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 * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, bytes memory returndata) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n _revert(returndata);\\n }\\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 or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) 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 assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/ContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @notice Shared `IContractNamer` instance.\\ncontract ContractNamer is ERC165, OwnableUpgradeable, UUPSUpgradeable, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /// @notice Initialize the contract.\\n /// @param owner_ The contract owner.\\n function initialize(address owner_) external initializer {\\n __Ownable_init(owner_);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return owner() == namer;\\n }\\n\\n /// @dev Allow owner to upgrade.\\n function _authorizeUpgrade(address) internal override onlyOwner {}\\n}\\n\",\"keccak256\":\"0x69dc17485dba9a662c0c577677eb9a06dcfbe1cdb0bc8471f23ae8fc6fcf856f\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": { + "initialize(address)": { + "notice": "Initialize the contract." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + } + }, + "notice": "Shared `IContractNamer` instance.", + "version": 1 + }, + "argsData": "0x", + "transaction": { + "hash": "0x7f8d3c0adafdf0ec9200bd8b916018f0fab72f89d7e0daa3c4ad62ec67d0ec6c", + "nonce": "0x1e48", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xdc2342dcf0c17e01413593e979ca4f1ae811eb9ef8b328a7824338a2aa7508d0", + "blockNumber": "0xa6a7bb", + "transactionIndex": "0x3b" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer_Proxy.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer_Proxy.json new file mode 100644 index 000000000..e59c8a9f2 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ContractNamer_Proxy.json @@ -0,0 +1,128 @@ +{ + "address": "0xfc8bf9234969d6b85729b756fa9e14bb84a06754", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "contractName": "ERC1967Proxy", + "sourceName": "solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol", + "bytecode": "0x608060405260405161084e38038061084e83398101604081905261002291610349565b61004d60017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd610417565b600080516020610807833981519152146100695761006961043c565b6100758282600061007c565b50506104a1565b610085836100b2565b6000825111806100925750805b156100ad576100ab83836100f260201b6100291760201c565b505b505050565b6100bb8161011e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606101178383604051806060016040528060278152602001610827602791396101de565b9392505050565b610131816102bc60201b6100551760201c565b6101985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101bd60008051602061080783398151915260001b6102cb60201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161018f565b600080856001600160a01b0316856040516102619190610452565b600060405180830381855af49150503d806000811461029c576040519150601f19603f3d011682016040523d82523d6000602084013e6102a1565b606091505b5090925090506102b28282866102ce565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102dd575081610117565b8251156102ed5782518084602001fd5b8160405162461bcd60e51b815260040161018f919061046e565b634e487b7160e01b600052604160045260246000fd5b60005b83811015610338578181015183820152602001610320565b838111156100ab5750506000910152565b6000806040838503121561035c57600080fd5b82516001600160a01b038116811461037357600080fd5b60208401519092506001600160401b038082111561039057600080fd5b818501915085601f8301126103a457600080fd5b8151818111156103b6576103b6610307565b604051601f8201601f19908116603f011681019083821181831017156103de576103de610307565b816040528281528860208487010111156103f757600080fd5b61040883602083016020880161031d565b80955050505050509250929050565b60008282101561043757634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825161046481846020870161031d565b9190910192915050565b602081526000825180602084015261048d81604085016020870161031d565b601f01601f19169190910160400192915050565b610357806104b06000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "devdoc": { + "details": "This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "171000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "": "infinite" + }, + "internal": { + "_implementation()": "2144" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":\"ERC1967Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\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\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 virtual 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(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\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\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 overriden 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 internall 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 overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/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\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 functionCall(target, data, \\\"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 require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason 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 // 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\\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}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 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 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 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 assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "solcInput": "{\n \"language\": \"Solidity\",\n \"sources\": {\n \"solc_0.8/openzeppelin/access/Ownable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 (address initialOwner) {\\n _transferOwnership(initialOwner);\\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 _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\"\n },\n \"solc_0.8/openzeppelin/utils/Context.sol\": {\n \"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\"\n },\n \"solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./TransparentUpgradeableProxy.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\n\\n/**\\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\\n */\\ncontract ProxyAdmin is Ownable {\\n\\n constructor (address initialOwner) Ownable(initialOwner) {}\\n\\n /**\\n * @dev Returns the current implementation of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"implementation()\\\")) == 0x5c60da1b\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"5c60da1b\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Returns the current admin of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"admin()\\\")) == 0xf851a440\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"f851a440\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Changes the admin of `proxy` to `newAdmin`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the current admin of `proxy`.\\n */\\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\\n proxy.changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\\n proxy.upgradeTo(implementation);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgradeAndCall(\\n TransparentUpgradeableProxy proxy,\\n address implementation,\\n bytes memory data\\n ) public payable virtual onlyOwner {\\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\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\"\n },\n \"solc_0.8/openzeppelin/proxy/Proxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 overriden 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 internall 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 overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 virtual 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(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\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\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\": {\n \"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\"\n },\n \"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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\"\n },\n \"solc_0.8/openzeppelin/utils/Address.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 functionCall(target, data, \\\"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 require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason 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 // 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\\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}\\n\"\n },\n \"solc_0.8/openzeppelin/utils/StorageSlot.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 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 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 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 assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\"\n },\n \"solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract OptimizedTransparentUpgradeableProxy is ERC1967Proxy {\\n address internal immutable _ADMIN;\\n\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _ADMIN = admin_;\\n\\n // still store it to work with EIP-1967\\n bytes32 slot = _ADMIN_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, admin_)\\n }\\n emit AdminChanged(address(0), admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n\\n function _getAdmin() internal view virtual override returns (address) {\\n return _ADMIN;\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/utils/UUPSUpgradeable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 that the this implementation remains valid after 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\"\n },\n \"solc_0.8/openzeppelin/proxy/utils/Initializable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.0;\\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 * 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 initialize the implementation contract, you can either invoke the\\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() initializer {}\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool 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 Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\\n // contract may have been reentered.\\n require(_initializing ? _isConstructor() : !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} modifier, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n function _isConstructor() private view returns (bool) {\\n return !Address.isContract(address(this));\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/UpgradeableBeacon.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\\n * implementation contract, which is where they will delegate all function calls.\\n *\\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\\n */\\ncontract UpgradeableBeacon is IBeacon, Ownable {\\n address private _implementation;\\n\\n /**\\n * @dev Emitted when the implementation returned by the beacon is changed.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\\n * beacon.\\n */\\n\\n constructor(address implementation_, address initialOwner) Ownable(initialOwner) {\\n _setImplementation(implementation_);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function implementation() public view virtual override returns (address) {\\n return _implementation;\\n }\\n\\n /**\\n * @dev Upgrades the beacon to a new implementation.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * Requirements:\\n *\\n * - msg.sender must be the owner of the contract.\\n * - `newImplementation` must be a contract.\\n */\\n function upgradeTo(address newImplementation) public virtual onlyOwner {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Sets the implementation contract address for this beacon\\n *\\n * Requirements:\\n *\\n * - `newImplementation` must be a contract.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"UpgradeableBeacon: implementation is not a contract\\\");\\n _implementation = newImplementation;\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/BeaconProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"../ERC1967/ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.\\n *\\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\\n * conflict with the storage layout of the implementation behind the proxy.\\n *\\n * _Available since v3.4._\\n */\\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the proxy with `beacon`.\\n *\\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\\n * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity\\n * constructor.\\n *\\n * Requirements:\\n *\\n * - `beacon` must be a contract with the interface {IBeacon}.\\n */\\n constructor(address beacon, bytes memory data) payable {\\n assert(_BEACON_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.beacon\\\")) - 1));\\n _upgradeBeaconToAndCall(beacon, data, false);\\n }\\n\\n /**\\n * @dev Returns the current beacon address.\\n */\\n function _beacon() internal view virtual returns (address) {\\n return _getBeacon();\\n }\\n\\n /**\\n * @dev Returns the current implementation address of the associated beacon.\\n */\\n function _implementation() internal view virtual override returns (address) {\\n return IBeacon(_getBeacon()).implementation();\\n }\\n\\n /**\\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\\n *\\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\\n *\\n * Requirements:\\n *\\n * - `beacon` must be a contract.\\n * - The implementation returned by `beacon` must be a contract.\\n */\\n function _setBeacon(address beacon, bytes memory data) internal virtual {\\n _upgradeBeaconToAndCall(beacon, data, false);\\n }\\n}\\n\"\n }\n },\n \"settings\": {\n \"optimizer\": {\n \"enabled\": true,\n \"runs\": 999999\n },\n \"outputSelection\": {\n \"*\": {\n \"*\": [\n \"abi\",\n \"evm.bytecode\",\n \"evm.deployedBytecode\",\n \"evm.methodIdentifiers\",\n \"metadata\",\n \"devdoc\",\n \"userdoc\",\n \"storageLayout\",\n \"evm.gasEstimates\"\n ],\n \"\": [\n \"ast\"\n ]\n }\n },\n \"metadata\": {\n \"useLiteralContent\": true\n }\n }\n}", + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "argsData": "0x0000000000000000000000002f11596dd12361a13e4d8a48a2e31fad170b0a3400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f8000000000000000000000000000000000000000000000000000000000", + "transaction": { + "hash": "0xcf2aeb70331178ce8c2b304d32e67a54d935cb8f101456697601623011cb2b5b", + "nonce": "0x1e49", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x8bce5b7555d62f9ef902af51c0acc25898badd5b97633e526ba8df27de8363b5", + "blockNumber": "0xa6a7bc", + "transactionIndex": "0x5e" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/DNSV1MirrorRootBatchRegistrar.json b/contracts/deployments/sepolia-official-v1-20260525-r2/DNSV1MirrorRootBatchRegistrar.json new file mode 100644 index 000000000..f72b7f327 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/DNSV1MirrorRootBatchRegistrar.json @@ -0,0 +1,282 @@ +{ + "address": "0x9c53569d0c545a6743d6073a081acb977154eaf9", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry_", + "type": "address" + }, + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InputLengthMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "string[]", + "name": "labels", + "type": "string[]" + }, + { + "internalType": "uint64[]", + "name": "expires", + "type": "uint64[]" + } + ], + "name": "batchRegister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "BatchRegistrar", + "sourceName": "src/registrar/BatchRegistrar.sol", + "bytecode": "0x60a060405234801561000f575f5ffd5b506040516109e53803806109e583398101604081905261002e916100de565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006581610078565b50506001600160a01b0316608052610116565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146100db575f5ffd5b50565b5f5f604083850312156100ef575f5ffd5b82516100fa816100c7565b602084015190925061010b816100c7565b809150509250929050565b6080516108a36101425f395f818160820152818161013901528181610240015261038a01526108a35ff3fe608060405234801561000f575f5ffd5b5060043610610064575f3560e01c8063715018a61161004d578063715018a6146100c05780638da5cb5b146100c8578063f2fde38b146100d8575f5ffd5b8063087be49f14610068578063475007081461007d575b5f5ffd5b61007b6100763660046105ea565b6100eb565b005b6100a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61007b610469565b5f546001600160a01b03166100a4565b61007b6100e636600461067e565b61047c565b6100f36104d7565b82811461012c576040517faaad13f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b83811015610460575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286101c688888681811061017b5761017b6106a0565b905060200281019061018d91906106b4565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061051c92505050565b6040518263ffffffff1660e01b81526004016101e491815260200190565b60a060405180830381865afa1580156101ff573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610735565b90505f81516002811115610239576102396107c3565b03610324577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f3e64387878581811061027f5761027f6106a0565b905060200281019061029191906106b4565b5f8c8c5f8b8b8b8181106102a7576102a76106a0565b90506020020160208101906102bc91906107d7565b6040518863ffffffff1660e01b81526004016102de97969594939291906107f2565b6020604051808303815f875af11580156102fa573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610856565b50610457565b600181516002811115610339576103396107c3565b1480156103835750806020015167ffffffffffffffff16848484818110610362576103626106a0565b905060200201602081019061037791906107d7565b67ffffffffffffffff16115b15610457577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635569f33d82606001518686868181106103ce576103ce6106a0565b90506020020160208101906103e391906107d7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925267ffffffffffffffff1660248201526044015f604051808303815f87803b158015610440575f5ffd5b505af1158015610452573d5f5f3e3d5ffd5b505050505b5060010161012e565b50505050505050565b6104716104d7565b61047a5f610527565b565b6104846104d7565b6001600160a01b0381166104cb576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d481610527565b50565b5f546001600160a01b0316331461047a576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104c2565b805160209091012090565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146104d4575f5ffd5b5f5f83601f8401126105b2575f5ffd5b50813567ffffffffffffffff8111156105c9575f5ffd5b6020830191508360208260051b85010111156105e3575f5ffd5b9250929050565b5f5f5f5f5f5f608087890312156105ff575f5ffd5b863561060a8161058e565b9550602087013561061a8161058e565b9450604087013567ffffffffffffffff811115610635575f5ffd5b61064189828a016105a2565b909550935050606087013567ffffffffffffffff811115610660575f5ffd5b61066c89828a016105a2565b979a9699509497509295939492505050565b5f6020828403121561068e575f5ffd5b81356106998161058e565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e198436030181126106c9575f5ffd5b83018035915067ffffffffffffffff8211156106e3575f5ffd5b6020019150368190038213156105e3575f5ffd5b805160038110610705575f5ffd5b919050565b67ffffffffffffffff811681146104d4575f5ffd5b80516107058161070a565b80516107058161058e565b5f60a0828403128015610746575f5ffd5b5060405160a0810167ffffffffffffffff8111828210171561077657634e487b7160e01b5f52604160045260245ffd5b604052610782836106f7565b81526107906020840161071f565b60208201526107a16040840161072a565b6040820152606083810151908201526080928301519281019290925250919050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156107e7575f5ffd5b81356106998161070a565b60c081528660c0820152868860e08301375f60e08883018101919091526001600160a01b0396871660208301529486166040820152929094166060830152608082015267ffffffffffffffff90921660a0830152601f909201601f19160101919050565b5f60208284031215610866575f5ffd5b505191905056fea2646970667358221220634a2efe5cac7c21eb3b64088dd3aa06d978ce9f20c62d54ca652ad4a858f0bf64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610064575f3560e01c8063715018a61161004d578063715018a6146100c05780638da5cb5b146100c8578063f2fde38b146100d8575f5ffd5b8063087be49f14610068578063475007081461007d575b5f5ffd5b61007b6100763660046105ea565b6100eb565b005b6100a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61007b610469565b5f546001600160a01b03166100a4565b61007b6100e636600461067e565b61047c565b6100f36104d7565b82811461012c576040517faaad13f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b83811015610460575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286101c688888681811061017b5761017b6106a0565b905060200281019061018d91906106b4565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061051c92505050565b6040518263ffffffff1660e01b81526004016101e491815260200190565b60a060405180830381865afa1580156101ff573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610735565b90505f81516002811115610239576102396107c3565b03610324577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f3e64387878581811061027f5761027f6106a0565b905060200281019061029191906106b4565b5f8c8c5f8b8b8b8181106102a7576102a76106a0565b90506020020160208101906102bc91906107d7565b6040518863ffffffff1660e01b81526004016102de97969594939291906107f2565b6020604051808303815f875af11580156102fa573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610856565b50610457565b600181516002811115610339576103396107c3565b1480156103835750806020015167ffffffffffffffff16848484818110610362576103626106a0565b905060200201602081019061037791906107d7565b67ffffffffffffffff16115b15610457577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635569f33d82606001518686868181106103ce576103ce6106a0565b90506020020160208101906103e391906107d7565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925267ffffffffffffffff1660248201526044015f604051808303815f87803b158015610440575f5ffd5b505af1158015610452573d5f5f3e3d5ffd5b505050505b5060010161012e565b50505050505050565b6104716104d7565b61047a5f610527565b565b6104846104d7565b6001600160a01b0381166104cb576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d481610527565b50565b5f546001600160a01b0316331461047a576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104c2565b805160209091012090565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146104d4575f5ffd5b5f5f83601f8401126105b2575f5ffd5b50813567ffffffffffffffff8111156105c9575f5ffd5b6020830191508360208260051b85010111156105e3575f5ffd5b9250929050565b5f5f5f5f5f5f608087890312156105ff575f5ffd5b863561060a8161058e565b9550602087013561061a8161058e565b9450604087013567ffffffffffffffff811115610635575f5ffd5b61064189828a016105a2565b909550935050606087013567ffffffffffffffff811115610660575f5ffd5b61066c89828a016105a2565b979a9699509497509295939492505050565b5f6020828403121561068e575f5ffd5b81356106998161058e565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e198436030181126106c9575f5ffd5b83018035915067ffffffffffffffff8211156106e3575f5ffd5b6020019150368190038213156105e3575f5ffd5b805160038110610705575f5ffd5b919050565b67ffffffffffffffff811681146104d4575f5ffd5b80516107058161070a565b80516107058161058e565b5f60a0828403128015610746575f5ffd5b5060405160a0810167ffffffffffffffff8111828210171561077657634e487b7160e01b5f52604160045260245ffd5b604052610782836106f7565b81526107906020840161071f565b60208201526107a16040840161072a565b6040820152606083810151908201526080928301519281019290925250919050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156107e7575f5ffd5b81356106998161070a565b60c081528660c0820152868860e08301375f60e08883018101919091526001600160a01b0396871660208301529486166040820152929094166060830152608082015267ffffffffffffffff90921660a0830152601f909201601f19160101919050565b5f60208284031215610866575f5ffd5b505191905056fea2646970667358221220634a2efe5cac7c21eb3b64088dd3aa06d978ce9f20c62d54ca652ad4a858f0bf64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "63803": [ + { + "length": 32, + "start": 130 + }, + { + "length": 32, + "start": 313 + }, + { + "length": 32, + "start": 576 + }, + { + "length": 32, + "start": 906 + } + ] + }, + "inputSourceName": "project/src/registrar/BatchRegistrar.sol", + "devdoc": { + "errors": { + "InputLengthMismatch()": [ + { + "details": "Error selector: `0xaaad13f7`" + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "kind": "dev", + "methods": { + "batchRegister(address,address,string[],uint64[])": { + "params": { + "expires": "Array of expiry timestamps corresponding to each label", + "labels": "Array of labels to reserve or renew", + "registry": "The registry for all names", + "resolver": "The resolver for all names" + } + }, + "constructor": { + "params": { + "ethRegistry_": "The ETH registry to use for batch registration.", + "owner_": "The owner of the contract." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "title": "BatchRegistrar", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "442200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ETH_REGISTRY()": "infinite", + "batchRegister(address,address,string[],uint64[])": "infinite", + "owner()": "2339", + "renounceOwnership()": "infinite", + "transferOwnership(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InputLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"labels\",\"type\":\"string[]\"},{\"internalType\":\"uint64[]\",\"name\":\"expires\",\"type\":\"uint64[]\"}],\"name\":\"batchRegister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InputLengthMismatch()\":[{\"details\":\"Error selector: `0xaaad13f7`\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"kind\":\"dev\",\"methods\":{\"batchRegister(address,address,string[],uint64[])\":{\"params\":{\"expires\":\"Array of expiry timestamps corresponding to each label\",\"labels\":\"Array of labels to reserve or renew\",\"registry\":\"The registry for all names\",\"resolver\":\"The resolver for all names\"}},\"constructor\":{\"params\":{\"ethRegistry_\":\"The ETH registry to use for batch registration.\",\"owner_\":\"The owner of the contract.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"BatchRegistrar\",\"version\":1},\"userdoc\":{\"errors\":{\"InputLengthMismatch()\":[{\"notice\":\"Thrown when batch registration inputs have different lengths.\"}]},\"kind\":\"user\",\"methods\":{\"ETH_REGISTRY()\":{\"notice\":\"The ETH registry to use for batch registration.\"},\"batchRegister(address,address,string[],uint64[])\":{\"notice\":\"Batch reserve or renew names for pre-migration\"}},\"notice\":\"Simple batch registration contract for pre-migration of ENS names. Only the owner can invoke batch registration.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/BatchRegistrar.sol\":\"BatchRegistrar\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registrar/BatchRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\n/// @title BatchRegistrar\\n/// @notice Simple batch registration contract for pre-migration of ENS names.\\n/// Only the owner can invoke batch registration.\\ncontract BatchRegistrar is Ownable {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ETH registry to use for batch registration.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Thrown when batch registration inputs have different lengths.\\n /// @dev Error selector: `0xaaad13f7`\\n error InputLengthMismatch();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param ethRegistry_ The ETH registry to use for batch registration.\\n /// @param owner_ The owner of the contract.\\n constructor(IPermissionedRegistry ethRegistry_, address owner_) Ownable(owner_) {\\n ETH_REGISTRY = ethRegistry_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Batch reserve or renew names for pre-migration\\n /// @param registry The registry for all names\\n /// @param resolver The resolver for all names\\n /// @param labels Array of labels to reserve or renew\\n /// @param expires Array of expiry timestamps corresponding to each label\\n function batchRegister(\\n IRegistry registry,\\n address resolver,\\n string[] calldata labels,\\n uint64[] calldata expires\\n )\\n external\\n onlyOwner\\n {\\n if (labels.length != expires.length) {\\n revert InputLengthMismatch();\\n }\\n\\n for (uint256 i = 0; i < labels.length; i++) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(labels[i]));\\n\\n if (state.status == IPermissionedRegistry.Status.AVAILABLE) {\\n ETH_REGISTRY.register(labels[i], address(0), registry, resolver, 0, expires[i]);\\n } else if (\\n state.status == IPermissionedRegistry.Status.RESERVED && expires[i] > state.expiry\\n ) {\\n ETH_REGISTRY.renew(state.tokenId, expires[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x500267938ff1c4abbf7fcb0155e65759a672e0d12c16217290e1c38fca25d6fd\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 34237, + "contract": "project/src/registrar/BatchRegistrar.sol:BatchRegistrar", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + }, + "userdoc": { + "errors": { + "InputLengthMismatch()": [ + { + "notice": "Thrown when batch registration inputs have different lengths." + } + ] + }, + "kind": "user", + "methods": { + "ETH_REGISTRY()": { + "notice": "The ETH registry to use for batch registration." + }, + "batchRegister(address,address,string[],uint64[])": { + "notice": "Batch reserve or renew names for pre-migration" + } + }, + "notice": "Simple batch registration contract for pre-migration of ENS names. Only the owner can invoke batch registration.", + "version": 1 + }, + "argsData": "0x000000000000000000000000c960f7217d3643b525ef36bec8adf86953cd9ab8000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80", + "transaction": { + "hash": "0x0ba1d7bcf8d76ec0ffb531329d18054ab1727fc348cf0abddb26588ea245c59f", + "nonce": "0x1e53", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x481b7a7460b9536d2b0bedda7d2f46db1b57fe9e647c19d7182a251e001dce0b", + "blockNumber": "0xa6a7c7", + "transactionIndex": "0x45" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ENSV1Resolver.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ENSV1Resolver.json new file mode 100644 index 000000000..4f85f4f8e --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ENSV1Resolver.json @@ -0,0 +1,738 @@ +{ + "address": "0x422484c2d51f92830bfb563fa5e172aa2d8b884b", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "batchGatewayProvider", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + }, + { + "internalType": "contract ENS", + "name": "registryV1", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBatchGatewayResponse", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "UnreachableName", + "type": "error" + }, + { + "inputs": [], + "name": "BATCH_GATEWAY_PROVIDER", + "outputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REGISTRY_V1", + "outputs": [ + { + "internalType": "contract ENS", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "hasContext", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "batchGateways", + "type": "string[]" + } + ], + "name": "callResolver", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "name": "ccipBatch", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipBatchCallback", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipReadCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveBatchCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "resolveDirectImmediateCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feature", + "type": "bytes4" + } + ], + "name": "supportsFeature", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "ENSV1Resolver", + "sourceName": "src/resolver/ENSV1Resolver.sol", + "bytecode": "0x610100604052348015610010575f5ffd5b50604051612b63380380612b6383398101604081905261002f91610069565b61c3506080526001600160a01b0391821660a05291811660c0521660e0526100b3565b6001600160a01b0381168114610066575f5ffd5b50565b5f5f5f6060848603121561007b575f5ffd5b835161008681610052565b602085015190935061009781610052565b60408501519092506100a881610052565b809150509250925092565b60805160a05160c05160e051612a686100fb5f395f818161023d0152610f6201525f8181610199015261054201525f8181610116015261042101525f61100c0152612a685ff3fe608060405234801561000f575f5ffd5b50600436106100e5575f3560e01c80639061b92311610088578063e370ecbe11610063578063e370ecbe14610238578063eea330f91461025f578063ef46c0b814610291578063f394443a146102a6575f5ffd5b80639061b923146101f25780639f28e99d14610205578063b536af7614610225575f5ffd5b8063582de3e7116100c3578063582de3e7146101705780636ccb8660146101945780636d6dd540146101bb5780636f3ff726146101df575f5ffd5b806301ffc9a7146100e957806348ee1bcc14610111578063491fc4f914610150575b5f5ffd5b6100fc6100f7366004611a22565b6102b9565b60405190151581526020015b60405180910390f35b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610108565b61016361015e366004611a7b565b610332565b6040516101089190611b15565b6100fc61017e366004611a22565b6001600160e01b0319166312d6c5b760e31b1490565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101d16101c9366004611a7b565b509192909150565b604051610108929190611b27565b6100fc6101ed366004611b79565b610400565b610163610200366004611a7b565b61048c565b610218610213366004611d87565b6105bb565b6040516101089190611f74565b610218610233366004611a7b565b61077c565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b61027261026d36600461203a565b6109cb565b604080516001600160a01b039093168352901515602083015201610108565b6102a461029f366004612079565b6109e4565b005b6101636102b43660046120f6565b610a69565b5f639061b92360e01b6001600160e01b03198316148061030257507feea330f9000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b8061031d575063582de3e760e01b6001600160e01b03198316145b8061032c575061032c82610da0565b92915050565b60605f61034185870187611d87565b5190505f80610352858701876121ce565b91509150811561038f576103668382610dd4565b6040516020016103769190612205565b60405160208183030381529060405293505050506103f8565b5f835f815181106103a2576103a2612268565b60209081029190910101516040810151606082015191925090600e16156103cb57805160208201fd5b82156103e857808060200190518101906103e591906122d0565b90505b94506103f89350505050565b5050505b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610468573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032c9190612302565b60606105b261049b8686610f5c565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f9201829052506040805160208101825282815281517f093a86d3000000000000000000000000000000000000000000000000000000008152915192955093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063093a86d391600480830192879291908290030181865afa15801561058b573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526102b491908101906123af565b50949350505050565b60408051808201909152606080825260208201525f5b82515181101561076e575f835f015182815181106105f1576105f1612268565b6020026020010151905060408160600151165f1461060f5750610766565b60608101516030165f036106b9575f61062a825f0151610fc6565b610635576010610638565b60205b9050825b8551518110156106b657825f01516001600160a01b0316865f0151828151811061066857610668612268565b60200260200101515f01516001600160a01b0316036106ae5781865f0151828151811061069757610697612268565b602002602001015160600181815117915081815250505b60010161063c565b50505b5f60208260600151165f1490505f5f6106db8315855f01518660200151610ff8565b91509150811580156107055750630556f18360e41b6106f9826123e1565b6001600160e01b031916145b1561071a57606084018051600117905261075a565b606084018051604017905282801561073157508051155b61074657816107465760608401805160021790525b80515f0361075a5760608401805160081790525b60409093019290925250505b6001016105d1565b506107788261108b565b5090565b60408051808201909152606080825260208201525f8061079e8688018861249c565b9150915080518251146107c45760405163252e18f560e11b815260040160405180910390fd5b6107d084860186611d87565b92505f5f5b8451518110156109a0575f855f015182815181106107f5576107f5612268565b6020026020010151905060408160600151165f0361099757835183101561098b575f84848151811061082957610829612268565b6020026020010151905085848151811061084557610845612268565b602002602001015115610862576060820180516044179052610985565b5f6108708360400151611276565b90505f815f01516001600160a01b0316826060015184846080015160405160240161089c929190612557565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516108da9190612592565b5f60405180830381855afa9150503d805f8114610912576040519150601f19603f3d011682016040523d82523d5f602084013e610917565b606091505b509350905080806109415750630556f18360e41b610934846123e1565b6001600160e01b03191614155b1561098257606084018051604017905280158061095d57508251155b1561096e5760608401805160021790525b82515f036109825760608401805160081790525b50505b60408201525b610994836125b1565b92505b506001016107d5565b50815181146109c25760405163252e18f560e11b815260040160405180910390fd5b6103f48461108b565b5f5f6109d78484610f5c565b5f915091505b9250929050565b5f818060200190518101906109f991906125df565b9050610a64815f01518260200151858460400151604051602401610a1e929190612557565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a08601516112ba565b505050565b6060866001600160a01b03163b5f03610ab957856040517f5fe9a5df000000000000000000000000000000000000000000000000000000008152600401610ab09190611b15565b60405180910390fd5b5f7fac9650d800000000000000000000000000000000000000000000000000000000610ae4876123e1565b6001600160e01b0319161490505f858015610b0b5750610b0b8963477cc53f60e11b61147d565b90505f8180610b265750610b268a639061b92360e01b61147d565b9050610b398a63582de3e760e01b61147d565b8015610bbd5750821580610bbd5750808015610bbd575060405163582de3e760e01b81526312d6c5b760e31b60048201526001600160a01b038b169063582de3e790602401602060405180830381865afa158015610b99573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bbd9190612302565b15610c07578015610be257610bdd8a610bd8848c8c8b611503565b611595565b610c07565b610c078a89636d6dd54060e01b5f60e01b60405180602001604052805f8152506112ba565b60608315610c4157610c27896004808c51610c2291906126ba565b6115ba565b806020019051810190610c3a91906126cd565b9050610c8c565b60408051600180825281830190925290816020015b6060815260200190600190039081610c5657905050905088815f81518110610c8057610c80612268565b60200260200101819052505b8115610ce9575f5b8151811015610ce757610cc2848c848481518110610cb457610cb4612268565b60200260200101518b611503565b828281518110610cd457610cd4612268565b6020908102919091010152600101610c94565b505b610d923080639f28e99d610cfe8f868c611616565b604051602401610d0e9190611f74565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b94909417909352519092507f491fc4f900000000000000000000000000000000000000000000000000000000915f91610d7e918b918a910191151582521515602082015260400190565b6040516020818303038152906040526112ba565b505050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b148061032c57506301ffc9a760e01b6001600160e01b031983161461032c565b6060825167ffffffffffffffff811115610df057610df0611b94565b604051908082528060200260200182016040528015610e2357816020015b6060815260200190600190039081610e0e5790505b5090505f5b8351811015610f55575f848281518110610e4457610e44612268565b60209081029190910101516040810151606082015191925090600e165f03610e88578415610e835780806020019051810190610e8091906122d0565b90505b610f2d565b805115610f2d578051601f1660048114610f2b575f60048210610eb557610eb06004836126ba565b610ec0565b610ec08260046126ba565b67ffffffffffffffff811115610ed857610ed8611b94565b6040519080825280601f01601f191660200182016040528015610f02576020820181803683370190505b5090508281604051602001610f1892919061277e565b6040516020818303038152906040529250505b505b80848481518110610f4057610f40612268565b60209081029190910101525050600101610e28565b5092915050565b5f610fbc7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920182905250925061172b915050565b5090949350505050565b5f306001600160a01b03831603610fdf57506001919050565b6113885a5f5f5f5f8786fa50815a909103109392505050565b5f6060836001600160a01b031685611030577f0000000000000000000000000000000000000000000000000000000000000000611032565b5a5b846040516110409190612592565b5f604051808303818686fa925050503d805f8114611079576040519150601f19603f3d011682016040523d82523d5f602084013e61107e565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff8111156110a8576110a8611b94565b60405190808252806020026020018201604052801561110557816020015b6110f260405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816110c65790505b5090505f5f5b8351518110156111b6575f845f0151828151811061112b5761112b612268565b6020026020010151905060408160600151165f036111ad575f6111518260400151611276565b90506040518060600160405280825f01516001600160a01b0316815260200182602001518152602001826040015181525085858061118e906125b1565b9650815181106111a0576111a0612268565b6020026020010181905250505b5060010161110b565b508015610a6457808252308360200151836040516024016111d79190612792565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af76000000000000000000000000000000000000000000000000000000009161124b91899101611f74565b60408051601f1981840301815290829052630556f18360e41b8252610ab09594939291600401612823565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915261032c6112b5836004808651610c2291906126ba565b611827565b5f5f6112cf6112c888610fc6565b8888610ff8565b91509150811580156112f95750630556f18360e41b6112ed826123e1565b6001600160e01b031916145b156113a7575f61130882611276565b9050876001600160a01b0316815f01516001600160a01b0316036113a557308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b03191681526020018981525060405160200161124b9190612886565b505b5f826113b357846113b5565b855b90506001600160e01b031981161561146757306001600160a01b03168183866040516024016113e5929190612557565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114239190612592565b5f60405180830381855afa9150503d805f811461145b576040519150601f19603f3d011682016040523d82523d5f602084013e611460565b606091505b5090935091505b821561147557815160208301f35b815160208301fd5b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f5190508280156114ed575060208210155b80156114f857505f81115b979650505050505050565b60608461154c57838360405160240161151d929190612557565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b17905261158c565b8383836040516024016115619392919061290d565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b1790525b95945050505050565b6115b682825f60e01b5f60e01b60405180602001604052805f8152506112ba565b5050565b60608167ffffffffffffffff8111156115d5576115d5611b94565b6040519080825280601f01601f1916602001820160405280156115ff576020820181803683370190505b50905061160f8484835f86611892565b9392505050565b60408051808201909152606080825260208201525f835167ffffffffffffffff81111561164557611645611b94565b6040519080825280602002602001820160405280156116a857816020015b61169560405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b8152602001906001900390816116635790505b5090505f5b845181101561170e575f8282815181106116c9576116c9612268565b60209081029190910101516001600160a01b038816815286519091508690839081106116f7576116f7612268565b6020908102919091018101519101526001016116ad565b506040805180820190915290815260208101929092525092915050565b5f5f5f5f5f61173a87876118cf565b9092509050811561181b575f5f5f6117538b8b8661172b565b92509250925061176c82865f9182526020526040902090565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018290529097506001600160a01b038c1690630178b8bf90602401602060405180830381865afa1580156117cb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117ef919061294f565b97506001600160a01b0388166118075782878261180b565b87878a5b975097509750505050505061181e565b50505b93509350939050565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915281806020019051810190611864919061296a565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6118a5856118a08387612a1f565b6118fc565b6118b3836118a08385612a1f565b6118c882602085010185602088010183611944565b5050505050565b5f5f5f6118dc858561198d565b9250905060ff8116156118f457806021858701012092505b509250929050565b81518111156115b65781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610ab0918391600401918252602082015260400190565b5b601f811115611965578151835260209283019290910190601f1901611945565b8015610a645790518251600160209390930360031b9290921b5f190180199091169116179052565b5f5f835183106119b2578360405163ba4adc2360e01b8152600401610ab09190611b15565b8383815181106119c4576119c4612268565b016020015160f81c915050818101600101816119e45783518114156119ea565b83518110155b156109dd578360405163ba4adc2360e01b8152600401610ab09190611b15565b6001600160e01b031981168114611a1f575f5ffd5b50565b5f60208284031215611a32575f5ffd5b813561160f81611a0a565b5f5f83601f840112611a4d575f5ffd5b50813567ffffffffffffffff811115611a64575f5ffd5b6020830191508360208285010111156109dd575f5ffd5b5f5f5f5f60408587031215611a8e575f5ffd5b843567ffffffffffffffff811115611aa4575f5ffd5b611ab087828801611a3d565b909550935050602085013567ffffffffffffffff811115611acf575f5ffd5b611adb87828801611a3d565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61160f6020830184611ae7565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b6001600160a01b0381168114611a1f575f5ffd5b8035611b7481611b55565b919050565b5f60208284031215611b89575f5ffd5b813561160f81611b55565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611bcb57611bcb611b94565b60405290565b6040516080810167ffffffffffffffff81118282101715611bcb57611bcb611b94565b60405160c0810167ffffffffffffffff81118282101715611bcb57611bcb611b94565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c4057611c40611b94565b604052919050565b5f67ffffffffffffffff821115611c6157611c61611b94565b5060051b60200190565b5f67ffffffffffffffff821115611c8457611c84611b94565b50601f01601f191660200190565b5f611ca4611c9f84611c6b565b611c17565b9050828152838383011115611cb7575f5ffd5b828260208301375f602084830101529392505050565b5f82601f830112611cdc575f5ffd5b61160f83833560208501611c92565b5f82601f830112611cfa575f5ffd5b8135611d08611c9f82611c48565b8082825260208201915060208360051b860101925085831115611d29575f5ffd5b602085015b83811015611d7d57803567ffffffffffffffff811115611d4c575f5ffd5b8601603f81018813611d5c575f5ffd5b611d6e88602083013560408401611c92565b84525060209283019201611d2e565b5095945050505050565b5f60208284031215611d97575f5ffd5b813567ffffffffffffffff811115611dad575f5ffd5b820160408185031215611dbe575f5ffd5b611dc6611ba8565b813567ffffffffffffffff811115611ddc575f5ffd5b8201601f81018613611dec575f5ffd5b8035611dfa611c9f82611c48565b8082825260208201915060208360051b850101925088831115611e1b575f5ffd5b602084015b83811015611ee157803567ffffffffffffffff811115611e3e575f5ffd5b85016080818c03601f19011215611e53575f5ffd5b611e5b611bd1565b6020820135611e6981611b55565b8152604082013567ffffffffffffffff811115611e84575f5ffd5b611e938d602083860101611ccd565b602083015250606082013567ffffffffffffffff811115611eb2575f5ffd5b611ec18d602083860101611ccd565b604083015250608091909101356060820152835260209283019201611e20565b508452505050602082013567ffffffffffffffff811115611f00575f5ffd5b611f0c86828501611ceb565b602083015250949350505050565b5f82825180855260208501945060208160051b830101602085015f5b83811015611f6857601f19858403018852611f52838351611ae7565b6020988901989093509190910190600101611f36565b50909695505050505050565b602081525f6060820183516040602085015281815180845260808601915060808160051b87010193506020830192505f5b8181101561201b57607f1987860301835283516001600160a01b038151168652602081015160806020880152611fde6080880182611ae7565b905060408201518782036040890152611ff78282611ae7565b60609384015198909301979097525094506020938401939290920191600101611fa5565b505050506020840151838203601f1901604085015261158c8282611f1a565b5f5f6020838503121561204b575f5ffd5b823567ffffffffffffffff811115612061575f5ffd5b61206d85828601611a3d565b90969095509350505050565b5f5f6040838503121561208a575f5ffd5b823567ffffffffffffffff8111156120a0575f5ffd5b6120ac85828601611ccd565b925050602083013567ffffffffffffffff8111156120c8575f5ffd5b6120d485828601611ccd565b9150509250929050565b8015158114611a1f575f5ffd5b8035611b74816120de565b5f5f5f5f5f5f60c0878903121561210b575f5ffd5b61211487611b69565b9550602087013567ffffffffffffffff81111561212f575f5ffd5b61213b89828a01611ccd565b955050604087013567ffffffffffffffff811115612157575f5ffd5b61216389828a01611ccd565b945050612172606088016120eb565b9250608087013567ffffffffffffffff81111561218d575f5ffd5b61219989828a01611ccd565b92505060a087013567ffffffffffffffff8111156121b5575f5ffd5b6121c189828a01611ceb565b9150509295509295509295565b5f5f604083850312156121df575f5ffd5b82356121ea816120de565b915060208301356121fa816120de565b809150509250929050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561225c57603f19878603018452612247858351611ae7565b9450602093840193919091019060010161222b565b50929695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f612289611c9f84611c6b565b905082815283838301111561229c575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f8301126122c1575f5ffd5b61160f8383516020850161227c565b5f602082840312156122e0575f5ffd5b815167ffffffffffffffff8111156122f6575f5ffd5b6103f8848285016122b2565b5f60208284031215612312575f5ffd5b815161160f816120de565b5f82601f83011261232c575f5ffd5b815161233a611c9f82611c48565b8082825260208201915060208360051b86010192508583111561235b575f5ffd5b602085015b83811015611d7d57805167ffffffffffffffff81111561237e575f5ffd5b8601603f8101881361238e575f5ffd5b6123a08860208301516040840161227c565b84525060209283019201612360565b5f602082840312156123bf575f5ffd5b815167ffffffffffffffff8111156123d5575f5ffd5b6103f88482850161231d565b805160208201516001600160e01b0319811691906004821015612416576001600160e01b0319808360040360031b1b82161692505b5050919050565b5f82601f83011261242c575f5ffd5b813561243a611c9f82611c48565b8082825260208201915060208360051b86010192508583111561245b575f5ffd5b602085015b83811015611d7d57803567ffffffffffffffff81111561247e575f5ffd5b61248d886020838a0101611ccd565b84525060209283019201612460565b5f5f604083850312156124ad575f5ffd5b823567ffffffffffffffff8111156124c3575f5ffd5b8301601f810185136124d3575f5ffd5b80356124e1611c9f82611c48565b8082825260208201915060208360051b850101925087831115612502575f5ffd5b6020840193505b8284101561252d57833561251c816120de565b825260209384019390910190612509565b9450505050602083013567ffffffffffffffff81111561254b575f5ffd5b6120d48582860161241d565b604081525f6125696040830185611ae7565b828103602084015261158c8185611ae7565b5f81518060208401855e5f93019283525090919050565b5f61160f828461257b565b634e487b7160e01b5f52601160045260245ffd5b5f600182016125c2576125c261259d565b5060010190565b8051611b7481611b55565b8051611b7481611a0a565b5f602082840312156125ef575f5ffd5b815167ffffffffffffffff811115612605575f5ffd5b820160c08185031215612616575f5ffd5b61261e611bf4565b612627826125c9565b8152612635602083016125d4565b6020820152604082015167ffffffffffffffff811115612653575f5ffd5b61265f868285016122b2565b604083015250612671606083016125d4565b6060820152612682608083016125d4565b608082015260a082015167ffffffffffffffff8111156126a0575f5ffd5b6126ac868285016122b2565b60a083015250949350505050565b8181038181111561032c5761032c61259d565b5f602082840312156126dd575f5ffd5b815167ffffffffffffffff8111156126f3575f5ffd5b8201601f81018413612703575f5ffd5b8051612711611c9f82611c48565b8082825260208201915060208360051b850101925086831115612732575f5ffd5b602084015b8381101561277357805167ffffffffffffffff811115612755575f5ffd5b612764896020838901016122b2565b84525060209283019201612737565b509695505050505050565b5f6103f861278c838661257b565b8461257b565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561225c57603f1987860301845281516001600160a01b0381511686526020810151606060208801526127f16060880182611f1a565b905060408201519150868103604088015261280c8183611ae7565b9650505060209384019391909101906001016127b8565b6001600160a01b038616815260a060208201525f61284460a0830187611f1a565b82810360408401526128568187611ae7565b90506001600160e01b031985166060840152828103608084015261287a8185611ae7565b98975050505050505050565b602081526001600160a01b0382511660208201526001600160e01b031960208301511660408201525f604083015160c060608401526128c860e0840182611ae7565b90506001600160e01b031960608501511660808401526001600160e01b031960808501511660a084015260a0840151601f198483030160c085015261158c8282611ae7565b606081525f61291f6060830186611ae7565b82810360208401526129318186611ae7565b905082810360408401526129458185611ae7565b9695505050505050565b5f6020828403121561295f575f5ffd5b815161160f81611b55565b5f5f5f5f5f60a0868803121561297e575f5ffd5b855161298981611b55565b602087015190955067ffffffffffffffff8111156129a5575f5ffd5b6129b18882890161231d565b945050604086015167ffffffffffffffff8111156129cd575f5ffd5b6129d9888289016122b2565b93505060608601516129ea81611a0a565b608087015190925067ffffffffffffffff811115612a06575f5ffd5b612a12888289016122b2565b9150509295509295909350565b8082018082111561032c5761032c61259d56fea2646970667358221220206d3bb9620ebb709db737a4bfd45212518755cebebb2c22e86da286d89958af64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100e5575f3560e01c80639061b92311610088578063e370ecbe11610063578063e370ecbe14610238578063eea330f91461025f578063ef46c0b814610291578063f394443a146102a6575f5ffd5b80639061b923146101f25780639f28e99d14610205578063b536af7614610225575f5ffd5b8063582de3e7116100c3578063582de3e7146101705780636ccb8660146101945780636d6dd540146101bb5780636f3ff726146101df575f5ffd5b806301ffc9a7146100e957806348ee1bcc14610111578063491fc4f914610150575b5f5ffd5b6100fc6100f7366004611a22565b6102b9565b60405190151581526020015b60405180910390f35b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610108565b61016361015e366004611a7b565b610332565b6040516101089190611b15565b6100fc61017e366004611a22565b6001600160e01b0319166312d6c5b760e31b1490565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101d16101c9366004611a7b565b509192909150565b604051610108929190611b27565b6100fc6101ed366004611b79565b610400565b610163610200366004611a7b565b61048c565b610218610213366004611d87565b6105bb565b6040516101089190611f74565b610218610233366004611a7b565b61077c565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b61027261026d36600461203a565b6109cb565b604080516001600160a01b039093168352901515602083015201610108565b6102a461029f366004612079565b6109e4565b005b6101636102b43660046120f6565b610a69565b5f639061b92360e01b6001600160e01b03198316148061030257507feea330f9000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b8061031d575063582de3e760e01b6001600160e01b03198316145b8061032c575061032c82610da0565b92915050565b60605f61034185870187611d87565b5190505f80610352858701876121ce565b91509150811561038f576103668382610dd4565b6040516020016103769190612205565b60405160208183030381529060405293505050506103f8565b5f835f815181106103a2576103a2612268565b60209081029190910101516040810151606082015191925090600e16156103cb57805160208201fd5b82156103e857808060200190518101906103e591906122d0565b90505b94506103f89350505050565b5050505b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610468573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032c9190612302565b60606105b261049b8686610f5c565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f9201829052506040805160208101825282815281517f093a86d3000000000000000000000000000000000000000000000000000000008152915192955093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063093a86d391600480830192879291908290030181865afa15801561058b573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526102b491908101906123af565b50949350505050565b60408051808201909152606080825260208201525f5b82515181101561076e575f835f015182815181106105f1576105f1612268565b6020026020010151905060408160600151165f1461060f5750610766565b60608101516030165f036106b9575f61062a825f0151610fc6565b610635576010610638565b60205b9050825b8551518110156106b657825f01516001600160a01b0316865f0151828151811061066857610668612268565b60200260200101515f01516001600160a01b0316036106ae5781865f0151828151811061069757610697612268565b602002602001015160600181815117915081815250505b60010161063c565b50505b5f60208260600151165f1490505f5f6106db8315855f01518660200151610ff8565b91509150811580156107055750630556f18360e41b6106f9826123e1565b6001600160e01b031916145b1561071a57606084018051600117905261075a565b606084018051604017905282801561073157508051155b61074657816107465760608401805160021790525b80515f0361075a5760608401805160081790525b60409093019290925250505b6001016105d1565b506107788261108b565b5090565b60408051808201909152606080825260208201525f8061079e8688018861249c565b9150915080518251146107c45760405163252e18f560e11b815260040160405180910390fd5b6107d084860186611d87565b92505f5f5b8451518110156109a0575f855f015182815181106107f5576107f5612268565b6020026020010151905060408160600151165f0361099757835183101561098b575f84848151811061082957610829612268565b6020026020010151905085848151811061084557610845612268565b602002602001015115610862576060820180516044179052610985565b5f6108708360400151611276565b90505f815f01516001600160a01b0316826060015184846080015160405160240161089c929190612557565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516108da9190612592565b5f60405180830381855afa9150503d805f8114610912576040519150601f19603f3d011682016040523d82523d5f602084013e610917565b606091505b509350905080806109415750630556f18360e41b610934846123e1565b6001600160e01b03191614155b1561098257606084018051604017905280158061095d57508251155b1561096e5760608401805160021790525b82515f036109825760608401805160081790525b50505b60408201525b610994836125b1565b92505b506001016107d5565b50815181146109c25760405163252e18f560e11b815260040160405180910390fd5b6103f48461108b565b5f5f6109d78484610f5c565b5f915091505b9250929050565b5f818060200190518101906109f991906125df565b9050610a64815f01518260200151858460400151604051602401610a1e929190612557565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a08601516112ba565b505050565b6060866001600160a01b03163b5f03610ab957856040517f5fe9a5df000000000000000000000000000000000000000000000000000000008152600401610ab09190611b15565b60405180910390fd5b5f7fac9650d800000000000000000000000000000000000000000000000000000000610ae4876123e1565b6001600160e01b0319161490505f858015610b0b5750610b0b8963477cc53f60e11b61147d565b90505f8180610b265750610b268a639061b92360e01b61147d565b9050610b398a63582de3e760e01b61147d565b8015610bbd5750821580610bbd5750808015610bbd575060405163582de3e760e01b81526312d6c5b760e31b60048201526001600160a01b038b169063582de3e790602401602060405180830381865afa158015610b99573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bbd9190612302565b15610c07578015610be257610bdd8a610bd8848c8c8b611503565b611595565b610c07565b610c078a89636d6dd54060e01b5f60e01b60405180602001604052805f8152506112ba565b60608315610c4157610c27896004808c51610c2291906126ba565b6115ba565b806020019051810190610c3a91906126cd565b9050610c8c565b60408051600180825281830190925290816020015b6060815260200190600190039081610c5657905050905088815f81518110610c8057610c80612268565b60200260200101819052505b8115610ce9575f5b8151811015610ce757610cc2848c848481518110610cb457610cb4612268565b60200260200101518b611503565b828281518110610cd457610cd4612268565b6020908102919091010152600101610c94565b505b610d923080639f28e99d610cfe8f868c611616565b604051602401610d0e9190611f74565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b94909417909352519092507f491fc4f900000000000000000000000000000000000000000000000000000000915f91610d7e918b918a910191151582521515602082015260400190565b6040516020818303038152906040526112ba565b505050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b148061032c57506301ffc9a760e01b6001600160e01b031983161461032c565b6060825167ffffffffffffffff811115610df057610df0611b94565b604051908082528060200260200182016040528015610e2357816020015b6060815260200190600190039081610e0e5790505b5090505f5b8351811015610f55575f848281518110610e4457610e44612268565b60209081029190910101516040810151606082015191925090600e165f03610e88578415610e835780806020019051810190610e8091906122d0565b90505b610f2d565b805115610f2d578051601f1660048114610f2b575f60048210610eb557610eb06004836126ba565b610ec0565b610ec08260046126ba565b67ffffffffffffffff811115610ed857610ed8611b94565b6040519080825280601f01601f191660200182016040528015610f02576020820181803683370190505b5090508281604051602001610f1892919061277e565b6040516020818303038152906040529250505b505b80848481518110610f4057610f40612268565b60209081029190910101525050600101610e28565b5092915050565b5f610fbc7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920182905250925061172b915050565b5090949350505050565b5f306001600160a01b03831603610fdf57506001919050565b6113885a5f5f5f5f8786fa50815a909103109392505050565b5f6060836001600160a01b031685611030577f0000000000000000000000000000000000000000000000000000000000000000611032565b5a5b846040516110409190612592565b5f604051808303818686fa925050503d805f8114611079576040519150601f19603f3d011682016040523d82523d5f602084013e61107e565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff8111156110a8576110a8611b94565b60405190808252806020026020018201604052801561110557816020015b6110f260405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816110c65790505b5090505f5f5b8351518110156111b6575f845f0151828151811061112b5761112b612268565b6020026020010151905060408160600151165f036111ad575f6111518260400151611276565b90506040518060600160405280825f01516001600160a01b0316815260200182602001518152602001826040015181525085858061118e906125b1565b9650815181106111a0576111a0612268565b6020026020010181905250505b5060010161110b565b508015610a6457808252308360200151836040516024016111d79190612792565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af76000000000000000000000000000000000000000000000000000000009161124b91899101611f74565b60408051601f1981840301815290829052630556f18360e41b8252610ab09594939291600401612823565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915261032c6112b5836004808651610c2291906126ba565b611827565b5f5f6112cf6112c888610fc6565b8888610ff8565b91509150811580156112f95750630556f18360e41b6112ed826123e1565b6001600160e01b031916145b156113a7575f61130882611276565b9050876001600160a01b0316815f01516001600160a01b0316036113a557308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b03191681526020018981525060405160200161124b9190612886565b505b5f826113b357846113b5565b855b90506001600160e01b031981161561146757306001600160a01b03168183866040516024016113e5929190612557565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114239190612592565b5f60405180830381855afa9150503d805f811461145b576040519150601f19603f3d011682016040523d82523d5f602084013e611460565b606091505b5090935091505b821561147557815160208301f35b815160208301fd5b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f5190508280156114ed575060208210155b80156114f857505f81115b979650505050505050565b60608461154c57838360405160240161151d929190612557565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b17905261158c565b8383836040516024016115619392919061290d565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b1790525b95945050505050565b6115b682825f60e01b5f60e01b60405180602001604052805f8152506112ba565b5050565b60608167ffffffffffffffff8111156115d5576115d5611b94565b6040519080825280601f01601f1916602001820160405280156115ff576020820181803683370190505b50905061160f8484835f86611892565b9392505050565b60408051808201909152606080825260208201525f835167ffffffffffffffff81111561164557611645611b94565b6040519080825280602002602001820160405280156116a857816020015b61169560405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b8152602001906001900390816116635790505b5090505f5b845181101561170e575f8282815181106116c9576116c9612268565b60209081029190910101516001600160a01b038816815286519091508690839081106116f7576116f7612268565b6020908102919091018101519101526001016116ad565b506040805180820190915290815260208101929092525092915050565b5f5f5f5f5f61173a87876118cf565b9092509050811561181b575f5f5f6117538b8b8661172b565b92509250925061176c82865f9182526020526040902090565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018290529097506001600160a01b038c1690630178b8bf90602401602060405180830381865afa1580156117cb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117ef919061294f565b97506001600160a01b0388166118075782878261180b565b87878a5b975097509750505050505061181e565b50505b93509350939050565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915281806020019051810190611864919061296a565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6118a5856118a08387612a1f565b6118fc565b6118b3836118a08385612a1f565b6118c882602085010185602088010183611944565b5050505050565b5f5f5f6118dc858561198d565b9250905060ff8116156118f457806021858701012092505b509250929050565b81518111156115b65781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610ab0918391600401918252602082015260400190565b5b601f811115611965578151835260209283019290910190601f1901611945565b8015610a645790518251600160209390930360031b9290921b5f190180199091169116179052565b5f5f835183106119b2578360405163ba4adc2360e01b8152600401610ab09190611b15565b8383815181106119c4576119c4612268565b016020015160f81c915050818101600101816119e45783518114156119ea565b83518110155b156109dd578360405163ba4adc2360e01b8152600401610ab09190611b15565b6001600160e01b031981168114611a1f575f5ffd5b50565b5f60208284031215611a32575f5ffd5b813561160f81611a0a565b5f5f83601f840112611a4d575f5ffd5b50813567ffffffffffffffff811115611a64575f5ffd5b6020830191508360208285010111156109dd575f5ffd5b5f5f5f5f60408587031215611a8e575f5ffd5b843567ffffffffffffffff811115611aa4575f5ffd5b611ab087828801611a3d565b909550935050602085013567ffffffffffffffff811115611acf575f5ffd5b611adb87828801611a3d565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61160f6020830184611ae7565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b6001600160a01b0381168114611a1f575f5ffd5b8035611b7481611b55565b919050565b5f60208284031215611b89575f5ffd5b813561160f81611b55565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611bcb57611bcb611b94565b60405290565b6040516080810167ffffffffffffffff81118282101715611bcb57611bcb611b94565b60405160c0810167ffffffffffffffff81118282101715611bcb57611bcb611b94565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c4057611c40611b94565b604052919050565b5f67ffffffffffffffff821115611c6157611c61611b94565b5060051b60200190565b5f67ffffffffffffffff821115611c8457611c84611b94565b50601f01601f191660200190565b5f611ca4611c9f84611c6b565b611c17565b9050828152838383011115611cb7575f5ffd5b828260208301375f602084830101529392505050565b5f82601f830112611cdc575f5ffd5b61160f83833560208501611c92565b5f82601f830112611cfa575f5ffd5b8135611d08611c9f82611c48565b8082825260208201915060208360051b860101925085831115611d29575f5ffd5b602085015b83811015611d7d57803567ffffffffffffffff811115611d4c575f5ffd5b8601603f81018813611d5c575f5ffd5b611d6e88602083013560408401611c92565b84525060209283019201611d2e565b5095945050505050565b5f60208284031215611d97575f5ffd5b813567ffffffffffffffff811115611dad575f5ffd5b820160408185031215611dbe575f5ffd5b611dc6611ba8565b813567ffffffffffffffff811115611ddc575f5ffd5b8201601f81018613611dec575f5ffd5b8035611dfa611c9f82611c48565b8082825260208201915060208360051b850101925088831115611e1b575f5ffd5b602084015b83811015611ee157803567ffffffffffffffff811115611e3e575f5ffd5b85016080818c03601f19011215611e53575f5ffd5b611e5b611bd1565b6020820135611e6981611b55565b8152604082013567ffffffffffffffff811115611e84575f5ffd5b611e938d602083860101611ccd565b602083015250606082013567ffffffffffffffff811115611eb2575f5ffd5b611ec18d602083860101611ccd565b604083015250608091909101356060820152835260209283019201611e20565b508452505050602082013567ffffffffffffffff811115611f00575f5ffd5b611f0c86828501611ceb565b602083015250949350505050565b5f82825180855260208501945060208160051b830101602085015f5b83811015611f6857601f19858403018852611f52838351611ae7565b6020988901989093509190910190600101611f36565b50909695505050505050565b602081525f6060820183516040602085015281815180845260808601915060808160051b87010193506020830192505f5b8181101561201b57607f1987860301835283516001600160a01b038151168652602081015160806020880152611fde6080880182611ae7565b905060408201518782036040890152611ff78282611ae7565b60609384015198909301979097525094506020938401939290920191600101611fa5565b505050506020840151838203601f1901604085015261158c8282611f1a565b5f5f6020838503121561204b575f5ffd5b823567ffffffffffffffff811115612061575f5ffd5b61206d85828601611a3d565b90969095509350505050565b5f5f6040838503121561208a575f5ffd5b823567ffffffffffffffff8111156120a0575f5ffd5b6120ac85828601611ccd565b925050602083013567ffffffffffffffff8111156120c8575f5ffd5b6120d485828601611ccd565b9150509250929050565b8015158114611a1f575f5ffd5b8035611b74816120de565b5f5f5f5f5f5f60c0878903121561210b575f5ffd5b61211487611b69565b9550602087013567ffffffffffffffff81111561212f575f5ffd5b61213b89828a01611ccd565b955050604087013567ffffffffffffffff811115612157575f5ffd5b61216389828a01611ccd565b945050612172606088016120eb565b9250608087013567ffffffffffffffff81111561218d575f5ffd5b61219989828a01611ccd565b92505060a087013567ffffffffffffffff8111156121b5575f5ffd5b6121c189828a01611ceb565b9150509295509295509295565b5f5f604083850312156121df575f5ffd5b82356121ea816120de565b915060208301356121fa816120de565b809150509250929050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561225c57603f19878603018452612247858351611ae7565b9450602093840193919091019060010161222b565b50929695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f612289611c9f84611c6b565b905082815283838301111561229c575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f8301126122c1575f5ffd5b61160f8383516020850161227c565b5f602082840312156122e0575f5ffd5b815167ffffffffffffffff8111156122f6575f5ffd5b6103f8848285016122b2565b5f60208284031215612312575f5ffd5b815161160f816120de565b5f82601f83011261232c575f5ffd5b815161233a611c9f82611c48565b8082825260208201915060208360051b86010192508583111561235b575f5ffd5b602085015b83811015611d7d57805167ffffffffffffffff81111561237e575f5ffd5b8601603f8101881361238e575f5ffd5b6123a08860208301516040840161227c565b84525060209283019201612360565b5f602082840312156123bf575f5ffd5b815167ffffffffffffffff8111156123d5575f5ffd5b6103f88482850161231d565b805160208201516001600160e01b0319811691906004821015612416576001600160e01b0319808360040360031b1b82161692505b5050919050565b5f82601f83011261242c575f5ffd5b813561243a611c9f82611c48565b8082825260208201915060208360051b86010192508583111561245b575f5ffd5b602085015b83811015611d7d57803567ffffffffffffffff81111561247e575f5ffd5b61248d886020838a0101611ccd565b84525060209283019201612460565b5f5f604083850312156124ad575f5ffd5b823567ffffffffffffffff8111156124c3575f5ffd5b8301601f810185136124d3575f5ffd5b80356124e1611c9f82611c48565b8082825260208201915060208360051b850101925087831115612502575f5ffd5b6020840193505b8284101561252d57833561251c816120de565b825260209384019390910190612509565b9450505050602083013567ffffffffffffffff81111561254b575f5ffd5b6120d48582860161241d565b604081525f6125696040830185611ae7565b828103602084015261158c8185611ae7565b5f81518060208401855e5f93019283525090919050565b5f61160f828461257b565b634e487b7160e01b5f52601160045260245ffd5b5f600182016125c2576125c261259d565b5060010190565b8051611b7481611b55565b8051611b7481611a0a565b5f602082840312156125ef575f5ffd5b815167ffffffffffffffff811115612605575f5ffd5b820160c08185031215612616575f5ffd5b61261e611bf4565b612627826125c9565b8152612635602083016125d4565b6020820152604082015167ffffffffffffffff811115612653575f5ffd5b61265f868285016122b2565b604083015250612671606083016125d4565b6060820152612682608083016125d4565b608082015260a082015167ffffffffffffffff8111156126a0575f5ffd5b6126ac868285016122b2565b60a083015250949350505050565b8181038181111561032c5761032c61259d565b5f602082840312156126dd575f5ffd5b815167ffffffffffffffff8111156126f3575f5ffd5b8201601f81018413612703575f5ffd5b8051612711611c9f82611c48565b8082825260208201915060208360051b850101925086831115612732575f5ffd5b602084015b8381101561277357805167ffffffffffffffff811115612755575f5ffd5b612764896020838901016122b2565b84525060209283019201612737565b509695505050505050565b5f6103f861278c838661257b565b8461257b565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561225c57603f1987860301845281516001600160a01b0381511686526020810151606060208801526127f16060880182611f1a565b905060408201519150868103604088015261280c8183611ae7565b9650505060209384019391909101906001016127b8565b6001600160a01b038616815260a060208201525f61284460a0830187611f1a565b82810360408401526128568187611ae7565b90506001600160e01b031985166060840152828103608084015261287a8185611ae7565b98975050505050505050565b602081526001600160a01b0382511660208201526001600160e01b031960208301511660408201525f604083015160c060608401526128c860e0840182611ae7565b90506001600160e01b031960608501511660808401526001600160e01b031960808501511660a084015260a0840151601f198483030160c085015261158c8282611ae7565b606081525f61291f6060830186611ae7565b82810360208401526129318186611ae7565b905082810360408401526129458185611ae7565b9695505050505050565b5f6020828403121561295f575f5ffd5b815161160f81611b55565b5f5f5f5f5f60a0868803121561297e575f5ffd5b855161298981611b55565b602087015190955067ffffffffffffffff8111156129a5575f5ffd5b6129b18882890161231d565b945050604086015167ffffffffffffffff8111156129cd575f5ffd5b6129d9888289016122b2565b93505060608601516129ea81611a0a565b608087015190925067ffffffffffffffff811115612a06575f5ffd5b612a12888289016122b2565b9150509295509295909350565b8082018082111561032c5761032c61259d56fea2646970667358221220206d3bb9620ebb709db737a4bfd45212518755cebebb2c22e86da286d89958af64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "1210": [ + { + "length": 32, + "start": 4108 + } + ], + "69129": [ + { + "length": 32, + "start": 409 + }, + { + "length": 32, + "start": 1346 + } + ], + "69270": [ + { + "length": 32, + "start": 573 + }, + { + "length": 32, + "start": 3938 + } + ], + "75212": [ + { + "length": 32, + "start": 278 + }, + { + "length": 32, + "start": 1057 + } + ] + }, + "inputSourceName": "project/src/resolver/ENSV1Resolver.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "InvalidBatchGatewayResponse()": [ + { + "details": "Error selector: `0x4a5c31ea`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "UnreachableName(bytes)": [ + { + "details": "`name` cannot be resolved. Error selector: `0x5fe9a5df`", + "params": { + "name": "The DNS-encoded ENS name." + } + } + ] + }, + "kind": "dev", + "methods": { + "callResolver(address,bytes,bytes,bool,bytes,string[])": { + "details": "Reverts `UnreachableName` if resolver is not a contract. This function never returns normally. The return type is necessary to define the result of the callback. Call this function externally or with `ccipRead()` to intercept the response.", + "params": { + "batchGateways": "The batch gateway URLs.", + "context": "The context for `IExtendedDNSResolver`.", + "data": "The calldata for the resolution.", + "hasContext": "True if `IExtendedDNSResolver` should be considered.", + "name": "The DNS-encoded ENS name.", + "resolver": "The resolver to call." + } + }, + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": { + "details": "Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`." + }, + "ccipBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \"done\".", + "params": { + "extraData": "The contextual data passed from `ccipBatch()`.", + "response": "The response from the batch gateway." + }, + "returns": { + "batch": "The batch where every lookup is \"done\"." + } + }, + "ccipReadCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.", + "params": { + "extraData": "The contextual data passed from `ccipRead()`.", + "response": "The response from offchain." + } + }, + "constructor": { + "params": { + "batchGatewayProvider": "The batch gateway provider.", + "contractNamer": "Delegated contract namer.", + "registryV1": "The ENSv1 registry." + } + }, + "getResolver(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The underlying resolver address.", + "_1": "`true` if `resolver` is offchain." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "resolveBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `callResolver()` from batch calling a resolver.", + "params": { + "extraData": "The abi-encoded properties of the call.", + "response": "The response data from the batch gateway." + }, + "returns": { + "_0": "result The response from the resolver." + } + }, + "resolveDirectImmediateCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `callResolver()` from direct calling an immediate resolver." + }, + "supportsFeature(bytes4)": { + "params": { + "featureId": "The feature identifier." + }, + "returns": { + "_0": "`true` if the feature is supported by the contract." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "2171200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BATCH_GATEWAY_PROVIDER()": "infinite", + "CONTRACT_NAMER()": "infinite", + "REGISTRY_V1()": "infinite", + "callResolver(address,bytes,bytes,bool,bytes,string[])": "infinite", + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": "infinite", + "ccipBatchCallback(bytes,bytes)": "infinite", + "ccipReadCallback(bytes,bytes)": "infinite", + "getResolver(bytes)": "infinite", + "isContractNamer(address)": "infinite", + "resolve(bytes,bytes)": "infinite", + "resolveBatchCallback(bytes,bytes)": "infinite", + "resolveDirectImmediateCallback(bytes,bytes)": "infinite", + "supportsFeature(bytes4)": "396", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_findResolver(bytes calldata)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"batchGatewayProvider\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"},{\"internalType\":\"contract ENS\",\"name\":\"registryV1\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBatchGatewayResponse\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"UnreachableName\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BATCH_GATEWAY_PROVIDER\",\"outputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REGISTRY_V1\",\"outputs\":[{\"internalType\":\"contract ENS\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"hasContext\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"batchGateways\",\"type\":\"string[]\"}],\"name\":\"callResolver\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"name\":\"ccipBatch\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipBatchCallback\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipReadCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveBatchCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"resolveDirectImmediateCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"feature\",\"type\":\"bytes4\"}],\"name\":\"supportsFeature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"InvalidBatchGatewayResponse()\":[{\"details\":\"Error selector: `0x4a5c31ea`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"UnreachableName(bytes)\":[{\"details\":\"`name` cannot be resolved. Error selector: `0x5fe9a5df`\",\"params\":{\"name\":\"The DNS-encoded ENS name.\"}}]},\"kind\":\"dev\",\"methods\":{\"callResolver(address,bytes,bytes,bool,bytes,string[])\":{\"details\":\"Reverts `UnreachableName` if resolver is not a contract. This function never returns normally. The return type is necessary to define the result of the callback. Call this function externally or with `ccipRead()` to intercept the response.\",\"params\":{\"batchGateways\":\"The batch gateway URLs.\",\"context\":\"The context for `IExtendedDNSResolver`.\",\"data\":\"The calldata for the resolution.\",\"hasContext\":\"True if `IExtendedDNSResolver` should be considered.\",\"name\":\"The DNS-encoded ENS name.\",\"resolver\":\"The resolver to call.\"}},\"ccipBatch(((address,bytes,bytes,uint256)[],string[]))\":{\"details\":\"Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`.\"},\"ccipBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\",\"params\":{\"extraData\":\"The contextual data passed from `ccipBatch()`.\",\"response\":\"The response from the batch gateway.\"},\"returns\":{\"batch\":\"The batch where every lookup is \\\"done\\\".\"}},\"ccipReadCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.\",\"params\":{\"extraData\":\"The contextual data passed from `ccipRead()`.\",\"response\":\"The response from offchain.\"}},\"constructor\":{\"params\":{\"batchGatewayProvider\":\"The batch gateway provider.\",\"contractNamer\":\"Delegated contract namer.\",\"registryV1\":\"The ENSv1 registry.\"}},\"getResolver(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The underlying resolver address.\",\"_1\":\"`true` if `resolver` is offchain.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"resolveBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `callResolver()` from batch calling a resolver.\",\"params\":{\"extraData\":\"The abi-encoded properties of the call.\",\"response\":\"The response data from the batch gateway.\"},\"returns\":{\"_0\":\"result The response from the resolver.\"}},\"resolveDirectImmediateCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `callResolver()` from direct calling an immediate resolver.\"},\"supportsFeature(bytes4)\":{\"params\":{\"featureId\":\"The feature identifier.\"},\"returns\":{\"_0\":\"`true` if the feature is supported by the contract.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBatchGatewayResponse()\":[{\"notice\":\"The batch gateway supplied an incorrect number of responses.\"}]},\"kind\":\"user\",\"methods\":{\"BATCH_GATEWAY_PROVIDER()\":{\"notice\":\"Shared batch gateway provider.\"},\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"REGISTRY_V1()\":{\"notice\":\"The ENSv1 registry used to look up resolvers for names.\"},\"callResolver(address,bytes,bytes,bool,bytes,string[])\":{\"notice\":\"Perform forward resolution. Call this function with `ccipRead()` to intercept the response. Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers. - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features, the call is performed directly without the batch gateway. - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature, the call is performed directly without the batch gateway. - Otherwise, the call is performed with the batch gateway. The batch gateway is only invoked if any call reverts `OffchainLookup`. If the calldata is `multicall()` it is disassembled, called separately, and reassembled.\"},\"getResolver(bytes)\":{\"notice\":\"Fetch the underlying resolver for `name`. Callers should enable EIP-3668. * If `offchain`, additional information is necessary to locate `resolver`. * If `resolver` is null, `offchain` is irrelevant.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"supportsFeature(bytes4)\":{\"notice\":\"Check if a feature is supported.\"}},\"notice\":\"Resolver that performs resolutions using ENSv1.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/resolver/ENSV1Resolver.sol\":\"ENSV1Resolver\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/CCIPBatcher.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {IBatchGateway} from \\\"./IBatchGateway.sol\\\";\\nimport {CCIPReader, EIP3668, OffchainLookup} from \\\"./CCIPReader.sol\\\";\\n\\n/// @dev CCIP-Read batch gateway client implementation.\\n///\\n/// Since requests are read-only, empty responses are considered an error.\\n///\\n/// Usage: `ccipRead(address(this), abi.encodeCall(this.ccipBatch, (createBatch(...))), ...)`\\n///\\nabstract contract CCIPBatcher is CCIPReader {\\n /// @notice The batch gateway supplied an incorrect number of responses.\\n /// @dev Error selector: `0x4a5c31ea`\\n error InvalidBatchGatewayResponse();\\n\\n uint256 constant FLAG_OFFCHAIN = 1 << 0; // the lookup reverted `OffchainLookup`\\n uint256 constant FLAG_CALL_ERROR = 1 << 1; // the initial call or callback reverted\\n uint256 constant FLAG_BATCH_ERROR = 1 << 2; // `OffchainLookup` failed on the batch gateway\\n uint256 constant FLAG_EMPTY_RESPONSE = 1 << 3; // the initial call or callback returned `0x`\\n uint256 constant FLAG_EIP140_BEFORE = 1 << 4; // does not have revert op code\\n uint256 constant FLAG_EIP140_AFTER = 1 << 5; // has revert op code\\n uint256 constant FLAG_DONE = 1 << 6; // the lookup has finished processing (private)\\n\\n uint256 constant FLAGS_ANY_ERROR =\\n FLAG_CALL_ERROR | FLAG_BATCH_ERROR | FLAG_EMPTY_RESPONSE;\\n uint256 constant FLAGS_ANY_EIP140 = FLAG_EIP140_BEFORE | FLAG_EIP140_AFTER;\\n\\n /// @dev An independent `OffchainLookup` session.\\n struct Lookup {\\n address target; // contract to call\\n bytes call; // initial calldata\\n bytes data; // response or error\\n uint256 flags; // see: FLAG_*\\n }\\n\\n /// @dev A batch gateway session.\\n struct Batch {\\n Lookup[] lookups;\\n string[] gateways;\\n }\\n\\n /// @dev Create a batch for a single target with multiple calls.\\n /// @param target The target contract.\\n /// @param calls The list of calldata.\\n /// @param gateways The batch gateway URLs.\\n function createBatch(\\n address target,\\n bytes[] memory calls,\\n string[] memory gateways\\n ) internal pure returns (Batch memory) {\\n Lookup[] memory lookups = new Lookup[](calls.length);\\n for (uint256 i; i < calls.length; ++i) {\\n Lookup memory lu = lookups[i];\\n lu.target = target;\\n lu.call = calls[i];\\n }\\n return Batch(lookups, gateways);\\n }\\n\\n /// @dev Use `ccipRead()` to call this function with a batch.\\n /// The callback response will be `abi.encode(batch)`.\\n function ccipBatch(\\n Batch memory batch\\n ) external view returns (Batch memory) {\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) != 0) {\\n continue; // don't call a lookup that's already done\\n }\\n if ((lu.flags & FLAGS_ANY_EIP140) == 0) {\\n uint256 flags = detectEIP140(lu.target)\\n ? FLAG_EIP140_AFTER\\n : FLAG_EIP140_BEFORE;\\n for (uint256 j = i; j < batch.lookups.length; ++j) {\\n if (batch.lookups[j].target == lu.target) {\\n batch.lookups[j].flags |= flags;\\n }\\n }\\n }\\n bool unsafe = (lu.flags & FLAG_EIP140_AFTER) == 0;\\n (bool ok, bytes memory v) = safeCall(!unsafe, lu.target, lu.call);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n lu.flags |= FLAG_OFFCHAIN;\\n } else {\\n lu.flags |= FLAG_DONE;\\n if (unsafe && v.length == 0) {\\n // unsafe contracts appear the same for throw and unimplemented fallback\\n // decision: interpret like an unimplemented function selector response\\n } else if (!ok) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n lu.data = v;\\n }\\n _revertBatchGateway(batch); // reverts if any offchain\\n return batch;\\n }\\n\\n /// @dev Check if the batch is \\\"done\\\". If not, revert `OffchainLookup` for batch gateway.\\n function _revertBatchGateway(Batch memory batch) internal view {\\n IBatchGateway.Request[] memory requests = new IBatchGateway.Request[](\\n batch.lookups.length\\n );\\n uint256 count;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n requests[count++] = IBatchGateway.Request(\\n p.sender,\\n p.urls,\\n p.callData\\n );\\n }\\n }\\n if (count > 0) {\\n assembly {\\n mstore(requests, count) // truncate to number of offchain requests\\n }\\n revert OffchainLookup(\\n address(this),\\n batch.gateways,\\n abi.encodeCall(IBatchGateway.query, (requests)),\\n this.ccipBatchCallback.selector,\\n abi.encode(batch)\\n );\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipBatch()`.\\n /// Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\\n /// @param response The response from the batch gateway.\\n /// @param extraData The contextual data passed from `ccipBatch()`.\\n /// @return batch The batch where every lookup is \\\"done\\\".\\n function ccipBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (Batch memory batch) {\\n (bool[] memory failures, bytes[] memory responses) = abi.decode(\\n response,\\n (bool[], bytes[])\\n );\\n if (failures.length != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n batch = abi.decode(extraData, (Batch));\\n uint256 expected;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n if (expected < responses.length) {\\n bytes memory v = responses[expected];\\n if (failures[expected]) {\\n lu.flags |= FLAG_DONE | FLAG_BATCH_ERROR;\\n } else {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n bool ok;\\n // assumption: unsafe contracts don't revert OffchainLookup()\\n (ok, v) = p.sender.staticcall(\\n abi.encodeWithSelector(\\n p.callbackFunction,\\n v,\\n p.extraData\\n )\\n );\\n if (ok || bytes4(v) != OffchainLookup.selector) {\\n lu.flags |= FLAG_DONE;\\n // decision: promote empty response from the callback => call error\\n // ie. the initial function was implemented but the callback was not\\n // this can be detected via FLAG_OFFCHAIN\\n if (!ok || v.length == 0) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n }\\n lu.data = v;\\n }\\n ++expected;\\n }\\n }\\n if (expected != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n _revertBatchGateway(batch);\\n }\\n\\n /// @dev Safely collapse `Lookup[]` into `bytes[]`.\\n /// If `FLAGS_ANY_ERROR` and response is non-empty, the response is zero-padded so that `length % 32 == 4`.\\n /// @param lookups Array of completed lookups.\\n /// @param wrapped If `true`, successful responses are unwrapped as `bytes`.\\n /// @return arr Array of call responses.\\n function _toResponseArray(Lookup[] memory lookups, bool wrapped) internal pure returns (bytes[] memory arr) {\\n arr = new bytes[](lookups.length);\\n for (uint256 i; i < lookups.length; ++i) {\\n Lookup memory lu = lookups[i];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) == 0) {\\n if (wrapped) {\\n v = abi.decode(v, (bytes));\\n }\\n } else if (v.length != 0) {\\n uint256 rem = v.length & 31;\\n if (rem != 4) {\\n bytes memory pad = new bytes(rem < 4 ? 4 - rem : rem - 4);\\n v = abi.encodePacked(v, pad); \\n }\\n }\\n arr[i] = v;\\n }\\n return arr;\\n }\\n}\",\"keccak256\":\"0x0979783da5e97d3024259857fc414d325874abd7ea1a68838b177003b511dc5d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/CCIPReader.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n/// @author Modified from https://github.com/unruggable-labs/CCIPReader.sol/blob/341576fe7ff2b6e0c93fc08f37740cf6439f5873/contracts/CCIPReader.sol\\n\\n/// MIT License\\n/// Portions Copyright (c) 2025 Unruggable\\n/// Portions Copyright (c) 2025 ENS Labs Ltd\\n\\n/// @dev Instructions:\\n/// 1. inherit this contract\\n/// 2. call `ccipRead()` similar to `staticcall()`\\n/// 3. do not put logic after this invocation\\n/// 4. implement all response logic in callback\\n/// 5. ensure that return type of calling function == callback function\\n\\nimport {EIP3668, OffchainLookup} from \\\"./EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\n\\ncontract CCIPReader {\\n /// @dev Default unsafe call gas (sufficient for legacy ENS resolver profiles).\\n uint256 constant DEFAULT_UNSAFE_CALL_GAS = 50000;\\n\\n /// @dev Special-purpose value for identity callback: `f(x) = x`.\\n bytes4 constant IDENTITY_FUNCTION = bytes4(0);\\n\\n /// @dev The gas limit for calling functions on unsafe contracts.\\n uint256 immutable unsafeCallGas;\\n\\n constructor(uint256 _unsafeCallGas) {\\n unsafeCallGas = _unsafeCallGas;\\n }\\n\\n /// @dev A recursive CCIP-Read session.\\n struct Context {\\n address target;\\n bytes4 callbackFunction;\\n bytes extraData;\\n bytes4 successCallbackFunction;\\n bytes4 failureCallbackFunction;\\n bytes myExtraData;\\n }\\n\\n /// @dev Same as `ccipRead()` but the callback function is the identity.\\n function ccipRead(address target, bytes memory call) internal view {\\n ccipRead(target, call, IDENTITY_FUNCTION, IDENTITY_FUNCTION, \\\"\\\");\\n }\\n\\n /// @dev Performs a CCIP-Read and handles internal recursion.\\n /// Reverts `OffchainLookup` if necessary.\\n /// Use `IDENTITY_FUNCTION` as the callback function selector for return/revert behavior.\\n /// @param target The contract address.\\n /// @param call The calldata to `staticcall()` on `target`.\\n /// @param successCallbackFunction The function selector of callback on success.\\n /// @param failureCallbackFunction The function selector of callback on failure.\\n /// @param extraData The contextual data relayed to callback function.\\n function ccipRead(\\n address target,\\n bytes memory call,\\n bytes4 successCallbackFunction,\\n bytes4 failureCallbackFunction,\\n bytes memory extraData\\n ) internal view {\\n // We call the intended function that **could** revert with an `OffchainLookup`\\n // We destructure the response into an execution status bool and our return bytes\\n (bool ok, bytes memory v) = safeCall(\\n detectEIP140(target),\\n target,\\n call\\n );\\n // IF the function reverted with an `OffchainLookup`\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n // We decode the response error into a tuple\\n // tuples allow flexibility noting stack too deep constraints\\n EIP3668.Params memory p = decodeOffchainLookup(v);\\n if (p.sender == target) {\\n // We then wrap the error data in an `OffchainLookup` sent/'owned' by this contract\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n this.ccipReadCallback.selector,\\n abi.encode(\\n Context(\\n target,\\n p.callbackFunction,\\n p.extraData,\\n successCallbackFunction,\\n failureCallbackFunction,\\n extraData\\n )\\n )\\n );\\n }\\n }\\n // IF we have gotten here, the 'real' target does not revert with an `OffchainLookup` error\\n // figure out what callback to call\\n bytes4 callbackFunction = ok\\n ? successCallbackFunction\\n : failureCallbackFunction;\\n if (callbackFunction != IDENTITY_FUNCTION) {\\n // The exit point of this architecture is OUR callback in the 'real'\\n // We pass through the response to that callback\\n (ok, v) = address(this).staticcall(\\n abi.encodeWithSelector(callbackFunction, v, extraData)\\n );\\n }\\n // OR the call to the 'real' target reverts with a different error selector\\n // OR the call to OUR callback reverts with ANY error selector\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipRead()`.\\n /// @param response The response from offchain.\\n /// @param extraData The contextual data passed from `ccipRead()`.\\n /// @dev The return type of this function is polymorphic depending on the caller.\\n function ccipReadCallback(\\n bytes memory response,\\n bytes memory extraData\\n ) external view {\\n Context memory ctx = abi.decode(extraData, (Context));\\n // Since the callback can revert too (but has the same return structure)\\n // We can reuse the calling infrastructure to call the callback\\n ccipRead(\\n ctx.target,\\n abi.encodeWithSelector(\\n ctx.callbackFunction,\\n response,\\n ctx.extraData\\n ),\\n ctx.successCallbackFunction,\\n ctx.failureCallbackFunction,\\n ctx.myExtraData\\n );\\n }\\n\\n /// @dev Decode `OffchainLookup` error data into a struct.\\n /// @param v The error data of the revert.\\n /// @return p The decoded `OffchainLookup` params.\\n function decodeOffchainLookup(\\n bytes memory v\\n ) internal pure returns (EIP3668.Params memory p) {\\n p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n }\\n\\n /// @dev Determine if `target` uses `revert()` instead of `invalid()`.\\n // Assumption: only newer contracts revert `OffchainLookup`.\\n /// @param target The contract to test.\\n /// @return safe True if safe to call.\\n function detectEIP140(address target) internal view returns (bool safe) {\\n if (target == address(this)) return true;\\n // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md\\n assembly {\\n let G := 5000\\n let g := gas()\\n pop(staticcall(G, target, 0, 0, 0, 0))\\n safe := lt(sub(g, gas()), G)\\n }\\n }\\n\\n /// @dev Same as `staticcall()` but prevents OOG when not `safe`.\\n function safeCall(\\n bool safe,\\n address target,\\n bytes memory call\\n ) internal view returns (bool ok, bytes memory v) {\\n (ok, v) = target.staticcall{gas: safe ? gasleft() : unsafeCallGas}(\\n call\\n );\\n }\\n}\\n\",\"keccak256\":\"0xa6f483e89e779385c2b7ea6376d92cd3c05c98f91d1a3c7c43dc7422fe6b014f\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IBatchGateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for Batch Gateway Offchain Lookup Protocol.\\n/// https://docs.ens.domains/ensip/21/\\n/// @dev Interface selector: `0xa780bab6`\\ninterface IBatchGateway {\\n /// @notice An HTTP error occurred.\\n /// @dev Error selector: `0x01800152`\\n error HttpError(uint16 status, string message);\\n\\n /// @dev Information extracted from an `OffchainLookup` revert.\\n struct Request {\\n address sender;\\n string[] urls;\\n bytes data;\\n }\\n\\n /// @notice Perform multiple `OffchainLookup` in parallel.\\n /// Callers should enable EIP-3668.\\n /// @param requests The array of requests to lookup in parallel.\\n /// @return failures The failure status of the corresponding request.\\n /// @return responses The response or error data of the corresponding request.\\n function query(\\n Request[] memory requests\\n ) external view returns (bool[] memory failures, bytes[] memory responses);\\n}\\n\",\"keccak256\":\"0xfd7f0c7bdc29fc732ec54da2ebaea241873e55082e484729901811bc9374d6f6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IGatewayProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for shared gateway URLs.\\n/// @dev Interface selector: `0x093a86d3`\\ninterface IGatewayProvider {\\n /// @notice Get the gateways.\\n /// @return The gateway URLs.\\n function gateways() external view returns (string[] memory);\\n}\\n\",\"keccak256\":\"0x7c169843cfb65657a88fb4d5f7ec44612994d7d87cb7b1a67cbfdb18758823e0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverFeatures.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary ResolverFeatures {\\n /// @notice Implements `resolve(multicall([...]))`.\\n /// @dev Feature: `0x96b62db8`\\n bytes4 constant RESOLVE_MULTICALL =\\n bytes4(keccak256(\\\"eth.ens.resolver.extended.multicall\\\"));\\n\\n /// @notice Returns the same records independent of name or node.\\n /// @dev Feature: `0x86fb8da8`\\n bytes4 constant SINGULAR = bytes4(keccak256(\\\"eth.ens.resolver.singular\\\"));\\n}\\n\",\"keccak256\":\"0x87d131fcbdd7951a17b0a94f7f02470ec3f62c6004cf91c2d2acc54098373be6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ICompositeResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport {IExtendedResolver} from \\\"./IExtendedResolver.sol\\\";\\n\\n/// @notice A resolver that calls other resolvers.\\n/// @dev Interface selector: `0xeea330f9`\\ninterface ICompositeResolver is IExtendedResolver {\\n /// @notice Fetch the underlying resolver for `name`.\\n /// Callers should enable EIP-3668.\\n ///\\n /// * If `offchain`, additional information is necessary to locate `resolver`.\\n /// * If `resolver` is null, `offchain` is irrelevant.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return resolver The underlying resolver address.\\n /// @return offchain `true` if `resolver` is offchain.\\n function getResolver(\\n bytes memory name\\n ) external view returns (address resolver, bool offchain);\\n}\\n\",\"keccak256\":\"0xe267bef9a45073c92129ededa0275acf29394fa3fb30547bab8138dac485e2b2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedDNSResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data,\\n bytes memory context\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x541f8799c34ff9e7035d09f06ae0f0f8a16b6065e9b60a15670b957321630f72\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/RegistryUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {ENS} from \\\"../registry/ENS.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\n\\nlibrary RegistryUtils {\\n /// @notice Find the resolver for `name[offset:]`.\\n /// @dev Reverts `DNSDecodingFailed`.\\n /// @param registry The ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return resolver The resolver, or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(\\n ENS registry,\\n bytes memory name,\\n uint256 offset\\n )\\n internal\\n view\\n returns (address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (\\n address parentResolver,\\n bytes32 parentNode,\\n uint256 parentOffset\\n ) = findResolver(registry, name, next);\\n node = NameCoder.namehash(parentNode, labelHash);\\n resolver = registry.resolver(node);\\n return\\n resolver != address(0)\\n ? (resolver, node, offset)\\n : (parentResolver, node, parentOffset);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x21e7f6027b4fd2aa8c2a3e2225f88d1794faeff9377ba5ebc7a80b97d46cc214\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/ResolverCaller.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {\\n ERC165Checker\\n} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {CCIPBatcher} from \\\"../ccipRead/CCIPBatcher.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\nimport {IERC7996} from \\\"../utils/IERC7996.sol\\\";\\nimport {ResolverFeatures} from \\\"../resolvers/ResolverFeatures.sol\\\";\\n\\n// resolver profiles\\nimport {IExtendedResolver} from \\\"../resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {\\n IExtendedDNSResolver\\n} from \\\"../resolvers/profiles/IExtendedDNSResolver.sol\\\";\\nimport {IMulticallable} from \\\"../resolvers/IMulticallable.sol\\\";\\n\\nabstract contract ResolverCaller is CCIPBatcher {\\n /// @dev `name` cannot be resolved.\\n /// Error selector: `0x5fe9a5df`\\n /// @param name The DNS-encoded ENS name.\\n error UnreachableName(bytes name);\\n\\n /// @notice Perform forward resolution.\\n ///\\n /// Call this function with `ccipRead()` to intercept the response.\\n /// Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers.\\n ///\\n /// - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features,\\n /// the call is performed directly without the batch gateway.\\n /// - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature,\\n /// the call is performed directly without the batch gateway.\\n /// - Otherwise, the call is performed with the batch gateway.\\n /// The batch gateway is only invoked if any call reverts `OffchainLookup`.\\n /// If the calldata is `multicall()` it is disassembled, called separately, and reassembled.\\n ///\\n /// @dev Reverts `UnreachableName` if resolver is not a contract.\\n\\t/// This function never returns normally.\\n\\t/// The return type is necessary to define the result of the callback.\\n\\t/// Call this function externally or with `ccipRead()` to intercept the response.\\n /// @param resolver The resolver to call.\\n /// @param name The DNS-encoded ENS name.\\n /// @param data The calldata for the resolution.\\n /// @param hasContext True if `IExtendedDNSResolver` should be considered.\\n /// @param context The context for `IExtendedDNSResolver`.\\n /// @param batchGateways The batch gateway URLs.\\n function callResolver(\\n address resolver,\\n bytes memory name,\\n bytes memory data,\\n bool hasContext,\\n bytes memory context,\\n string[] memory batchGateways\\n ) public view returns (bytes memory) {\\n if (resolver.code.length == 0) {\\n revert UnreachableName(name);\\n }\\n bool multi = bytes4(data) == IMulticallable.multicall.selector;\\n bool extendedDNS = hasContext &&\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IExtendedDNSResolver).interfaceId\\n );\\n bool extended = extendedDNS ||\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IExtendedResolver).interfaceId\\n );\\n if (\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IERC7996).interfaceId\\n ) &&\\n (!multi ||\\n (extended &&\\n IERC7996(resolver).supportsFeature(\\n ResolverFeatures.RESOLVE_MULTICALL\\n )))\\n ) {\\n if (extended) {\\n // resolve() has the same return signature as callResolver()\\n ccipRead(\\n resolver,\\n _makeExtendedCall(extendedDNS, name, data, context)\\n );\\n } else {\\n ccipRead(\\n resolver,\\n data,\\n this.resolveDirectImmediateCallback.selector, // ==> step 2\\n IDENTITY_FUNCTION,\\n \\\"\\\"\\n );\\n }\\n }\\n bytes[] memory calls;\\n if (multi) {\\n calls = abi.decode(\\n BytesUtils.substring(data, 4, data.length - 4),\\n (bytes[])\\n );\\n } else {\\n calls = new bytes[](1);\\n calls[0] = data;\\n }\\n if (extended) {\\n for (uint256 i; i < calls.length; ++i) {\\n calls[i] = _makeExtendedCall(\\n extendedDNS,\\n name,\\n calls[i],\\n context\\n );\\n }\\n }\\n ccipRead(\\n address(this),\\n abi.encodeCall(\\n this.ccipBatch,\\n (createBatch(resolver, calls, batchGateways))\\n ),\\n this.resolveBatchCallback.selector, // ==> step 2\\n IDENTITY_FUNCTION,\\n abi.encode(multi, extended)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `callResolver()` from direct calling an immediate resolver.\\n function resolveDirectImmediateCallback(\\n bytes calldata response,\\n bytes calldata\\n ) external pure returns (bytes calldata) {\\n return response; // the calldata was direct, so wrap it\\n }\\n\\n /// @dev CCIP-Read callback for `callResolver()` from batch calling a resolver.\\n /// @param response The response data from the batch gateway.\\n /// @param extraData The abi-encoded properties of the call.\\n /// @return result The response from the resolver.\\n function resolveBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external pure returns (bytes memory) {\\n Lookup[] memory lookups = abi.decode(response, (Batch)).lookups;\\n (bool multi, bool extended) = abi.decode(extraData, (bool, bool));\\n if (multi) {\\n return abi.encode(_toResponseArray(lookups, extended));\\n } else {\\n Lookup memory lu = lookups[0];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) != 0) {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n if (extended) {\\n v = abi.decode(v, (bytes)); // unwrap resolve()\\n }\\n return v;\\n }\\n }\\n\\n /// @dev Create extended resolver calldata.\\n function _makeExtendedCall(\\n bool extendedDNS,\\n bytes memory name,\\n bytes memory call,\\n bytes memory context\\n ) internal pure returns (bytes memory) {\\n return\\n extendedDNS\\n ? abi.encodeCall(\\n IExtendedDNSResolver.resolve,\\n (name, call, context)\\n )\\n : abi.encodeCall(IExtendedResolver.resolve, (name, call));\\n }\\n}\\n\",\"keccak256\":\"0xf639a50d41e390b0c156667b59960b0422e738027a87a111464a196fb71638d7\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/IERC7996.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for expressing contract features not visible from the ABI.\\n/// @dev Interface selector: `0x582de3e7`\\ninterface IERC7996 {\\n /// @notice Check if a feature is supported.\\n /// @param featureId The feature identifier.\\n /// @return `true` if the feature is supported by the contract.\\n function supportsFeature(bytes4 featureId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf499a48e4e879ec7775f375d2cb5af047720ab6ae4b6f89a40a578c4e0f51631\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x5a08ad61f4e82b8a3323562661a86fb10b10190848073fdc13d4ac43710ffba5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/resolver/AbstractMirrorResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {CCIPReader} from \\\"@ens/contracts/ccipRead/CCIPReader.sol\\\";\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {ICompositeResolver} from \\\"@ens/contracts/resolvers/profiles/ICompositeResolver.sol\\\";\\nimport {IExtendedResolver} from \\\"@ens/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {ResolverFeatures} from \\\"@ens/contracts/resolvers/ResolverFeatures.sol\\\";\\nimport {ResolverCaller} from \\\"@ens/contracts/universalResolver/ResolverCaller.sol\\\";\\nimport {IERC7996} from \\\"@ens/contracts/utils/IERC7996.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\n/// @dev Resolver that mirrors resolution of the same name to a different registry.\\nabstract contract AbstractMirrorResolver is\\n ICompositeResolver,\\n IERC7996,\\n ResolverCaller,\\n DelegatedContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Shared batch gateway provider.\\n IGatewayProvider public immutable BATCH_GATEWAY_PROVIDER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n constructor(IGatewayProvider batchGatewayProvider, IContractNamer contractNamer)\\n CCIPReader(DEFAULT_UNSAFE_CALL_GAS)\\n DelegatedContractNamer(contractNamer)\\n {\\n BATCH_GATEWAY_PROVIDER = batchGatewayProvider;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(DelegatedContractNamer)\\n returns (bool)\\n {\\n return\\n type(IExtendedResolver).interfaceId == interfaceId ||\\n type(ICompositeResolver).interfaceId == interfaceId ||\\n type(IERC7996).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /// @inheritdoc IERC7996\\n function supportsFeature(bytes4 feature) external pure returns (bool) {\\n return ResolverFeatures.RESOLVE_MULTICALL == feature;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IExtendedResolver\\n function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory) {\\n callResolver(_findResolver(name), name, data, false, \\\"\\\", BATCH_GATEWAY_PROVIDER.gateways());\\n }\\n\\n /// @inheritdoc ICompositeResolver\\n function getResolver(bytes calldata name) external view returns (address, bool) {\\n return (_findResolver(name), false);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Determine the resolver for `name`.\\n function _findResolver(bytes calldata name) internal view virtual returns (address);\\n}\\n\",\"keccak256\":\"0x4297a896783bb27602ce3891ec9839fff69e81621c12bbdcce9f1ac73c14ed57\",\"license\":\"MIT\"},\"project/src/resolver/ENSV1Resolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {RegistryUtils} from \\\"@ens/contracts/universalResolver/RegistryUtils.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {AbstractMirrorResolver} from \\\"./AbstractMirrorResolver.sol\\\";\\n\\n/// @notice Resolver that performs resolutions using ENSv1.\\ncontract ENSV1Resolver is AbstractMirrorResolver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 registry used to look up resolvers for names.\\n ENS public immutable REGISTRY_V1;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n /// @param registryV1 The ENSv1 registry.\\n constructor(IGatewayProvider batchGatewayProvider, IContractNamer contractNamer, ENS registryV1)\\n AbstractMirrorResolver(batchGatewayProvider, contractNamer)\\n {\\n REGISTRY_V1 = registryV1;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc AbstractMirrorResolver\\n function _findResolver(bytes calldata name) internal view override returns (address resolver) {\\n (resolver, , ) = RegistryUtils.findResolver(REGISTRY_V1, name, 0);\\n }\\n}\\n\",\"keccak256\":\"0xed764abc8297b680aacf12d0feb6a3e33c006db01b371c9af2b96689cb6d32c4\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "InvalidBatchGatewayResponse()": [ + { + "notice": "The batch gateway supplied an incorrect number of responses." + } + ] + }, + "kind": "user", + "methods": { + "BATCH_GATEWAY_PROVIDER()": { + "notice": "Shared batch gateway provider." + }, + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "REGISTRY_V1()": { + "notice": "The ENSv1 registry used to look up resolvers for names." + }, + "callResolver(address,bytes,bytes,bool,bytes,string[])": { + "notice": "Perform forward resolution. Call this function with `ccipRead()` to intercept the response. Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers. - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features, the call is performed directly without the batch gateway. - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature, the call is performed directly without the batch gateway. - Otherwise, the call is performed with the batch gateway. The batch gateway is only invoked if any call reverts `OffchainLookup`. If the calldata is `multicall()` it is disassembled, called separately, and reassembled." + }, + "getResolver(bytes)": { + "notice": "Fetch the underlying resolver for `name`. Callers should enable EIP-3668. * If `offchain`, additional information is necessary to locate `resolver`. * If `resolver` is null, `offchain` is irrelevant." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "supportsFeature(bytes4)": { + "notice": "Check if a feature is supported." + } + }, + "notice": "Resolver that performs resolutions using ENSv1.", + "version": 1 + }, + "argsData": "0x000000000000000000000000e4e7245716d12d0f6aea01dfe0e635c43d7d083c000000000000000000000000fc8bf9234969d6b85729b756fa9e14bb84a0675400000000000000000000000000000000000c2e074ec69a0dfb2997ba6c7d2e1e", + "transaction": { + "hash": "0xd09e253214001757842c5fc53da5428d25a1e289be7dc7a47b1bbb701b1d8d90", + "nonce": "0x1e4a", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x1e322c7a7d104e5fa0b4c8230306610ecc3ef24303e6cc754645d724130cf114", + "blockNumber": "0xa6a7bd", + "transactionIndex": "0x47" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ENSV2Resolver.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ENSV2Resolver.json new file mode 100644 index 000000000..8d197a07b --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ENSV2Resolver.json @@ -0,0 +1,775 @@ +{ + "address": "0x6a923e0b9d722510b268280a381878818841629c", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "batchGatewayProvider", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "rootRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "ethResolver", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBatchGatewayResponse", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "UnreachableName", + "type": "error" + }, + { + "inputs": [], + "name": "BATCH_GATEWAY_PROVIDER", + "outputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "hasContext", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "batchGateways", + "type": "string[]" + } + ], + "name": "callResolver", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "name": "ccipBatch", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipBatchCallback", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipReadCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveBatchCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "resolveDirectImmediateCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feature", + "type": "bytes4" + } + ], + "name": "supportsFeature", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "ENSV2Resolver", + "sourceName": "src/resolver/ENSV2Resolver.sol", + "bytecode": "0x610120604052348015610010575f5ffd5b50604051612d4e380380612d4e83398101604081905261002f9161006f565b61c3506080526001600160a01b0392831660a05292821660c052811660e05216610100526100cb565b6001600160a01b038116811461006c575f5ffd5b50565b5f5f5f5f60808587031215610082575f5ffd5b845161008d81610058565b602086015190945061009e81610058565b60408601519093506100af81610058565b60608601519092506100c081610058565b939692955090935050565b60805160a05160c05160e05161010051612c2361012b5f395f818161026f01528181611022015261105501525f81816102480152610f9501525f81816101a4015261057401525f8181610121015261045301525f6110c10152612c235ff3fe608060405234801561000f575f5ffd5b50600436106100f0575f3560e01c80639061b92311610093578063d8b55d2711610063578063d8b55d271461026a578063eea330f914610291578063ef46c0b8146102c3578063f394443a146102d8575f5ffd5b80639061b923146101fd5780639f28e99d14610210578063b536af7614610230578063c92cc49a14610243575f5ffd5b8063582de3e7116100ce578063582de3e71461017b5780636ccb86601461019f5780636d6dd540146101c65780636f3ff726146101ea575f5ffd5b806301ffc9a7146100f457806348ee1bcc1461011c578063491fc4f91461015b575b5f5ffd5b610107610102366004611bdd565b6102eb565b60405190151581526020015b60405180910390f35b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610113565b61016e610169366004611c36565b610364565b6040516101139190611cd0565b610107610189366004611bdd565b6001600160e01b0319166312d6c5b760e31b1490565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101dc6101d4366004611c36565b509192909150565b604051610113929190611ce2565b6101076101f8366004611d34565b610432565b61016e61020b366004611c36565b6104be565b61022361021e366004611f42565b6105ed565b604051610113919061212f565b61022361023e366004611c36565b6107ae565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6102a461029f3660046121f5565b6109fd565b604080516001600160a01b039093168352901515602083015201610113565b6102d66102d1366004612234565b610a16565b005b61016e6102e63660046122b1565b610a9b565b5f639061b92360e01b6001600160e01b03198316148061033457507feea330f9000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b8061034f575063582de3e760e01b6001600160e01b03198316145b8061035e575061035e82610dd2565b92915050565b60605f61037385870187611f42565b5190505f8061038485870187612389565b9150915081156103c1576103988382610e06565b6040516020016103a891906123c0565b604051602081830303815290604052935050505061042a565b5f835f815181106103d4576103d4612423565b60209081029190910101516040810151606082015191925090600e16156103fd57805160208201fd5b821561041a5780806020019051810190610417919061248b565b90505b945061042a9350505050565b5050505b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561049a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061035e91906124bd565b60606105e46104cd8686610f8e565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f9201829052506040805160208101825282815281517f093a86d3000000000000000000000000000000000000000000000000000000008152915192955093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063093a86d391600480830192879291908290030181865afa1580156105bd573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526102e6919081019061256a565b50949350505050565b60408051808201909152606080825260208201525f5b8251518110156107a0575f835f0151828151811061062357610623612423565b6020026020010151905060408160600151165f146106415750610798565b60608101516030165f036106eb575f61065c825f015161107b565b61066757601061066a565b60205b9050825b8551518110156106e857825f01516001600160a01b0316865f0151828151811061069a5761069a612423565b60200260200101515f01516001600160a01b0316036106e05781865f015182815181106106c9576106c9612423565b602002602001015160600181815117915081815250505b60010161066e565b50505b5f60208260600151165f1490505f5f61070d8315855f015186602001516110ad565b91509150811580156107375750630556f18360e41b61072b8261259c565b6001600160e01b031916145b1561074c57606084018051600117905261078c565b606084018051604017905282801561076357508051155b61077857816107785760608401805160021790525b80515f0361078c5760608401805160081790525b60409093019290925250505b600101610603565b506107aa82611140565b5090565b60408051808201909152606080825260208201525f806107d086880188612657565b9150915080518251146107f65760405163252e18f560e11b815260040160405180910390fd5b61080284860186611f42565b92505f5f5b8451518110156109d2575f855f0151828151811061082757610827612423565b6020026020010151905060408160600151165f036109c95783518310156109bd575f84848151811061085b5761085b612423565b6020026020010151905085848151811061087757610877612423565b6020026020010151156108945760608201805160441790526109b7565b5f6108a2836040015161132b565b90505f815f01516001600160a01b031682606001518484608001516040516024016108ce929190612712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161090c919061274d565b5f60405180830381855afa9150503d805f8114610944576040519150601f19603f3d011682016040523d82523d5f602084013e610949565b606091505b509350905080806109735750630556f18360e41b6109668461259c565b6001600160e01b03191614155b156109b457606084018051604017905280158061098f57508251155b156109a05760608401805160021790525b82515f036109b45760608401805160081790525b50505b60408201525b6109c68361276c565b92505b50600101610807565b50815181146109f45760405163252e18f560e11b815260040160405180910390fd5b61042684611140565b5f5f610a098484610f8e565b5f915091505b9250929050565b5f81806020019051810190610a2b919061279a565b9050610a96815f01518260200151858460400151604051602401610a50929190612712565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a086015161136f565b505050565b6060866001600160a01b03163b5f03610aeb57856040517f5fe9a5df000000000000000000000000000000000000000000000000000000008152600401610ae29190611cd0565b60405180910390fd5b5f7fac9650d800000000000000000000000000000000000000000000000000000000610b168761259c565b6001600160e01b0319161490505f858015610b3d5750610b3d8963477cc53f60e11b611532565b90505f8180610b585750610b588a639061b92360e01b611532565b9050610b6b8a63582de3e760e01b611532565b8015610bef5750821580610bef5750808015610bef575060405163582de3e760e01b81526312d6c5b760e31b60048201526001600160a01b038b169063582de3e790602401602060405180830381865afa158015610bcb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bef91906124bd565b15610c39578015610c1457610c0f8a610c0a848c8c8b6115b8565b61164a565b610c39565b610c398a89636d6dd54060e01b5f60e01b60405180602001604052805f81525061136f565b60608315610c7357610c59896004808c51610c549190612875565b61166f565b806020019051810190610c6c9190612888565b9050610cbe565b60408051600180825281830190925290816020015b6060815260200190600190039081610c8857905050905088815f81518110610cb257610cb2612423565b60200260200101819052505b8115610d1b575f5b8151811015610d1957610cf4848c848481518110610ce657610ce6612423565b60200260200101518b6115b8565b828281518110610d0657610d06612423565b6020908102919091010152600101610cc6565b505b610dc43080639f28e99d610d308f868c6116cb565b604051602401610d40919061212f565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b94909417909352519092507f491fc4f900000000000000000000000000000000000000000000000000000000915f91610db0918b918a910191151582521515602082015260400190565b60405160208183030381529060405261136f565b505050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b148061035e57506301ffc9a760e01b6001600160e01b031983161461035e565b6060825167ffffffffffffffff811115610e2257610e22611d4f565b604051908082528060200260200182016040528015610e5557816020015b6060815260200190600190039081610e405790505b5090505f5b8351811015610f87575f848281518110610e7657610e76612423565b60209081029190910101516040810151606082015191925090600e165f03610eba578415610eb55780806020019051810190610eb2919061248b565b90505b610f5f565b805115610f5f578051601f1660048114610f5d575f60048210610ee757610ee2600483612875565b610ef2565b610ef2826004612875565b67ffffffffffffffff811115610f0a57610f0a611d4f565b6040519080825280601f01601f191660200182016040528015610f34576020820181803683370190505b5090508281604051602001610f4a929190612939565b6040516020818303038152906040529250505b505b80848481518110610f7257610f72612423565b60209081029190910101525050600101610e5a565b5092915050565b5f5f610fef7f000000000000000000000000000000000000000000000000000000000000000085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506117e0915050565b509093509150507f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae8114801561104d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b15610f8757507f00000000000000000000000000000000000000000000000000000000000000009392505050565b5f306001600160a01b0383160361109457506001919050565b6113885a5f5f5f5f8786fa50815a909103109392505050565b5f6060836001600160a01b0316856110e5577f00000000000000000000000000000000000000000000000000000000000000006110e7565b5a5b846040516110f5919061274d565b5f604051808303818686fa925050503d805f811461112e576040519150601f19603f3d011682016040523d82523d5f602084013e611133565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff81111561115d5761115d611d4f565b6040519080825280602002602001820160405280156111ba57816020015b6111a760405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161117b5790505b5090505f5f5b83515181101561126b575f845f015182815181106111e0576111e0612423565b6020026020010151905060408160600151165f03611262575f611206826040015161132b565b90506040518060600160405280825f01516001600160a01b031681526020018260200151815260200182604001518152508585806112439061276c565b96508151811061125557611255612423565b6020026020010181905250505b506001016111c0565b508015610a96578082523083602001518360405160240161128c919061294d565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af7600000000000000000000000000000000000000000000000000000000916113009189910161212f565b60408051601f1981840301815290829052630556f18360e41b8252610ae295949392916004016129de565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915261035e61136a836004808651610c549190612875565b611965565b5f5f61138461137d8861107b565b88886110ad565b91509150811580156113ae5750630556f18360e41b6113a28261259c565b6001600160e01b031916145b1561145c575f6113bd8261132b565b9050876001600160a01b0316815f01516001600160a01b03160361145a57308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b0319168152602001898152506040516020016113009190612a41565b505b5f82611468578461146a565b855b90506001600160e01b031981161561151c57306001600160a01b031681838660405160240161149a929190612712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114d8919061274d565b5f60405180830381855afa9150503d805f8114611510576040519150601f19603f3d011682016040523d82523d5f602084013e611515565b606091505b5090935091505b821561152a57815160208301f35b815160208301fd5b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f5190508280156115a2575060208210155b80156115ad57505f81115b979650505050505050565b6060846116015783836040516024016115d2929190612712565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b179052611641565b83838360405160240161161693929190612ac8565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b1790525b95945050505050565b61166b82825f60e01b5f60e01b60405180602001604052805f81525061136f565b5050565b60608167ffffffffffffffff81111561168a5761168a611d4f565b6040519080825280601f01601f1916602001820160405280156116b4576020820181803683370190505b5090506116c48484835f866119d0565b9392505050565b60408051808201909152606080825260208201525f835167ffffffffffffffff8111156116fa576116fa611d4f565b60405190808252806020026020018201604052801561175d57816020015b61174a60405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b8152602001906001900390816117185790505b5090505f5b84518110156117c3575f82828151811061177e5761177e612423565b60209081029190910101516001600160a01b038816815286519091508690839081106117ac576117ac612423565b602090810291909101810151910152600101611762565b506040805180820190915290815260208101929092525092915050565b5f5f5f5f5f5f6117f08888611a0d565b90925090508161180e57508794505f935083925085915061195c9050565b6118198989836117e0565b929850909650945092506001600160a01b0386161561194d575f61183d8989611a3a565b5090505f876001600160a01b031663e4ae7d77836040518263ffffffff1660e01b815260040161186d9190611cd0565b602060405180830381865afa158015611888573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118ac9190612b0a565b90506001600160a01b038116156118c4578096508894505b6040517f35af62160000000000000000000000000000000000000000000000000000000081526001600160a01b038916906335af621690611909908590600401611cd0565b602060405180830381865afa158015611924573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119489190612b0a565b975050505b505f9283526020526040909120905b93509350935093565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906119a29190612b25565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6119e3856119de8387612bda565b611ab7565b6119f1836119de8385612bda565b611a0682602085010185602088010183611aff565b5050505050565b5f5f5f611a1a8585611b48565b9250905060ff811615611a3257806021858701012092505b509250929050565b60605f5f611a488585611b48565b925090505f60ff821667ffffffffffffffff811115611a6957611a69611d4f565b6040519080825280601f01601f191660200182016040528015611a93576020820181803683370190505b509050611aac6020820160218888010160ff8516611aff565b959194509092505050565b815181111561166b5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610ae2918391600401918252602082015260400190565b5b601f811115611b20578151835260209283019290910190601f1901611b00565b8015610a965790518251600160209390930360031b9290921b5f190180199091169116179052565b5f5f83518310611b6d578360405163ba4adc2360e01b8152600401610ae29190611cd0565b838381518110611b7f57611b7f612423565b016020015160f81c91505081810160010181611b9f578351811415611ba5565b83518110155b15610a0f578360405163ba4adc2360e01b8152600401610ae29190611cd0565b6001600160e01b031981168114611bda575f5ffd5b50565b5f60208284031215611bed575f5ffd5b81356116c481611bc5565b5f5f83601f840112611c08575f5ffd5b50813567ffffffffffffffff811115611c1f575f5ffd5b602083019150836020828501011115610a0f575f5ffd5b5f5f5f5f60408587031215611c49575f5ffd5b843567ffffffffffffffff811115611c5f575f5ffd5b611c6b87828801611bf8565b909550935050602085013567ffffffffffffffff811115611c8a575f5ffd5b611c9687828801611bf8565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6116c46020830184611ca2565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b6001600160a01b0381168114611bda575f5ffd5b8035611d2f81611d10565b919050565b5f60208284031215611d44575f5ffd5b81356116c481611d10565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611d8657611d86611d4f565b60405290565b6040516080810167ffffffffffffffff81118282101715611d8657611d86611d4f565b60405160c0810167ffffffffffffffff81118282101715611d8657611d86611d4f565b604051601f8201601f1916810167ffffffffffffffff81118282101715611dfb57611dfb611d4f565b604052919050565b5f67ffffffffffffffff821115611e1c57611e1c611d4f565b5060051b60200190565b5f67ffffffffffffffff821115611e3f57611e3f611d4f565b50601f01601f191660200190565b5f611e5f611e5a84611e26565b611dd2565b9050828152838383011115611e72575f5ffd5b828260208301375f602084830101529392505050565b5f82601f830112611e97575f5ffd5b6116c483833560208501611e4d565b5f82601f830112611eb5575f5ffd5b8135611ec3611e5a82611e03565b8082825260208201915060208360051b860101925085831115611ee4575f5ffd5b602085015b83811015611f3857803567ffffffffffffffff811115611f07575f5ffd5b8601603f81018813611f17575f5ffd5b611f2988602083013560408401611e4d565b84525060209283019201611ee9565b5095945050505050565b5f60208284031215611f52575f5ffd5b813567ffffffffffffffff811115611f68575f5ffd5b820160408185031215611f79575f5ffd5b611f81611d63565b813567ffffffffffffffff811115611f97575f5ffd5b8201601f81018613611fa7575f5ffd5b8035611fb5611e5a82611e03565b8082825260208201915060208360051b850101925088831115611fd6575f5ffd5b602084015b8381101561209c57803567ffffffffffffffff811115611ff9575f5ffd5b85016080818c03601f1901121561200e575f5ffd5b612016611d8c565b602082013561202481611d10565b8152604082013567ffffffffffffffff81111561203f575f5ffd5b61204e8d602083860101611e88565b602083015250606082013567ffffffffffffffff81111561206d575f5ffd5b61207c8d602083860101611e88565b604083015250608091909101356060820152835260209283019201611fdb565b508452505050602082013567ffffffffffffffff8111156120bb575f5ffd5b6120c786828501611ea6565b602083015250949350505050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561212357601f1985840301885261210d838351611ca2565b60209889019890935091909101906001016120f1565b50909695505050505050565b602081525f6060820183516040602085015281815180845260808601915060808160051b87010193506020830192505f5b818110156121d657607f1987860301835283516001600160a01b0381511686526020810151608060208801526121996080880182611ca2565b9050604082015187820360408901526121b28282611ca2565b60609384015198909301979097525094506020938401939290920191600101612160565b505050506020840151838203601f1901604085015261164182826120d5565b5f5f60208385031215612206575f5ffd5b823567ffffffffffffffff81111561221c575f5ffd5b61222885828601611bf8565b90969095509350505050565b5f5f60408385031215612245575f5ffd5b823567ffffffffffffffff81111561225b575f5ffd5b61226785828601611e88565b925050602083013567ffffffffffffffff811115612283575f5ffd5b61228f85828601611e88565b9150509250929050565b8015158114611bda575f5ffd5b8035611d2f81612299565b5f5f5f5f5f5f60c087890312156122c6575f5ffd5b6122cf87611d24565b9550602087013567ffffffffffffffff8111156122ea575f5ffd5b6122f689828a01611e88565b955050604087013567ffffffffffffffff811115612312575f5ffd5b61231e89828a01611e88565b94505061232d606088016122a6565b9250608087013567ffffffffffffffff811115612348575f5ffd5b61235489828a01611e88565b92505060a087013567ffffffffffffffff811115612370575f5ffd5b61237c89828a01611ea6565b9150509295509295509295565b5f5f6040838503121561239a575f5ffd5b82356123a581612299565b915060208301356123b581612299565b809150509250929050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561241757603f19878603018452612402858351611ca2565b945060209384019391909101906001016123e6565b50929695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f612444611e5a84611e26565b9050828152838383011115612457575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f83011261247c575f5ffd5b6116c483835160208501612437565b5f6020828403121561249b575f5ffd5b815167ffffffffffffffff8111156124b1575f5ffd5b61042a8482850161246d565b5f602082840312156124cd575f5ffd5b81516116c481612299565b5f82601f8301126124e7575f5ffd5b81516124f5611e5a82611e03565b8082825260208201915060208360051b860101925085831115612516575f5ffd5b602085015b83811015611f3857805167ffffffffffffffff811115612539575f5ffd5b8601603f81018813612549575f5ffd5b61255b88602083015160408401612437565b8452506020928301920161251b565b5f6020828403121561257a575f5ffd5b815167ffffffffffffffff811115612590575f5ffd5b61042a848285016124d8565b805160208201516001600160e01b03198116919060048210156125d1576001600160e01b0319808360040360031b1b82161692505b5050919050565b5f82601f8301126125e7575f5ffd5b81356125f5611e5a82611e03565b8082825260208201915060208360051b860101925085831115612616575f5ffd5b602085015b83811015611f3857803567ffffffffffffffff811115612639575f5ffd5b612648886020838a0101611e88565b8452506020928301920161261b565b5f5f60408385031215612668575f5ffd5b823567ffffffffffffffff81111561267e575f5ffd5b8301601f8101851361268e575f5ffd5b803561269c611e5a82611e03565b8082825260208201915060208360051b8501019250878311156126bd575f5ffd5b6020840193505b828410156126e85783356126d781612299565b8252602093840193909101906126c4565b9450505050602083013567ffffffffffffffff811115612706575f5ffd5b61228f858286016125d8565b604081525f6127246040830185611ca2565b82810360208401526116418185611ca2565b5f81518060208401855e5f93019283525090919050565b5f6116c48284612736565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161277d5761277d612758565b5060010190565b8051611d2f81611d10565b8051611d2f81611bc5565b5f602082840312156127aa575f5ffd5b815167ffffffffffffffff8111156127c0575f5ffd5b820160c081850312156127d1575f5ffd5b6127d9611daf565b6127e282612784565b81526127f06020830161278f565b6020820152604082015167ffffffffffffffff81111561280e575f5ffd5b61281a8682850161246d565b60408301525061282c6060830161278f565b606082015261283d6080830161278f565b608082015260a082015167ffffffffffffffff81111561285b575f5ffd5b6128678682850161246d565b60a083015250949350505050565b8181038181111561035e5761035e612758565b5f60208284031215612898575f5ffd5b815167ffffffffffffffff8111156128ae575f5ffd5b8201601f810184136128be575f5ffd5b80516128cc611e5a82611e03565b8082825260208201915060208360051b8501019250868311156128ed575f5ffd5b602084015b8381101561292e57805167ffffffffffffffff811115612910575f5ffd5b61291f8960208389010161246d565b845250602092830192016128f2565b509695505050505050565b5f61042a6129478386612736565b84612736565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561241757603f1987860301845281516001600160a01b0381511686526020810151606060208801526129ac60608801826120d5565b90506040820151915086810360408801526129c78183611ca2565b965050506020938401939190910190600101612973565b6001600160a01b038616815260a060208201525f6129ff60a08301876120d5565b8281036040840152612a118187611ca2565b90506001600160e01b0319851660608401528281036080840152612a358185611ca2565b98975050505050505050565b602081526001600160a01b0382511660208201526001600160e01b031960208301511660408201525f604083015160c06060840152612a8360e0840182611ca2565b90506001600160e01b031960608501511660808401526001600160e01b031960808501511660a084015260a0840151601f198483030160c08501526116418282611ca2565b606081525f612ada6060830186611ca2565b8281036020840152612aec8186611ca2565b90508281036040840152612b008185611ca2565b9695505050505050565b5f60208284031215612b1a575f5ffd5b81516116c481611d10565b5f5f5f5f5f60a08688031215612b39575f5ffd5b8551612b4481611d10565b602087015190955067ffffffffffffffff811115612b60575f5ffd5b612b6c888289016124d8565b945050604086015167ffffffffffffffff811115612b88575f5ffd5b612b948882890161246d565b9350506060860151612ba581611bc5565b608087015190925067ffffffffffffffff811115612bc1575f5ffd5b612bcd8882890161246d565b9150509295509295909350565b8082018082111561035e5761035e61275856fea26469706673582212207d23079a1e8651c44c7b0cded3e72682066e809f3024009abd5ad3eb9a2f4f6d64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100f0575f3560e01c80639061b92311610093578063d8b55d2711610063578063d8b55d271461026a578063eea330f914610291578063ef46c0b8146102c3578063f394443a146102d8575f5ffd5b80639061b923146101fd5780639f28e99d14610210578063b536af7614610230578063c92cc49a14610243575f5ffd5b8063582de3e7116100ce578063582de3e71461017b5780636ccb86601461019f5780636d6dd540146101c65780636f3ff726146101ea575f5ffd5b806301ffc9a7146100f457806348ee1bcc1461011c578063491fc4f91461015b575b5f5ffd5b610107610102366004611bdd565b6102eb565b60405190151581526020015b60405180910390f35b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610113565b61016e610169366004611c36565b610364565b6040516101139190611cd0565b610107610189366004611bdd565b6001600160e01b0319166312d6c5b760e31b1490565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101dc6101d4366004611c36565b509192909150565b604051610113929190611ce2565b6101076101f8366004611d34565b610432565b61016e61020b366004611c36565b6104be565b61022361021e366004611f42565b6105ed565b604051610113919061212f565b61022361023e366004611c36565b6107ae565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6102a461029f3660046121f5565b6109fd565b604080516001600160a01b039093168352901515602083015201610113565b6102d66102d1366004612234565b610a16565b005b61016e6102e63660046122b1565b610a9b565b5f639061b92360e01b6001600160e01b03198316148061033457507feea330f9000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b8061034f575063582de3e760e01b6001600160e01b03198316145b8061035e575061035e82610dd2565b92915050565b60605f61037385870187611f42565b5190505f8061038485870187612389565b9150915081156103c1576103988382610e06565b6040516020016103a891906123c0565b604051602081830303815290604052935050505061042a565b5f835f815181106103d4576103d4612423565b60209081029190910101516040810151606082015191925090600e16156103fd57805160208201fd5b821561041a5780806020019051810190610417919061248b565b90505b945061042a9350505050565b5050505b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561049a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061035e91906124bd565b60606105e46104cd8686610f8e565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f9201829052506040805160208101825282815281517f093a86d3000000000000000000000000000000000000000000000000000000008152915192955093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063093a86d391600480830192879291908290030181865afa1580156105bd573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526102e6919081019061256a565b50949350505050565b60408051808201909152606080825260208201525f5b8251518110156107a0575f835f0151828151811061062357610623612423565b6020026020010151905060408160600151165f146106415750610798565b60608101516030165f036106eb575f61065c825f015161107b565b61066757601061066a565b60205b9050825b8551518110156106e857825f01516001600160a01b0316865f0151828151811061069a5761069a612423565b60200260200101515f01516001600160a01b0316036106e05781865f015182815181106106c9576106c9612423565b602002602001015160600181815117915081815250505b60010161066e565b50505b5f60208260600151165f1490505f5f61070d8315855f015186602001516110ad565b91509150811580156107375750630556f18360e41b61072b8261259c565b6001600160e01b031916145b1561074c57606084018051600117905261078c565b606084018051604017905282801561076357508051155b61077857816107785760608401805160021790525b80515f0361078c5760608401805160081790525b60409093019290925250505b600101610603565b506107aa82611140565b5090565b60408051808201909152606080825260208201525f806107d086880188612657565b9150915080518251146107f65760405163252e18f560e11b815260040160405180910390fd5b61080284860186611f42565b92505f5f5b8451518110156109d2575f855f0151828151811061082757610827612423565b6020026020010151905060408160600151165f036109c95783518310156109bd575f84848151811061085b5761085b612423565b6020026020010151905085848151811061087757610877612423565b6020026020010151156108945760608201805160441790526109b7565b5f6108a2836040015161132b565b90505f815f01516001600160a01b031682606001518484608001516040516024016108ce929190612712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161090c919061274d565b5f60405180830381855afa9150503d805f8114610944576040519150601f19603f3d011682016040523d82523d5f602084013e610949565b606091505b509350905080806109735750630556f18360e41b6109668461259c565b6001600160e01b03191614155b156109b457606084018051604017905280158061098f57508251155b156109a05760608401805160021790525b82515f036109b45760608401805160081790525b50505b60408201525b6109c68361276c565b92505b50600101610807565b50815181146109f45760405163252e18f560e11b815260040160405180910390fd5b61042684611140565b5f5f610a098484610f8e565b5f915091505b9250929050565b5f81806020019051810190610a2b919061279a565b9050610a96815f01518260200151858460400151604051602401610a50929190612712565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a086015161136f565b505050565b6060866001600160a01b03163b5f03610aeb57856040517f5fe9a5df000000000000000000000000000000000000000000000000000000008152600401610ae29190611cd0565b60405180910390fd5b5f7fac9650d800000000000000000000000000000000000000000000000000000000610b168761259c565b6001600160e01b0319161490505f858015610b3d5750610b3d8963477cc53f60e11b611532565b90505f8180610b585750610b588a639061b92360e01b611532565b9050610b6b8a63582de3e760e01b611532565b8015610bef5750821580610bef5750808015610bef575060405163582de3e760e01b81526312d6c5b760e31b60048201526001600160a01b038b169063582de3e790602401602060405180830381865afa158015610bcb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bef91906124bd565b15610c39578015610c1457610c0f8a610c0a848c8c8b6115b8565b61164a565b610c39565b610c398a89636d6dd54060e01b5f60e01b60405180602001604052805f81525061136f565b60608315610c7357610c59896004808c51610c549190612875565b61166f565b806020019051810190610c6c9190612888565b9050610cbe565b60408051600180825281830190925290816020015b6060815260200190600190039081610c8857905050905088815f81518110610cb257610cb2612423565b60200260200101819052505b8115610d1b575f5b8151811015610d1957610cf4848c848481518110610ce657610ce6612423565b60200260200101518b6115b8565b828281518110610d0657610d06612423565b6020908102919091010152600101610cc6565b505b610dc43080639f28e99d610d308f868c6116cb565b604051602401610d40919061212f565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b94909417909352519092507f491fc4f900000000000000000000000000000000000000000000000000000000915f91610db0918b918a910191151582521515602082015260400190565b60405160208183030381529060405261136f565b505050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b148061035e57506301ffc9a760e01b6001600160e01b031983161461035e565b6060825167ffffffffffffffff811115610e2257610e22611d4f565b604051908082528060200260200182016040528015610e5557816020015b6060815260200190600190039081610e405790505b5090505f5b8351811015610f87575f848281518110610e7657610e76612423565b60209081029190910101516040810151606082015191925090600e165f03610eba578415610eb55780806020019051810190610eb2919061248b565b90505b610f5f565b805115610f5f578051601f1660048114610f5d575f60048210610ee757610ee2600483612875565b610ef2565b610ef2826004612875565b67ffffffffffffffff811115610f0a57610f0a611d4f565b6040519080825280601f01601f191660200182016040528015610f34576020820181803683370190505b5090508281604051602001610f4a929190612939565b6040516020818303038152906040529250505b505b80848481518110610f7257610f72612423565b60209081029190910101525050600101610e5a565b5092915050565b5f5f610fef7f000000000000000000000000000000000000000000000000000000000000000085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506117e0915050565b509093509150507f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae8114801561104d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b15610f8757507f00000000000000000000000000000000000000000000000000000000000000009392505050565b5f306001600160a01b0383160361109457506001919050565b6113885a5f5f5f5f8786fa50815a909103109392505050565b5f6060836001600160a01b0316856110e5577f00000000000000000000000000000000000000000000000000000000000000006110e7565b5a5b846040516110f5919061274d565b5f604051808303818686fa925050503d805f811461112e576040519150601f19603f3d011682016040523d82523d5f602084013e611133565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff81111561115d5761115d611d4f565b6040519080825280602002602001820160405280156111ba57816020015b6111a760405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161117b5790505b5090505f5f5b83515181101561126b575f845f015182815181106111e0576111e0612423565b6020026020010151905060408160600151165f03611262575f611206826040015161132b565b90506040518060600160405280825f01516001600160a01b031681526020018260200151815260200182604001518152508585806112439061276c565b96508151811061125557611255612423565b6020026020010181905250505b506001016111c0565b508015610a96578082523083602001518360405160240161128c919061294d565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af7600000000000000000000000000000000000000000000000000000000916113009189910161212f565b60408051601f1981840301815290829052630556f18360e41b8252610ae295949392916004016129de565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915261035e61136a836004808651610c549190612875565b611965565b5f5f61138461137d8861107b565b88886110ad565b91509150811580156113ae5750630556f18360e41b6113a28261259c565b6001600160e01b031916145b1561145c575f6113bd8261132b565b9050876001600160a01b0316815f01516001600160a01b03160361145a57308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b0319168152602001898152506040516020016113009190612a41565b505b5f82611468578461146a565b855b90506001600160e01b031981161561151c57306001600160a01b031681838660405160240161149a929190612712565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114d8919061274d565b5f60405180830381855afa9150503d805f8114611510576040519150601f19603f3d011682016040523d82523d5f602084013e611515565b606091505b5090935091505b821561152a57815160208301f35b815160208301fd5b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f5190508280156115a2575060208210155b80156115ad57505f81115b979650505050505050565b6060846116015783836040516024016115d2929190612712565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b179052611641565b83838360405160240161161693929190612ac8565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b1790525b95945050505050565b61166b82825f60e01b5f60e01b60405180602001604052805f81525061136f565b5050565b60608167ffffffffffffffff81111561168a5761168a611d4f565b6040519080825280601f01601f1916602001820160405280156116b4576020820181803683370190505b5090506116c48484835f866119d0565b9392505050565b60408051808201909152606080825260208201525f835167ffffffffffffffff8111156116fa576116fa611d4f565b60405190808252806020026020018201604052801561175d57816020015b61174a60405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b8152602001906001900390816117185790505b5090505f5b84518110156117c3575f82828151811061177e5761177e612423565b60209081029190910101516001600160a01b038816815286519091508690839081106117ac576117ac612423565b602090810291909101810151910152600101611762565b506040805180820190915290815260208101929092525092915050565b5f5f5f5f5f5f6117f08888611a0d565b90925090508161180e57508794505f935083925085915061195c9050565b6118198989836117e0565b929850909650945092506001600160a01b0386161561194d575f61183d8989611a3a565b5090505f876001600160a01b031663e4ae7d77836040518263ffffffff1660e01b815260040161186d9190611cd0565b602060405180830381865afa158015611888573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118ac9190612b0a565b90506001600160a01b038116156118c4578096508894505b6040517f35af62160000000000000000000000000000000000000000000000000000000081526001600160a01b038916906335af621690611909908590600401611cd0565b602060405180830381865afa158015611924573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119489190612b0a565b975050505b505f9283526020526040909120905b93509350935093565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906119a29190612b25565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6119e3856119de8387612bda565b611ab7565b6119f1836119de8385612bda565b611a0682602085010185602088010183611aff565b5050505050565b5f5f5f611a1a8585611b48565b9250905060ff811615611a3257806021858701012092505b509250929050565b60605f5f611a488585611b48565b925090505f60ff821667ffffffffffffffff811115611a6957611a69611d4f565b6040519080825280601f01601f191660200182016040528015611a93576020820181803683370190505b509050611aac6020820160218888010160ff8516611aff565b959194509092505050565b815181111561166b5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610ae2918391600401918252602082015260400190565b5b601f811115611b20578151835260209283019290910190601f1901611b00565b8015610a965790518251600160209390930360031b9290921b5f190180199091169116179052565b5f5f83518310611b6d578360405163ba4adc2360e01b8152600401610ae29190611cd0565b838381518110611b7f57611b7f612423565b016020015160f81c91505081810160010181611b9f578351811415611ba5565b83518110155b15610a0f578360405163ba4adc2360e01b8152600401610ae29190611cd0565b6001600160e01b031981168114611bda575f5ffd5b50565b5f60208284031215611bed575f5ffd5b81356116c481611bc5565b5f5f83601f840112611c08575f5ffd5b50813567ffffffffffffffff811115611c1f575f5ffd5b602083019150836020828501011115610a0f575f5ffd5b5f5f5f5f60408587031215611c49575f5ffd5b843567ffffffffffffffff811115611c5f575f5ffd5b611c6b87828801611bf8565b909550935050602085013567ffffffffffffffff811115611c8a575f5ffd5b611c9687828801611bf8565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6116c46020830184611ca2565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b6001600160a01b0381168114611bda575f5ffd5b8035611d2f81611d10565b919050565b5f60208284031215611d44575f5ffd5b81356116c481611d10565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611d8657611d86611d4f565b60405290565b6040516080810167ffffffffffffffff81118282101715611d8657611d86611d4f565b60405160c0810167ffffffffffffffff81118282101715611d8657611d86611d4f565b604051601f8201601f1916810167ffffffffffffffff81118282101715611dfb57611dfb611d4f565b604052919050565b5f67ffffffffffffffff821115611e1c57611e1c611d4f565b5060051b60200190565b5f67ffffffffffffffff821115611e3f57611e3f611d4f565b50601f01601f191660200190565b5f611e5f611e5a84611e26565b611dd2565b9050828152838383011115611e72575f5ffd5b828260208301375f602084830101529392505050565b5f82601f830112611e97575f5ffd5b6116c483833560208501611e4d565b5f82601f830112611eb5575f5ffd5b8135611ec3611e5a82611e03565b8082825260208201915060208360051b860101925085831115611ee4575f5ffd5b602085015b83811015611f3857803567ffffffffffffffff811115611f07575f5ffd5b8601603f81018813611f17575f5ffd5b611f2988602083013560408401611e4d565b84525060209283019201611ee9565b5095945050505050565b5f60208284031215611f52575f5ffd5b813567ffffffffffffffff811115611f68575f5ffd5b820160408185031215611f79575f5ffd5b611f81611d63565b813567ffffffffffffffff811115611f97575f5ffd5b8201601f81018613611fa7575f5ffd5b8035611fb5611e5a82611e03565b8082825260208201915060208360051b850101925088831115611fd6575f5ffd5b602084015b8381101561209c57803567ffffffffffffffff811115611ff9575f5ffd5b85016080818c03601f1901121561200e575f5ffd5b612016611d8c565b602082013561202481611d10565b8152604082013567ffffffffffffffff81111561203f575f5ffd5b61204e8d602083860101611e88565b602083015250606082013567ffffffffffffffff81111561206d575f5ffd5b61207c8d602083860101611e88565b604083015250608091909101356060820152835260209283019201611fdb565b508452505050602082013567ffffffffffffffff8111156120bb575f5ffd5b6120c786828501611ea6565b602083015250949350505050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561212357601f1985840301885261210d838351611ca2565b60209889019890935091909101906001016120f1565b50909695505050505050565b602081525f6060820183516040602085015281815180845260808601915060808160051b87010193506020830192505f5b818110156121d657607f1987860301835283516001600160a01b0381511686526020810151608060208801526121996080880182611ca2565b9050604082015187820360408901526121b28282611ca2565b60609384015198909301979097525094506020938401939290920191600101612160565b505050506020840151838203601f1901604085015261164182826120d5565b5f5f60208385031215612206575f5ffd5b823567ffffffffffffffff81111561221c575f5ffd5b61222885828601611bf8565b90969095509350505050565b5f5f60408385031215612245575f5ffd5b823567ffffffffffffffff81111561225b575f5ffd5b61226785828601611e88565b925050602083013567ffffffffffffffff811115612283575f5ffd5b61228f85828601611e88565b9150509250929050565b8015158114611bda575f5ffd5b8035611d2f81612299565b5f5f5f5f5f5f60c087890312156122c6575f5ffd5b6122cf87611d24565b9550602087013567ffffffffffffffff8111156122ea575f5ffd5b6122f689828a01611e88565b955050604087013567ffffffffffffffff811115612312575f5ffd5b61231e89828a01611e88565b94505061232d606088016122a6565b9250608087013567ffffffffffffffff811115612348575f5ffd5b61235489828a01611e88565b92505060a087013567ffffffffffffffff811115612370575f5ffd5b61237c89828a01611ea6565b9150509295509295509295565b5f5f6040838503121561239a575f5ffd5b82356123a581612299565b915060208301356123b581612299565b809150509250929050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561241757603f19878603018452612402858351611ca2565b945060209384019391909101906001016123e6565b50929695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f612444611e5a84611e26565b9050828152838383011115612457575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f83011261247c575f5ffd5b6116c483835160208501612437565b5f6020828403121561249b575f5ffd5b815167ffffffffffffffff8111156124b1575f5ffd5b61042a8482850161246d565b5f602082840312156124cd575f5ffd5b81516116c481612299565b5f82601f8301126124e7575f5ffd5b81516124f5611e5a82611e03565b8082825260208201915060208360051b860101925085831115612516575f5ffd5b602085015b83811015611f3857805167ffffffffffffffff811115612539575f5ffd5b8601603f81018813612549575f5ffd5b61255b88602083015160408401612437565b8452506020928301920161251b565b5f6020828403121561257a575f5ffd5b815167ffffffffffffffff811115612590575f5ffd5b61042a848285016124d8565b805160208201516001600160e01b03198116919060048210156125d1576001600160e01b0319808360040360031b1b82161692505b5050919050565b5f82601f8301126125e7575f5ffd5b81356125f5611e5a82611e03565b8082825260208201915060208360051b860101925085831115612616575f5ffd5b602085015b83811015611f3857803567ffffffffffffffff811115612639575f5ffd5b612648886020838a0101611e88565b8452506020928301920161261b565b5f5f60408385031215612668575f5ffd5b823567ffffffffffffffff81111561267e575f5ffd5b8301601f8101851361268e575f5ffd5b803561269c611e5a82611e03565b8082825260208201915060208360051b8501019250878311156126bd575f5ffd5b6020840193505b828410156126e85783356126d781612299565b8252602093840193909101906126c4565b9450505050602083013567ffffffffffffffff811115612706575f5ffd5b61228f858286016125d8565b604081525f6127246040830185611ca2565b82810360208401526116418185611ca2565b5f81518060208401855e5f93019283525090919050565b5f6116c48284612736565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161277d5761277d612758565b5060010190565b8051611d2f81611d10565b8051611d2f81611bc5565b5f602082840312156127aa575f5ffd5b815167ffffffffffffffff8111156127c0575f5ffd5b820160c081850312156127d1575f5ffd5b6127d9611daf565b6127e282612784565b81526127f06020830161278f565b6020820152604082015167ffffffffffffffff81111561280e575f5ffd5b61281a8682850161246d565b60408301525061282c6060830161278f565b606082015261283d6080830161278f565b608082015260a082015167ffffffffffffffff81111561285b575f5ffd5b6128678682850161246d565b60a083015250949350505050565b8181038181111561035e5761035e612758565b5f60208284031215612898575f5ffd5b815167ffffffffffffffff8111156128ae575f5ffd5b8201601f810184136128be575f5ffd5b80516128cc611e5a82611e03565b8082825260208201915060208360051b8501019250868311156128ed575f5ffd5b602084015b8381101561292e57805167ffffffffffffffff811115612910575f5ffd5b61291f8960208389010161246d565b845250602092830192016128f2565b509695505050505050565b5f61042a6129478386612736565b84612736565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561241757603f1987860301845281516001600160a01b0381511686526020810151606060208801526129ac60608801826120d5565b90506040820151915086810360408801526129c78183611ca2565b965050506020938401939190910190600101612973565b6001600160a01b038616815260a060208201525f6129ff60a08301876120d5565b8281036040840152612a118187611ca2565b90506001600160e01b0319851660608401528281036080840152612a358185611ca2565b98975050505050505050565b602081526001600160a01b0382511660208201526001600160e01b031960208301511660408201525f604083015160c06060840152612a8360e0840182611ca2565b90506001600160e01b031960608501511660808401526001600160e01b031960808501511660a084015260a0840151601f198483030160c08501526116418282611ca2565b606081525f612ada6060830186611ca2565b8281036020840152612aec8186611ca2565b90508281036040840152612b008185611ca2565b9695505050505050565b5f60208284031215612b1a575f5ffd5b81516116c481611d10565b5f5f5f5f5f60a08688031215612b39575f5ffd5b8551612b4481611d10565b602087015190955067ffffffffffffffff811115612b60575f5ffd5b612b6c888289016124d8565b945050604086015167ffffffffffffffff811115612b88575f5ffd5b612b948882890161246d565b9350506060860151612ba581611bc5565b608087015190925067ffffffffffffffff811115612bc1575f5ffd5b612bcd8882890161246d565b9150509295509295909350565b8082018082111561035e5761035e61275856fea26469706673582212207d23079a1e8651c44c7b0cded3e72682066e809f3024009abd5ad3eb9a2f4f6d64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "1210": [ + { + "length": 32, + "start": 4289 + } + ], + "69129": [ + { + "length": 32, + "start": 420 + }, + { + "length": 32, + "start": 1396 + } + ], + "69334": [ + { + "length": 32, + "start": 584 + }, + { + "length": 32, + "start": 3989 + } + ], + "69337": [ + { + "length": 32, + "start": 623 + }, + { + "length": 32, + "start": 4130 + }, + { + "length": 32, + "start": 4181 + } + ], + "75212": [ + { + "length": 32, + "start": 289 + }, + { + "length": 32, + "start": 1107 + } + ] + }, + "inputSourceName": "project/src/resolver/ENSV2Resolver.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "InvalidBatchGatewayResponse()": [ + { + "details": "Error selector: `0x4a5c31ea`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "UnreachableName(bytes)": [ + { + "details": "`name` cannot be resolved. Error selector: `0x5fe9a5df`", + "params": { + "name": "The DNS-encoded ENS name." + } + } + ] + }, + "kind": "dev", + "methods": { + "callResolver(address,bytes,bytes,bool,bytes,string[])": { + "details": "Reverts `UnreachableName` if resolver is not a contract. This function never returns normally. The return type is necessary to define the result of the callback. Call this function externally or with `ccipRead()` to intercept the response.", + "params": { + "batchGateways": "The batch gateway URLs.", + "context": "The context for `IExtendedDNSResolver`.", + "data": "The calldata for the resolution.", + "hasContext": "True if `IExtendedDNSResolver` should be considered.", + "name": "The DNS-encoded ENS name.", + "resolver": "The resolver to call." + } + }, + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": { + "details": "Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`." + }, + "ccipBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \"done\".", + "params": { + "extraData": "The contextual data passed from `ccipBatch()`.", + "response": "The response from the batch gateway." + }, + "returns": { + "batch": "The batch where every lookup is \"done\"." + } + }, + "ccipReadCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.", + "params": { + "extraData": "The contextual data passed from `ccipRead()`.", + "response": "The response from offchain." + } + }, + "constructor": { + "params": { + "batchGatewayProvider": "The batch gateway provider.", + "contractNamer": "Delegated contract namer.", + "ethResolver": "The override resolver for \"eth\" or null to use ENSv2.", + "rootRegistry": "The ENSv2 root registry." + } + }, + "getResolver(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The underlying resolver address.", + "_1": "`true` if `resolver` is offchain." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "resolveBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `callResolver()` from batch calling a resolver.", + "params": { + "extraData": "The abi-encoded properties of the call.", + "response": "The response data from the batch gateway." + }, + "returns": { + "_0": "result The response from the resolver." + } + }, + "resolveDirectImmediateCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `callResolver()` from direct calling an immediate resolver." + }, + "supportsFeature(bytes4)": { + "params": { + "featureId": "The feature identifier." + }, + "returns": { + "_0": "`true` if the feature is supported by the contract." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "2259800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BATCH_GATEWAY_PROVIDER()": "infinite", + "CONTRACT_NAMER()": "infinite", + "ETH_RESOLVER()": "infinite", + "ROOT_REGISTRY()": "infinite", + "callResolver(address,bytes,bytes,bool,bytes,string[])": "infinite", + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": "infinite", + "ccipBatchCallback(bytes,bytes)": "infinite", + "ccipReadCallback(bytes,bytes)": "infinite", + "getResolver(bytes)": "infinite", + "isContractNamer(address)": "infinite", + "resolve(bytes,bytes)": "infinite", + "resolveBatchCallback(bytes,bytes)": "infinite", + "resolveDirectImmediateCallback(bytes,bytes)": "infinite", + "supportsFeature(bytes4)": "396", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_findResolver(bytes calldata)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"batchGatewayProvider\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"rootRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ethResolver\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBatchGatewayResponse\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"UnreachableName\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BATCH_GATEWAY_PROVIDER\",\"outputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"hasContext\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"batchGateways\",\"type\":\"string[]\"}],\"name\":\"callResolver\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"name\":\"ccipBatch\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipBatchCallback\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipReadCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveBatchCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"resolveDirectImmediateCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"feature\",\"type\":\"bytes4\"}],\"name\":\"supportsFeature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"InvalidBatchGatewayResponse()\":[{\"details\":\"Error selector: `0x4a5c31ea`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"UnreachableName(bytes)\":[{\"details\":\"`name` cannot be resolved. Error selector: `0x5fe9a5df`\",\"params\":{\"name\":\"The DNS-encoded ENS name.\"}}]},\"kind\":\"dev\",\"methods\":{\"callResolver(address,bytes,bytes,bool,bytes,string[])\":{\"details\":\"Reverts `UnreachableName` if resolver is not a contract. This function never returns normally. The return type is necessary to define the result of the callback. Call this function externally or with `ccipRead()` to intercept the response.\",\"params\":{\"batchGateways\":\"The batch gateway URLs.\",\"context\":\"The context for `IExtendedDNSResolver`.\",\"data\":\"The calldata for the resolution.\",\"hasContext\":\"True if `IExtendedDNSResolver` should be considered.\",\"name\":\"The DNS-encoded ENS name.\",\"resolver\":\"The resolver to call.\"}},\"ccipBatch(((address,bytes,bytes,uint256)[],string[]))\":{\"details\":\"Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`.\"},\"ccipBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\",\"params\":{\"extraData\":\"The contextual data passed from `ccipBatch()`.\",\"response\":\"The response from the batch gateway.\"},\"returns\":{\"batch\":\"The batch where every lookup is \\\"done\\\".\"}},\"ccipReadCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.\",\"params\":{\"extraData\":\"The contextual data passed from `ccipRead()`.\",\"response\":\"The response from offchain.\"}},\"constructor\":{\"params\":{\"batchGatewayProvider\":\"The batch gateway provider.\",\"contractNamer\":\"Delegated contract namer.\",\"ethResolver\":\"The override resolver for \\\"eth\\\" or null to use ENSv2.\",\"rootRegistry\":\"The ENSv2 root registry.\"}},\"getResolver(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The underlying resolver address.\",\"_1\":\"`true` if `resolver` is offchain.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"resolveBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `callResolver()` from batch calling a resolver.\",\"params\":{\"extraData\":\"The abi-encoded properties of the call.\",\"response\":\"The response data from the batch gateway.\"},\"returns\":{\"_0\":\"result The response from the resolver.\"}},\"resolveDirectImmediateCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `callResolver()` from direct calling an immediate resolver.\"},\"supportsFeature(bytes4)\":{\"params\":{\"featureId\":\"The feature identifier.\"},\"returns\":{\"_0\":\"`true` if the feature is supported by the contract.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBatchGatewayResponse()\":[{\"notice\":\"The batch gateway supplied an incorrect number of responses.\"}]},\"kind\":\"user\",\"methods\":{\"BATCH_GATEWAY_PROVIDER()\":{\"notice\":\"Shared batch gateway provider.\"},\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"ETH_RESOLVER()\":{\"notice\":\"The ENSv1 resolver for \\\"eth\\\".\"},\"ROOT_REGISTRY()\":{\"notice\":\"The ENSv2 root registry used to traverse the registry hierarchy and locate resolvers.\"},\"callResolver(address,bytes,bytes,bool,bytes,string[])\":{\"notice\":\"Perform forward resolution. Call this function with `ccipRead()` to intercept the response. Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers. - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features, the call is performed directly without the batch gateway. - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature, the call is performed directly without the batch gateway. - Otherwise, the call is performed with the batch gateway. The batch gateway is only invoked if any call reverts `OffchainLookup`. If the calldata is `multicall()` it is disassembled, called separately, and reassembled.\"},\"getResolver(bytes)\":{\"notice\":\"Fetch the underlying resolver for `name`. Callers should enable EIP-3668. * If `offchain`, additional information is necessary to locate `resolver`. * If `resolver` is null, `offchain` is irrelevant.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"supportsFeature(bytes4)\":{\"notice\":\"Check if a feature is supported.\"}},\"notice\":\"Resolver that performs resolutions using ENSv2 with override for ENSv1 \\\"eth\\\" resolver.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/resolver/ENSV2Resolver.sol\":\"ENSV2Resolver\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/CCIPBatcher.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {IBatchGateway} from \\\"./IBatchGateway.sol\\\";\\nimport {CCIPReader, EIP3668, OffchainLookup} from \\\"./CCIPReader.sol\\\";\\n\\n/// @dev CCIP-Read batch gateway client implementation.\\n///\\n/// Since requests are read-only, empty responses are considered an error.\\n///\\n/// Usage: `ccipRead(address(this), abi.encodeCall(this.ccipBatch, (createBatch(...))), ...)`\\n///\\nabstract contract CCIPBatcher is CCIPReader {\\n /// @notice The batch gateway supplied an incorrect number of responses.\\n /// @dev Error selector: `0x4a5c31ea`\\n error InvalidBatchGatewayResponse();\\n\\n uint256 constant FLAG_OFFCHAIN = 1 << 0; // the lookup reverted `OffchainLookup`\\n uint256 constant FLAG_CALL_ERROR = 1 << 1; // the initial call or callback reverted\\n uint256 constant FLAG_BATCH_ERROR = 1 << 2; // `OffchainLookup` failed on the batch gateway\\n uint256 constant FLAG_EMPTY_RESPONSE = 1 << 3; // the initial call or callback returned `0x`\\n uint256 constant FLAG_EIP140_BEFORE = 1 << 4; // does not have revert op code\\n uint256 constant FLAG_EIP140_AFTER = 1 << 5; // has revert op code\\n uint256 constant FLAG_DONE = 1 << 6; // the lookup has finished processing (private)\\n\\n uint256 constant FLAGS_ANY_ERROR =\\n FLAG_CALL_ERROR | FLAG_BATCH_ERROR | FLAG_EMPTY_RESPONSE;\\n uint256 constant FLAGS_ANY_EIP140 = FLAG_EIP140_BEFORE | FLAG_EIP140_AFTER;\\n\\n /// @dev An independent `OffchainLookup` session.\\n struct Lookup {\\n address target; // contract to call\\n bytes call; // initial calldata\\n bytes data; // response or error\\n uint256 flags; // see: FLAG_*\\n }\\n\\n /// @dev A batch gateway session.\\n struct Batch {\\n Lookup[] lookups;\\n string[] gateways;\\n }\\n\\n /// @dev Create a batch for a single target with multiple calls.\\n /// @param target The target contract.\\n /// @param calls The list of calldata.\\n /// @param gateways The batch gateway URLs.\\n function createBatch(\\n address target,\\n bytes[] memory calls,\\n string[] memory gateways\\n ) internal pure returns (Batch memory) {\\n Lookup[] memory lookups = new Lookup[](calls.length);\\n for (uint256 i; i < calls.length; ++i) {\\n Lookup memory lu = lookups[i];\\n lu.target = target;\\n lu.call = calls[i];\\n }\\n return Batch(lookups, gateways);\\n }\\n\\n /// @dev Use `ccipRead()` to call this function with a batch.\\n /// The callback response will be `abi.encode(batch)`.\\n function ccipBatch(\\n Batch memory batch\\n ) external view returns (Batch memory) {\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) != 0) {\\n continue; // don't call a lookup that's already done\\n }\\n if ((lu.flags & FLAGS_ANY_EIP140) == 0) {\\n uint256 flags = detectEIP140(lu.target)\\n ? FLAG_EIP140_AFTER\\n : FLAG_EIP140_BEFORE;\\n for (uint256 j = i; j < batch.lookups.length; ++j) {\\n if (batch.lookups[j].target == lu.target) {\\n batch.lookups[j].flags |= flags;\\n }\\n }\\n }\\n bool unsafe = (lu.flags & FLAG_EIP140_AFTER) == 0;\\n (bool ok, bytes memory v) = safeCall(!unsafe, lu.target, lu.call);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n lu.flags |= FLAG_OFFCHAIN;\\n } else {\\n lu.flags |= FLAG_DONE;\\n if (unsafe && v.length == 0) {\\n // unsafe contracts appear the same for throw and unimplemented fallback\\n // decision: interpret like an unimplemented function selector response\\n } else if (!ok) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n lu.data = v;\\n }\\n _revertBatchGateway(batch); // reverts if any offchain\\n return batch;\\n }\\n\\n /// @dev Check if the batch is \\\"done\\\". If not, revert `OffchainLookup` for batch gateway.\\n function _revertBatchGateway(Batch memory batch) internal view {\\n IBatchGateway.Request[] memory requests = new IBatchGateway.Request[](\\n batch.lookups.length\\n );\\n uint256 count;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n requests[count++] = IBatchGateway.Request(\\n p.sender,\\n p.urls,\\n p.callData\\n );\\n }\\n }\\n if (count > 0) {\\n assembly {\\n mstore(requests, count) // truncate to number of offchain requests\\n }\\n revert OffchainLookup(\\n address(this),\\n batch.gateways,\\n abi.encodeCall(IBatchGateway.query, (requests)),\\n this.ccipBatchCallback.selector,\\n abi.encode(batch)\\n );\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipBatch()`.\\n /// Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\\n /// @param response The response from the batch gateway.\\n /// @param extraData The contextual data passed from `ccipBatch()`.\\n /// @return batch The batch where every lookup is \\\"done\\\".\\n function ccipBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (Batch memory batch) {\\n (bool[] memory failures, bytes[] memory responses) = abi.decode(\\n response,\\n (bool[], bytes[])\\n );\\n if (failures.length != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n batch = abi.decode(extraData, (Batch));\\n uint256 expected;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n if (expected < responses.length) {\\n bytes memory v = responses[expected];\\n if (failures[expected]) {\\n lu.flags |= FLAG_DONE | FLAG_BATCH_ERROR;\\n } else {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n bool ok;\\n // assumption: unsafe contracts don't revert OffchainLookup()\\n (ok, v) = p.sender.staticcall(\\n abi.encodeWithSelector(\\n p.callbackFunction,\\n v,\\n p.extraData\\n )\\n );\\n if (ok || bytes4(v) != OffchainLookup.selector) {\\n lu.flags |= FLAG_DONE;\\n // decision: promote empty response from the callback => call error\\n // ie. the initial function was implemented but the callback was not\\n // this can be detected via FLAG_OFFCHAIN\\n if (!ok || v.length == 0) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n }\\n lu.data = v;\\n }\\n ++expected;\\n }\\n }\\n if (expected != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n _revertBatchGateway(batch);\\n }\\n\\n /// @dev Safely collapse `Lookup[]` into `bytes[]`.\\n /// If `FLAGS_ANY_ERROR` and response is non-empty, the response is zero-padded so that `length % 32 == 4`.\\n /// @param lookups Array of completed lookups.\\n /// @param wrapped If `true`, successful responses are unwrapped as `bytes`.\\n /// @return arr Array of call responses.\\n function _toResponseArray(Lookup[] memory lookups, bool wrapped) internal pure returns (bytes[] memory arr) {\\n arr = new bytes[](lookups.length);\\n for (uint256 i; i < lookups.length; ++i) {\\n Lookup memory lu = lookups[i];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) == 0) {\\n if (wrapped) {\\n v = abi.decode(v, (bytes));\\n }\\n } else if (v.length != 0) {\\n uint256 rem = v.length & 31;\\n if (rem != 4) {\\n bytes memory pad = new bytes(rem < 4 ? 4 - rem : rem - 4);\\n v = abi.encodePacked(v, pad); \\n }\\n }\\n arr[i] = v;\\n }\\n return arr;\\n }\\n}\",\"keccak256\":\"0x0979783da5e97d3024259857fc414d325874abd7ea1a68838b177003b511dc5d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/CCIPReader.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n/// @author Modified from https://github.com/unruggable-labs/CCIPReader.sol/blob/341576fe7ff2b6e0c93fc08f37740cf6439f5873/contracts/CCIPReader.sol\\n\\n/// MIT License\\n/// Portions Copyright (c) 2025 Unruggable\\n/// Portions Copyright (c) 2025 ENS Labs Ltd\\n\\n/// @dev Instructions:\\n/// 1. inherit this contract\\n/// 2. call `ccipRead()` similar to `staticcall()`\\n/// 3. do not put logic after this invocation\\n/// 4. implement all response logic in callback\\n/// 5. ensure that return type of calling function == callback function\\n\\nimport {EIP3668, OffchainLookup} from \\\"./EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\n\\ncontract CCIPReader {\\n /// @dev Default unsafe call gas (sufficient for legacy ENS resolver profiles).\\n uint256 constant DEFAULT_UNSAFE_CALL_GAS = 50000;\\n\\n /// @dev Special-purpose value for identity callback: `f(x) = x`.\\n bytes4 constant IDENTITY_FUNCTION = bytes4(0);\\n\\n /// @dev The gas limit for calling functions on unsafe contracts.\\n uint256 immutable unsafeCallGas;\\n\\n constructor(uint256 _unsafeCallGas) {\\n unsafeCallGas = _unsafeCallGas;\\n }\\n\\n /// @dev A recursive CCIP-Read session.\\n struct Context {\\n address target;\\n bytes4 callbackFunction;\\n bytes extraData;\\n bytes4 successCallbackFunction;\\n bytes4 failureCallbackFunction;\\n bytes myExtraData;\\n }\\n\\n /// @dev Same as `ccipRead()` but the callback function is the identity.\\n function ccipRead(address target, bytes memory call) internal view {\\n ccipRead(target, call, IDENTITY_FUNCTION, IDENTITY_FUNCTION, \\\"\\\");\\n }\\n\\n /// @dev Performs a CCIP-Read and handles internal recursion.\\n /// Reverts `OffchainLookup` if necessary.\\n /// Use `IDENTITY_FUNCTION` as the callback function selector for return/revert behavior.\\n /// @param target The contract address.\\n /// @param call The calldata to `staticcall()` on `target`.\\n /// @param successCallbackFunction The function selector of callback on success.\\n /// @param failureCallbackFunction The function selector of callback on failure.\\n /// @param extraData The contextual data relayed to callback function.\\n function ccipRead(\\n address target,\\n bytes memory call,\\n bytes4 successCallbackFunction,\\n bytes4 failureCallbackFunction,\\n bytes memory extraData\\n ) internal view {\\n // We call the intended function that **could** revert with an `OffchainLookup`\\n // We destructure the response into an execution status bool and our return bytes\\n (bool ok, bytes memory v) = safeCall(\\n detectEIP140(target),\\n target,\\n call\\n );\\n // IF the function reverted with an `OffchainLookup`\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n // We decode the response error into a tuple\\n // tuples allow flexibility noting stack too deep constraints\\n EIP3668.Params memory p = decodeOffchainLookup(v);\\n if (p.sender == target) {\\n // We then wrap the error data in an `OffchainLookup` sent/'owned' by this contract\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n this.ccipReadCallback.selector,\\n abi.encode(\\n Context(\\n target,\\n p.callbackFunction,\\n p.extraData,\\n successCallbackFunction,\\n failureCallbackFunction,\\n extraData\\n )\\n )\\n );\\n }\\n }\\n // IF we have gotten here, the 'real' target does not revert with an `OffchainLookup` error\\n // figure out what callback to call\\n bytes4 callbackFunction = ok\\n ? successCallbackFunction\\n : failureCallbackFunction;\\n if (callbackFunction != IDENTITY_FUNCTION) {\\n // The exit point of this architecture is OUR callback in the 'real'\\n // We pass through the response to that callback\\n (ok, v) = address(this).staticcall(\\n abi.encodeWithSelector(callbackFunction, v, extraData)\\n );\\n }\\n // OR the call to the 'real' target reverts with a different error selector\\n // OR the call to OUR callback reverts with ANY error selector\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipRead()`.\\n /// @param response The response from offchain.\\n /// @param extraData The contextual data passed from `ccipRead()`.\\n /// @dev The return type of this function is polymorphic depending on the caller.\\n function ccipReadCallback(\\n bytes memory response,\\n bytes memory extraData\\n ) external view {\\n Context memory ctx = abi.decode(extraData, (Context));\\n // Since the callback can revert too (but has the same return structure)\\n // We can reuse the calling infrastructure to call the callback\\n ccipRead(\\n ctx.target,\\n abi.encodeWithSelector(\\n ctx.callbackFunction,\\n response,\\n ctx.extraData\\n ),\\n ctx.successCallbackFunction,\\n ctx.failureCallbackFunction,\\n ctx.myExtraData\\n );\\n }\\n\\n /// @dev Decode `OffchainLookup` error data into a struct.\\n /// @param v The error data of the revert.\\n /// @return p The decoded `OffchainLookup` params.\\n function decodeOffchainLookup(\\n bytes memory v\\n ) internal pure returns (EIP3668.Params memory p) {\\n p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n }\\n\\n /// @dev Determine if `target` uses `revert()` instead of `invalid()`.\\n // Assumption: only newer contracts revert `OffchainLookup`.\\n /// @param target The contract to test.\\n /// @return safe True if safe to call.\\n function detectEIP140(address target) internal view returns (bool safe) {\\n if (target == address(this)) return true;\\n // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md\\n assembly {\\n let G := 5000\\n let g := gas()\\n pop(staticcall(G, target, 0, 0, 0, 0))\\n safe := lt(sub(g, gas()), G)\\n }\\n }\\n\\n /// @dev Same as `staticcall()` but prevents OOG when not `safe`.\\n function safeCall(\\n bool safe,\\n address target,\\n bytes memory call\\n ) internal view returns (bool ok, bytes memory v) {\\n (ok, v) = target.staticcall{gas: safe ? gasleft() : unsafeCallGas}(\\n call\\n );\\n }\\n}\\n\",\"keccak256\":\"0xa6f483e89e779385c2b7ea6376d92cd3c05c98f91d1a3c7c43dc7422fe6b014f\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IBatchGateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for Batch Gateway Offchain Lookup Protocol.\\n/// https://docs.ens.domains/ensip/21/\\n/// @dev Interface selector: `0xa780bab6`\\ninterface IBatchGateway {\\n /// @notice An HTTP error occurred.\\n /// @dev Error selector: `0x01800152`\\n error HttpError(uint16 status, string message);\\n\\n /// @dev Information extracted from an `OffchainLookup` revert.\\n struct Request {\\n address sender;\\n string[] urls;\\n bytes data;\\n }\\n\\n /// @notice Perform multiple `OffchainLookup` in parallel.\\n /// Callers should enable EIP-3668.\\n /// @param requests The array of requests to lookup in parallel.\\n /// @return failures The failure status of the corresponding request.\\n /// @return responses The response or error data of the corresponding request.\\n function query(\\n Request[] memory requests\\n ) external view returns (bool[] memory failures, bytes[] memory responses);\\n}\\n\",\"keccak256\":\"0xfd7f0c7bdc29fc732ec54da2ebaea241873e55082e484729901811bc9374d6f6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IGatewayProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for shared gateway URLs.\\n/// @dev Interface selector: `0x093a86d3`\\ninterface IGatewayProvider {\\n /// @notice Get the gateways.\\n /// @return The gateway URLs.\\n function gateways() external view returns (string[] memory);\\n}\\n\",\"keccak256\":\"0x7c169843cfb65657a88fb4d5f7ec44612994d7d87cb7b1a67cbfdb18758823e0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverFeatures.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary ResolverFeatures {\\n /// @notice Implements `resolve(multicall([...]))`.\\n /// @dev Feature: `0x96b62db8`\\n bytes4 constant RESOLVE_MULTICALL =\\n bytes4(keccak256(\\\"eth.ens.resolver.extended.multicall\\\"));\\n\\n /// @notice Returns the same records independent of name or node.\\n /// @dev Feature: `0x86fb8da8`\\n bytes4 constant SINGULAR = bytes4(keccak256(\\\"eth.ens.resolver.singular\\\"));\\n}\\n\",\"keccak256\":\"0x87d131fcbdd7951a17b0a94f7f02470ec3f62c6004cf91c2d2acc54098373be6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ICompositeResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport {IExtendedResolver} from \\\"./IExtendedResolver.sol\\\";\\n\\n/// @notice A resolver that calls other resolvers.\\n/// @dev Interface selector: `0xeea330f9`\\ninterface ICompositeResolver is IExtendedResolver {\\n /// @notice Fetch the underlying resolver for `name`.\\n /// Callers should enable EIP-3668.\\n ///\\n /// * If `offchain`, additional information is necessary to locate `resolver`.\\n /// * If `resolver` is null, `offchain` is irrelevant.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return resolver The underlying resolver address.\\n /// @return offchain `true` if `resolver` is offchain.\\n function getResolver(\\n bytes memory name\\n ) external view returns (address resolver, bool offchain);\\n}\\n\",\"keccak256\":\"0xe267bef9a45073c92129ededa0275acf29394fa3fb30547bab8138dac485e2b2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedDNSResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data,\\n bytes memory context\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x541f8799c34ff9e7035d09f06ae0f0f8a16b6065e9b60a15670b957321630f72\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/ResolverCaller.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {\\n ERC165Checker\\n} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {CCIPBatcher} from \\\"../ccipRead/CCIPBatcher.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\nimport {IERC7996} from \\\"../utils/IERC7996.sol\\\";\\nimport {ResolverFeatures} from \\\"../resolvers/ResolverFeatures.sol\\\";\\n\\n// resolver profiles\\nimport {IExtendedResolver} from \\\"../resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {\\n IExtendedDNSResolver\\n} from \\\"../resolvers/profiles/IExtendedDNSResolver.sol\\\";\\nimport {IMulticallable} from \\\"../resolvers/IMulticallable.sol\\\";\\n\\nabstract contract ResolverCaller is CCIPBatcher {\\n /// @dev `name` cannot be resolved.\\n /// Error selector: `0x5fe9a5df`\\n /// @param name The DNS-encoded ENS name.\\n error UnreachableName(bytes name);\\n\\n /// @notice Perform forward resolution.\\n ///\\n /// Call this function with `ccipRead()` to intercept the response.\\n /// Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers.\\n ///\\n /// - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features,\\n /// the call is performed directly without the batch gateway.\\n /// - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature,\\n /// the call is performed directly without the batch gateway.\\n /// - Otherwise, the call is performed with the batch gateway.\\n /// The batch gateway is only invoked if any call reverts `OffchainLookup`.\\n /// If the calldata is `multicall()` it is disassembled, called separately, and reassembled.\\n ///\\n /// @dev Reverts `UnreachableName` if resolver is not a contract.\\n\\t/// This function never returns normally.\\n\\t/// The return type is necessary to define the result of the callback.\\n\\t/// Call this function externally or with `ccipRead()` to intercept the response.\\n /// @param resolver The resolver to call.\\n /// @param name The DNS-encoded ENS name.\\n /// @param data The calldata for the resolution.\\n /// @param hasContext True if `IExtendedDNSResolver` should be considered.\\n /// @param context The context for `IExtendedDNSResolver`.\\n /// @param batchGateways The batch gateway URLs.\\n function callResolver(\\n address resolver,\\n bytes memory name,\\n bytes memory data,\\n bool hasContext,\\n bytes memory context,\\n string[] memory batchGateways\\n ) public view returns (bytes memory) {\\n if (resolver.code.length == 0) {\\n revert UnreachableName(name);\\n }\\n bool multi = bytes4(data) == IMulticallable.multicall.selector;\\n bool extendedDNS = hasContext &&\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IExtendedDNSResolver).interfaceId\\n );\\n bool extended = extendedDNS ||\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IExtendedResolver).interfaceId\\n );\\n if (\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IERC7996).interfaceId\\n ) &&\\n (!multi ||\\n (extended &&\\n IERC7996(resolver).supportsFeature(\\n ResolverFeatures.RESOLVE_MULTICALL\\n )))\\n ) {\\n if (extended) {\\n // resolve() has the same return signature as callResolver()\\n ccipRead(\\n resolver,\\n _makeExtendedCall(extendedDNS, name, data, context)\\n );\\n } else {\\n ccipRead(\\n resolver,\\n data,\\n this.resolveDirectImmediateCallback.selector, // ==> step 2\\n IDENTITY_FUNCTION,\\n \\\"\\\"\\n );\\n }\\n }\\n bytes[] memory calls;\\n if (multi) {\\n calls = abi.decode(\\n BytesUtils.substring(data, 4, data.length - 4),\\n (bytes[])\\n );\\n } else {\\n calls = new bytes[](1);\\n calls[0] = data;\\n }\\n if (extended) {\\n for (uint256 i; i < calls.length; ++i) {\\n calls[i] = _makeExtendedCall(\\n extendedDNS,\\n name,\\n calls[i],\\n context\\n );\\n }\\n }\\n ccipRead(\\n address(this),\\n abi.encodeCall(\\n this.ccipBatch,\\n (createBatch(resolver, calls, batchGateways))\\n ),\\n this.resolveBatchCallback.selector, // ==> step 2\\n IDENTITY_FUNCTION,\\n abi.encode(multi, extended)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `callResolver()` from direct calling an immediate resolver.\\n function resolveDirectImmediateCallback(\\n bytes calldata response,\\n bytes calldata\\n ) external pure returns (bytes calldata) {\\n return response; // the calldata was direct, so wrap it\\n }\\n\\n /// @dev CCIP-Read callback for `callResolver()` from batch calling a resolver.\\n /// @param response The response data from the batch gateway.\\n /// @param extraData The abi-encoded properties of the call.\\n /// @return result The response from the resolver.\\n function resolveBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external pure returns (bytes memory) {\\n Lookup[] memory lookups = abi.decode(response, (Batch)).lookups;\\n (bool multi, bool extended) = abi.decode(extraData, (bool, bool));\\n if (multi) {\\n return abi.encode(_toResponseArray(lookups, extended));\\n } else {\\n Lookup memory lu = lookups[0];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) != 0) {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n if (extended) {\\n v = abi.decode(v, (bytes)); // unwrap resolve()\\n }\\n return v;\\n }\\n }\\n\\n /// @dev Create extended resolver calldata.\\n function _makeExtendedCall(\\n bool extendedDNS,\\n bytes memory name,\\n bytes memory call,\\n bytes memory context\\n ) internal pure returns (bytes memory) {\\n return\\n extendedDNS\\n ? abi.encodeCall(\\n IExtendedDNSResolver.resolve,\\n (name, call, context)\\n )\\n : abi.encodeCall(IExtendedResolver.resolve, (name, call));\\n }\\n}\\n\",\"keccak256\":\"0xf639a50d41e390b0c156667b59960b0422e738027a87a111464a196fb71638d7\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/IERC7996.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for expressing contract features not visible from the ABI.\\n/// @dev Interface selector: `0x582de3e7`\\ninterface IERC7996 {\\n /// @notice Check if a feature is supported.\\n /// @param featureId The feature identifier.\\n /// @return `true` if the feature is supported by the contract.\\n function supportsFeature(bytes4 featureId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf499a48e4e879ec7775f375d2cb5af047720ab6ae4b6f89a40a578c4e0f51631\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x5a08ad61f4e82b8a3323562661a86fb10b10190848073fdc13d4ac43710ffba5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/resolver/AbstractMirrorResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {CCIPReader} from \\\"@ens/contracts/ccipRead/CCIPReader.sol\\\";\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {ICompositeResolver} from \\\"@ens/contracts/resolvers/profiles/ICompositeResolver.sol\\\";\\nimport {IExtendedResolver} from \\\"@ens/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {ResolverFeatures} from \\\"@ens/contracts/resolvers/ResolverFeatures.sol\\\";\\nimport {ResolverCaller} from \\\"@ens/contracts/universalResolver/ResolverCaller.sol\\\";\\nimport {IERC7996} from \\\"@ens/contracts/utils/IERC7996.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\n/// @dev Resolver that mirrors resolution of the same name to a different registry.\\nabstract contract AbstractMirrorResolver is\\n ICompositeResolver,\\n IERC7996,\\n ResolverCaller,\\n DelegatedContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Shared batch gateway provider.\\n IGatewayProvider public immutable BATCH_GATEWAY_PROVIDER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n constructor(IGatewayProvider batchGatewayProvider, IContractNamer contractNamer)\\n CCIPReader(DEFAULT_UNSAFE_CALL_GAS)\\n DelegatedContractNamer(contractNamer)\\n {\\n BATCH_GATEWAY_PROVIDER = batchGatewayProvider;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(DelegatedContractNamer)\\n returns (bool)\\n {\\n return\\n type(IExtendedResolver).interfaceId == interfaceId ||\\n type(ICompositeResolver).interfaceId == interfaceId ||\\n type(IERC7996).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /// @inheritdoc IERC7996\\n function supportsFeature(bytes4 feature) external pure returns (bool) {\\n return ResolverFeatures.RESOLVE_MULTICALL == feature;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IExtendedResolver\\n function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory) {\\n callResolver(_findResolver(name), name, data, false, \\\"\\\", BATCH_GATEWAY_PROVIDER.gateways());\\n }\\n\\n /// @inheritdoc ICompositeResolver\\n function getResolver(bytes calldata name) external view returns (address, bool) {\\n return (_findResolver(name), false);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Determine the resolver for `name`.\\n function _findResolver(bytes calldata name) internal view virtual returns (address);\\n}\\n\",\"keccak256\":\"0x4297a896783bb27602ce3891ec9839fff69e81621c12bbdcce9f1ac73c14ed57\",\"license\":\"MIT\"},\"project/src/resolver/ENSV2Resolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {LibRegistry} from \\\"../universalResolver/libraries/LibRegistry.sol\\\";\\n\\nimport {AbstractMirrorResolver} from \\\"./AbstractMirrorResolver.sol\\\";\\n\\n/// @notice Resolver that performs resolutions using ENSv2 with override for ENSv1 \\\"eth\\\" resolver.\\ncontract ENSV2Resolver is AbstractMirrorResolver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 root registry used to traverse the registry hierarchy and locate resolvers.\\n IPermissionedRegistry public immutable ROOT_REGISTRY;\\n\\n /// @notice The ENSv1 resolver for \\\"eth\\\".\\n address public immutable ETH_RESOLVER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n /// @param rootRegistry The ENSv2 root registry.\\n /// @param ethResolver The override resolver for \\\"eth\\\" or null to use ENSv2.\\n constructor(\\n IGatewayProvider batchGatewayProvider,\\n IContractNamer contractNamer,\\n IPermissionedRegistry rootRegistry,\\n address ethResolver\\n )\\n AbstractMirrorResolver(batchGatewayProvider, contractNamer)\\n {\\n ROOT_REGISTRY = rootRegistry;\\n ETH_RESOLVER = ethResolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc AbstractMirrorResolver\\n function _findResolver(bytes calldata name) internal view override returns (address resolver) {\\n bytes32 node;\\n (, resolver, node, ) = LibRegistry.findResolver(ROOT_REGISTRY, name, 0);\\n if (node == NameCoder.ETH_NODE && address(ETH_RESOLVER) != address(0)) {\\n resolver = ETH_RESOLVER;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x85207e437c6723428d79e5a3ee47eb019d1fbbd6f0434bc01d8f1b880de226a9\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/universalResolver/libraries/LibRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"../../registry/interfaces/IOwnedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Recursive traversal helpers for the namechain registry tree \\u2014 resolver lookup, registry\\n/// discovery, canonical name construction, and ancestry enumeration.\\nlibrary LibRegistry {\\n /// @dev Find the resolver address for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return exactRegistry The exact registry or null if not exact.\\n /// @return resolver The resolver or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n // supply if end of name\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return (rootRegistry, address(0), bytes32(0), offset);\\n }\\n // lookup parent name\\n (exactRegistry, resolver, node, resolverOffset) = findResolver(rootRegistry, name, next);\\n // if there was a parent registry...\\n if (address(exactRegistry) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n // remember the resolver (if it exists)\\n address res = exactRegistry.getResolver(label);\\n if (res != address(0)) {\\n resolver = res;\\n resolverOffset = offset;\\n }\\n exactRegistry = exactRegistry.getSubregistry(label);\\n }\\n node = NameCoder.namehash(node, labelHash); // update namehash\\n }\\n\\n /// @dev Find the owner for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return owner The owner address or null if unowned or not found.\\n function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (address owner)\\n {\\n IRegistry registry = findParentRegistry(rootRegistry, name, offset);\\n if (\\n address(registry) != address(0) &&\\n ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId)\\n ) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n owner = IOwnedRegistry(address(registry)).findOwner(label);\\n }\\n }\\n\\n /// @dev Construct the canonical name for `registry`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param registry The registry to name.\\n /// @return name The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry rootRegistry, IRegistry registry)\\n internal\\n view\\n returns (bytes memory name)\\n {\\n if (address(registry) == address(0)) {\\n return \\\"\\\";\\n }\\n for (;;) {\\n if (address(registry) == address(rootRegistry)) {\\n return abi.encodePacked(name, uint8(0)); // add terminator\\n }\\n (IRegistry parent, string memory label) = registry.getParent();\\n if (address(parent) == address(0)) {\\n return \\\"\\\"; // no canonical parent\\n }\\n IRegistry child = parent.getSubregistry(label);\\n if (address(child) != address(registry)) {\\n return \\\"\\\"; // wrong canonical child\\n }\\n name = abi.encodePacked(name, NameCoder.assertLabelSize(label), label); // reverts if invalid label\\n registry = parent;\\n }\\n }\\n\\n /// @dev Find the registry for `name` and return it iff it is canonical for that name.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name)\\n internal\\n view\\n returns (IRegistry)\\n {\\n IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0);\\n return\\n address(registry) != address(0) &&\\n keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) ==\\n keccak256(name)\\n ? registry\\n : IRegistry(address(0));\\n }\\n\\n /// @dev Find the exact registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return exactRegistry The exact registry or null if not found.\\n function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return rootRegistry;\\n }\\n IRegistry parent = findExactRegistry(rootRegistry, name, next);\\n if (address(parent) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n exactRegistry = parent.getSubregistry(label);\\n }\\n }\\n\\n /// @dev Find the parent registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return parentRegistry The parent registry or null if not found.\\n function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry parentRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n parentRegistry = findExactRegistry(rootRegistry, name, next);\\n }\\n }\\n\\n /// @dev Find all registries in the ancestry of `name`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return registries Array of registries in label-order.\\n function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry[] memory registries)\\n {\\n registries = new IRegistry[](1 + NameCoder.countLabels(name, offset));\\n registries[registries.length - 1] = rootRegistry;\\n _findRegistries(name, offset, registries, 0);\\n }\\n\\n /// @dev Recursive function for building ancestry.\\n function _findRegistries(\\n bytes memory name,\\n uint256 offset,\\n IRegistry[] memory registries,\\n uint256 index\\n )\\n private\\n view\\n returns (IRegistry registry)\\n {\\n (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset);\\n if (bytes(label).length == 0) {\\n return registries[registries.length - 1];\\n }\\n registry = _findRegistries(name, nextOffset, registries, index + 1);\\n if (address(registry) != address(0)) {\\n registry = registry.getSubregistry(label);\\n registries[index] = registry;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0b5f34bcc76ee3e49d300444fbcbe1ed152faee49a91c87eaea5f6d61ce6fb0b\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "InvalidBatchGatewayResponse()": [ + { + "notice": "The batch gateway supplied an incorrect number of responses." + } + ] + }, + "kind": "user", + "methods": { + "BATCH_GATEWAY_PROVIDER()": { + "notice": "Shared batch gateway provider." + }, + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "ETH_RESOLVER()": { + "notice": "The ENSv1 resolver for \"eth\"." + }, + "ROOT_REGISTRY()": { + "notice": "The ENSv2 root registry used to traverse the registry hierarchy and locate resolvers." + }, + "callResolver(address,bytes,bytes,bool,bytes,string[])": { + "notice": "Perform forward resolution. Call this function with `ccipRead()` to intercept the response. Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers. - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features, the call is performed directly without the batch gateway. - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature, the call is performed directly without the batch gateway. - Otherwise, the call is performed with the batch gateway. The batch gateway is only invoked if any call reverts `OffchainLookup`. If the calldata is `multicall()` it is disassembled, called separately, and reassembled." + }, + "getResolver(bytes)": { + "notice": "Fetch the underlying resolver for `name`. Callers should enable EIP-3668. * If `offchain`, additional information is necessary to locate `resolver`. * If `resolver` is null, `offchain` is irrelevant." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "supportsFeature(bytes4)": { + "notice": "Check if a feature is supported." + } + }, + "notice": "Resolver that performs resolutions using ENSv2 with override for ENSv1 \"eth\" resolver.", + "version": 1 + }, + "argsData": "0x000000000000000000000000e4e7245716d12d0f6aea01dfe0e635c43d7d083c000000000000000000000000fc8bf9234969d6b85729b756fa9e14bb84a06754000000000000000000000000c960f7217d3643b525ef36bec8adf86953cd9ab800000000000000000000000060c7c2a24b5e86c38639fd1586917a8fef66a56d", + "transaction": { + "hash": "0xbb89769c02981be9f290c214755c44596e693a2771f576521037f04007fec038", + "nonce": "0x1e4f", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xaf16578a1f1bd0651645aa04471c019b8743bf678fde21cfc94fb7f8da4e34d1", + "blockNumber": "0xa6a7c2", + "transactionIndex": "0x57" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRegistrar.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRegistrar.json new file mode 100644 index 000000000..f843a4841 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRegistrar.json @@ -0,0 +1,1412 @@ +{ + "address": "0x8c2e866b439358c41ae05de9cbe8a00bfefaffca", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + }, + { + "internalType": "uint64", + "name": "gracePeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minCommitmentAge", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxCommitmentAge", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minRegisterDuration", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "validFrom", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockTimestamp", + "type": "uint64" + } + ], + "name": "CommitmentTooNew", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "validTo", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockTimestamp", + "type": "uint64" + } + ], + "name": "CommitmentTooOld", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minDuration", + "type": "uint64" + } + ], + "name": "DurationTooShort", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCommitmentAgeTooLow", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "NameNotAvailable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "NameNotRenewable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + } + ], + "name": "UnexpiredCommitmentExists", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + } + ], + "name": "CommitmentMade", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "base", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "premium", + "type": "uint256" + } + ], + "name": "NameRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NameRenewed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + } + ], + "name": "RentPriceOracleUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "BENEFICIARY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GRACE_PERIOD", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_COMMITMENT_AGE", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_COMMITMENT_AGE", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_REGISTER_DURATION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_RENEW_DURATION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + } + ], + "name": "commit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + } + ], + "name": "commitmentAt", + "outputs": [ + { + "internalType": "uint64", + "name": "commitTime", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRegisterPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "bae", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "premium", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getRemainingGracePeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRenewPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "isAvailable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "isRenewable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "secret", + "type": "bytes32" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "makeCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "secret", + "type": "bytes32" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rentPriceOracle", + "outputs": [ + { + "internalType": "contract IRentPriceOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + } + ], + "name": "setRentPriceOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "ETHRegistrar", + "sourceName": "src/registrar/ETHRegistrar.sol", + "bytecode": "0x610160604052348015610010575f5ffd5b5060405161221038038061221083398101604081905261002f916101b3565b888888888883856001600160a01b03811661006357604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006c81610132565b506001600160a01b0390811660805283811660a05282811660c052600180546001600160a01b03191691831691821790556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac99060200160405180910390a15050505050826001600160401b0316826001600160401b031611610107576040516307cb550760e31b815260040160405180910390fd5b6001600160401b0393841660e052918316610100528216610120521661014052506102639350505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610195575f5ffd5b50565b80516001600160401b03811681146101ae575f5ffd5b919050565b5f5f5f5f5f5f5f5f5f6101208a8c0312156101cc575f5ffd5b89516101d781610181565b60208b01519099506101e881610181565b60408b01519098506101f981610181565b60608b015190975061020a81610181565b60808b015190965061021b81610181565b945061022960a08b01610198565b935061023760c08b01610198565b925061024560e08b01610198565b91506102546101008b01610198565b90509295985092959850929598565b60805160a05160c05160e051610100516101205161014051611ed76103395f395f81816103ba0152818161109101526110eb01525f818161035d01528181610d97015261155501525f818161023601526114bf01525f81816103e10152818161076701528181611136015261162501525f818161025d0152818161085b0152610bb501525f81816102cb0152818161049801528181610662015281816108c50152818161097b01528181610bed01528181610f8201526112aa01525f81816102a40152818161170801526117690152611ed75ff3fe608060405234801561000f575f5ffd5b506004361061018f575f3560e01c8063802295ef116100dd578063a40938bd11610088578063ddf0effc11610063578063ddf0effc14610416578063f14fcbc814610429578063f2fde38b1461043c575f5ffd5b8063a40938bd146103b5578063c1a287e2146103dc578063cff3e7c214610403575f5ffd5b80638da5cb5b116100b85780638da5cb5b1461037f578063965306aa1461038f578063a2a11fbe146103a2575f5ffd5b8063802295ef1461033257806389d779c3146103455780638ccb9ea614610358575f5ffd5b8063307a64a51161013d57806361907b121161011857806361907b12146102ed578063715018a6146103155780637b39ba161461031f575f5ffd5b8063307a64a514610297578063319c22bb1461029f57806347500708146102c6575f5ffd5b80631e966f071161016d5780631e966f07146102105780632e4f692a146102315780632f99c6cc14610258575f5ffd5b806301ffc9a714610193578063130d6f00146101bb57806316a92535146101ce575b5f5ffd5b6101a66101a13660046117f6565b61044f565b60405190151581526020015b60405180910390f35b6101a66101c9366004611862565b610492565b6101f76101dc3660046118a1565b60026020525f908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101b2565b61022361021e3660046118e1565b61056c565b6040519081526020016101b2565b6101f77f000000000000000000000000000000000000000000000000000000000000000081565b61027f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b2565b6101f7600181565b61027f7f000000000000000000000000000000000000000000000000000000000000000081565b61027f7f000000000000000000000000000000000000000000000000000000000000000081565b6103006102fb36600461197d565b6105b0565b604080519283526020830191909152016101b2565b61031d61064b565b005b60015461027f906001600160a01b031681565b6101f7610340366004611862565b61065e565b61031d6103533660046119e1565b610794565b6101f77f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b031661027f565b6101a661039d366004611862565b610975565b61031d6103b0366004611a4c565b610a48565b6101f77f000000000000000000000000000000000000000000000000000000000000000081565b6101f77f000000000000000000000000000000000000000000000000000000000000000081565b610223610411366004611a67565b610ab2565b61022361042436600461197d565b610cf3565b61031d6104373660046118a1565b610d81565b61031d61044a366004611a4c565b610e69565b5f6001600160e01b031982167fc1401b8000000000000000000000000000000000000000000000000000000000148061048c575061048c82610ebf565b92915050565b5f6105657f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861050386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b815260040161052191815260200190565b60a060405180830381865afa15801561053c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105609190611b3a565b610f30565b9392505050565b5f888888888888888860405160200161058c989796959493929190611bf0565b60405160208183030381529060405280519060200120905098975050505050505050565b6001545f9081906001600160a01b031663e1de9c8387876105de6105d583838b610f56565b60200151611118565b88886040518663ffffffff1660e01b8152600401610600959493929190611c4b565b6040805180830381865afa15801561061a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061063e9190611c99565b9150915094509492505050565b610653611188565b61065c5f6111fe565b565b5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286106cd86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b81526004016106eb91815260200190565b60a060405180830381865afa158015610706573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072a9190611b3a565b90506107358161125a565b61073f575f61078c565b60208101516107589067ffffffffffffffff1642611ccf565b61078c9067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611ccf565b949350505050565b5f6107a086868661127e565b90505f8482602001516107b39190611ce2565b60015460208401516040517f3ad860830000000000000000000000000000000000000000000000000000000081529293505f926001600160a01b0390921691633ad860839161080c918c918c918c908c90600401611c4b565b602060405180830381865afa158015610827573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061084b9190611d02565b9050610880856108596113f6565b7f000000000000000000000000000000000000000000000000000000000000000084611404565b60608301516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff831660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b15801561090e575f5ffd5b505af1158015610920573d5f5f3e3d5ffd5b505050508383606001517fbd0c01e5bf66003280556423db4a8bf79043c146ac57f657c30049dd433166498a8a8a878b8860405161096396959493929190611d19565b60405180910390a35050505050505050565b5f6105657f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286109e686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b8152600401610a0491815260200190565b60a060405180830381865afa158015610a1f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a439190611b3a565b611492565b610a50611188565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac9906020015b60405180910390a150565b5f6001600160a01b038816610af3576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b0b610b068b8b8b8b8b8b8b8a61056c565b61149d565b5f610b178b8b87610f56565b60015460208201519192505f9182916001600160a01b03169063e1de9c83908f908f90610b4390611118565b8b8b6040518663ffffffff1660e01b8152600401610b65959493929190611c4b565b6040805180830381865afa158015610b7f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba39190611c99565b91509150610be386610bb36113f6565b7f0000000000000000000000000000000000000000000000000000000000000000610bde8587611d64565b611404565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166385f3e6438e8e8e8d8d731110000000000000000000000000000001100000610c368f42611ce2565b6040518863ffffffff1660e01b8152600401610c589796959493929190611d77565b6020604051808303815f875af1158015610c74573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c989190611d02565b935084847febd3982eafd13b820e3edb2a4abd57a82ce3b8802e0cd45637a5de51383f9fac8f8f8f8e8e8e8e8b8b604051610cdb99989796959493929190611ddb565b60405180910390a35050509998505050505050505050565b6001545f906001600160a01b0316633ad860838686610d1382828961127e565b6020015187876040518663ffffffff1660e01b8152600401610d39959493929190611c4b565b602060405180830381865afa158015610d54573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d789190611d02565b95945050505050565b5f818152600260205260409020544290610dc6907f00000000000000000000000000000000000000000000000000000000000000009067ffffffffffffffff16611ce2565b67ffffffffffffffff161115610e10576040517f0a059d71000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b5f81815260026020908152604091829020805467ffffffffffffffff19164267ffffffffffffffff1617905590518281527f561eb038a114723afa3c72b445add7b8602de546264da1e7e826af628316dbcb9101610aa7565b610e71611188565b6001600160a01b038116610eb3576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610e07565b610ebc816111fe565b50565b5f6001600160e01b031982167f06aaeb3200000000000000000000000000000000000000000000000000000000148061048c57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461048c565b805160209091012090565b5f600282516002811115610f4657610f46611e3f565b148061048c575061048c8261125a565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610fed86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b815260040161100b91815260200190565b60a060405180830381865afa158015611026573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104a9190611b3a565b905061105581611492565b61108f5783836040517f477707e8000000000000000000000000000000000000000000000000000000008152600401610e07929190611e53565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16101561056557604051632825ae1160e21b815267ffffffffffffffff80841660048301527f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610e07565b5f4267ffffffffffffffff831682036111315792915050565b61115b7f000000000000000000000000000000000000000000000000000000000000000084611ce2565b92508267ffffffffffffffff168167ffffffffffffffff161161117e575f610565565b6105658382611e66565b6111906113f6565b6001600160a01b03166111aa5f546001600160a01b031690565b6001600160a01b03161461065c576111c06113f6565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610e07565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408101515f906001600160a01b03161580159061048c575061048c826001611606565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861131586868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b815260040161133391815260200190565b60a060405180830381865afa15801561134e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113729190611b3a565b905061137d81610f30565b6113b75783836040517f1caefaa0000000000000000000000000000000000000000000000000000000008152600401610e07929190611e53565b600167ffffffffffffffff8316101561056557604051632825ae1160e21b815267ffffffffffffffff8316600482015260016024820152604401610e07565b5f6113ff611677565b905090565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261148c908590611680565b50505050565b5f61048c825f611606565b5f81815260026020526040812054429167ffffffffffffffff909116906114e47f000000000000000000000000000000000000000000000000000000000000000083611ce2565b90508067ffffffffffffffff168367ffffffffffffffff16101561154f576040517f6be614e30000000000000000000000000000000000000000000000000000000081526004810185905267ffffffffffffffff808316602483015284166044820152606401610e07565b5f61157a7f000000000000000000000000000000000000000000000000000000000000000084611ce2565b90508067ffffffffffffffff168467ffffffffffffffff16106115e4576040517f0cb9df3f0000000000000000000000000000000000000000000000000000000081526004810186905267ffffffffffffffff808316602483015285166044820152606401610e07565b5050505f91825250600260205260409020805467ffffffffffffffff19169055565b5f808351600281111561161b5761161b611e3f565b14801561056557507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16836020015167ffffffffffffffff16426116689190611ccf565b10151582151514905092915050565b5f6113ff611705565b5f5f60205f8451602086015f885af18061169f576040513d5f823e3d81fd5b50505f513d915081156116b65780600114156116c3565b6001600160a01b0384163b155b1561148c576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610e07565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661173957503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa1580156117b6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117da9190611e86565b90506001600160a01b0381166117f1573391505090565b919050565b5f60208284031215611806575f5ffd5b81356001600160e01b031981168114610565575f5ffd5b5f5f83601f84011261182d575f5ffd5b50813567ffffffffffffffff811115611844575f5ffd5b60208301915083602082850101111561185b575f5ffd5b9250929050565b5f5f60208385031215611873575f5ffd5b823567ffffffffffffffff811115611889575f5ffd5b6118958582860161181d565b90969095509350505050565b5f602082840312156118b1575f5ffd5b5035919050565b6001600160a01b0381168114610ebc575f5ffd5b67ffffffffffffffff81168114610ebc575f5ffd5b5f5f5f5f5f5f5f5f60e0898b0312156118f8575f5ffd5b883567ffffffffffffffff81111561190e575f5ffd5b61191a8b828c0161181d565b909950975050602089013561192e816118b8565b9550604089013594506060890135611945816118b8565b93506080890135611955816118b8565b925060a0890135611965816118cc565b979a969950949793969295919450919260c001359150565b5f5f5f5f60608587031215611990575f5ffd5b843567ffffffffffffffff8111156119a6575f5ffd5b6119b28782880161181d565b90955093505060208501356119c6816118cc565b915060408501356119d6816118b8565b939692955090935050565b5f5f5f5f5f608086880312156119f5575f5ffd5b853567ffffffffffffffff811115611a0b575f5ffd5b611a178882890161181d565b9096509450506020860135611a2b816118cc565b92506040860135611a3b816118b8565b949793965091946060013592915050565b5f60208284031215611a5c575f5ffd5b8135610565816118b8565b5f5f5f5f5f5f5f5f5f6101008a8c031215611a80575f5ffd5b893567ffffffffffffffff811115611a96575f5ffd5b611aa28c828d0161181d565b909a5098505060208a0135611ab6816118b8565b965060408a0135955060608a0135611acd816118b8565b945060808a0135611add816118b8565b935060a08a0135611aed816118cc565b925060c08a0135611afd816118b8565b989b979a50959894979396929550909360e00135919050565b8051600381106117f1575f5ffd5b80516117f1816118cc565b80516117f1816118b8565b5f60a0828403128015611b4b575f5ffd5b5060405160a0810167ffffffffffffffff81118282101715611b7b57634e487b7160e01b5f52604160045260245ffd5b604052611b8783611b16565b8152611b9560208401611b24565b6020820152611ba660408401611b2f565b6040820152606083810151908201526080928301519281019290925250919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60e081525f611c0360e083018a8c611bc8565b6001600160a01b039889166020840152604083019790975250938616606085015291909416608083015267ffffffffffffffff90931660a082015260c0019190915292915050565b608081525f611c5e608083018789611bc8565b905067ffffffffffffffff8516602083015267ffffffffffffffff841660408301526001600160a01b03831660608301529695505050505050565b5f5f60408385031215611caa575f5ffd5b505080516020909101519092909150565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561048c5761048c611cbb565b67ffffffffffffffff818116838216019081111561048c5761048c611cbb565b5f60208284031215611d12575f5ffd5b5051919050565b60a081525f611d2c60a08301888a611bc8565b67ffffffffffffffff96871660208401529490951660408201526001600160a01b039290921660608301526080909101529392505050565b8082018082111561048c5761048c611cbb565b60c081525f611d8a60c08301898b611bc8565b90506001600160a01b03871660208301526001600160a01b03861660408301526001600160a01b038516606083015283608083015267ffffffffffffffff831660a083015298975050505050505050565b61010081525f611df061010083018b8d611bc8565b6001600160a01b03998a166020840152978916604083015250948716606086015267ffffffffffffffff939093166080850152941660a083015260c082019390935260e0019190915292915050565b634e487b7160e01b5f52602160045260245ffd5b602081525f61078c602083018486611bc8565b67ffffffffffffffff828116828216039081111561048c5761048c611cbb565b5f60208284031215611e96575f5ffd5b8151610565816118b856fea26469706673582212209d3a9c029df8fa7e8c3a2a6ed00a01a91415be266b77f6a07cd3756c9a93375564736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061018f575f3560e01c8063802295ef116100dd578063a40938bd11610088578063ddf0effc11610063578063ddf0effc14610416578063f14fcbc814610429578063f2fde38b1461043c575f5ffd5b8063a40938bd146103b5578063c1a287e2146103dc578063cff3e7c214610403575f5ffd5b80638da5cb5b116100b85780638da5cb5b1461037f578063965306aa1461038f578063a2a11fbe146103a2575f5ffd5b8063802295ef1461033257806389d779c3146103455780638ccb9ea614610358575f5ffd5b8063307a64a51161013d57806361907b121161011857806361907b12146102ed578063715018a6146103155780637b39ba161461031f575f5ffd5b8063307a64a514610297578063319c22bb1461029f57806347500708146102c6575f5ffd5b80631e966f071161016d5780631e966f07146102105780632e4f692a146102315780632f99c6cc14610258575f5ffd5b806301ffc9a714610193578063130d6f00146101bb57806316a92535146101ce575b5f5ffd5b6101a66101a13660046117f6565b61044f565b60405190151581526020015b60405180910390f35b6101a66101c9366004611862565b610492565b6101f76101dc3660046118a1565b60026020525f908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101b2565b61022361021e3660046118e1565b61056c565b6040519081526020016101b2565b6101f77f000000000000000000000000000000000000000000000000000000000000000081565b61027f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101b2565b6101f7600181565b61027f7f000000000000000000000000000000000000000000000000000000000000000081565b61027f7f000000000000000000000000000000000000000000000000000000000000000081565b6103006102fb36600461197d565b6105b0565b604080519283526020830191909152016101b2565b61031d61064b565b005b60015461027f906001600160a01b031681565b6101f7610340366004611862565b61065e565b61031d6103533660046119e1565b610794565b6101f77f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b031661027f565b6101a661039d366004611862565b610975565b61031d6103b0366004611a4c565b610a48565b6101f77f000000000000000000000000000000000000000000000000000000000000000081565b6101f77f000000000000000000000000000000000000000000000000000000000000000081565b610223610411366004611a67565b610ab2565b61022361042436600461197d565b610cf3565b61031d6104373660046118a1565b610d81565b61031d61044a366004611a4c565b610e69565b5f6001600160e01b031982167fc1401b8000000000000000000000000000000000000000000000000000000000148061048c575061048c82610ebf565b92915050565b5f6105657f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861050386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b815260040161052191815260200190565b60a060405180830381865afa15801561053c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105609190611b3a565b610f30565b9392505050565b5f888888888888888860405160200161058c989796959493929190611bf0565b60405160208183030381529060405280519060200120905098975050505050505050565b6001545f9081906001600160a01b031663e1de9c8387876105de6105d583838b610f56565b60200151611118565b88886040518663ffffffff1660e01b8152600401610600959493929190611c4b565b6040805180830381865afa15801561061a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061063e9190611c99565b9150915094509492505050565b610653611188565b61065c5f6111fe565b565b5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286106cd86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b81526004016106eb91815260200190565b60a060405180830381865afa158015610706573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072a9190611b3a565b90506107358161125a565b61073f575f61078c565b60208101516107589067ffffffffffffffff1642611ccf565b61078c9067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611ccf565b949350505050565b5f6107a086868661127e565b90505f8482602001516107b39190611ce2565b60015460208401516040517f3ad860830000000000000000000000000000000000000000000000000000000081529293505f926001600160a01b0390921691633ad860839161080c918c918c918c908c90600401611c4b565b602060405180830381865afa158015610827573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061084b9190611d02565b9050610880856108596113f6565b7f000000000000000000000000000000000000000000000000000000000000000084611404565b60608301516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff831660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b15801561090e575f5ffd5b505af1158015610920573d5f5f3e3d5ffd5b505050508383606001517fbd0c01e5bf66003280556423db4a8bf79043c146ac57f657c30049dd433166498a8a8a878b8860405161096396959493929190611d19565b60405180910390a35050505050505050565b5f6105657f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286109e686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b8152600401610a0491815260200190565b60a060405180830381865afa158015610a1f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a439190611b3a565b611492565b610a50611188565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac9906020015b60405180910390a150565b5f6001600160a01b038816610af3576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b0b610b068b8b8b8b8b8b8b8a61056c565b61149d565b5f610b178b8b87610f56565b60015460208201519192505f9182916001600160a01b03169063e1de9c83908f908f90610b4390611118565b8b8b6040518663ffffffff1660e01b8152600401610b65959493929190611c4b565b6040805180830381865afa158015610b7f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba39190611c99565b91509150610be386610bb36113f6565b7f0000000000000000000000000000000000000000000000000000000000000000610bde8587611d64565b611404565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166385f3e6438e8e8e8d8d731110000000000000000000000000000001100000610c368f42611ce2565b6040518863ffffffff1660e01b8152600401610c589796959493929190611d77565b6020604051808303815f875af1158015610c74573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c989190611d02565b935084847febd3982eafd13b820e3edb2a4abd57a82ce3b8802e0cd45637a5de51383f9fac8f8f8f8e8e8e8e8b8b604051610cdb99989796959493929190611ddb565b60405180910390a35050509998505050505050505050565b6001545f906001600160a01b0316633ad860838686610d1382828961127e565b6020015187876040518663ffffffff1660e01b8152600401610d39959493929190611c4b565b602060405180830381865afa158015610d54573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d789190611d02565b95945050505050565b5f818152600260205260409020544290610dc6907f00000000000000000000000000000000000000000000000000000000000000009067ffffffffffffffff16611ce2565b67ffffffffffffffff161115610e10576040517f0a059d71000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b5f81815260026020908152604091829020805467ffffffffffffffff19164267ffffffffffffffff1617905590518281527f561eb038a114723afa3c72b445add7b8602de546264da1e7e826af628316dbcb9101610aa7565b610e71611188565b6001600160a01b038116610eb3576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610e07565b610ebc816111fe565b50565b5f6001600160e01b031982167f06aaeb3200000000000000000000000000000000000000000000000000000000148061048c57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461048c565b805160209091012090565b5f600282516002811115610f4657610f46611e3f565b148061048c575061048c8261125a565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610fed86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b815260040161100b91815260200190565b60a060405180830381865afa158015611026573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104a9190611b3a565b905061105581611492565b61108f5783836040517f477707e8000000000000000000000000000000000000000000000000000000008152600401610e07929190611e53565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16101561056557604051632825ae1160e21b815267ffffffffffffffff80841660048301527f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610e07565b5f4267ffffffffffffffff831682036111315792915050565b61115b7f000000000000000000000000000000000000000000000000000000000000000084611ce2565b92508267ffffffffffffffff168167ffffffffffffffff161161117e575f610565565b6105658382611e66565b6111906113f6565b6001600160a01b03166111aa5f546001600160a01b031690565b6001600160a01b03161461065c576111c06113f6565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610e07565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408101515f906001600160a01b03161580159061048c575061048c826001611606565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861131586868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f2592505050565b6040518263ffffffff1660e01b815260040161133391815260200190565b60a060405180830381865afa15801561134e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113729190611b3a565b905061137d81610f30565b6113b75783836040517f1caefaa0000000000000000000000000000000000000000000000000000000008152600401610e07929190611e53565b600167ffffffffffffffff8316101561056557604051632825ae1160e21b815267ffffffffffffffff8316600482015260016024820152604401610e07565b5f6113ff611677565b905090565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261148c908590611680565b50505050565b5f61048c825f611606565b5f81815260026020526040812054429167ffffffffffffffff909116906114e47f000000000000000000000000000000000000000000000000000000000000000083611ce2565b90508067ffffffffffffffff168367ffffffffffffffff16101561154f576040517f6be614e30000000000000000000000000000000000000000000000000000000081526004810185905267ffffffffffffffff808316602483015284166044820152606401610e07565b5f61157a7f000000000000000000000000000000000000000000000000000000000000000084611ce2565b90508067ffffffffffffffff168467ffffffffffffffff16106115e4576040517f0cb9df3f0000000000000000000000000000000000000000000000000000000081526004810186905267ffffffffffffffff808316602483015285166044820152606401610e07565b5050505f91825250600260205260409020805467ffffffffffffffff19169055565b5f808351600281111561161b5761161b611e3f565b14801561056557507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16836020015167ffffffffffffffff16426116689190611ccf565b10151582151514905092915050565b5f6113ff611705565b5f5f60205f8451602086015f885af18061169f576040513d5f823e3d81fd5b50505f513d915081156116b65780600114156116c3565b6001600160a01b0384163b155b1561148c576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610e07565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661173957503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa1580156117b6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117da9190611e86565b90506001600160a01b0381166117f1573391505090565b919050565b5f60208284031215611806575f5ffd5b81356001600160e01b031981168114610565575f5ffd5b5f5f83601f84011261182d575f5ffd5b50813567ffffffffffffffff811115611844575f5ffd5b60208301915083602082850101111561185b575f5ffd5b9250929050565b5f5f60208385031215611873575f5ffd5b823567ffffffffffffffff811115611889575f5ffd5b6118958582860161181d565b90969095509350505050565b5f602082840312156118b1575f5ffd5b5035919050565b6001600160a01b0381168114610ebc575f5ffd5b67ffffffffffffffff81168114610ebc575f5ffd5b5f5f5f5f5f5f5f5f60e0898b0312156118f8575f5ffd5b883567ffffffffffffffff81111561190e575f5ffd5b61191a8b828c0161181d565b909950975050602089013561192e816118b8565b9550604089013594506060890135611945816118b8565b93506080890135611955816118b8565b925060a0890135611965816118cc565b979a969950949793969295919450919260c001359150565b5f5f5f5f60608587031215611990575f5ffd5b843567ffffffffffffffff8111156119a6575f5ffd5b6119b28782880161181d565b90955093505060208501356119c6816118cc565b915060408501356119d6816118b8565b939692955090935050565b5f5f5f5f5f608086880312156119f5575f5ffd5b853567ffffffffffffffff811115611a0b575f5ffd5b611a178882890161181d565b9096509450506020860135611a2b816118cc565b92506040860135611a3b816118b8565b949793965091946060013592915050565b5f60208284031215611a5c575f5ffd5b8135610565816118b8565b5f5f5f5f5f5f5f5f5f6101008a8c031215611a80575f5ffd5b893567ffffffffffffffff811115611a96575f5ffd5b611aa28c828d0161181d565b909a5098505060208a0135611ab6816118b8565b965060408a0135955060608a0135611acd816118b8565b945060808a0135611add816118b8565b935060a08a0135611aed816118cc565b925060c08a0135611afd816118b8565b989b979a50959894979396929550909360e00135919050565b8051600381106117f1575f5ffd5b80516117f1816118cc565b80516117f1816118b8565b5f60a0828403128015611b4b575f5ffd5b5060405160a0810167ffffffffffffffff81118282101715611b7b57634e487b7160e01b5f52604160045260245ffd5b604052611b8783611b16565b8152611b9560208401611b24565b6020820152611ba660408401611b2f565b6040820152606083810151908201526080928301519281019290925250919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60e081525f611c0360e083018a8c611bc8565b6001600160a01b039889166020840152604083019790975250938616606085015291909416608083015267ffffffffffffffff90931660a082015260c0019190915292915050565b608081525f611c5e608083018789611bc8565b905067ffffffffffffffff8516602083015267ffffffffffffffff841660408301526001600160a01b03831660608301529695505050505050565b5f5f60408385031215611caa575f5ffd5b505080516020909101519092909150565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561048c5761048c611cbb565b67ffffffffffffffff818116838216019081111561048c5761048c611cbb565b5f60208284031215611d12575f5ffd5b5051919050565b60a081525f611d2c60a08301888a611bc8565b67ffffffffffffffff96871660208401529490951660408201526001600160a01b039290921660608301526080909101529392505050565b8082018082111561048c5761048c611cbb565b60c081525f611d8a60c08301898b611bc8565b90506001600160a01b03871660208301526001600160a01b03861660408301526001600160a01b038516606083015283608083015267ffffffffffffffff831660a083015298975050505050505050565b61010081525f611df061010083018b8d611bc8565b6001600160a01b03998a166020840152978916604083015250948716606086015267ffffffffffffffff939093166080850152941660a083015260c082019390935260e0019190915292915050565b634e487b7160e01b5f52602160045260245ffd5b602081525f61078c602083018486611bc8565b67ffffffffffffffff828116828216039081111561048c5761048c611cbb565b5f60208284031215611e96575f5ffd5b8151610565816118b856fea26469706673582212209d3a9c029df8fa7e8c3a2a6ed00a01a91415be266b77f6a07cd3756c9a93375564736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60111": [ + { + "length": 32, + "start": 676 + }, + { + "length": 32, + "start": 5896 + }, + { + "length": 32, + "start": 5993 + } + ], + "63497": [ + { + "length": 32, + "start": 715 + }, + { + "length": 32, + "start": 1176 + }, + { + "length": 32, + "start": 1634 + }, + { + "length": 32, + "start": 2245 + }, + { + "length": 32, + "start": 2427 + }, + { + "length": 32, + "start": 3053 + }, + { + "length": 32, + "start": 3970 + }, + { + "length": 32, + "start": 4778 + } + ], + "63500": [ + { + "length": 32, + "start": 605 + }, + { + "length": 32, + "start": 2139 + }, + { + "length": 32, + "start": 2997 + } + ], + "63981": [ + { + "length": 32, + "start": 993 + }, + { + "length": 32, + "start": 1895 + }, + { + "length": 32, + "start": 4406 + }, + { + "length": 32, + "start": 5669 + } + ], + "63984": [ + { + "length": 32, + "start": 566 + }, + { + "length": 32, + "start": 5311 + } + ], + "63987": [ + { + "length": 32, + "start": 861 + }, + { + "length": 32, + "start": 3479 + }, + { + "length": 32, + "start": 5461 + } + ], + "63990": [ + { + "length": 32, + "start": 954 + }, + { + "length": 32, + "start": 4241 + }, + { + "length": 32, + "start": 4331 + } + ] + }, + "inputSourceName": "project/src/registrar/ETHRegistrar.sol", + "devdoc": { + "errors": { + "CommitmentTooNew(bytes32,uint64,uint64)": [ + { + "details": "Error selector: `0x6be614e3`" + } + ], + "CommitmentTooOld(bytes32,uint64,uint64)": [ + { + "details": "Error selector: `0x0cb9df3f`" + } + ], + "DurationTooShort(uint64,uint64)": [ + { + "details": "Error selector: `0xa096b844`" + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "MaxCommitmentAgeTooLow()": [ + { + "details": "Error selector: `0x3e5aa838`" + } + ], + "NameNotAvailable(string)": [ + { + "details": "Error selector: `0x477707e8`" + } + ], + "NameNotRenewable(string)": [ + { + "details": "Error selector: `0x1caefaa0`" + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ], + "SafeERC20FailedOperation(address)": [ + { + "details": "An operation with an ERC-20 token failed." + } + ], + "UnexpiredCommitmentExists(bytes32)": [ + { + "details": "Error selector: `0x0a059d71`" + } + ] + }, + "events": { + "CommitmentMade(bytes32)": { + "params": { + "commitment": "The commitment hash from `makeCommitment()`." + } + }, + "NameRegistered(uint256,string,address,address,address,uint64,address,bytes32,uint256,uint256)": { + "params": { + "base": "The amount of `paymentToken` for the registration.", + "duration": "The registration duration, in seconds.", + "label": "The name of the registration.", + "owner": "The owner address.", + "paymentToken": "The payment token.", + "premium": "The amount of `paymentToken` due to premium.", + "referrer": "The referrer hash.", + "resolver": "The initial resolver address.", + "subregistry": "The initial registry address.", + "tokenId": "The registry token id." + } + }, + "NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)": { + "params": { + "amount": "The amount of `paymentToken`.", + "duration": "The duration extension, in seconds.", + "label": "The name of the renewal.", + "newExpiry": "The new expiry, in seconds.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash.", + "tokenId": "The registry token id." + } + }, + "RentPriceOracleUpdated(address)": { + "params": { + "oracle": "The new `IRentPriceOracle` contract." + } + } + }, + "kind": "dev", + "methods": { + "commit(bytes32)": { + "details": "Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.", + "params": { + "commitment": "The commitment hash." + } + }, + "constructor": { + "params": { + "beneficiary": "Address that receives payments.", + "ethRegistry": "ENSv2 .eth `PermissionedRegistry`.", + "gracePeriod": "Post-expiry period where still renewable and not available, in seconds.", + "hcaFactory": "HCA factory.", + "maxCommitmentAge": "Maximum seconds a commitment remains valid; expired commitments are rejected.", + "minCommitmentAge": "Minimum seconds a commitment must age before registration can proceed.", + "minRegisterDuration": "Minimum register duration, in seconds.", + "oracle": "Initial oracle for registration and renewal costs.", + "owner_": "Contract owner." + } + }, + "getRegisterPrice(string,uint64,address)": { + "params": { + "duration": "The registration duration, in seconds.", + "label": "The name to register.", + "paymentToken": "The payment token." + }, + "returns": { + "bae": "The amount of `paymentToken` for registration.", + "premium": "The amount of `paymentToken` due to premium." + } + }, + "getRemainingGracePeriod(string)": { + "details": "Defined over `[expiry, expiry + GRACE_PERIOD)`.", + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "The remaining grace period, in seconds." + } + }, + "getRenewPrice(string,uint64,address)": { + "params": { + "duration": "The duration extension, in seconds.", + "label": "The name to renew.", + "paymentToken": "The payment token." + }, + "returns": { + "_0": "The amount of `paymentToken`." + } + }, + "isAvailable(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "`true` if registerable." + } + }, + "isRenewable(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "`true` if renewable." + } + }, + "makeCommitment(string,address,bytes32,address,address,uint64,bytes32)": { + "params": { + "duration": "The registration duration, in seconds.", + "label": "The name to register.", + "owner": "The owner address.", + "referrer": "The referrer hash.", + "resolver": "The initial resolver address.", + "secret": "The secret for the registration.", + "subregistry": "The initial registry address." + }, + "returns": { + "_0": "The commitment hash." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "register(string,address,bytes32,address,address,uint64,address,bytes32)": { + "params": { + "duration": "The registration from commitment.", + "label": "The name from commitment.", + "owner": "The owner from commitment.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash.", + "resolver": "The resolver from commitment.", + "secret": "The secret from commitment.", + "subregistry": "The registry from commitment." + }, + "returns": { + "tokenId": "The registered token ID." + } + }, + "renew(string,uint64,address,bytes32)": { + "params": { + "duration": "The duration extension, in seconds.", + "label": "The name to renew.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash." + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setRentPriceOracle(address)": { + "params": { + "oracle": "The new `IRentPriceOracle` instance." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "stateVariables": { + "MIN_COMMITMENT_AGE": { + "details": "If zero, front-running protection is disabled." + }, + "commitmentAt": { + "params": { + "commitment": "The commitment hash." + }, + "return": "commitTime The commitment time, in seconds, or 0 if unknown.", + "returns": { + "commitTime": "The commitment time, in seconds, or 0 if unknown." + } + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1579000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BENEFICIARY()": "infinite", + "ETH_REGISTRY()": "infinite", + "GRACE_PERIOD()": "infinite", + "HCA_FACTORY()": "infinite", + "MAX_COMMITMENT_AGE()": "infinite", + "MIN_COMMITMENT_AGE()": "infinite", + "MIN_REGISTER_DURATION()": "infinite", + "MIN_RENEW_DURATION()": "249", + "commit(bytes32)": "infinite", + "commitmentAt(bytes32)": "2541", + "getRegisterPrice(string,uint64,address)": "infinite", + "getRemainingGracePeriod(string)": "infinite", + "getRenewPrice(string,uint64,address)": "infinite", + "isAvailable(string)": "infinite", + "isRenewable(string)": "infinite", + "makeCommitment(string,address,bytes32,address,address,uint64,bytes32)": "infinite", + "owner()": "2374", + "register(string,address,bytes32,address,address,uint64,address,bytes32)": "infinite", + "renew(string,uint64,address,bytes32)": "infinite", + "renounceOwnership()": "infinite", + "rentPriceOracle()": "2425", + "setRentPriceOracle(address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "transferOwnership(address)": "infinite" + }, + "internal": { + "_availablePeriod(uint64)": "infinite", + "_checkGrace(struct IPermissionedRegistry.State memory,bool)": "infinite", + "_consumeCommitment(bytes32)": "infinite", + "_isAvailable(struct IPermissionedRegistry.State memory)": "infinite", + "_isRenewable(struct IPermissionedRegistry.State memory)": "infinite", + "_isRenewableGrace(struct IPermissionedRegistry.State memory)": "infinite", + "_requireAvailable(string calldata,uint64)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"gracePeriod\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minCommitmentAge\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxCommitmentAge\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minRegisterDuration\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"validFrom\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"blockTimestamp\",\"type\":\"uint64\"}],\"name\":\"CommitmentTooNew\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"validTo\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"blockTimestamp\",\"type\":\"uint64\"}],\"name\":\"CommitmentTooOld\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minDuration\",\"type\":\"uint64\"}],\"name\":\"DurationTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxCommitmentAgeTooLow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"NameNotAvailable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"NameNotRenewable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"}],\"name\":\"UnexpiredCommitmentExists\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"}],\"name\":\"CommitmentMade\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"base\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"premium\",\"type\":\"uint256\"}],\"name\":\"NameRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NameRenewed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"RentPriceOracleUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BENEFICIARY\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GRACE_PERIOD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_COMMITMENT_AGE\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_COMMITMENT_AGE\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_REGISTER_DURATION\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_RENEW_DURATION\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"}],\"name\":\"commitmentAt\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"commitTime\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRegisterPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"bae\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"premium\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getRemainingGracePeriod\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRenewPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"isAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"isRenewable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"secret\",\"type\":\"bytes32\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"makeCommitment\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"secret\",\"type\":\"bytes32\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rentPriceOracle\",\"outputs\":[{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"setRentPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CommitmentTooNew(bytes32,uint64,uint64)\":[{\"details\":\"Error selector: `0x6be614e3`\"}],\"CommitmentTooOld(bytes32,uint64,uint64)\":[{\"details\":\"Error selector: `0x0cb9df3f`\"}],\"DurationTooShort(uint64,uint64)\":[{\"details\":\"Error selector: `0xa096b844`\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"MaxCommitmentAgeTooLow()\":[{\"details\":\"Error selector: `0x3e5aa838`\"}],\"NameNotAvailable(string)\":[{\"details\":\"Error selector: `0x477707e8`\"}],\"NameNotRenewable(string)\":[{\"details\":\"Error selector: `0x1caefaa0`\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}],\"UnexpiredCommitmentExists(bytes32)\":[{\"details\":\"Error selector: `0x0a059d71`\"}]},\"events\":{\"CommitmentMade(bytes32)\":{\"params\":{\"commitment\":\"The commitment hash from `makeCommitment()`.\"}},\"NameRegistered(uint256,string,address,address,address,uint64,address,bytes32,uint256,uint256)\":{\"params\":{\"base\":\"The amount of `paymentToken` for the registration.\",\"duration\":\"The registration duration, in seconds.\",\"label\":\"The name of the registration.\",\"owner\":\"The owner address.\",\"paymentToken\":\"The payment token.\",\"premium\":\"The amount of `paymentToken` due to premium.\",\"referrer\":\"The referrer hash.\",\"resolver\":\"The initial resolver address.\",\"subregistry\":\"The initial registry address.\",\"tokenId\":\"The registry token id.\"}},\"NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)\":{\"params\":{\"amount\":\"The amount of `paymentToken`.\",\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name of the renewal.\",\"newExpiry\":\"The new expiry, in seconds.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\",\"tokenId\":\"The registry token id.\"}},\"RentPriceOracleUpdated(address)\":{\"params\":{\"oracle\":\"The new `IRentPriceOracle` contract.\"}}},\"kind\":\"dev\",\"methods\":{\"commit(bytes32)\":{\"details\":\"Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.\",\"params\":{\"commitment\":\"The commitment hash.\"}},\"constructor\":{\"params\":{\"beneficiary\":\"Address that receives payments.\",\"ethRegistry\":\"ENSv2 .eth `PermissionedRegistry`.\",\"gracePeriod\":\"Post-expiry period where still renewable and not available, in seconds.\",\"hcaFactory\":\"HCA factory.\",\"maxCommitmentAge\":\"Maximum seconds a commitment remains valid; expired commitments are rejected.\",\"minCommitmentAge\":\"Minimum seconds a commitment must age before registration can proceed.\",\"minRegisterDuration\":\"Minimum register duration, in seconds.\",\"oracle\":\"Initial oracle for registration and renewal costs.\",\"owner_\":\"Contract owner.\"}},\"getRegisterPrice(string,uint64,address)\":{\"params\":{\"duration\":\"The registration duration, in seconds.\",\"label\":\"The name to register.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"bae\":\"The amount of `paymentToken` for registration.\",\"premium\":\"The amount of `paymentToken` due to premium.\"}},\"getRemainingGracePeriod(string)\":{\"details\":\"Defined over `[expiry, expiry + GRACE_PERIOD)`.\",\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"The remaining grace period, in seconds.\"}},\"getRenewPrice(string,uint64,address)\":{\"params\":{\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name to renew.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"_0\":\"The amount of `paymentToken`.\"}},\"isAvailable(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"`true` if registerable.\"}},\"isRenewable(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"`true` if renewable.\"}},\"makeCommitment(string,address,bytes32,address,address,uint64,bytes32)\":{\"params\":{\"duration\":\"The registration duration, in seconds.\",\"label\":\"The name to register.\",\"owner\":\"The owner address.\",\"referrer\":\"The referrer hash.\",\"resolver\":\"The initial resolver address.\",\"secret\":\"The secret for the registration.\",\"subregistry\":\"The initial registry address.\"},\"returns\":{\"_0\":\"The commitment hash.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"register(string,address,bytes32,address,address,uint64,address,bytes32)\":{\"params\":{\"duration\":\"The registration from commitment.\",\"label\":\"The name from commitment.\",\"owner\":\"The owner from commitment.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\",\"resolver\":\"The resolver from commitment.\",\"secret\":\"The secret from commitment.\",\"subregistry\":\"The registry from commitment.\"},\"returns\":{\"tokenId\":\"The registered token ID.\"}},\"renew(string,uint64,address,bytes32)\":{\"params\":{\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name to renew.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setRentPriceOracle(address)\":{\"params\":{\"oracle\":\"The new `IRentPriceOracle` instance.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"stateVariables\":{\"MIN_COMMITMENT_AGE\":{\"details\":\"If zero, front-running protection is disabled.\"},\"commitmentAt\":{\"params\":{\"commitment\":\"The commitment hash.\"},\"return\":\"commitTime The commitment time, in seconds, or 0 if unknown.\",\"returns\":{\"commitTime\":\"The commitment time, in seconds, or 0 if unknown.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"CommitmentTooNew(bytes32,uint64,uint64)\":[{\"notice\":\"`commitment` cannot be consumed yet.\"}],\"CommitmentTooOld(bytes32,uint64,uint64)\":[{\"notice\":\"`commitment` has expired.\"}],\"DurationTooShort(uint64,uint64)\":[{\"notice\":\"`duration` less than `minDuration`.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"MaxCommitmentAgeTooLow()\":[{\"notice\":\"`maxCommitmentAge` was not greater than `minCommitmentAge`.\"}],\"NameNotAvailable(string)\":[{\"notice\":\"`label` cannot be registered.\"}],\"NameNotRenewable(string)\":[{\"notice\":\"`label` cannot be renewed.\"}],\"UnexpiredCommitmentExists(bytes32)\":[{\"notice\":\"`commitment` is still usable for registration.\"}]},\"events\":{\"CommitmentMade(bytes32)\":{\"notice\":\"`commitment` was recorded onchain at `block.timestamp`.\"},\"NameRegistered(uint256,string,address,address,address,uint64,address,bytes32,uint256,uint256)\":{\"notice\":\"A name was registered.\"},\"NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)\":{\"notice\":\"A name was extended by `duration`.\"},\"RentPriceOracleUpdated(address)\":{\"notice\":\"`IRentPriceOracle` was replaced.\"}},\"kind\":\"user\",\"methods\":{\"BENEFICIARY()\":{\"notice\":\"Address that receives payments.\"},\"ETH_REGISTRY()\":{\"notice\":\"ENSv2 .eth `PermissionedRegistry`.\"},\"GRACE_PERIOD()\":{\"notice\":\"Post-expiry period where still renewable and not available, in seconds.\"},\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"MAX_COMMITMENT_AGE()\":{\"notice\":\"Maximum seconds a commitment remains valid; expired commitments are rejected.\"},\"MIN_COMMITMENT_AGE()\":{\"notice\":\"Minimum seconds a commitment must age before registration can proceed.\"},\"MIN_REGISTER_DURATION()\":{\"notice\":\"Minimum register duration, in seconds.\"},\"MIN_RENEW_DURATION()\":{\"notice\":\"Minimum renew duration, in seconds.\"},\"commit(bytes32)\":{\"notice\":\"Registration step #1: record intent to register without revealing any information.\"},\"commitmentAt(bytes32)\":{\"notice\":\"Get timestamp of a prior commitment.\"},\"getRegisterPrice(string,uint64,address)\":{\"notice\":\"Determine register price for a name.\"},\"getRemainingGracePeriod(string)\":{\"notice\":\"Determine remaining grace period.\"},\"getRenewPrice(string,uint64,address)\":{\"notice\":\"Determine renew price for a name.\"},\"isAvailable(string)\":{\"notice\":\"Check if name is available.\"},\"isRenewable(string)\":{\"notice\":\"Check if name is renewable.\"},\"makeCommitment(string,address,bytes32,address,address,uint64,bytes32)\":{\"notice\":\"Compute hash of registration parameters.\"},\"register(string,address,bytes32,address,address,uint64,address,bytes32)\":{\"notice\":\"Register a name.\"},\"renew(string,uint64,address,bytes32)\":{\"notice\":\"Renew a name.\"},\"rentPriceOracle()\":{\"notice\":\"Oracle for registration and renewal costs.\"},\"setRentPriceOracle(address)\":{\"notice\":\"Change the rent price oracle.\"}},\"notice\":\"Commit-reveal registrar for .eth names. Registration requires two transactions: first `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment age but before the maximum commitment age has elapsed. The commitment hash binds all registration parameters (label, owner, secret, subregistry, resolver, duration, referrer) to prevent front-running. Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed set of roles (set subregistry, set resolver, and transfer \\u2014 each with their admin counterpart). Pricing and payment are delegated to a swappable `IRentPriceOracle`.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/ETHRegistrar.sol\":\"ETHRegistrar\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n /*\\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n * 0xb0202a11 ===\\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n */\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @param data Additional data with no specified format, sent in call to `spender`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\",\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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 /**\\n * @dev An operation with an ERC-20 token failed.\\n */\\n error SafeERC20FailedOperation(address token);\\n\\n /**\\n * @dev Indicates a failed `decreaseAllowance` request.\\n */\\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n forceApprove(token, spender, oldAllowance + value);\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n * value, non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n unchecked {\\n uint256 currentAllowance = token.allowance(address(this), spender);\\n if (currentAllowance < requestedDecrease) {\\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n }\\n forceApprove(token, spender, currentAllowance - requestedDecrease);\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n *\\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n * set here.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n safeTransfer(token, to, value);\\n } else if (!token.transferAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferFromAndCallRelaxed(\\n IERC1363 token,\\n address from,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length == 0) {\\n safeTransferFrom(token, from, to, value);\\n } else if (!token.transferFromAndCall(from, to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n * once without retrying, and relies on the returned value to be true.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n forceApprove(token, to, value);\\n } else if (!token.approveAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n // bubble errors\\n if iszero(success) {\\n let ptr := mload(0x40)\\n returndatacopy(ptr, 0, returndatasize())\\n revert(ptr, returndatasize())\\n }\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n\\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\n }\\n}\\n\",\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`.\\nabstract contract AbstractETHRegistrar is Ownable, HCAContext, ERC165, IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Minimum renew duration, in seconds.\\n uint64 public constant MIN_RENEW_DURATION = 1;\\n\\n /// @notice ENSv2 .eth `PermissionedRegistry`.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice Address that receives payments.\\n address public immutable BENEFICIARY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Oracle for registration and renewal costs.\\n IRentPriceOracle public rentPriceOracle;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `IRentPriceOracle` was replaced.\\n /// @param oracle The new `IRentPriceOracle` contract.\\n event RentPriceOracleUpdated(IRentPriceOracle oracle);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param hcaFactory HCA factory.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n constructor(\\n address owner_,\\n IHCAFactoryBasic hcaFactory,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle\\n )\\n Ownable(owner_)\\n HCAEquivalence(hcaFactory)\\n {\\n ETH_REGISTRY = ethRegistry;\\n BENEFICIARY = beneficiary;\\n\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Change the rent price oracle.\\n /// @param oracle The new `IRentPriceOracle` instance.\\n function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner {\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external\\n {\\n IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not\\n uint64 newExpiry = state.expiry + duration; // reverts if overflow\\n uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, amount); // reverts if payment failed\\n ETH_REGISTRY.renew(state.tokenId, newExpiry);\\n _onRenew(label, duration);\\n emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function isRenewable(string calldata label) external view returns (bool) {\\n return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n public\\n view\\n returns (uint256)\\n {\\n return\\n rentPriceOracle.getRenewPrice(\\n label,\\n _requireRenewable(label, duration).expiry,\\n duration,\\n paymentToken\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Callback for when a name is renewed.\\n function _onRenew(string calldata label, uint64 duration) internal virtual {}\\n\\n /// @dev Returns whether the name is renewable by this contract.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n virtual\\n returns (bool);\\n\\n /// @dev Ensure name is renewable.\\n function _requireRenewable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isRenewable(state)) {\\n revert NameNotRenewable(label);\\n }\\n if (duration < MIN_RENEW_DURATION) {\\n revert DurationTooShort(duration, MIN_RENEW_DURATION);\\n }\\n }\\n\\n /// @inheritdoc HCAContext\\n function _msgSender() internal view override(Context, HCAContext) returns (address) {\\n return super._msgSender();\\n }\\n}\\n\",\"keccak256\":\"0xb1cf6d7413558f8d257bdf8f734aaa57d4323e27854ae3ce79b7f017ff133510\",\"license\":\"MIT\"},\"project/src/registrar/ETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"../registry/libraries/RegistryRolesLib.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {AbstractETHRegistrar} from \\\"./AbstractETHRegistrar.sol\\\";\\nimport {IETHRegistrar} from \\\"./interfaces/IETHRegistrar.sol\\\";\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Roles assigned to owners at registration. Includes set-subregistry, set-resolver, and can-transfer (with admin variants).\\nuint256 constant REGISTRATION_ROLE_BITMAP =\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY |\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN |\\n RegistryRolesLib.ROLE_SET_RESOLVER |\\n RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN |\\n RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN;\\n\\n/// @notice Commit-reveal registrar for .eth names. Registration requires two transactions: first\\n/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment\\n/// age but before the maximum commitment age has elapsed. The commitment hash binds all\\n/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer)\\n/// to prevent front-running.\\n///\\n/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed\\n/// set of roles (set subregistry, set resolver, and transfer \\u2014 each with their admin\\n/// counterpart).\\n///\\n/// Pricing and payment are delegated to a swappable `IRentPriceOracle`.\\n///\\ncontract ETHRegistrar is AbstractETHRegistrar, IETHRegistrar {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRenewer\\n uint64 public immutable GRACE_PERIOD;\\n\\n /// @notice Minimum seconds a commitment must age before registration can proceed.\\n /// @dev If zero, front-running protection is disabled.\\n uint64 public immutable MIN_COMMITMENT_AGE;\\n\\n /// @notice Maximum seconds a commitment remains valid; expired commitments are rejected.\\n uint64 public immutable MAX_COMMITMENT_AGE;\\n\\n /// @notice Minimum register duration, in seconds.\\n uint64 public immutable MIN_REGISTER_DURATION;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n mapping(bytes32 commitment => uint64 commitTime) public commitmentAt;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`.\\n /// @dev Error selector: `0x3e5aa838`\\n error MaxCommitmentAgeTooLow();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param hcaFactory HCA factory.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n /// @param gracePeriod Post-expiry period where still renewable and not available, in seconds.\\n /// @param minCommitmentAge Minimum seconds a commitment must age before registration can proceed.\\n /// @param maxCommitmentAge Maximum seconds a commitment remains valid; expired commitments are rejected.\\n /// @param minRegisterDuration Minimum register duration, in seconds.\\n constructor(\\n address owner_,\\n IHCAFactoryBasic hcaFactory,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle,\\n uint64 gracePeriod,\\n uint64 minCommitmentAge,\\n uint64 maxCommitmentAge,\\n uint64 minRegisterDuration\\n )\\n AbstractETHRegistrar(owner_, hcaFactory, ethRegistry, beneficiary, oracle)\\n {\\n if (maxCommitmentAge <= minCommitmentAge) {\\n revert MaxCommitmentAgeTooLow();\\n }\\n GRACE_PERIOD = gracePeriod;\\n MIN_COMMITMENT_AGE = minCommitmentAge;\\n MAX_COMMITMENT_AGE = maxCommitmentAge;\\n MIN_REGISTER_DURATION = minRegisterDuration;\\n }\\n\\n /// @inheritdoc AbstractETHRegistrar\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return\\n interfaceId == type(IETHRegistrar).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n function commit(bytes32 commitment) external {\\n if (commitmentAt[commitment] + MAX_COMMITMENT_AGE > block.timestamp) {\\n revert UnexpiredCommitmentExists(commitment);\\n }\\n commitmentAt[commitment] = uint64(block.timestamp);\\n emit CommitmentMade(commitment);\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function register(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256 tokenId)\\n {\\n if (owner == address(0)) {\\n revert InvalidOwner();\\n }\\n _consumeCommitment(\\n makeCommitment(label, owner, secret, subregistry, resolver, duration, referrer)\\n ); // reverts if no commitment\\n IPermissionedRegistry.State memory state = _requireAvailable(label, duration); // reverts if not\\n (uint256 base, uint256 premium) =\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(state.expiry),\\n duration,\\n paymentToken\\n ); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, base + premium); // reverts if payment failed\\n tokenId = ETH_REGISTRY.register(\\n label,\\n owner,\\n subregistry,\\n resolver,\\n REGISTRATION_ROLE_BITMAP,\\n uint64(block.timestamp) + duration // new expiry\\n ); // should not revert\\n emit NameRegistered(\\n tokenId,\\n label,\\n owner,\\n subregistry,\\n resolver,\\n duration,\\n paymentToken,\\n referrer,\\n base,\\n premium\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function isAvailable(string calldata label) external view returns (bool) {\\n return _isAvailable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 bae, uint256 premium)\\n {\\n return\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(_requireAvailable(label, duration).expiry),\\n duration,\\n paymentToken\\n );\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n return\\n uint64(\\n _isRenewableGrace(state)\\n ? GRACE_PERIOD - (block.timestamp - state.expiry)\\n : 0\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n public\\n pure\\n override\\n returns (bytes32)\\n {\\n return\\n keccak256(abi.encode(label, owner, secret, subregistry, resolver, duration, referrer));\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates that the given `commitment` was recorded within the allowed time window\\n /// (between minimum and maximum commitment age), then deletes it so it cannot be reused.\\n /// @param commitment The commitment hash to validate and consume.\\n function _consumeCommitment(bytes32 commitment) internal {\\n uint64 t = uint64(block.timestamp);\\n uint64 t0 = commitmentAt[commitment];\\n uint64 tMin = t0 + MIN_COMMITMENT_AGE;\\n if (t < tMin) {\\n revert CommitmentTooNew(commitment, tMin, t);\\n }\\n uint64 tMax = t0 + MAX_COMMITMENT_AGE;\\n if (t >= tMax) {\\n revert CommitmentTooOld(commitment, tMax, t);\\n }\\n delete commitmentAt[commitment];\\n }\\n\\n /// @dev Ensure name is registerable.\\n function _requireAvailable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isAvailable(state)) {\\n revert NameNotAvailable(label);\\n }\\n if (duration < MIN_REGISTER_DURATION) {\\n revert DurationTooShort(duration, MIN_REGISTER_DURATION);\\n }\\n }\\n\\n /// @dev Determine if `AVAILABLE` and not in grace.\\n function _isAvailable(IPermissionedRegistry.State memory state) internal view returns (bool) {\\n return _checkGrace(state, false);\\n }\\n\\n /// @dev Determine if `REGISTERED` or in grace was `REGISTERED`.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n override\\n returns (bool)\\n {\\n return state.status == IPermissionedRegistry.Status.REGISTERED || _isRenewableGrace(state);\\n }\\n\\n /// @dev Determine if was `REGISTERED` and in grace.\\n function _isRenewableGrace(IPermissionedRegistry.State memory state)\\n internal\\n view\\n returns (bool)\\n {\\n return state.latestOwner != address(0) && _checkGrace(state, true);\\n }\\n\\n /// @dev Check if `AVAILABLE` and conditionally in grace.\\n function _checkGrace(IPermissionedRegistry.State memory state, bool grace)\\n internal\\n view\\n returns (bool)\\n {\\n return\\n state.status == IPermissionedRegistry.Status.AVAILABLE &&\\n (grace == (block.timestamp - state.expiry) < GRACE_PERIOD);\\n }\\n\\n /// @dev Determine duration name has been available.\\n function _availablePeriod(uint64 expiry) internal view returns (uint64) {\\n uint64 t = uint64(block.timestamp);\\n if (expiry == 0) {\\n return t; // never registered\\n }\\n expiry += GRACE_PERIOD;\\n return t > expiry ? t - expiry : 0;\\n }\\n}\\n\",\"keccak256\":\"0x98448c1cb629eec852d9e6ba65ab8b1d46b68f813c2687b0c84d115fbc84b91c\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./IETHRenewer.sol\\\";\\n\\n/// @notice Interface for registering \\\".eth\\\" names.\\n/// @dev Interface selector: `0xc1401b80`\\ninterface IETHRegistrar is IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` was recorded onchain at `block.timestamp`.\\n /// @param commitment The commitment hash from `makeCommitment()`.\\n event CommitmentMade(bytes32 commitment);\\n\\n /// @notice A name was registered.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the registration.\\n /// @param owner The owner address.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param base The amount of `paymentToken` for the registration.\\n /// @param premium The amount of `paymentToken` due to premium.\\n event NameRegistered(\\n uint256 indexed tokenId,\\n string label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 base,\\n uint256 premium\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` is still usable for registration.\\n /// @dev Error selector: `0x0a059d71`\\n error UnexpiredCommitmentExists(bytes32 commitment);\\n\\n /// @notice `commitment` cannot be consumed yet.\\n /// @dev Error selector: `0x6be614e3`\\n error CommitmentTooNew(bytes32 commitment, uint64 validFrom, uint64 blockTimestamp);\\n\\n /// @notice `commitment` has expired.\\n /// @dev Error selector: `0x0cb9df3f`\\n error CommitmentTooOld(bytes32 commitment, uint64 validTo, uint64 blockTimestamp);\\n\\n /// @notice `label` cannot be registered.\\n /// @dev Error selector: `0x477707e8`\\n error NameNotAvailable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registration step #1: record intent to register without revealing any information.\\n /// @dev Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.\\n /// @param commitment The commitment hash.\\n function commit(bytes32 commitment) external;\\n\\n /// @notice Register a name.\\n /// @param label The name from commitment.\\n /// @param owner The owner from commitment.\\n /// @param secret The secret from commitment.\\n /// @param subregistry The registry from commitment.\\n /// @param resolver The resolver from commitment.\\n /// @param duration The registration from commitment.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @return The registered token ID.\\n function register(\\n string memory label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256);\\n\\n /// @notice Get timestamp of a prior commitment.\\n /// @param commitment The commitment hash.\\n /// @return The commitment time, in seconds, or 0 if unknown.\\n function commitmentAt(bytes32 commitment) external view returns (uint64);\\n\\n /// @notice Determine register price for a name.\\n /// @param label The name to register.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Check if name is available.\\n /// @param label The name to check.\\n /// @return `true` if registerable.\\n function isAvailable(string memory label) external view returns (bool);\\n\\n /// @notice Compute hash of registration parameters.\\n /// @param label The name to register.\\n /// @param owner The owner address.\\n /// @param secret The secret for the registration.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param referrer The referrer hash.\\n /// @return The commitment hash.\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n external\\n pure\\n returns (bytes32);\\n}\\n\",\"keccak256\":\"0x7e824c5019f8eb7d7a283451700234716353e01d649c811b5ced5cf58b476289\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for renewing \\\".eth\\\" names.\\n/// @dev Interface selector: `0x06aaeb32`\\ninterface IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A name was extended by `duration`.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the renewal.\\n /// @param duration The duration extension, in seconds.\\n /// @param newExpiry The new expiry, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param amount The amount of `paymentToken`.\\n event NameRenewed(\\n uint256 indexed tokenId,\\n string label,\\n uint64 duration,\\n uint64 newExpiry,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 amount\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `duration` less than `minDuration`.\\n /// @dev Error selector: `0xa096b844`\\n error DurationTooShort(uint64 duration, uint64 minDuration);\\n\\n /// @notice `label` cannot be renewed.\\n /// @dev Error selector: `0x1caefaa0`\\n error NameNotRenewable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Renew a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external;\\n\\n /// @notice Determine renew price for a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice Check if name is renewable.\\n /// @param label The name to check.\\n /// @return `true` if renewable.\\n function isRenewable(string calldata label) external view returns (bool);\\n\\n /// @notice Determine remaining grace period.\\n /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`.\\n /// @param label The name to check.\\n /// @return The remaining grace period, in seconds.\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64);\\n\\n /// @notice Post-expiry period where still renewable and not available, in seconds.\\n function GRACE_PERIOD() external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 7: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x6bd37001025ec90ffe9b852fcfdf68be81a9f70f8777d80136bea1c04da30041\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 34237, + "contract": "project/src/registrar/ETHRegistrar.sol:ETHRegistrar", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 63504, + "contract": "project/src/registrar/ETHRegistrar.sol:ETHRegistrar", + "label": "rentPriceOracle", + "offset": 0, + "slot": "1", + "type": "t_contract(IRentPriceOracle)66102" + }, + { + "astId": 63995, + "contract": "project/src/registrar/ETHRegistrar.sol:ETHRegistrar", + "label": "commitmentAt", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_uint64)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRentPriceOracle)66102": { + "encoding": "inplace", + "label": "contract IRentPriceOracle", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint64)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint64)", + "numberOfBytes": "32", + "value": "t_uint64" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CommitmentTooNew(bytes32,uint64,uint64)": [ + { + "notice": "`commitment` cannot be consumed yet." + } + ], + "CommitmentTooOld(bytes32,uint64,uint64)": [ + { + "notice": "`commitment` has expired." + } + ], + "DurationTooShort(uint64,uint64)": [ + { + "notice": "`duration` less than `minDuration`." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "MaxCommitmentAgeTooLow()": [ + { + "notice": "`maxCommitmentAge` was not greater than `minCommitmentAge`." + } + ], + "NameNotAvailable(string)": [ + { + "notice": "`label` cannot be registered." + } + ], + "NameNotRenewable(string)": [ + { + "notice": "`label` cannot be renewed." + } + ], + "UnexpiredCommitmentExists(bytes32)": [ + { + "notice": "`commitment` is still usable for registration." + } + ] + }, + "events": { + "CommitmentMade(bytes32)": { + "notice": "`commitment` was recorded onchain at `block.timestamp`." + }, + "NameRegistered(uint256,string,address,address,address,uint64,address,bytes32,uint256,uint256)": { + "notice": "A name was registered." + }, + "NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)": { + "notice": "A name was extended by `duration`." + }, + "RentPriceOracleUpdated(address)": { + "notice": "`IRentPriceOracle` was replaced." + } + }, + "kind": "user", + "methods": { + "BENEFICIARY()": { + "notice": "Address that receives payments." + }, + "ETH_REGISTRY()": { + "notice": "ENSv2 .eth `PermissionedRegistry`." + }, + "GRACE_PERIOD()": { + "notice": "Post-expiry period where still renewable and not available, in seconds." + }, + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "MAX_COMMITMENT_AGE()": { + "notice": "Maximum seconds a commitment remains valid; expired commitments are rejected." + }, + "MIN_COMMITMENT_AGE()": { + "notice": "Minimum seconds a commitment must age before registration can proceed." + }, + "MIN_REGISTER_DURATION()": { + "notice": "Minimum register duration, in seconds." + }, + "MIN_RENEW_DURATION()": { + "notice": "Minimum renew duration, in seconds." + }, + "commit(bytes32)": { + "notice": "Registration step #1: record intent to register without revealing any information." + }, + "commitmentAt(bytes32)": { + "notice": "Get timestamp of a prior commitment." + }, + "getRegisterPrice(string,uint64,address)": { + "notice": "Determine register price for a name." + }, + "getRemainingGracePeriod(string)": { + "notice": "Determine remaining grace period." + }, + "getRenewPrice(string,uint64,address)": { + "notice": "Determine renew price for a name." + }, + "isAvailable(string)": { + "notice": "Check if name is available." + }, + "isRenewable(string)": { + "notice": "Check if name is renewable." + }, + "makeCommitment(string,address,bytes32,address,address,uint64,bytes32)": { + "notice": "Compute hash of registration parameters." + }, + "register(string,address,bytes32,address,address,uint64,address,bytes32)": { + "notice": "Register a name." + }, + "renew(string,uint64,address,bytes32)": { + "notice": "Renew a name." + }, + "rentPriceOracle()": { + "notice": "Oracle for registration and renewal costs." + }, + "setRentPriceOracle(address)": { + "notice": "Change the rent price oracle." + } + }, + "notice": "Commit-reveal registrar for .eth names. Registration requires two transactions: first `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment age but before the maximum commitment age has elapsed. The commitment hash binds all registration parameters (label, owner, secret, subregistry, resolver, duration, referrer) to prevent front-running. Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed set of roles (set subregistry, set resolver, and transfer — each with their admin counterpart). Pricing and payment are delegated to a swappable `IRentPriceOracle`.", + "version": 1 + }, + "argsData": "0x000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf943000000000000000000000000dedb92913a25abe1f7bcdd85d8a344a43b398b67000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80000000000000000000000000e19d37839f42f7d2694d8c5712f412c66a218161000000000000000000000000000000000000000000000000000000000024ea00000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000024ea00", + "transaction": { + "hash": "0x2a1565815dd7652eba5770bc6d5aca2d59023f787025d17321b69dff9bdc8b62", + "nonce": "0x1e95", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xf8511df78493927d6140d572da97bbd87f309066e682720c163bc83ebe59afad", + "blockNumber": "0xa6a80a", + "transactionIndex": "0x4c" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRegistry.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRegistry.json new file mode 100644 index 000000000..a9d23ec82 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRegistry.json @@ -0,0 +1,2800 @@ +{ + "address": "0xdedb92913a25abe1f7bcdd85d8a344a43b398b67", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "contract ILabelStore", + "name": "labelStore", + "type": "address" + }, + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "oldExpiry", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "CannotReduceExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "CannotSetPastExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "LabelExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "TransferDisallowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExpiryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ParentUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RegistryCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ResolverUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SubregistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTokenId", + "type": "uint256" + } + ], + "name": "TokenRegenerated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "TokenResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "renderer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "URIUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LABEL_STORE", + "outputs": [ + { + "internalType": "contract ILabelStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParent", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getResource", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "internalType": "address", + "name": "latestOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "internalType": "struct IPermissionedRegistry.State", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getStatus", + "outputs": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getSubregistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "latestOwnerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setParent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "setSubregistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + }, + { + "internalType": "contract IRegistryURIRenderer", + "name": "renderer", + "type": "address" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "PermissionedRegistry", + "sourceName": "src/registry/PermissionedRegistry.sol", + "bytecode": "0x60c060405234801561000f575f5ffd5b50604051614be8380380614be883398101604081905261002e91610cb8565b6001600160a01b0384166080526040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16001600160a01b03831660a05261007c5f828482610086565b5050505050610f15565b5f835f0361009557505f610190565b61009e84610198565b6001600160a01b0383166100c55760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461018a575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616610125888260016101e4565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561017e5761017e888785858b610314565b60019350505050610190565b5f925050505b949350505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156101e157604051630153d96960e51b8152600481018290526024015b60405180910390fd5b50565b5f6101ee83610324565b90508115610284575f848152600360205260409020546102349082161980195f516020614bc85f395f51905f5291909101165f516020614ba85f395f51905f5216151590565b1561025c57604051631f22ca6960e31b815260048101859052602481018490526044016101d8565b5f8481526003602052604081208054859290610279908490610d1c565b9091555061030e9050565b5f848152600360205260409020546102c3901982161980195f516020614bc85f395f51905f5291909101165f516020614ba85f395f51905f5216151590565b156102eb57604051631f80c19b60e01b815260048101859052602481018490526044016101d8565b5f8481526003602052604081208054859290610308908490610d2f565b90915550505b50505050565b61031d8561033e565b5050505050565b5f61032e82610198565b50600181901b17600281901b1790565b80156101e15763ffffffff811681185f9081526101086020526040812090610366838361042a565b5f818152602081905260409020549091506001600160a01b031661038c8183600161044d565b825483906004906103aa90640100000000900463ffffffff16610d42565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6103d9838561042a60201b60201c565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a361031d8282600160405180602001604052805f8152506104b460201b60201c565b80545f9063ffffffff808516851864010000000090920416185b90505b92915050565b6001600160a01b03831661047557604051626a0d4560e21b81525f60048201526024016101d8565b604080516001808252602082018590528183019081526060820184905260a082019092525f6080820181815291929161031d9187918590859083610529565b6001600160a01b0384166104dd57604051632bfa23e760e11b81525f60048201526024016101d8565b604080516001808252602082018690528183019081526060820185905260808201909252906105105f8784848784610529565b505050505050565b63ffffffff82811690921891161890565b6105358686868661058c565b6001600160a01b03851615610510575f61054d610667565b9050811561056857610563818888888888610675565b610583565b60208581015190850151610580838a8a85858a610796565b50505b50505050505050565b6105988484848461087d565b6001600160a01b038316158015906105b857506001600160a01b03841615155b1561030e575f5b825181101561031d575f8382815181106105db576105db610d66565b602002602001015190506105fa816001609c1b88610a8660201b60201c565b610629576040516372c7b6ad60e11b8152600481018290526001600160a01b03871660248201526044016101d8565b5f83838151811061063c5761063c610d66565b6020026020010151111561065e5761065e61065682610ae5565b87875f610b0c565b506001016105bf565b5f610670610b4d565b905090565b6001600160a01b0384163b156105105760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906106b99089908990889088908890600401610de2565b6020604051808303815f875af19250505080156106f3575060408051601f3d908101601f191682019092526106f091810190610e3f565b60015b61075a573d808015610720576040519150601f19603f3d011682016040523d82523d5f602084013e610725565b606091505b5080515f0361075257604051632bfa23e760e11b81526001600160a01b03861660048201526024016101d8565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461058357604051632bfa23e760e11b81526001600160a01b03861660048201526024016101d8565b6001600160a01b0384163b156105105760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906107da9089908990889088908890600401610e6d565b6020604051808303815f875af1925050508015610814575060408051601f3d908101601f1916820190925261081191810190610e3f565b60015b610841573d808015610720576040519150601f19603f3d011682016040523d82523d5f602084013e610725565b6001600160e01b0319811663f23a6e6160e01b1461058357604051632bfa23e760e11b81526001600160a01b03861660048201526024016101d8565b80518251146108ac5781518151604051635b05999160e01b8152600481019290925260248201526044016101d8565b5f6108b5610667565b90505f5b83518110156109a857602081810285810182015190850190910151801561099e575f828152602081905260409020546001600160a01b039081169089168114610934576040516303dee4c560e01b81526001600160a01b038a1660048201525f602482015260448101839052606481018490526084016101d8565b6001821115610976576040516303dee4c560e01b81526001600160a01b038a1660048201526001602482015260448101839052606481018490526084016101d8565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0389161790555b50506001016108b9565b508251600103610a285760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051610a19929190918252602082015260400190565b60405180910390a4505061031d565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051610a77929190610eb1565b60405180910390a45050505050565b5f610190610a9385610ae5565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f61044782610b078163ffffffff8116185f9081526101086020526040902090565b610bea565b5f8481526002602090815260408083206001600160a01b0387168452909152902054801561031d57610b4085828685610c38565b5061051085828585610086565b6080515f906001600160a01b0316610b6457503390565b60805160405163110ac5cb60e21b81523360048201525f916001600160a01b03169063442b172c90602401602060405180830381865afa158015610baa573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bce9190610ede565b90506001600160a01b038116610be5573391505090565b919050565b5f82610bf7575081610447565b60018201546104449084906001600160401b0316421015610c2557835463ffffffff82811690921891161890565b83546105189063ffffffff166001610ef9565b5f610c4284610198565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461018a575f8781526002602090815260408083206001600160a01b038916845290915281208290558683169061012590899083906101e4565b6001600160a01b03811681146101e1575f5ffd5b5f5f5f5f60808587031215610ccb575f5ffd5b8451610cd681610ca4565b6020860151909450610ce781610ca4565b6040860151909350610cf881610ca4565b6060959095015193969295505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561044757610447610d08565b8181038181111561044757610447610d08565b5f63ffffffff821663ffffffff8103610d5d57610d5d610d08565b60010192915050565b634e487b7160e01b5f52603260045260245ffd5b5f8151808452602084019350602083015f5b82811015610daa578151865260209586019590910190600101610d8c565b5093949350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0386811682528516602082015260a0604082018190525f90610e0d90830186610d7a565b8281036060840152610e1f8186610d7a565b90508281036080840152610e338185610db4565b98975050505050505050565b5f60208284031215610e4f575f5ffd5b81516001600160e01b031981168114610e66575f5ffd5b9392505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f90610ea690830184610db4565b979650505050505050565b604081525f610ec36040830185610d7a565b8281036020840152610ed58185610d7a565b95945050505050565b5f60208284031215610eee575f5ffd5b8151610e6681610ca4565b63ffffffff818116838216019081111561044757610447610d08565b60805160a051613c5d610f4b5f395f81816106250152611bb501525f81816104070152818161245701526124b80152613c5d5ff3fe608060405234801561000f575f5ffd5b50600436106102cc575f3560e01c80635c622a0e1161017c5780639dbba19d116100dd578063ce156e8211610093578063e4ae7d771161006e578063e4ae7d77146106cc578063e985e9c5146106df578063f242432a1461071a575f5ffd5b8063ce156e8214610693578063d3bf89b1146106a6578063dfa70d8b146106b9575f5ffd5b8063a22cb465116100c3578063a22cb4651461065a578063bc7b6d621461066d578063bd242bcb14610680575f5ffd5b80639dbba19d14610620578063a02b161e14610647575f5ffd5b8063781ef8db1161013257806380f760211161011857806380f76021146105e457806385f3e643146105fa57806391b3c0371461060d575f5ffd5b8063781ef8db146105875780637c300586146105d1575f5ffd5b806363560a8e1161016257806363560a8e1461054e5780636f3ff726146105615780636f537c7214610574575f5ffd5b80635c622a0e1461051b5780636352211e1461053b575f5ffd5b80632f27fa241161023157806344c9af28116101e75780635357263f116101c25780635357263f146104e25780635569f33d146104f55780635adf472414610508575f5ffd5b806344c9af281461048f57806348688f95146104af5780634e1273f4146104c2575f5ffd5b8063341ec55911610217578063341ec5591461044157806335af6216146104545780633634f91114610467575f5ffd5b80632f27fa24146103ef578063319c22bb14610402575f5ffd5b806313c72608116102865780631c3fc3eb1161026c5780631c3fc3eb146103c05780631e8fca2d146103c75780632eb2c2d6146103da575f5ffd5b806313c726081461035f57806314ff5ea3146103ad575f5ffd5b8063072d5d77116102b6578063072d5d77146103195780630e89341c1461032c57806311b8e00a1461034c575f5ffd5b8062fdd58e146102d057806301ffc9a7146102f6575b5f5ffd5b6102e36102de366004612fe9565b61072d565b6040519081526020015b60405180910390f35b610309610304366004613028565b610764565b60405190151581526020016102ed565b610309610327366004613043565b6108d9565b61033f61033a366004613071565b610904565b6040516102ed91906130b6565b61030961035a3660046130c8565b610a34565b61039461036d366004613071565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016102ed565b6102e36103bb366004613071565b610a4e565b6102e35f81565b6102e36103d5366004613071565b610a75565b6103ed6103e8366004613230565b610a9c565b005b6102e36103fd366004613071565b610b39565b6104297f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102ed565b6103ed61044f366004613043565b610b57565b610429610462366004613321565b610bf5565b61047a6104753660046130c8565b610c90565b604080519283526020830191909152016102ed565b6104a261049d366004613071565b610cb0565b6040516102ed9190613394565b6103ed6104bd3660046133e7565b610d82565b6104d56104d036600461343a565b610e24565b6040516102ed9190613539565b6103ed6104f036600461354b565b610eef565b6103ed6105033660046135a5565b610f8d565b6102e3610516366004613043565b61112a565b61052e610529366004613071565b61115c565b6040516102ed91906135cf565b610429610549366004613071565b6111b2565b61042961055c366004613321565b611217565b61030961056f3660046135dd565b611225565b610394610582366004613321565b611276565b610309610595366004613043565b6001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b6103096105df3660046135f8565b6112b8565b6105ec6112cc565b6040516102ed929190613623565b6102e3610608366004613644565b611377565b6102e361061b366004613321565b611393565b6104297f000000000000000000000000000000000000000000000000000000000000000081565b6103ed610655366004613071565b6113d5565b6103ed6106683660046136cd565b6114e2565b6103ed61067b366004613043565b6114f8565b61042961068e366004613071565b61159b565b6103096106a1366004613043565b6115b7565b6103096106b43660046135f8565b6115d9565b6103096106c73660046135f8565b611638565b6104296106da366004613321565b61164c565b6103096106ed3660046136fd565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6103ed610728366004613729565b6116c7565b5f826001600160a01b0316610741836111b2565b6001600160a01b031614610755575f610758565b60015b60ff1690505b92915050565b5f6001600160e01b031982167fafff3a630000000000000000000000000000000000000000000000000000000014806107c657506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b806107fa57506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b8061082e57506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b8061086257506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b8061089657506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b806108ca57506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061075e575061075e82611757565b5f5f836108ee82826108e9611794565b6117a2565b6108fb5f868660016117f0565b95945050505050565b610107546060906001600160a01b03166109a757610106805461092690613781565b80601f016020809104026020016040519081016040528092919081815260200182805461095290613781565b801561099d5780601f106109745761010080835404028352916020019161099d565b820191905f5260205f20905b81548152906001019060200180831161098057829003601f168201915b505050505061075e565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610a0d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261075e91908101906137b9565b5f610a47610a4184610a75565b83611919565b9392505050565b5f61075e82610a708463ffffffff8116185f9081526101086020526040902090565b611930565b5f61075e82610a978463ffffffff8116185f9081526101086020526040902090565b61194e565b5f610aa5611794565b9050806001600160a01b0316866001600160a01b031614158015610aee57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b15610b245760405163711bec9160e11b81526001600160a01b038083166004830152871660248201526044015b60405180910390fd5b610b3186868686866119a8565b505050505050565b5f61075e610b4683610a75565b5f9081526003602052604090205490565b5f5f610b668462100000611a0f565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038716021781559092509050610baf611794565b6001600160a01b0316836001600160a01b0316837fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a450505050565b5f5f610c51610c3885858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610c865780546801000000000000000090046001600160a01b0316610c88565b5f5b949350505050565b5f5f610ca4610c9e85610a75565b84611a85565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610d0e8584611930565b606085018190529050610d21858461194e565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610d4f8382611aa8565b85906002811115610d6257610d62613360565b90816002811115610d7557610d75613360565b8152505050505050919050565b641000000000610d9a5f82610d95611794565b611adf565b610106610da8848683613872565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416179055610dda611794565b6001600160a01b03167fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd5858585604051610e169392919061392c565b60405180910390a250505050565b60608151835114610e555781518351604051635b05999160e01b815260048101929092526024820152604401610b1b565b5f835167ffffffffffffffff811115610e7057610e706130e8565b604051908082528060200260200182016040528015610e99578160200160208202803683370190505b5090505f5b8451811015610ee757602080820286010151610ec29060208084028701015161072d565b828281518110610ed457610ed461396c565b6020908102919091010152600101610e9e565b509392505050565b610100610eff5f82610d95611794565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105610f358382613980565b50610f3e611794565b6001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff484604051610f8091906130b6565b60405180910390a3505050565b63ffffffff821682185f9081526101086020526040812090610faf8483611930565b90505f610fba611794565b600184015490915067ffffffffffffffff164281116110515767ffffffffffffffff8116158061102b575061102962010000836001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b155b1561104c5760405163311388dd60e21b815260048101849052602401610b1b565b611068565b61106861105e878661194e565b6201000084611adf565b8067ffffffffffffffff168567ffffffffffffffff1610156110ca576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015286166024820152604401610b1b565b60018401805467ffffffffffffffff191667ffffffffffffffff87169081179091556040516001600160a01b038416919085907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a4505050505050565b5f610a4761113784610a75565b5f9081526002602090815260408083206001600160a01b038716845290915290205490565b63ffffffff811681185f908152610108602052604081206001810154610a479067ffffffffffffffff166111ad6111938685611930565b5f908152602081905260409020546001600160a01b031690565b611aa8565b63ffffffff811681185f908152610108602052604081206111d38382611930565b831415806111ef5750600181015467ffffffffffffffff164210155b61120f575f838152602081905260409020546001600160a01b0316610a47565b5f9392505050565b5f610a476105498484611393565b6001600160a01b0381165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b60205260408120546f010000000000000000000000000000009081161461075e565b5f610a4761036d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b5f610c886112c585610a75565b8484611b3e565b6101045461010580545f926060926001600160a01b039091169181906112f190613781565b80601f016020809104026020016040519081016040528092919081815260200182805461131d90613781565b80156113685780601f1061133f57610100808354040283529160200191611368565b820191905f5260205f20905b81548152906001019060200180831161134b57829003601f168201915b50505050509050915091509091565b5f6113888787878787876001611b83565b979650505050505050565b5f610a476103bb84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b5f5f6113e383611000611a0f565b915091506113ef611794565b6001600160a01b0316827f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea860405160405180910390a35f828152602081905260409020546001600160a01b031680156114bf5761144e818460016120e4565b815482905f906114639063ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166114a090613a4f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b6114f46114ed611794565b838361214b565b5050565b5f5f611508846301000000611a0f565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038816021790559092509050611555611794565b6001600160a01b0316836001600160a01b0316837f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a450505050565b5f818152602081905260408120546001600160a01b031661075e565b5f5f836115cc82826115c7611794565b6121f1565b6108fb5f86866001612252565b5f610c886115e685610a75565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f610c8861164585610a75565b84846122be565b5f5f61168f610c3885858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b600181015490915067ffffffffffffffff16421015610c865760018101546801000000000000000090046001600160a01b0316610c88565b5f6116d0611794565b9050806001600160a01b0316866001600160a01b03161415801561171957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561174a5760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610b1b565b610b3186868686866122f9565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061075e575061075e82612386565b5f61179d612454565b905090565b5f6117ad8483612545565b905080198316156117ea5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610b1b565b50505050565b5f835f036117ff57505f610c88565b6118088461260b565b6001600160a01b038316611848576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461190d575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166118a88882600161266b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561190157611901888785858b612800565b60019350505050610c88565b505f9695505050505050565b5f5f6119258484610c90565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610a47565b5f8261195b57508161075e565b6001820154610a4790849067ffffffffffffffff1642101561198457835463ffffffff16611997565b83546119979063ffffffff166001613a73565b63ffffffff82811690921891161890565b6001600160a01b0384166119d157604051632bfa23e760e11b81525f6004820152602401610b1b565b6001600160a01b0385166119f957604051626a0d4560e21b81525f6004820152602401610b1b565b611a0885858585856001612809565b5050505050565b63ffffffff821682185f90815261010860205260408120611a308482611930565b600182015490925067ffffffffffffffff164210611a645760405163311388dd60e21b815260048101839052602401610b1b565b610ca9611a71858361194e565b84610d95611794565b805160209091012090565b5f5f611a908361286b565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff83164210611ac157505f61075e565b6001600160a01b038216611ad75750600161075e565b50600261075e565b611aea8383836115d9565b611b39576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610b1b565b505050565b5f8383611b4e82826108e9611794565b85611b6c57604051631850848b60e31b815260040160405180910390fd5b611b7986868660016117f0565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990611bea908b906004016130b6565b5f604051808303815f87803b158015611c01575f5ffd5b505af1158015611c13573d5f5f3e3d5ffd5b5050895160208b012091505f9050611c3e8263ffffffff8116185f9081526101086020526040902090565b9050611c4a8282611930565b5f818152602081905260408120549194506001600160a01b0390911690611c6f611794565b600184015490915067ffffffffffffffff164210611cea578515611c9957611c995f600183611adf565b6001600160a01b038b16158015611caf57508715155b15611ce55760405163d1a3b35560e01b81525f6004820152602481018990526001600160a01b0382166044820152606401610b1b565b611daf565b6001600160a01b03821615611d2d578b6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610b1b91906130b6565b6001600160a01b038b16611d6f578b6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610b1b91906130b6565b8515611d8157611d815f601083611adf565b8667ffffffffffffffff165f03611da457600183015467ffffffffffffffff1696505b640100000000881797505b6001600160a01b038b1615611dd15767ffffffffffffffff8716421015611dde565b67ffffffffffffffff8716155b15611e21576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff88166004820152602401610b1b565b6001600160a01b03821615611eb957611e3c828660016120e4565b825483905f90611e519063ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550825f01600481819054906101000a900463ffffffff16611e8e90613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550611eb68584611930565b94505b60018301805484546001600160a01b03808e16680100000000000000009081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921787558c81169091026001600160e01b031990921667ffffffffffffffff8b1617919091179091558b16611f7a57806001600160a01b0316845f1b867f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88f8b604051611f6d929190613a8f565b60405180910390a4612033565b806001600160a01b0316845f1b867f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8f8f8c604051611fbb93929190613aba565b60405180910390a4611fde8b86600160405180602001604052805f815250612885565b5f611fe9868561194e565b905080611ff857611ff8613af5565b604051819087907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a3612030818a8e5f6117f0565b50505b6001600160a01b038a161561208457806001600160a01b03168a6001600160a01b0316867fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a45b6001600160a01b038916156120d557806001600160a01b0316896001600160a01b0316867f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a45b50505050979650505050505050565b6001600160a01b03831661210c57604051626a0d4560e21b81525f6004820152602401610b1b565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291611a089187918590859083612809565b6001600160a01b03821661218d576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610b1b565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610f80565b5f6121fc84836128e1565b905080198316156117ea576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610b1b565b5f61225c8461260b565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461190d575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906118a8908990839061266b565b5f83836122ce82826115c7611794565b856122ec57604051631850848b60e31b815260040160405180910390fd5b611b798686866001612252565b6001600160a01b03841661232257604051632bfa23e760e11b81525f6004820152602401610b1b565b6001600160a01b03851661234a57604051626a0d4560e21b81525f6004820152602401610b1b565b6040805160018082526020820186905281830190815260608201859052608082019092529061237d87878484875f612809565b50505050505050565b5f6001600160e01b031982167fd9b67a260000000000000000000000000000000000000000000000000000000014806123e857506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b8061241c57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061075e57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461075e565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661248857503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015612505573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125299190613b09565b90506001600160a01b038116612540573391505090565b919050565b5f5f6125b784846001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b9050836125c557905061075e565b5f6125ea61054986610a708163ffffffff8116185f9081526101086020526040902090565b6001600160a01b031603612601575f91505061075e565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612668576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610b1b565b50565b5f6126758361286b565b9050811561273e575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612716576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610b1b565b5f8481526003602052604081208054859290612733908490613b24565b909155506117ea9050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156127d8576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610b1b565b5f84815260036020526040812080548592906127f5908490613b37565b909155505050505050565b611a0885612998565b61281586868686612a78565b6001600160a01b03851615610b31575f61282d611794565b9050811561284857612843818888888888612b76565b61237d565b60208581015190850151612860838a8a85858a612c97565b505050505050505050565b5f6128758261260b565b50600181901b17600281901b1790565b6001600160a01b0384166128ae57604051632bfa23e760e11b81525f6004820152602401610b1b565b60408051600180825260208201869052818301908152606082018590526080820190925290610b315f8784848784612809565b5f821580159061291c57505f61291161054985610a708163ffffffff8116185f9081526101086020526040902090565b6001600160a01b0316145b1561292857505f61075e565b610a4783836001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b80156126685763ffffffff811681185f90815261010860205260408120906129c08383611930565b5f818152602081905260409020549091506001600160a01b03166129e6818360016120e4565b82548390600490612a0490640100000000900463ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f612a2d8385611930565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3611a088282600160405180602001604052805f815250612885565b612a8484848484612d7e565b6001600160a01b03831615801590612aa457506001600160a01b03841615155b156117ea575f5b8251811015611a08575f838281518110612ac757612ac761396c565b60200260200101519050612af081731000000000000000000000000000000000000000886115d9565b612b38576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610b1b565b5f838381518110612b4b57612b4b61396c565b60200260200101511115612b6d57612b6d612b6582610a75565b87875f612f94565b50600101612aab565b6001600160a01b0384163b15610b315760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612bba9089908990889088908890600401613b4a565b6020604051808303815f875af1925050508015612bf4575060408051601f3d908101601f19168201909252612bf191810190613bac565b60015b612c5b573d808015612c21576040519150601f19603f3d011682016040523d82523d5f602084013e612c26565b606091505b5080515f03612c5357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461237d57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b6001600160a01b0384163b15610b315760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612cdb9089908990889088908890600401613bc7565b6020604051808303815f875af1925050508015612d15575060408051601f3d908101601f19168201909252612d1291810190613bac565b60015b612d42573d808015612c21576040519150601f19603f3d011682016040523d82523d5f602084013e612c26565b6001600160e01b0319811663f23a6e6160e01b1461237d57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b8051825114612dad5781518151604051635b05999160e01b815260048101929092526024820152604401610b1b565b5f612db6611794565b90505f5b8351811015612eb6576020818102858101820151908501909101518015612eac575f828152602081905260409020546001600160a01b039081169089168114612e35576040516303dee4c560e01b81526001600160a01b038a1660048201525f60248201526044810183905260648101849052608401610b1b565b6001821115612e77576040516303dee4c560e01b81526001600160a01b038a166004820152600160248201526044810183905260648101849052608401610b1b565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389161790555b5050600101612dba565b508251600103612f365760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051612f27929190918252602082015260400190565b60405180910390a45050611a08565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051612f85929190613c03565b60405180910390a45050505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015611a0857612fc885828685612252565b50610b31858285856117f0565b6001600160a01b0381168114612668575f5ffd5b5f5f60408385031215612ffa575f5ffd5b823561300581612fd5565b946020939093013593505050565b6001600160e01b031981168114612668575f5ffd5b5f60208284031215613038575f5ffd5b8135610a4781613013565b5f5f60408385031215613054575f5ffd5b82359150602083013561306681612fd5565b809150509250929050565b5f60208284031215613081575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610a476020830184613088565b5f5f604083850312156130d9575f5ffd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613125576131256130e8565b604052919050565b5f67ffffffffffffffff821115613146576131466130e8565b5060051b60200190565b5f82601f83011261315f575f5ffd5b813561317261316d8261312d565b6130fc565b8082825260208201915060208360051b860101925085831115613193575f5ffd5b602085015b838110156131b0578035835260209283019201613198565b5095945050505050565b5f67ffffffffffffffff8211156131d3576131d36130e8565b50601f01601f191660200190565b5f82601f8301126131f0575f5ffd5b8135602083015f61320361316d846131ba565b9050828152858383011115613216575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f5f5f60a08688031215613244575f5ffd5b853561324f81612fd5565b9450602086013561325f81612fd5565b9350604086013567ffffffffffffffff81111561327a575f5ffd5b61328688828901613150565b935050606086013567ffffffffffffffff8111156132a2575f5ffd5b6132ae88828901613150565b925050608086013567ffffffffffffffff8111156132ca575f5ffd5b6132d6888289016131e1565b9150509295509295909350565b5f5f83601f8401126132f3575f5ffd5b50813567ffffffffffffffff81111561330a575f5ffd5b602083019150836020828501011115610ca9575f5ffd5b5f5f60208385031215613332575f5ffd5b823567ffffffffffffffff811115613348575f5ffd5b613354858286016132e3565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b6003811061339057634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506133a6828451613374565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f5f5f604084860312156133f9575f5ffd5b833567ffffffffffffffff81111561340f575f5ffd5b61341b868287016132e3565b909450925050602084013561342f81612fd5565b809150509250925092565b5f5f6040838503121561344b575f5ffd5b823567ffffffffffffffff811115613461575f5ffd5b8301601f81018513613471575f5ffd5b803561347f61316d8261312d565b8082825260208201915060208360051b8501019250878311156134a0575f5ffd5b6020840193505b828410156134cb5783356134ba81612fd5565b8252602093840193909101906134a7565b9450505050602083013567ffffffffffffffff8111156134e9575f5ffd5b6134f585828601613150565b9150509250929050565b5f8151808452602084019350602083015f5b8281101561352f578151865260209586019590910190600101613511565b5093949350505050565b602081525f610a4760208301846134ff565b5f5f6040838503121561355c575f5ffd5b823561356781612fd5565b9150602083013567ffffffffffffffff811115613582575f5ffd5b6134f5858286016131e1565b803567ffffffffffffffff81168114612540575f5ffd5b5f5f604083850312156135b6575f5ffd5b823591506135c66020840161358e565b90509250929050565b6020810161075e8284613374565b5f602082840312156135ed575f5ffd5b8135610a4781612fd5565b5f5f5f6060848603121561360a575f5ffd5b8335925060208401359150604084013561342f81612fd5565b6001600160a01b0383168152604060208201525f610c886040830184613088565b5f5f5f5f5f5f60c08789031215613659575f5ffd5b863567ffffffffffffffff81111561366f575f5ffd5b61367b89828a016131e1565b965050602087013561368c81612fd5565b9450604087013561369c81612fd5565b935060608701356136ac81612fd5565b9250608087013591506136c160a0880161358e565b90509295509295509295565b5f5f604083850312156136de575f5ffd5b82356136e981612fd5565b915060208301358015158114613066575f5ffd5b5f5f6040838503121561370e575f5ffd5b823561371981612fd5565b9150602083013561306681612fd5565b5f5f5f5f5f60a0868803121561373d575f5ffd5b853561374881612fd5565b9450602086013561375881612fd5565b93506040860135925060608601359150608086013567ffffffffffffffff8111156132ca575f5ffd5b600181811c9082168061379557607f821691505b6020821081036137b357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f602082840312156137c9575f5ffd5b815167ffffffffffffffff8111156137df575f5ffd5b8201601f810184136137ef575f5ffd5b80516137fd61316d826131ba565b818152856020838501011115613811575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b601f821115611b3957805f5260205f20601f840160051c810160208510156138535750805b601f840160051c820191505b81811015611a08575f815560010161385f565b67ffffffffffffffff83111561388a5761388a6130e8565b61389e836138988354613781565b8361382e565b5f601f8411600181146138cf575f85156138b85750838201355b5f19600387901b1c1916600186901b178355611a08565b5f83815260208120601f198716915b828110156138fe57868501358255602094850194600190920191016138de565b508682101561391a575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff81111561399a5761399a6130e8565b6139ae816139a88454613781565b8461382e565b6020601f8211600181146139e0575f83156139c95750848201515b5f19600385901b1c1916600184901b178455611a08565b5f84815260208120601f198516915b82811015613a0f57878501518255602094850194600190920191016139ef565b5084821015613a2c57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff821663ffffffff8103613a6a57613a6a613a3b565b60010192915050565b63ffffffff818116838216019081111561075e5761075e613a3b565b604081525f613aa16040830185613088565b905067ffffffffffffffff831660208301529392505050565b606081525f613acc6060830186613088565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613b19575f5ffd5b8151610a4781612fd5565b8082018082111561075e5761075e613a3b565b8181038181111561075e5761075e613a3b565b6001600160a01b03861681526001600160a01b038516602082015260a060408201525f613b7a60a08301866134ff565b8281036060840152613b8c81866134ff565b90508281036080840152613ba08185613088565b98975050505050505050565b5f60208284031215613bbc575f5ffd5b8151610a4781613013565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a060808201525f61138860a0830184613088565b604081525f613c1560408301856134ff565b82810360208401526108fb81856134ff56fea26469706673582212203914af91977250fe376ae8bb05590e09aa035e67aac01531e596e3fa8023817f64736f6c634300081b00338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106102cc575f3560e01c80635c622a0e1161017c5780639dbba19d116100dd578063ce156e8211610093578063e4ae7d771161006e578063e4ae7d77146106cc578063e985e9c5146106df578063f242432a1461071a575f5ffd5b8063ce156e8214610693578063d3bf89b1146106a6578063dfa70d8b146106b9575f5ffd5b8063a22cb465116100c3578063a22cb4651461065a578063bc7b6d621461066d578063bd242bcb14610680575f5ffd5b80639dbba19d14610620578063a02b161e14610647575f5ffd5b8063781ef8db1161013257806380f760211161011857806380f76021146105e457806385f3e643146105fa57806391b3c0371461060d575f5ffd5b8063781ef8db146105875780637c300586146105d1575f5ffd5b806363560a8e1161016257806363560a8e1461054e5780636f3ff726146105615780636f537c7214610574575f5ffd5b80635c622a0e1461051b5780636352211e1461053b575f5ffd5b80632f27fa241161023157806344c9af28116101e75780635357263f116101c25780635357263f146104e25780635569f33d146104f55780635adf472414610508575f5ffd5b806344c9af281461048f57806348688f95146104af5780634e1273f4146104c2575f5ffd5b8063341ec55911610217578063341ec5591461044157806335af6216146104545780633634f91114610467575f5ffd5b80632f27fa24146103ef578063319c22bb14610402575f5ffd5b806313c72608116102865780631c3fc3eb1161026c5780631c3fc3eb146103c05780631e8fca2d146103c75780632eb2c2d6146103da575f5ffd5b806313c726081461035f57806314ff5ea3146103ad575f5ffd5b8063072d5d77116102b6578063072d5d77146103195780630e89341c1461032c57806311b8e00a1461034c575f5ffd5b8062fdd58e146102d057806301ffc9a7146102f6575b5f5ffd5b6102e36102de366004612fe9565b61072d565b6040519081526020015b60405180910390f35b610309610304366004613028565b610764565b60405190151581526020016102ed565b610309610327366004613043565b6108d9565b61033f61033a366004613071565b610904565b6040516102ed91906130b6565b61030961035a3660046130c8565b610a34565b61039461036d366004613071565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016102ed565b6102e36103bb366004613071565b610a4e565b6102e35f81565b6102e36103d5366004613071565b610a75565b6103ed6103e8366004613230565b610a9c565b005b6102e36103fd366004613071565b610b39565b6104297f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102ed565b6103ed61044f366004613043565b610b57565b610429610462366004613321565b610bf5565b61047a6104753660046130c8565b610c90565b604080519283526020830191909152016102ed565b6104a261049d366004613071565b610cb0565b6040516102ed9190613394565b6103ed6104bd3660046133e7565b610d82565b6104d56104d036600461343a565b610e24565b6040516102ed9190613539565b6103ed6104f036600461354b565b610eef565b6103ed6105033660046135a5565b610f8d565b6102e3610516366004613043565b61112a565b61052e610529366004613071565b61115c565b6040516102ed91906135cf565b610429610549366004613071565b6111b2565b61042961055c366004613321565b611217565b61030961056f3660046135dd565b611225565b610394610582366004613321565b611276565b610309610595366004613043565b6001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b6103096105df3660046135f8565b6112b8565b6105ec6112cc565b6040516102ed929190613623565b6102e3610608366004613644565b611377565b6102e361061b366004613321565b611393565b6104297f000000000000000000000000000000000000000000000000000000000000000081565b6103ed610655366004613071565b6113d5565b6103ed6106683660046136cd565b6114e2565b6103ed61067b366004613043565b6114f8565b61042961068e366004613071565b61159b565b6103096106a1366004613043565b6115b7565b6103096106b43660046135f8565b6115d9565b6103096106c73660046135f8565b611638565b6104296106da366004613321565b61164c565b6103096106ed3660046136fd565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6103ed610728366004613729565b6116c7565b5f826001600160a01b0316610741836111b2565b6001600160a01b031614610755575f610758565b60015b60ff1690505b92915050565b5f6001600160e01b031982167fafff3a630000000000000000000000000000000000000000000000000000000014806107c657506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b806107fa57506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b8061082e57506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b8061086257506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b8061089657506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b806108ca57506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061075e575061075e82611757565b5f5f836108ee82826108e9611794565b6117a2565b6108fb5f868660016117f0565b95945050505050565b610107546060906001600160a01b03166109a757610106805461092690613781565b80601f016020809104026020016040519081016040528092919081815260200182805461095290613781565b801561099d5780601f106109745761010080835404028352916020019161099d565b820191905f5260205f20905b81548152906001019060200180831161098057829003601f168201915b505050505061075e565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610a0d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261075e91908101906137b9565b5f610a47610a4184610a75565b83611919565b9392505050565b5f61075e82610a708463ffffffff8116185f9081526101086020526040902090565b611930565b5f61075e82610a978463ffffffff8116185f9081526101086020526040902090565b61194e565b5f610aa5611794565b9050806001600160a01b0316866001600160a01b031614158015610aee57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b15610b245760405163711bec9160e11b81526001600160a01b038083166004830152871660248201526044015b60405180910390fd5b610b3186868686866119a8565b505050505050565b5f61075e610b4683610a75565b5f9081526003602052604090205490565b5f5f610b668462100000611a0f565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038716021781559092509050610baf611794565b6001600160a01b0316836001600160a01b0316837fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a450505050565b5f5f610c51610c3885858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610c865780546801000000000000000090046001600160a01b0316610c88565b5f5b949350505050565b5f5f610ca4610c9e85610a75565b84611a85565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610d0e8584611930565b606085018190529050610d21858461194e565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610d4f8382611aa8565b85906002811115610d6257610d62613360565b90816002811115610d7557610d75613360565b8152505050505050919050565b641000000000610d9a5f82610d95611794565b611adf565b610106610da8848683613872565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416179055610dda611794565b6001600160a01b03167fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd5858585604051610e169392919061392c565b60405180910390a250505050565b60608151835114610e555781518351604051635b05999160e01b815260048101929092526024820152604401610b1b565b5f835167ffffffffffffffff811115610e7057610e706130e8565b604051908082528060200260200182016040528015610e99578160200160208202803683370190505b5090505f5b8451811015610ee757602080820286010151610ec29060208084028701015161072d565b828281518110610ed457610ed461396c565b6020908102919091010152600101610e9e565b509392505050565b610100610eff5f82610d95611794565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105610f358382613980565b50610f3e611794565b6001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff484604051610f8091906130b6565b60405180910390a3505050565b63ffffffff821682185f9081526101086020526040812090610faf8483611930565b90505f610fba611794565b600184015490915067ffffffffffffffff164281116110515767ffffffffffffffff8116158061102b575061102962010000836001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b155b1561104c5760405163311388dd60e21b815260048101849052602401610b1b565b611068565b61106861105e878661194e565b6201000084611adf565b8067ffffffffffffffff168567ffffffffffffffff1610156110ca576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015286166024820152604401610b1b565b60018401805467ffffffffffffffff191667ffffffffffffffff87169081179091556040516001600160a01b038416919085907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a4505050505050565b5f610a4761113784610a75565b5f9081526002602090815260408083206001600160a01b038716845290915290205490565b63ffffffff811681185f908152610108602052604081206001810154610a479067ffffffffffffffff166111ad6111938685611930565b5f908152602081905260409020546001600160a01b031690565b611aa8565b63ffffffff811681185f908152610108602052604081206111d38382611930565b831415806111ef5750600181015467ffffffffffffffff164210155b61120f575f838152602081905260409020546001600160a01b0316610a47565b5f9392505050565b5f610a476105498484611393565b6001600160a01b0381165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b60205260408120546f010000000000000000000000000000009081161461075e565b5f610a4761036d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b5f610c886112c585610a75565b8484611b3e565b6101045461010580545f926060926001600160a01b039091169181906112f190613781565b80601f016020809104026020016040519081016040528092919081815260200182805461131d90613781565b80156113685780601f1061133f57610100808354040283529160200191611368565b820191905f5260205f20905b81548152906001019060200180831161134b57829003601f168201915b50505050509050915091509091565b5f6113888787878787876001611b83565b979650505050505050565b5f610a476103bb84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b5f5f6113e383611000611a0f565b915091506113ef611794565b6001600160a01b0316827f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea860405160405180910390a35f828152602081905260409020546001600160a01b031680156114bf5761144e818460016120e4565b815482905f906114639063ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166114a090613a4f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b6114f46114ed611794565b838361214b565b5050565b5f5f611508846301000000611a0f565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038816021790559092509050611555611794565b6001600160a01b0316836001600160a01b0316837f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a450505050565b5f818152602081905260408120546001600160a01b031661075e565b5f5f836115cc82826115c7611794565b6121f1565b6108fb5f86866001612252565b5f610c886115e685610a75565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f610c8861164585610a75565b84846122be565b5f5f61168f610c3885858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b600181015490915067ffffffffffffffff16421015610c865760018101546801000000000000000090046001600160a01b0316610c88565b5f6116d0611794565b9050806001600160a01b0316866001600160a01b03161415801561171957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561174a5760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610b1b565b610b3186868686866122f9565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061075e575061075e82612386565b5f61179d612454565b905090565b5f6117ad8483612545565b905080198316156117ea5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610b1b565b50505050565b5f835f036117ff57505f610c88565b6118088461260b565b6001600160a01b038316611848576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461190d575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166118a88882600161266b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561190157611901888785858b612800565b60019350505050610c88565b505f9695505050505050565b5f5f6119258484610c90565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610a47565b5f8261195b57508161075e565b6001820154610a4790849067ffffffffffffffff1642101561198457835463ffffffff16611997565b83546119979063ffffffff166001613a73565b63ffffffff82811690921891161890565b6001600160a01b0384166119d157604051632bfa23e760e11b81525f6004820152602401610b1b565b6001600160a01b0385166119f957604051626a0d4560e21b81525f6004820152602401610b1b565b611a0885858585856001612809565b5050505050565b63ffffffff821682185f90815261010860205260408120611a308482611930565b600182015490925067ffffffffffffffff164210611a645760405163311388dd60e21b815260048101839052602401610b1b565b610ca9611a71858361194e565b84610d95611794565b805160209091012090565b5f5f611a908361286b565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff83164210611ac157505f61075e565b6001600160a01b038216611ad75750600161075e565b50600261075e565b611aea8383836115d9565b611b39576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610b1b565b505050565b5f8383611b4e82826108e9611794565b85611b6c57604051631850848b60e31b815260040160405180910390fd5b611b7986868660016117f0565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990611bea908b906004016130b6565b5f604051808303815f87803b158015611c01575f5ffd5b505af1158015611c13573d5f5f3e3d5ffd5b5050895160208b012091505f9050611c3e8263ffffffff8116185f9081526101086020526040902090565b9050611c4a8282611930565b5f818152602081905260408120549194506001600160a01b0390911690611c6f611794565b600184015490915067ffffffffffffffff164210611cea578515611c9957611c995f600183611adf565b6001600160a01b038b16158015611caf57508715155b15611ce55760405163d1a3b35560e01b81525f6004820152602481018990526001600160a01b0382166044820152606401610b1b565b611daf565b6001600160a01b03821615611d2d578b6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610b1b91906130b6565b6001600160a01b038b16611d6f578b6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610b1b91906130b6565b8515611d8157611d815f601083611adf565b8667ffffffffffffffff165f03611da457600183015467ffffffffffffffff1696505b640100000000881797505b6001600160a01b038b1615611dd15767ffffffffffffffff8716421015611dde565b67ffffffffffffffff8716155b15611e21576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff88166004820152602401610b1b565b6001600160a01b03821615611eb957611e3c828660016120e4565b825483905f90611e519063ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550825f01600481819054906101000a900463ffffffff16611e8e90613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550611eb68584611930565b94505b60018301805484546001600160a01b03808e16680100000000000000009081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921787558c81169091026001600160e01b031990921667ffffffffffffffff8b1617919091179091558b16611f7a57806001600160a01b0316845f1b867f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88f8b604051611f6d929190613a8f565b60405180910390a4612033565b806001600160a01b0316845f1b867f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8f8f8c604051611fbb93929190613aba565b60405180910390a4611fde8b86600160405180602001604052805f815250612885565b5f611fe9868561194e565b905080611ff857611ff8613af5565b604051819087907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a3612030818a8e5f6117f0565b50505b6001600160a01b038a161561208457806001600160a01b03168a6001600160a01b0316867fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a45b6001600160a01b038916156120d557806001600160a01b0316896001600160a01b0316867f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a45b50505050979650505050505050565b6001600160a01b03831661210c57604051626a0d4560e21b81525f6004820152602401610b1b565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291611a089187918590859083612809565b6001600160a01b03821661218d576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610b1b565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610f80565b5f6121fc84836128e1565b905080198316156117ea576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610b1b565b5f61225c8461260b565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461190d575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906118a8908990839061266b565b5f83836122ce82826115c7611794565b856122ec57604051631850848b60e31b815260040160405180910390fd5b611b798686866001612252565b6001600160a01b03841661232257604051632bfa23e760e11b81525f6004820152602401610b1b565b6001600160a01b03851661234a57604051626a0d4560e21b81525f6004820152602401610b1b565b6040805160018082526020820186905281830190815260608201859052608082019092529061237d87878484875f612809565b50505050505050565b5f6001600160e01b031982167fd9b67a260000000000000000000000000000000000000000000000000000000014806123e857506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b8061241c57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061075e57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461075e565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661248857503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015612505573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125299190613b09565b90506001600160a01b038116612540573391505090565b919050565b5f5f6125b784846001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b9050836125c557905061075e565b5f6125ea61054986610a708163ffffffff8116185f9081526101086020526040902090565b6001600160a01b031603612601575f91505061075e565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612668576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610b1b565b50565b5f6126758361286b565b9050811561273e575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612716576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610b1b565b5f8481526003602052604081208054859290612733908490613b24565b909155506117ea9050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156127d8576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610b1b565b5f84815260036020526040812080548592906127f5908490613b37565b909155505050505050565b611a0885612998565b61281586868686612a78565b6001600160a01b03851615610b31575f61282d611794565b9050811561284857612843818888888888612b76565b61237d565b60208581015190850151612860838a8a85858a612c97565b505050505050505050565b5f6128758261260b565b50600181901b17600281901b1790565b6001600160a01b0384166128ae57604051632bfa23e760e11b81525f6004820152602401610b1b565b60408051600180825260208201869052818301908152606082018590526080820190925290610b315f8784848784612809565b5f821580159061291c57505f61291161054985610a708163ffffffff8116185f9081526101086020526040902090565b6001600160a01b0316145b1561292857505f61075e565b610a4783836001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b80156126685763ffffffff811681185f90815261010860205260408120906129c08383611930565b5f818152602081905260409020549091506001600160a01b03166129e6818360016120e4565b82548390600490612a0490640100000000900463ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f612a2d8385611930565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3611a088282600160405180602001604052805f815250612885565b612a8484848484612d7e565b6001600160a01b03831615801590612aa457506001600160a01b03841615155b156117ea575f5b8251811015611a08575f838281518110612ac757612ac761396c565b60200260200101519050612af081731000000000000000000000000000000000000000886115d9565b612b38576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610b1b565b5f838381518110612b4b57612b4b61396c565b60200260200101511115612b6d57612b6d612b6582610a75565b87875f612f94565b50600101612aab565b6001600160a01b0384163b15610b315760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612bba9089908990889088908890600401613b4a565b6020604051808303815f875af1925050508015612bf4575060408051601f3d908101601f19168201909252612bf191810190613bac565b60015b612c5b573d808015612c21576040519150601f19603f3d011682016040523d82523d5f602084013e612c26565b606091505b5080515f03612c5357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461237d57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b6001600160a01b0384163b15610b315760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612cdb9089908990889088908890600401613bc7565b6020604051808303815f875af1925050508015612d15575060408051601f3d908101601f19168201909252612d1291810190613bac565b60015b612d42573d808015612c21576040519150601f19603f3d011682016040523d82523d5f602084013e612c26565b6001600160e01b0319811663f23a6e6160e01b1461237d57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b8051825114612dad5781518151604051635b05999160e01b815260048101929092526024820152604401610b1b565b5f612db6611794565b90505f5b8351811015612eb6576020818102858101820151908501909101518015612eac575f828152602081905260409020546001600160a01b039081169089168114612e35576040516303dee4c560e01b81526001600160a01b038a1660048201525f60248201526044810183905260648101849052608401610b1b565b6001821115612e77576040516303dee4c560e01b81526001600160a01b038a166004820152600160248201526044810183905260648101849052608401610b1b565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389161790555b5050600101612dba565b508251600103612f365760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051612f27929190918252602082015260400190565b60405180910390a45050611a08565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051612f85929190613c03565b60405180910390a45050505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015611a0857612fc885828685612252565b50610b31858285856117f0565b6001600160a01b0381168114612668575f5ffd5b5f5f60408385031215612ffa575f5ffd5b823561300581612fd5565b946020939093013593505050565b6001600160e01b031981168114612668575f5ffd5b5f60208284031215613038575f5ffd5b8135610a4781613013565b5f5f60408385031215613054575f5ffd5b82359150602083013561306681612fd5565b809150509250929050565b5f60208284031215613081575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610a476020830184613088565b5f5f604083850312156130d9575f5ffd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613125576131256130e8565b604052919050565b5f67ffffffffffffffff821115613146576131466130e8565b5060051b60200190565b5f82601f83011261315f575f5ffd5b813561317261316d8261312d565b6130fc565b8082825260208201915060208360051b860101925085831115613193575f5ffd5b602085015b838110156131b0578035835260209283019201613198565b5095945050505050565b5f67ffffffffffffffff8211156131d3576131d36130e8565b50601f01601f191660200190565b5f82601f8301126131f0575f5ffd5b8135602083015f61320361316d846131ba565b9050828152858383011115613216575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f5f5f60a08688031215613244575f5ffd5b853561324f81612fd5565b9450602086013561325f81612fd5565b9350604086013567ffffffffffffffff81111561327a575f5ffd5b61328688828901613150565b935050606086013567ffffffffffffffff8111156132a2575f5ffd5b6132ae88828901613150565b925050608086013567ffffffffffffffff8111156132ca575f5ffd5b6132d6888289016131e1565b9150509295509295909350565b5f5f83601f8401126132f3575f5ffd5b50813567ffffffffffffffff81111561330a575f5ffd5b602083019150836020828501011115610ca9575f5ffd5b5f5f60208385031215613332575f5ffd5b823567ffffffffffffffff811115613348575f5ffd5b613354858286016132e3565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b6003811061339057634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506133a6828451613374565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f5f5f604084860312156133f9575f5ffd5b833567ffffffffffffffff81111561340f575f5ffd5b61341b868287016132e3565b909450925050602084013561342f81612fd5565b809150509250925092565b5f5f6040838503121561344b575f5ffd5b823567ffffffffffffffff811115613461575f5ffd5b8301601f81018513613471575f5ffd5b803561347f61316d8261312d565b8082825260208201915060208360051b8501019250878311156134a0575f5ffd5b6020840193505b828410156134cb5783356134ba81612fd5565b8252602093840193909101906134a7565b9450505050602083013567ffffffffffffffff8111156134e9575f5ffd5b6134f585828601613150565b9150509250929050565b5f8151808452602084019350602083015f5b8281101561352f578151865260209586019590910190600101613511565b5093949350505050565b602081525f610a4760208301846134ff565b5f5f6040838503121561355c575f5ffd5b823561356781612fd5565b9150602083013567ffffffffffffffff811115613582575f5ffd5b6134f5858286016131e1565b803567ffffffffffffffff81168114612540575f5ffd5b5f5f604083850312156135b6575f5ffd5b823591506135c66020840161358e565b90509250929050565b6020810161075e8284613374565b5f602082840312156135ed575f5ffd5b8135610a4781612fd5565b5f5f5f6060848603121561360a575f5ffd5b8335925060208401359150604084013561342f81612fd5565b6001600160a01b0383168152604060208201525f610c886040830184613088565b5f5f5f5f5f5f60c08789031215613659575f5ffd5b863567ffffffffffffffff81111561366f575f5ffd5b61367b89828a016131e1565b965050602087013561368c81612fd5565b9450604087013561369c81612fd5565b935060608701356136ac81612fd5565b9250608087013591506136c160a0880161358e565b90509295509295509295565b5f5f604083850312156136de575f5ffd5b82356136e981612fd5565b915060208301358015158114613066575f5ffd5b5f5f6040838503121561370e575f5ffd5b823561371981612fd5565b9150602083013561306681612fd5565b5f5f5f5f5f60a0868803121561373d575f5ffd5b853561374881612fd5565b9450602086013561375881612fd5565b93506040860135925060608601359150608086013567ffffffffffffffff8111156132ca575f5ffd5b600181811c9082168061379557607f821691505b6020821081036137b357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f602082840312156137c9575f5ffd5b815167ffffffffffffffff8111156137df575f5ffd5b8201601f810184136137ef575f5ffd5b80516137fd61316d826131ba565b818152856020838501011115613811575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b601f821115611b3957805f5260205f20601f840160051c810160208510156138535750805b601f840160051c820191505b81811015611a08575f815560010161385f565b67ffffffffffffffff83111561388a5761388a6130e8565b61389e836138988354613781565b8361382e565b5f601f8411600181146138cf575f85156138b85750838201355b5f19600387901b1c1916600186901b178355611a08565b5f83815260208120601f198716915b828110156138fe57868501358255602094850194600190920191016138de565b508682101561391a575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff81111561399a5761399a6130e8565b6139ae816139a88454613781565b8461382e565b6020601f8211600181146139e0575f83156139c95750848201515b5f19600385901b1c1916600184901b178455611a08565b5f84815260208120601f198516915b82811015613a0f57878501518255602094850194600190920191016139ef565b5084821015613a2c57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff821663ffffffff8103613a6a57613a6a613a3b565b60010192915050565b63ffffffff818116838216019081111561075e5761075e613a3b565b604081525f613aa16040830185613088565b905067ffffffffffffffff831660208301529392505050565b606081525f613acc6060830186613088565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613b19575f5ffd5b8151610a4781612fd5565b8082018082111561075e5761075e613a3b565b8181038181111561075e5761075e613a3b565b6001600160a01b03861681526001600160a01b038516602082015260a060408201525f613b7a60a08301866134ff565b8281036060840152613b8c81866134ff565b90508281036080840152613ba08185613088565b98975050505050505050565b5f60208284031215613bbc575f5ffd5b8151610a4781613013565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a060808201525f61138860a0830184613088565b604081525f613c1560408301856134ff565b82810360208401526108fb81856134ff56fea26469706673582212203914af91977250fe376ae8bb05590e09aa035e67aac01531e596e3fa8023817f64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60111": [ + { + "length": 32, + "start": 1031 + }, + { + "length": 32, + "start": 9303 + }, + { + "length": 32, + "start": 9400 + } + ], + "66658": [ + { + "length": 32, + "start": 1573 + }, + { + "length": 32, + "start": 7093 + } + ] + }, + "inputSourceName": "project/src/registry/PermissionedRegistry.sol", + "devdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "details": "Error selector: `0x68c1425a`" + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "details": "Error selector: `0xf1d446c3`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1155InsufficientBalance(address,uint256,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred.", + "tokenId": "Identifier number of a token." + } + } + ], + "ERC1155InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "ERC1155InvalidOperator(address)": [ + { + "details": "Indicates a failure with the `operator` to be approved. Used in approvals.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC1155InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC1155InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC1155MissingApprovalForAll(address,address)": [ + { + "details": "Indicates a failure with the `operator`’s approval. Used in transfers.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner.", + "owner": "Address of the current owner of a token." + } + } + ], + "LabelAlreadyRegistered(string)": [ + { + "details": "Error selector: `0xdef545a4`" + } + ], + "LabelAlreadyReserved(string)": [ + { + "details": "Error selector: `0xf60759e0`" + } + ], + "LabelExpired(uint256)": [ + { + "details": "Error selector: `0xc44e2374`" + } + ], + "TransferDisallowed(uint256,address)": [ + { + "details": "Error selector: `0xe58f6d5a`" + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "ExpiryUpdated(uint256,uint64,address)": { + "params": { + "newExpiry": "The new expiry of the label.", + "sender": "The sender of the call to update the expiry.", + "tokenId": "The token ID of the label." + } + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label registered.", + "labelHash": "The label hash registered.", + "owner": "The owner of the label.", + "sender": "The sender of the call to register.", + "tokenId": "The token ID registered." + } + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label reserved.", + "labelHash": "The label hash reserved.", + "sender": "The sender of the call to reserve.", + "tokenId": "The token ID reserved." + } + }, + "LabelUnregistered(uint256,address)": { + "params": { + "sender": "The sender of the call to unregister.", + "tokenId": "The token ID unregistered." + } + }, + "ParentUpdated(address,string,address)": { + "params": { + "label": "The new label.", + "parent": "The new parent.", + "sender": "The sender of the call to update the parent." + } + }, + "ResolverUpdated(uint256,address,address)": { + "params": { + "resolver": "The new resolver.", + "sender": "The sender of the call to update the resolver.", + "tokenId": "The token ID of the label." + } + }, + "SubregistryUpdated(uint256,address,address)": { + "params": { + "sender": "The sender of the call to update the subregistry.", + "subregistry": "The new subregistry.", + "tokenId": "The token ID of the label." + } + }, + "TokenRegenerated(uint256,uint256)": { + "params": { + "newTokenId": "The new token ID.", + "oldTokenId": "The old token ID." + } + }, + "TokenResource(uint256,uint256)": { + "params": { + "resource": "The EAC resource.", + "tokenId": "The token ID." + } + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + }, + "URIUpdated(string,address,address)": { + "params": { + "renderer": "The new render address.", + "sender": "The sender of the call to update the URI.", + "uri": "The new URI." + } + } + }, + "kind": "dev", + "methods": { + "balanceOf(address,uint256)": { + "params": { + "account": "The account to get the balance for.", + "id": "The token ID." + }, + "returns": { + "_0": "balance The balance of the token for the account. This will only ever be 1 or 0." + } + }, + "balanceOfBatch(address[],uint256[])": { + "details": "`accounts` and `ids` must have the same length.", + "params": { + "accounts": "The accounts to get the balances for.", + "ids": "The token IDs." + }, + "returns": { + "_0": "batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0." + } + }, + "constructor": { + "params": { + "hcaFactory": "The HCA factory to use.", + "labelStore": "The shared label database.", + "roleBitmap": "The role bitmap granted to `rootAccount`.", + "rootAccount": "Account granted root roles." + } + }, + "findExpiry(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The expiry of the label." + } + }, + "findOwner(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The owner of the label." + } + }, + "findTokenId(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The token ID of the label." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getExpiry(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The expiry of the label, in seconds." + } + }, + "getParent()": { + "returns": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "getResolver(string)": { + "params": { + "label": "The label to fetch a resolver for." + }, + "returns": { + "_0": "resolver The address of a resolver responsible for this label, or `address(0)` if none exists." + } + }, + "getResource(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The resource." + } + }, + "getState(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "state": "The state of the label." + } + }, + "getStatus(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The status of the label." + } + }, + "getSubregistry(string)": { + "params": { + "label": "The label to resolve." + }, + "returns": { + "_0": "The address of the registry for this label, or `address(0)` if none exists." + } + }, + "getTokenId(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token ID." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "account": "The account to get the approval for.", + "operator": "The operator to get the approval for." + }, + "returns": { + "_0": "approved The approval status." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "latestOwnerOf(uint256)": { + "params": { + "tokenId": "The token ID to query." + }, + "returns": { + "_0": "The latest owner address." + } + }, + "ownerOf(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The owner of the token." + } + }, + "register(string,address,address,address,uint256,uint64)": { + "params": { + "expiry": "The expiry of the label, in seconds.", + "label": "The label to register.", + "owner": "The address of the owner of the label.", + "registry": "The registry to set as the label.", + "resolver": "The resolver to set for the label.", + "roleBitmap": "The role bitmap to set for the label." + }, + "returns": { + "_0": "The token ID." + } + }, + "renew(uint256,uint64)": { + "details": "If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.", + "params": { + "anyId": "The labelhash, token ID, or resource.", + "newExpiry": "The new expiry, in seconds." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the tokens from.", + "ids": "The token IDs.", + "to": "The address to transfer the tokens to.", + "values": "The amounts of tokens to transfer." + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the token from.", + "id": "The token ID.", + "to": "The address to transfer the token to.", + "value": "The amount of tokens to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "The approval status.", + "operator": "The operator to set the approval for." + } + }, + "setParent(address,string)": { + "details": "Should emit `ParentUpdated`.", + "params": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "setResolver(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "resolver": "The new resolver." + } + }, + "setSubregistry(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "registry": "The new registry." + } + }, + "setURI(string,address)": { + "params": { + "renderer": "The new renderer address.", + "uri_": "The new URI." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "unregister(uint256)": { + "details": "Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.", + "params": { + "anyId": "The labelhash, token ID, or resource." + } + }, + "uri(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The URI for the token." + } + } + }, + "stateVariables": { + "__gap": { + "details": "Storage gap for future changes." + }, + "_childLabel": { + "details": "The child label of this registry." + }, + "_entries": { + "details": "The entries of this registry." + }, + "_parentRegistry": { + "details": "The parent registry of this registry." + }, + "_uri": { + "details": "The metadata URI." + }, + "_uriRenderer": { + "details": "The metadata renderer." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "3090600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "HCA_FACTORY()": "infinite", + "LABEL_STORE()": "infinite", + "ROOT_RESOURCE()": "250", + "balanceOf(address,uint256)": "infinite", + "balanceOfBatch(address[],uint256[])": "infinite", + "findExpiry(string)": "infinite", + "findOwner(string)": "infinite", + "findTokenId(string)": "infinite", + "getAssigneeCount(uint256,uint256)": "7307", + "getExpiry(uint256)": "2537", + "getParent()": "infinite", + "getResolver(string)": "infinite", + "getResource(uint256)": "4834", + "getState(uint256)": "infinite", + "getStatus(uint256)": "infinite", + "getSubregistry(string)": "infinite", + "getTokenId(uint256)": "2663", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "infinite", + "hasRoles(uint256,uint256,address)": "9465", + "hasRootRoles(uint256,address)": "2641", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "2673", + "latestOwnerOf(uint256)": "2619", + "ownerOf(uint256)": "infinite", + "register(string,address,address,address,uint256,uint64)": "infinite", + "renew(uint256,uint64)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "infinite", + "roles(uint256,address)": "infinite", + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": "infinite", + "safeTransferFrom(address,address,uint256,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "infinite", + "setParent(address,string)": "infinite", + "setResolver(uint256,address)": "infinite", + "setSubregistry(uint256,address)": "infinite", + "setURI(string,address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "unregister(uint256)": "infinite", + "uri(uint256)": "infinite" + }, + "internal": { + "_checkExpiryAndTokenRoles(uint256,uint256)": "infinite", + "_constructResource(uint256,struct PermissionedRegistry.Entry storage pointer)": "4430", + "_constructStatus(uint64,address)": "101", + "_constructTokenId(uint256,struct PermissionedRegistry.Entry storage pointer)": "2179", + "_entry(uint256)": "infinite", + "_getRevokableRoles(uint256,address)": "4553", + "_getSettableRoles(uint256,address)": "infinite", + "_isExpired(uint64)": "infinite", + "_onRolesGranted(uint256,address,uint256,uint256,uint256)": "infinite", + "_onRolesRevoked(uint256,address,uint256,uint256,uint256)": "infinite", + "_regenerate(uint256)": "infinite", + "_register(string memory,address,contract IRegistry,address,uint256,uint64,bool)": "infinite", + "_update(address,address,uint256[] memory,uint256[] memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"contract ILabelStore\",\"name\":\"labelStore\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"oldExpiry\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"CannotReduceExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"CannotSetPastExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyReserved\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"LabelExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"TransferDisallowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ExpiryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelReserved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelUnregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ParentUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RegistryCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ResolverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SubregistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldTokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newTokenId\",\"type\":\"uint256\"}],\"name\":\"TokenRegenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"TokenResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"renderer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"URIUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LABEL_STORE\",\"outputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getParent\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getResource\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"latestOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"internalType\":\"struct IPermissionedRegistry.State\",\"name\":\"state\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getSubregistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"latestOwnerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setParent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"setSubregistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"},{\"internalType\":\"contract IRegistryURIRenderer\",\"name\":\"renderer\",\"type\":\"address\"}],\"name\":\"setURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"details\":\"Error selector: `0x68c1425a`\"}],\"CannotSetPastExpiry(uint64)\":[{\"details\":\"Error selector: `0xf1d446c3`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1155InsufficientBalance(address,uint256,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\",\"tokenId\":\"Identifier number of a token.\"}}],\"ERC1155InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"ERC1155InvalidOperator(address)\":[{\"details\":\"Indicates a failure with the `operator` to be approved. Used in approvals.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC1155InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC1155InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC1155MissingApprovalForAll(address,address)\":[{\"details\":\"Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\",\"owner\":\"Address of the current owner of a token.\"}}],\"LabelAlreadyRegistered(string)\":[{\"details\":\"Error selector: `0xdef545a4`\"}],\"LabelAlreadyReserved(string)\":[{\"details\":\"Error selector: `0xf60759e0`\"}],\"LabelExpired(uint256)\":[{\"details\":\"Error selector: `0xc44e2374`\"}],\"TransferDisallowed(uint256,address)\":[{\"details\":\"Error selector: `0xe58f6d5a`\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"ExpiryUpdated(uint256,uint64,address)\":{\"params\":{\"newExpiry\":\"The new expiry of the label.\",\"sender\":\"The sender of the call to update the expiry.\",\"tokenId\":\"The token ID of the label.\"}},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label registered.\",\"labelHash\":\"The label hash registered.\",\"owner\":\"The owner of the label.\",\"sender\":\"The sender of the call to register.\",\"tokenId\":\"The token ID registered.\"}},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label reserved.\",\"labelHash\":\"The label hash reserved.\",\"sender\":\"The sender of the call to reserve.\",\"tokenId\":\"The token ID reserved.\"}},\"LabelUnregistered(uint256,address)\":{\"params\":{\"sender\":\"The sender of the call to unregister.\",\"tokenId\":\"The token ID unregistered.\"}},\"ParentUpdated(address,string,address)\":{\"params\":{\"label\":\"The new label.\",\"parent\":\"The new parent.\",\"sender\":\"The sender of the call to update the parent.\"}},\"ResolverUpdated(uint256,address,address)\":{\"params\":{\"resolver\":\"The new resolver.\",\"sender\":\"The sender of the call to update the resolver.\",\"tokenId\":\"The token ID of the label.\"}},\"SubregistryUpdated(uint256,address,address)\":{\"params\":{\"sender\":\"The sender of the call to update the subregistry.\",\"subregistry\":\"The new subregistry.\",\"tokenId\":\"The token ID of the label.\"}},\"TokenRegenerated(uint256,uint256)\":{\"params\":{\"newTokenId\":\"The new token ID.\",\"oldTokenId\":\"The old token ID.\"}},\"TokenResource(uint256,uint256)\":{\"params\":{\"resource\":\"The EAC resource.\",\"tokenId\":\"The token ID.\"}},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"},\"URIUpdated(string,address,address)\":{\"params\":{\"renderer\":\"The new render address.\",\"sender\":\"The sender of the call to update the URI.\",\"uri\":\"The new URI.\"}}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"params\":{\"account\":\"The account to get the balance for.\",\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"balance The balance of the token for the account. This will only ever be 1 or 0.\"}},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"`accounts` and `ids` must have the same length.\",\"params\":{\"accounts\":\"The accounts to get the balances for.\",\"ids\":\"The token IDs.\"},\"returns\":{\"_0\":\"batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\"}},\"constructor\":{\"params\":{\"hcaFactory\":\"The HCA factory to use.\",\"labelStore\":\"The shared label database.\",\"roleBitmap\":\"The role bitmap granted to `rootAccount`.\",\"rootAccount\":\"Account granted root roles.\"}},\"findExpiry(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The expiry of the label.\"}},\"findOwner(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The owner of the label.\"}},\"findTokenId(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The token ID of the label.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getExpiry(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The expiry of the label, in seconds.\"}},\"getParent()\":{\"returns\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"getResolver(string)\":{\"params\":{\"label\":\"The label to fetch a resolver for.\"},\"returns\":{\"_0\":\"resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\"}},\"getResource(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The resource.\"}},\"getState(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"state\":\"The state of the label.\"}},\"getStatus(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The status of the label.\"}},\"getSubregistry(string)\":{\"params\":{\"label\":\"The label to resolve.\"},\"returns\":{\"_0\":\"The address of the registry for this label, or `address(0)` if none exists.\"}},\"getTokenId(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"account\":\"The account to get the approval for.\",\"operator\":\"The operator to get the approval for.\"},\"returns\":{\"_0\":\"approved The approval status.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"latestOwnerOf(uint256)\":{\"params\":{\"tokenId\":\"The token ID to query.\"},\"returns\":{\"_0\":\"The latest owner address.\"}},\"ownerOf(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The owner of the token.\"}},\"register(string,address,address,address,uint256,uint64)\":{\"params\":{\"expiry\":\"The expiry of the label, in seconds.\",\"label\":\"The label to register.\",\"owner\":\"The address of the owner of the label.\",\"registry\":\"The registry to set as the label.\",\"resolver\":\"The resolver to set for the label.\",\"roleBitmap\":\"The role bitmap to set for the label.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"renew(uint256,uint64)\":{\"details\":\"If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"newExpiry\":\"The new expiry, in seconds.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the tokens from.\",\"ids\":\"The token IDs.\",\"to\":\"The address to transfer the tokens to.\",\"values\":\"The amounts of tokens to transfer.\"}},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the token from.\",\"id\":\"The token ID.\",\"to\":\"The address to transfer the token to.\",\"value\":\"The amount of tokens to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"The approval status.\",\"operator\":\"The operator to set the approval for.\"}},\"setParent(address,string)\":{\"details\":\"Should emit `ParentUpdated`.\",\"params\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"setResolver(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"resolver\":\"The new resolver.\"}},\"setSubregistry(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"registry\":\"The new registry.\"}},\"setURI(string,address)\":{\"params\":{\"renderer\":\"The new renderer address.\",\"uri_\":\"The new URI.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"unregister(uint256)\":{\"details\":\"Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"}},\"uri(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The URI for the token.\"}}},\"stateVariables\":{\"__gap\":{\"details\":\"Storage gap for future changes.\"},\"_childLabel\":{\"details\":\"The child label of this registry.\"},\"_entries\":{\"details\":\"The entries of this registry.\"},\"_parentRegistry\":{\"details\":\"The parent registry of this registry.\"},\"_uri\":{\"details\":\"The metadata URI.\"},\"_uriRenderer\":{\"details\":\"The metadata renderer.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"notice\":\"Label expiry cannot be reduced.\"}],\"CannotSetPastExpiry(uint64)\":[{\"notice\":\"Label expiry cannot be before now.\"}],\"LabelAlreadyRegistered(string)\":[{\"notice\":\"Label is already registered.\"}],\"LabelAlreadyReserved(string)\":[{\"notice\":\"Label cannot be reserved again.\"}],\"LabelExpired(uint256)\":[{\"notice\":\"Label is expired/unregistered.\"}],\"TransferDisallowed(uint256,address)\":[{\"notice\":\"Transfer is not allowed due to missing transfer admin role.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"ExpiryUpdated(uint256,uint64,address)\":{\"notice\":\"Expiry of label was changed.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"notice\":\"A label was registered.\"},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"notice\":\"A label was reserved.\"},\"LabelUnregistered(uint256,address)\":{\"notice\":\"A label was unregistered.\"},\"ParentUpdated(address,string,address)\":{\"notice\":\"Parent was changed.\"},\"RegistryCreated()\":{\"notice\":\"A registry was created/initialized.\"},\"ResolverUpdated(uint256,address,address)\":{\"notice\":\"Resolver of label was changed.\"},\"SubregistryUpdated(uint256,address,address)\":{\"notice\":\"Subregistry of label was changed.\"},\"TokenRegenerated(uint256,uint256)\":{\"notice\":\"Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance.\"},\"TokenResource(uint256,uint256)\":{\"notice\":\"Associate a token with an EAC resource.\"},\"URIUpdated(string,address,address)\":{\"notice\":\"URI was changed.\"}},\"kind\":\"user\",\"methods\":{\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"LABEL_STORE()\":{\"notice\":\"The shared label database.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"balanceOf(address,uint256)\":{\"notice\":\"Returns the balance of a token for an account.\"},\"balanceOfBatch(address[],uint256[])\":{\"notice\":\"Returns the balances of a batch of tokens for an account.\"},\"findExpiry(string)\":{\"notice\":\"Fetches the label expiry.\"},\"findOwner(string)\":{\"notice\":\"Fetches the label owner.\"},\"findTokenId(string)\":{\"notice\":\"Fetches the token ID for a label.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getExpiry(uint256)\":{\"notice\":\"Get expiry of label.\"},\"getParent()\":{\"notice\":\"Get canonical \\\"location\\\" of this registry.\"},\"getResolver(string)\":{\"notice\":\"Fetches the resolver responsible for the specified label.\"},\"getResource(uint256)\":{\"notice\":\"Get `resource` from `anyId`.\"},\"getState(uint256)\":{\"notice\":\"Get the state of a label.\"},\"getStatus(uint256)\":{\"notice\":\"Get `Status` from `anyId`.\"},\"getSubregistry(string)\":{\"notice\":\"Fetches the registry for a label.\"},\"getTokenId(uint256)\":{\"notice\":\"Get `tokenId` from `anyId`.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Returns the approval for all operator.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"latestOwnerOf(uint256)\":{\"notice\":\"Get the latest owner of a token. If the token was burned, returns null.\"},\"ownerOf(uint256)\":{\"notice\":\"Returns the owner of a token.\"},\"register(string,address,address,address,uint256,uint64)\":{\"notice\":\"Registers a new label.\"},\"renew(uint256,uint64)\":{\"notice\":\"Renew a label.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Transfers multiple tokens from one address to another.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"notice\":\"Transfers a single token from one address to another.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Sets the approval for all operator.\"},\"setParent(address,string)\":{\"notice\":\"Change canonical \\\"location\\\".\"},\"setResolver(uint256,address)\":{\"notice\":\"Change resolver of label.\"},\"setSubregistry(uint256,address)\":{\"notice\":\"Change registry of label.\"},\"setURI(string,address)\":{\"notice\":\"Set the URI for the registry.\"},\"unregister(uint256)\":{\"notice\":\"Delete a label.\"},\"uri(uint256)\":{\"notice\":\"Returns the URI for a token.\"}},\"notice\":\"A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`) to resolve any of these to the canonical storage slot for the name. The registry maintains two independent version counters per name: - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form the EAC resource ID. This means a re-registered name gets a fresh permission scope. - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint) due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring changes to roles create new tokens and prevent frontrunning a transfer with a role revocation. Names are treated as `AVAILABLE` once `block.timestamp >= expiry`. URI renderer address is embedded into URI data as `abi.encodePacked(uint8(1), address)`. State diagram: register() +ROLE_REGISTRAR +------------------->----------------------+ | | | renew() | renew() | +ROLE_RENEW | +ROLE_RENEW | +------+ | +------+ | | | | | | \\u028c \\u028c v v v | AVAILABLE --------> RESERVED -------------> REGISTERED >--+ \\u028c register() v register() v | w/owner=0 | +ROLE_REGISTER_RESERVED | | +ROLE_REGISTRAR | | | | | +--------<---------+------------<------------+ unregister() +ROLE_UNREGISTER\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/PermissionedRegistry.sol\":\"PermissionedRegistry\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155} from \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x35d120c427299af1525aaf07955314d9e36a62f14408eb93dec71a2e001f74d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/utils/ERC1155Utils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\nimport {IERC1155Errors} from \\\"../../../interfaces/draft-IERC6093.sol\\\";\\n\\n/**\\n * @dev Library that provide common ERC-1155 utility functions.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].\\n *\\n * _Available since v5.1._\\n */\\nlibrary ERC1155Utils {\\n /**\\n * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155Received(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver.onERC1155Received.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155BatchReceived(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x22f099c02c252dd1f6ddc464916ce683294a63b23b3c6ee3d290b77398e2474b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)\\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\\n\\npragma solidity ^0.8.20;\\n\\nimport {Comparators} from \\\"./Comparators.sol\\\";\\nimport {SlotDerivation} from \\\"./SlotDerivation.sol\\\";\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\nimport {Math} from \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to array types.\\n */\\nlibrary Arrays {\\n using SlotDerivation for bytes32;\\n using StorageSlot for bytes32;\\n\\n /**\\n * @dev Sort an array of uint256 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n uint256[] memory array,\\n function(uint256, uint256) pure returns (bool) comp\\n ) internal pure returns (uint256[] memory) {\\n _quickSort(_begin(array), _end(array), comp);\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\\n */\\n function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\\n sort(array, Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of address (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n address[] memory array,\\n function(address, address) pure returns (bool) comp\\n ) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of address in increasing order.\\n */\\n function sort(address[] memory array) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n bytes32[] memory array,\\n function(bytes32, bytes32) pure returns (bool) comp\\n ) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\\n */\\n function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\\n * at end (exclusive). Sorting follows the `comp` comparator.\\n *\\n * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\\n *\\n * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\\n * be used only if the limits are within a memory array.\\n */\\n function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\\n unchecked {\\n if (end - begin < 0x40) return;\\n\\n // Use first element as pivot\\n uint256 pivot = _mload(begin);\\n // Position where the pivot should be at the end of the loop\\n uint256 pos = begin;\\n\\n for (uint256 it = begin + 0x20; it < end; it += 0x20) {\\n if (comp(_mload(it), pivot)) {\\n // If the value stored at the iterator's position comes before the pivot, we increment the\\n // position of the pivot and move the value there.\\n pos += 0x20;\\n _swap(pos, it);\\n }\\n }\\n\\n _swap(begin, pos); // Swap pivot into place\\n _quickSort(begin, pos, comp); // Sort the left side of the pivot\\n _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first element of `array`.\\n */\\n function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\\n assembly (\\\"memory-safe\\\") {\\n ptr := add(array, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\\n * that comes just after the last element of the array.\\n */\\n function _end(uint256[] memory array) private pure returns (uint256 ptr) {\\n unchecked {\\n return _begin(array) + array.length * 0x20;\\n }\\n }\\n\\n /**\\n * @dev Load memory word (as a uint256) at location `ptr`.\\n */\\n function _mload(uint256 ptr) private pure returns (uint256 value) {\\n assembly {\\n value := mload(ptr)\\n }\\n }\\n\\n /**\\n * @dev Swaps the elements memory location `ptr1` and `ptr2`.\\n */\\n function _swap(uint256 ptr1, uint256 ptr2) private pure {\\n assembly {\\n let value1 := mload(ptr1)\\n let value2 := mload(ptr2)\\n mstore(ptr1, value2)\\n mstore(ptr2, value1)\\n }\\n }\\n\\n /// @dev Helper: low level cast address memory array to uint256 memory array\\n function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\\n function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast address comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(address, address) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(bytes32, bytes32) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /**\\n * @dev Searches a sorted `array` and returns the first index that contains\\n * a value greater or equal to `element`. If no such index exists (i.e. all\\n * values in the array are strictly less than `element`), the array length is\\n * returned. Time complexity O(log n).\\n *\\n * NOTE: The `array` is expected to be sorted in ascending order, and to\\n * contain no repeated elements.\\n *\\n * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\\n * support for repeated elements in the array. The {lowerBound} function should\\n * be used instead.\\n */\\n function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n low = mid + 1;\\n }\\n }\\n\\n // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\\n if (low > 0 && unsafeAccess(array, low - 1).value == element) {\\n return low - 1;\\n } else {\\n return low;\\n }\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value greater or equal than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\\n */\\n function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value strictly greater than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\\n */\\n function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {lowerBound}, but with an array in memory.\\n */\\n function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {upperBound}, but with an array in memory.\\n */\\n function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getAddressSlot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getBytes32Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getUint256Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(address[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(uint256[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55a4fdb408e3db950b48f4a6131e538980be8c5f48ee59829d92d66477140cd6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides a set of functions to compare values.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Comparators {\\n function lt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a < b;\\n }\\n\\n function gt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a > b;\\n }\\n}\\n\",\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\\n * the solidity language / compiler.\\n *\\n * 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.].\\n *\\n * Example usage:\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using StorageSlot for bytes32;\\n * using SlotDerivation for bytes32;\\n *\\n * // Declare a namespace\\n * string private constant _NAMESPACE = \\\"\\\"; // eg. OpenZeppelin.Slot\\n *\\n * function setValueInNamespace(uint256 key, address newValue) internal {\\n * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\\n * }\\n *\\n * function getValueInNamespace(uint256 key) internal view returns (address) {\\n * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {StorageSlot}.\\n *\\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\\n * upgrade safety will ignore the slots accessed through this library.\\n *\\n * _Available since v5.1._\\n */\\nlibrary SlotDerivation {\\n /**\\n * @dev Derive an ERC-7201 slot from a string (namespace).\\n */\\n function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\\n slot := and(keccak256(0x00, 0x20), not(0xff))\\n }\\n }\\n\\n /**\\n * @dev Add an offset to a slot to get the n-th element of a structure or an array.\\n */\\n function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\\n unchecked {\\n return bytes32(uint256(slot) + pos);\\n }\\n }\\n\\n /**\\n * @dev Derive the location of the first element in an array from the slot where the length is stored.\\n */\\n function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, slot)\\n result := keccak256(0x00, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, and(key, shr(96, not(0))))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, iszero(iszero(key)))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x67672e4ca1dafdcc661d4eba8475cfac631fa0933309258e3af7644b92e1fb26\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, _msgSender());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _roles[ROOT_RESOURCE][account] & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return\\n (_roles[ROOT_RESOURCE][account] | _roles[resource][account]) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (_hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (_hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function _hasZeroNybbles(uint256 value) private pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 hasZeroNybbles;\\n unchecked {\\n hasZeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return hasZeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xdf8918a909b0ab3bf17bc3a560fbdff6ca6e9502cbee54eb0923f1fae04d2fb1\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x9f29748b40665df976c08cdaf434b469dc73ef50e938c36be6773dc7b6a6f014\",\"license\":\"MIT\"},\"project/src/erc1155/ERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {\\n IERC1155MetadataURI\\n} from \\\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\\\";\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport {ERC1155Utils} from \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol\\\";\\nimport {Arrays} from \\\"@openzeppelin/contracts/utils/Arrays.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IERC1155Singleton} from \\\"./interfaces/IERC1155Singleton.sol\\\";\\n\\n/// @notice ERC1155 variant enforcing exactly one owner per token ID.\\n///\\n/// Instead of the standard nested balance mapping (`id \\u2192 address \\u2192 balance`), uses a flat\\n/// `id \\u2192 address` ownership mapping. `balanceOf` returns 1 if the account is the owner,\\n/// 0 otherwise. Transferring value > 1 reverts.\\n///\\n/// Used by `PermissionedRegistry` to represent domain name ownership as non-divisible tokens.\\n/// The registry overrides `ownerOf` to add expiry and version validation on top of raw ownership.\\n///\\n/// Inherits `HCAContext` so that `_msgSender()` resolves HCA proxy accounts to their real\\n/// owners for approval checks and operator tracking.\\n///\\n/// @author OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC1155/ERC1155.sol)\\n/// @dev This contract has been modified from the implementation at the above link.\\nabstract contract ERC1155Singleton is\\n HCAContext,\\n ERC165,\\n IERC1155Singleton,\\n IERC1155Errors,\\n IERC1155MetadataURI\\n{\\n using Arrays for uint256[];\\n\\n using Arrays for address[];\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Maps each token ID to its single owner address.\\n mapping(uint256 id => address account) private _owners;\\n\\n /// @dev Standard ERC1155 operator approval mapping.\\n mapping(address account => mapping(address operator => bool)) private _operatorApprovals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155Singleton).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Sets the approval for all operator.\\n /// @param operator The operator to set the approval for.\\n /// @param approved The approval status.\\n function setApprovalForAll(address operator, bool approved) public virtual {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /// @notice Transfers a single token from one address to another.\\n /// @param from The address to transfer the token from.\\n /// @param to The address to transfer the token to.\\n /// @param id The token ID.\\n /// @param value The amount of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `to` cannot be the zero address.\\n /// @dev If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.\\n /// @dev `from` must have a balance of tokens of type `id` of at least `value` amount.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the\\n /// acceptance magic value.\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data)\\n public\\n virtual\\n {\\n address sender = _msgSender();\\n if (from != sender && !isApprovedForAll(from, sender)) {\\n revert ERC1155MissingApprovalForAll(sender, from);\\n }\\n _safeTransferFrom(from, to, id, value, data);\\n }\\n\\n /// @notice Transfers multiple tokens from one address to another.\\n /// @param from The address to transfer the tokens from.\\n /// @param to The address to transfer the tokens to.\\n /// @param ids The token IDs.\\n /// @param values The amounts of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `ids` and `values` must have the same length.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the\\n /// acceptance magic value.\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n public\\n virtual\\n {\\n address sender = _msgSender();\\n if (from != sender && !isApprovedForAll(from, sender)) {\\n revert ERC1155MissingApprovalForAll(sender, from);\\n }\\n _safeBatchTransferFrom(from, to, ids, values, data);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 id) public view virtual returns (address owner) {\\n return _owners[id];\\n }\\n\\n /// @notice Returns the URI for a token.\\n /// @param id The token ID.\\n /// @return uri The URI for the token.\\n function uri(uint256 id) public view virtual returns (string memory uri);\\n\\n /// @notice Returns the balance of a token for an account.\\n /// @param account The account to get the balance for.\\n /// @param id The token ID.\\n /// @return balance The balance of the token for the account. This will only ever be 1 or 0.\\n function balanceOf(address account, uint256 id) public view virtual returns (uint256) {\\n return ownerOf(id) == account ? 1 : 0;\\n }\\n\\n /// @notice Returns the balances of a batch of tokens for an account.\\n /// @param accounts The accounts to get the balances for.\\n /// @param ids The token IDs.\\n /// @return batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\\n /// @dev `accounts` and `ids` must have the same length.\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n returns (uint256[] memory)\\n {\\n if (accounts.length != ids.length) {\\n revert ERC1155InvalidArrayLength(ids.length, accounts.length);\\n }\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));\\n }\\n\\n return batchBalances;\\n }\\n\\n /// @notice Returns the approval for all operator.\\n /// @param account The account to get the approval for.\\n /// @param operator The operator to get the approval for.\\n /// @return approved The approval status.\\n function isApprovedForAll(address account, address operator) public view virtual returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Apply token updates for each pair in `ids` and `values`.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not the current owner or `value > 1`.\\n /// @dev This function does not perform ERC-1155 receiver acceptance checks.\\n /// @dev Emits `TransferSingle` when one token ID is updated, otherwise emits `TransferBatch`.\\n function _update(address from, address to, uint256[] memory ids, uint256[] memory values)\\n internal\\n virtual\\n {\\n if (ids.length != values.length) {\\n revert ERC1155InvalidArrayLength(ids.length, values.length);\\n }\\n\\n address operator = _msgSender();\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids.unsafeMemoryAccess(i);\\n uint256 value = values.unsafeMemoryAccess(i);\\n\\n if (value > 0) {\\n address owner = _owners[id];\\n if (owner != from) {\\n revert ERC1155InsufficientBalance(from, 0, value, id);\\n } else if (value > 1) {\\n revert ERC1155InsufficientBalance(from, 1, value, id);\\n }\\n _owners[id] = to;\\n }\\n }\\n\\n if (ids.length == 1) {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n emit TransferSingle(operator, from, to, id, value);\\n } else {\\n emit TransferBatch(operator, from, to, ids, values);\\n }\\n }\\n\\n /// @notice Apply token updates and run ERC-1155 receiver acceptance checks.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @param batch `true` if a batch operation.\\n /// @dev Calls `_update` before external receiver callbacks.\\n /// @dev If `to` is a contract, this calls `onERC1155Received` or `onERC1155BatchReceived`.\\n /// @dev Overriding is discouraged because post-callback state writes can introduce reentrancy bugs.\\n function _updateWithAcceptanceCheck(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data,\\n bool batch\\n )\\n internal\\n virtual\\n {\\n _update(from, to, ids, values);\\n if (to != address(0)) {\\n address operator = _msgSender();\\n if (batch) {\\n ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data);\\n } else {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data);\\n }\\n }\\n }\\n\\n /// @notice Safely transfer `value` tokens of token ID `id` from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param id Token ID to transfer.\\n /// @param value Amount to transfer.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, to, ids, values, data, false);\\n }\\n\\n /// @notice Safely transfer multiple token IDs from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param ids Token IDs to transfer.\\n /// @param values Amounts to transfer for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferBatch`.\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n _updateWithAcceptanceCheck(from, to, ids, values, data, true);\\n }\\n\\n /// @notice Mint `value` tokens of token ID `id` to `to`.\\n /// @param to Address receiving the minted token.\\n /// @param id Token ID to mint.\\n /// @param value Amount to mint.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(address(0), to, ids, values, data, false);\\n }\\n\\n /// @notice Burn `value` tokens of token ID `id` from `from`.\\n /// @param from Address to burn from.\\n /// @param id Token ID to burn.\\n /// @param value Amount to burn.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not current owner or `value > 1`.\\n /// @dev Emits `TransferSingle`.\\n function _burn(address from, uint256 id, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, address(0), ids, values, \\\"\\\", false);\\n }\\n\\n /// @notice Set or clear approval for `operator` to manage all tokens owned by `owner`.\\n /// @param owner Token owner granting or revoking approval.\\n /// @param operator Operator receiving approval.\\n /// @param approved Approval status to set.\\n /// @dev Reverts with `ERC1155InvalidOperator` if `operator` is the zero address.\\n /// @dev Emits `ApprovalForAll`.\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n if (operator == address(0)) {\\n revert ERC1155InvalidOperator(address(0));\\n }\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Gas-optimized assembly helper that creates two length-1 memory arrays without Solidity's\\n /// default zero-initialization overhead. Used to adapt single-token operations (`_mint`,\\n /// `_burn`, `_safeTransferFrom`) to the array-based `_update` function.\\n function _asSingletonArrays(uint256 element1, uint256 element2)\\n private\\n pure\\n returns (uint256[] memory array1, uint256[] memory array2)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Load the free memory pointer\\n array1 := mload(0x40)\\n // Set array length to 1\\n mstore(array1, 1)\\n // Store the single element at the next word after the length (where content starts)\\n mstore(add(array1, 0x20), element1)\\n\\n // Repeat for next array locating it right after the first array\\n array2 := add(array1, 0x40)\\n mstore(array2, 1)\\n mstore(add(array2, 0x20), element2)\\n\\n // Update the free memory pointer by pointing after the second array\\n mstore(0x40, add(array2, 0x40))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9af9852c17f9d19765bd2b21fe2076d96845f0c0f7e9b0faa1d905793d3b677d\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/registry/PermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IEnhancedAccessControl} from \\\"../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {ERC1155Singleton} from \\\"../erc1155/ERC1155Singleton.sol\\\";\\nimport {IERC1155Singleton} from \\\"../erc1155/interfaces/IERC1155Singleton.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {ILabelStore} from \\\"../utils/interfaces/ILabelStore.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./interfaces/IOwnedRegistry.sol\\\";\\nimport {IPermissionedRegistry} from \\\"./interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"./interfaces/IRegistry.sol\\\";\\nimport {IRegistryURIRenderer} from \\\"./interfaces/IRegistryURIRenderer.sol\\\";\\nimport {IStandardRegistry} from \\\"./interfaces/IStandardRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./interfaces/ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./interfaces/ITokenizedRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"./libraries/RegistryRolesLib.sol\\\";\\n\\n/// @notice A tokenized (ERC1155) registry with resource-scoped access control for subdomain management.\\n///\\n/// Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource\\n/// interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`)\\n/// to resolve any of these to the canonical storage slot for the name.\\n///\\n/// The registry maintains two independent version counters per name:\\n/// - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form\\n/// the EAC resource ID. This means a re-registered name gets a fresh permission scope.\\n/// - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint)\\n/// due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring\\n/// changes to roles create new tokens and prevent frontrunning a transfer with a role revocation.\\n///\\n/// Names are treated as `AVAILABLE` once `block.timestamp >= expiry`.\\n///\\n/// URI renderer address is embedded into URI data as `abi.encodePacked(uint8(1), address)`.\\n///\\n/// State diagram:\\n///\\n/// register()\\n/// +ROLE_REGISTRAR\\n/// +------------------->----------------------+\\n/// | |\\n/// | renew() | renew()\\n/// | +ROLE_RENEW | +ROLE_RENEW\\n/// | +------+ | +------+\\n/// | | | | | |\\n/// \\u028c \\u028c v v v |\\n/// AVAILABLE --------> RESERVED -------------> REGISTERED >--+\\n/// \\u028c register() v register() v\\n/// | w/owner=0 | +ROLE_REGISTER_RESERVED |\\n/// | +ROLE_REGISTRAR | |\\n/// | | |\\n/// +--------<---------+------------<------------+\\n/// unregister()\\n/// +ROLE_UNREGISTER\\n///\\ncontract PermissionedRegistry is ERC1155Singleton, EnhancedAccessControl, IPermissionedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n struct Entry {\\n /// @dev Incremented on unregister; combined with labelhash to form the EAC resource ID.\\n uint32 eacVersionId;\\n /// @dev Incremented on unregister and on token regeneration; combined with labelhash to form the ERC1155 token ID.\\n uint32 tokenVersionId;\\n /// @dev Child registry for this name.\\n IRegistry subregistry;\\n /// @dev Timestamp at or after which the name is considered expired/available.\\n uint64 expiry;\\n /// @dev Resolver address for this name.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The shared label database.\\n ILabelStore public immutable LABEL_STORE;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The parent registry of this registry.\\n IRegistry internal _parentRegistry;\\n\\n /// @dev The child label of this registry.\\n string internal _childLabel;\\n\\n /// @dev The metadata URI.\\n string internal _uri;\\n\\n /// @dev The metadata renderer.\\n IRegistryURIRenderer internal _uriRenderer;\\n\\n /// @dev The entries of this registry.\\n mapping(uint256 storageId => Entry entry) internal _entries;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory to use.\\n /// @param labelStore The shared label database.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n constructor(\\n IHCAFactoryBasic hcaFactory,\\n ILabelStore labelStore,\\n address rootAccount,\\n uint256 roleBitmap\\n )\\n HCAEquivalence(hcaFactory)\\n {\\n emit RegistryCreated();\\n LABEL_STORE = labelStore;\\n _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false);\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(IERC165, ERC1155Singleton, EnhancedAccessControl)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IPermissionedRegistry).interfaceId ||\\n interfaceId == type(IStandardRegistry).interfaceId ||\\n interfaceId == type(ITokenizedRegistry).interfaceId ||\\n interfaceId == type(ITemporalRegistry).interfaceId ||\\n interfaceId == type(IOwnedRegistry).interfaceId ||\\n interfaceId == type(IRegistry).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IStandardRegistry\\n function setSubregistry(uint256 anyId, IRegistry registry) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_SUBREGISTRY);\\n entry.subregistry = registry;\\n emit SubregistryUpdated(tokenId, registry, _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setResolver(uint256 anyId, address resolver) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_RESOLVER);\\n entry.resolver = resolver;\\n emit ResolverUpdated(tokenId, resolver, _msgSender());\\n }\\n\\n /// @notice Set the URI for the registry.\\n /// @param uri_ The new URI.\\n /// @param renderer The new renderer address.\\n function setURI(string calldata uri_, IRegistryURIRenderer renderer)\\n public\\n virtual\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_URI)\\n {\\n _uri = uri_;\\n _uriRenderer = renderer;\\n emit URIUpdated(uri_, address(renderer), _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setParent(IRegistry parent, string memory label)\\n public\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_PARENT)\\n {\\n _parentRegistry = parent;\\n _childLabel = label;\\n emit ParentUpdated(parent, label, _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n public\\n virtual\\n returns (uint256)\\n {\\n return _register(label, owner, registry, resolver, roleBitmap, expiry, true);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\\n function unregister(uint256 anyId) public {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_UNREGISTER);\\n emit LabelUnregistered(tokenId, _msgSender());\\n address owner = super.ownerOf(tokenId);\\n if (owner != address(0)) {\\n _burn(owner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n }\\n entry.expiry = uint64(block.timestamp);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev If `REGISTERED | RESERVED`, requires `ROLE_RENEW`.\\n /// If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\\n function renew(uint256 anyId, uint64 newExpiry) public override {\\n Entry storage entry = _entry(anyId);\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n address sender = _msgSender();\\n uint64 expiry = entry.expiry;\\n if (_isExpired(expiry)) {\\n if (expiry == 0 || !hasRootRoles(RegistryRolesLib.ROLE_RENEW, sender)) {\\n revert LabelExpired(tokenId); // never registered OR cannot revive\\n }\\n } else {\\n _checkRoles(_constructResource(anyId, entry), RegistryRolesLib.ROLE_RENEW, sender);\\n }\\n if (newExpiry < expiry) {\\n revert CannotReduceExpiry(expiry, newExpiry);\\n }\\n entry.expiry = newExpiry;\\n emit ExpiryUpdated(tokenId, newExpiry, sender);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function grantRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.grantRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function revokeRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.revokeRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IRegistry\\n function getSubregistry(string calldata label) public view virtual returns (IRegistry) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return\\n _isExpired(entry.expiry)\\n ? IRegistry(address(0))\\n : entry.subregistry;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getResolver(string calldata label) public view virtual returns (address) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? address(0) : entry.resolver;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getParent() public view returns (IRegistry parent, string memory label) {\\n return (_parentRegistry, _childLabel);\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) public view returns (bool) {\\n return hasRootRoles(RegistryRolesLib.ROLE_CAN_NAME, namer);\\n }\\n\\n /// @inheritdoc ITemporalRegistry\\n function findExpiry(string calldata label) public view returns (uint64) {\\n return getExpiry(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc IOwnedRegistry\\n function findOwner(string calldata label) public view returns (address) {\\n return ownerOf(findTokenId(label));\\n }\\n\\n /// @inheritdoc ITokenizedRegistry\\n function findTokenId(string calldata label) public view returns (uint256) {\\n return getTokenId(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ERC1155Singleton\\n function uri(uint256 tokenId) public view override returns (string memory) {\\n return\\n address(_uriRenderer) != address(0)\\n ? _uriRenderer.renderURI(this, tokenId)\\n : _uri;\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function getExpiry(uint256 anyId) public view returns (uint64) {\\n return _entry(anyId).expiry;\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getResource(uint256 anyId) public view returns (uint256) {\\n return _constructResource(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getTokenId(uint256 anyId) public view returns (uint256) {\\n return _constructTokenId(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getStatus(uint256 anyId) public view returns (Status) {\\n Entry storage entry = _entry(anyId);\\n return _constructStatus(entry.expiry, super.ownerOf(_constructTokenId(anyId, entry)));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getState(uint256 anyId) public view returns (State memory state) {\\n Entry storage entry = _entry(anyId);\\n uint64 expiry = entry.expiry;\\n state.expiry = expiry;\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n state.tokenId = tokenId;\\n state.resource = _constructResource(anyId, entry);\\n address owner = super.ownerOf(tokenId);\\n state.latestOwner = owner;\\n state.status = _constructStatus(expiry, owner);\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function latestOwnerOf(uint256 tokenId) public view returns (address) {\\n return super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 tokenId)\\n public\\n view\\n override(ERC1155Singleton, IERC1155Singleton)\\n returns (address)\\n {\\n Entry storage entry = _entry(tokenId);\\n return\\n tokenId != _constructTokenId(tokenId, entry) || _isExpired(entry.expiry)\\n ? address(0)\\n : super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 anyId, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roles(getResource(anyId), account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 anyId)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roleCount(getResource(anyId));\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasAssignees(getResource(anyId), roleBitmap);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256 counts, uint256 mask)\\n {\\n return super.getAssigneeCount(getResource(anyId), roleBitmap);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev If `AVAILABLE`, requires `ROLE_REGISTRAR` on root and status becomes `REGISTERED`.\\n /// * If `owner` is null (`roleBitmap` must be 0), status becomes `RESERVED`.\\n /// If `RESERVED`, requires `ROLE_REGISTER_RESERVED` on root and status becomes `REGISTERED`.\\n /// * If `expiry` is 0, uses current expiry.\\n function _register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry,\\n bool checkRoles\\n )\\n internal\\n returns (uint256 tokenId)\\n {\\n LABEL_STORE.setLabel(label);\\n uint256 labelId = LibLabel.id(label);\\n Entry storage entry = _entry(labelId);\\n tokenId = _constructTokenId(labelId, entry);\\n address prevOwner = super.ownerOf(tokenId);\\n address sender = _msgSender(); // the registrar, not the registrant\\n if (_isExpired(entry.expiry)) {\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTRAR, sender);\\n }\\n if (owner == address(0) && roleBitmap != 0) {\\n revert EACCannotGrantRoles(ROOT_RESOURCE, roleBitmap, sender); // strict\\n }\\n } else {\\n if (prevOwner != address(0)) {\\n revert LabelAlreadyRegistered(label); // cannot overwrite REGISTERED\\n } else if (owner == address(0)) {\\n revert LabelAlreadyReserved(label); // cannot overwrite RESERVED\\n }\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTER_RESERVED, sender);\\n }\\n if (expiry == 0) {\\n expiry = entry.expiry; // use RESERVED expiry\\n }\\n roleBitmap |= RegistryRolesLib.ROLE_WAS_RESERVED; // remember\\n }\\n if (owner == address(0) ? expiry == 0 : _isExpired(expiry)) {\\n revert CannotSetPastExpiry(expiry);\\n }\\n if (prevOwner != address(0)) {\\n _burn(prevOwner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n tokenId = _constructTokenId(tokenId, entry);\\n }\\n entry.expiry = expiry;\\n entry.subregistry = registry;\\n entry.resolver = resolver;\\n if (owner == address(0)) {\\n emit LabelReserved(tokenId, bytes32(labelId), label, expiry, sender);\\n } else {\\n emit LabelRegistered(tokenId, bytes32(labelId), label, owner, expiry, sender);\\n _mint(owner, tokenId, 1, \\\"\\\");\\n uint256 resource = _constructResource(tokenId, entry);\\n assert(resource != ROOT_RESOURCE);\\n emit TokenResource(tokenId, resource);\\n _grantRoles(resource, roleBitmap, owner, false);\\n }\\n if (address(registry) != address(0)) {\\n emit SubregistryUpdated(tokenId, registry, sender);\\n }\\n if (address(resolver) != address(0)) {\\n emit ResolverUpdated(tokenId, resolver, sender);\\n }\\n }\\n\\n /// @dev Override `ERC1155Singleton._update()` to transfer the roles to the new owner if the token is transferred.\\n function _update(address from, address to, uint256[] memory tokenIds, uint256[] memory amounts)\\n internal\\n override\\n {\\n super._update(from, to, tokenIds, amounts); // ensures amounts[i] is 0 or 1\\n if (to != address(0) && from != address(0)) {\\n // only transfers (skip mint and burn)\\n for (uint256 i; i < tokenIds.length; ++i) {\\n uint256 tokenId = tokenIds[i];\\n // only check ROLE_CAN_TRANSFER_ADMIN on original owner (from)\\n // ROLE_CAN_TRANSFER_ADMIN is technically a property of the token\\n if (!hasRoles(tokenId, RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, from)) {\\n revert TransferDisallowed(tokenId, from);\\n } else if (amounts[i] > 0) {\\n _transferRoles(getResource(tokenId), from, to, false);\\n }\\n }\\n }\\n }\\n\\n /// @dev Override the base registry _onRolesGranted function to regenerate the token when the roles are granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Override the base registry _onRolesRevoked function to regenerate the token when the roles are revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Bump `tokenVersionId` via burn+mint if token is not expired.\\n function _regenerate(uint256 resource) internal {\\n if (resource != ROOT_RESOURCE) {\\n Entry storage entry = _entry(resource);\\n uint256 tokenId = _constructTokenId(resource, entry);\\n address owner = super.ownerOf(tokenId); // grant/revoke only on registered\\n _burn(owner, tokenId, 1);\\n ++entry.tokenVersionId;\\n uint256 newTokenId = _constructTokenId(tokenId, entry);\\n emit TokenRegenerated(tokenId, newTokenId); // resource is unchanged\\n _mint(owner, newTokenId, 1, \\\"\\\");\\n }\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token non-admin roles can only be granted to registered tokens.\\n ///\\n /// Token admin roles are only assigned during name registration to maintain\\n /// controlled permission management. This ensures that role delegation\\n /// follows the intended security model where admin privileges are granted at\\n /// registration time and cannot be arbitrarily granted afterward.\\n ///\\n /// Root admin roles are unaffected.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles (regular roles only, not admin roles).\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n override\\n returns (uint256)\\n {\\n uint256 roleBitmap = super._getSettableRoles(resource, account);\\n if (resource == ROOT_RESOURCE) {\\n return roleBitmap;\\n } else if (ownerOf(_constructTokenId(resource, _entry(resource))) == address(0)) {\\n return 0; // available or reserved\\n }\\n return roleBitmap >> 128; // remove admin\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token roles can only be revoked from registered tokens.\\n ///\\n /// Root roles are unaffected.\\n ///\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n override\\n returns (uint256)\\n {\\n if (\\n resource != ROOT_RESOURCE &&\\n ownerOf(_constructTokenId(resource, _entry(resource))) == address(0)\\n ) {\\n return 0; // available or reserved\\n }\\n return super._getRevokableRoles(resource, account);\\n }\\n\\n /// @dev Zeroes version bits in `anyId` to return the canonical storage entry for the name.\\n function _entry(uint256 anyId) internal view returns (Entry storage) {\\n return _entries[LibLabel.withVersion(anyId, 0)];\\n }\\n\\n /// @dev Assert token is not expired and caller has necessary roles.\\n function _checkExpiryAndTokenRoles(uint256 anyId, uint256 roleBitmap)\\n internal\\n view\\n returns (uint256 tokenId, Entry storage entry)\\n {\\n entry = _entry(anyId);\\n tokenId = _constructTokenId(anyId, entry);\\n if (_isExpired(entry.expiry)) {\\n revert LabelExpired(tokenId);\\n }\\n _checkRoles(_constructResource(anyId, entry), roleBitmap, _msgSender());\\n }\\n\\n /// @dev Internal logic for expired status.\\n function _isExpired(uint64 expiry) internal view returns (bool) {\\n return block.timestamp >= expiry;\\n }\\n\\n /// @dev Create `resource` from parts.\\n /// Does nothing if `ROOT_RESOURCE`.\\n /// Returns next resource if expired.\\n function _constructResource(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n if (anyId == ROOT_RESOURCE) {\\n return anyId;\\n }\\n return\\n LibLabel.withVersion(\\n anyId,\\n _isExpired(entry.expiry)\\n ? entry.eacVersionId + 1\\n : entry.eacVersionId\\n );\\n }\\n\\n /// @dev Create `tokenId` from parts.\\n function _constructTokenId(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n return LibLabel.withVersion(anyId, entry.tokenVersionId);\\n }\\n\\n /// @dev Create `Status` from parts.\\n function _constructStatus(uint64 expiry, address owner) internal view returns (Status) {\\n if (_isExpired(expiry)) {\\n return Status.AVAILABLE;\\n } else if (owner == address(0)) {\\n return Status.RESERVED;\\n } else {\\n return Status.REGISTERED;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3d065298bcd998d8a638d5e52ff7ed15b8eff4ef43666eb8219a5858ace5a5e7\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryURIRenderer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6c55e19b`\\ninterface IRegistryURIRenderer {\\n /// @notice Generate URI for `tokenId` from `registry`.\\n /// @param registry The registry.\\n /// @param tokenId The token ID in the registry.\\n /// @return The generated URI.\\n function renderURI(IRegistry registry, uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa6ea64ff73d10fa58118ae9c0d0c2caa72f2f3488776227a22bd0cd9cd6586f6\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 7: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x6bd37001025ec90ffe9b852fcfdf68be81a9f70f8777d80136bea1c04da30041\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/interfaces/ILabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @notice Interface for a shared label database.\\n/// @dev Interface selector: `0x0d48fe93`\\ninterface ILabelStore {\\n /// @notice A label was recorded.\\n /// @param labelHash The hash of `label`.\\n /// @param label The recorded label.\\n event Label(bytes32 indexed labelHash, string label);\\n\\n /// @notice Ensure `label` can be inverted from `anyId`.\\n /// @param label The label.\\n function setLabel(string calldata label) external;\\n\\n /// @notice Invert `anyId` to the corresponding label.\\n /// @param anyId The truncated labelhash.\\n /// @return The label or null if unknown.\\n function getLabel(uint256 anyId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 59110, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_owners", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 59117, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 55601, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_roles", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 55606, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_roleCount", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 55611, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "__gap", + "offset": 0, + "slot": "4", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 66662, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_parentRegistry", + "offset": 0, + "slot": "260", + "type": "t_contract(IRegistry)68656" + }, + { + "astId": 66665, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_childLabel", + "offset": 0, + "slot": "261", + "type": "t_string_storage" + }, + { + "astId": 66668, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_uri", + "offset": 0, + "slot": "262", + "type": "t_string_storage" + }, + { + "astId": 66672, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_uriRenderer", + "offset": 0, + "slot": "263", + "type": "t_contract(IRegistryURIRenderer)68771" + }, + { + "astId": 66678, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_entries", + "offset": 0, + "slot": "264", + "type": "t_mapping(t_uint256,t_struct(Entry)66654_storage)" + }, + { + "astId": 66683, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "__gap", + "offset": 0, + "slot": "265", + "type": "t_array(t_uint256)256_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRegistry)68656": { + "encoding": "inplace", + "label": "contract IRegistry", + "numberOfBytes": "20" + }, + "t_contract(IRegistryURIRenderer)68771": { + "encoding": "inplace", + "label": "contract IRegistryURIRenderer", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "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_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_struct(Entry)66654_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct PermissionedRegistry.Entry)", + "numberOfBytes": "32", + "value": "t_struct(Entry)66654_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Entry)66654_storage": { + "encoding": "inplace", + "label": "struct PermissionedRegistry.Entry", + "members": [ + { + "astId": 66640, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "eacVersionId", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 66643, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "tokenVersionId", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 66647, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "subregistry", + "offset": 8, + "slot": "0", + "type": "t_contract(IRegistry)68656" + }, + { + "astId": 66650, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "expiry", + "offset": 0, + "slot": "1", + "type": "t_uint64" + }, + { + "astId": 66653, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "resolver", + "offset": 8, + "slot": "1", + "type": "t_address" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "notice": "Label expiry cannot be reduced." + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "notice": "Label expiry cannot be before now." + } + ], + "LabelAlreadyRegistered(string)": [ + { + "notice": "Label is already registered." + } + ], + "LabelAlreadyReserved(string)": [ + { + "notice": "Label cannot be reserved again." + } + ], + "LabelExpired(uint256)": [ + { + "notice": "Label is expired/unregistered." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "notice": "Transfer is not allowed due to missing transfer admin role." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "ExpiryUpdated(uint256,uint64,address)": { + "notice": "Expiry of label was changed." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "notice": "A label was registered." + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "notice": "A label was reserved." + }, + "LabelUnregistered(uint256,address)": { + "notice": "A label was unregistered." + }, + "ParentUpdated(address,string,address)": { + "notice": "Parent was changed." + }, + "RegistryCreated()": { + "notice": "A registry was created/initialized." + }, + "ResolverUpdated(uint256,address,address)": { + "notice": "Resolver of label was changed." + }, + "SubregistryUpdated(uint256,address,address)": { + "notice": "Subregistry of label was changed." + }, + "TokenRegenerated(uint256,uint256)": { + "notice": "Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance." + }, + "TokenResource(uint256,uint256)": { + "notice": "Associate a token with an EAC resource." + }, + "URIUpdated(string,address,address)": { + "notice": "URI was changed." + } + }, + "kind": "user", + "methods": { + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "LABEL_STORE()": { + "notice": "The shared label database." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "balanceOf(address,uint256)": { + "notice": "Returns the balance of a token for an account." + }, + "balanceOfBatch(address[],uint256[])": { + "notice": "Returns the balances of a batch of tokens for an account." + }, + "findExpiry(string)": { + "notice": "Fetches the label expiry." + }, + "findOwner(string)": { + "notice": "Fetches the label owner." + }, + "findTokenId(string)": { + "notice": "Fetches the token ID for a label." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getExpiry(uint256)": { + "notice": "Get expiry of label." + }, + "getParent()": { + "notice": "Get canonical \"location\" of this registry." + }, + "getResolver(string)": { + "notice": "Fetches the resolver responsible for the specified label." + }, + "getResource(uint256)": { + "notice": "Get `resource` from `anyId`." + }, + "getState(uint256)": { + "notice": "Get the state of a label." + }, + "getStatus(uint256)": { + "notice": "Get `Status` from `anyId`." + }, + "getSubregistry(string)": { + "notice": "Fetches the registry for a label." + }, + "getTokenId(uint256)": { + "notice": "Get `tokenId` from `anyId`." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "isApprovedForAll(address,address)": { + "notice": "Returns the approval for all operator." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "latestOwnerOf(uint256)": { + "notice": "Get the latest owner of a token. If the token was burned, returns null." + }, + "ownerOf(uint256)": { + "notice": "Returns the owner of a token." + }, + "register(string,address,address,address,uint256,uint64)": { + "notice": "Registers a new label." + }, + "renew(uint256,uint64)": { + "notice": "Renew a label." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "notice": "Transfers multiple tokens from one address to another." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "notice": "Transfers a single token from one address to another." + }, + "setApprovalForAll(address,bool)": { + "notice": "Sets the approval for all operator." + }, + "setParent(address,string)": { + "notice": "Change canonical \"location\"." + }, + "setResolver(uint256,address)": { + "notice": "Change resolver of label." + }, + "setSubregistry(uint256,address)": { + "notice": "Change registry of label." + }, + "setURI(string,address)": { + "notice": "Set the URI for the registry." + }, + "unregister(uint256)": { + "notice": "Delete a label." + }, + "uri(uint256)": { + "notice": "Returns the URI for a token." + } + }, + "notice": "A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`) to resolve any of these to the canonical storage slot for the name. The registry maintains two independent version counters per name: - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form the EAC resource ID. This means a re-registered name gets a fresh permission scope. - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint) due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring changes to roles create new tokens and prevent frontrunning a transfer with a role revocation. Names are treated as `AVAILABLE` once `block.timestamp >= expiry`. URI renderer address is embedded into URI data as `abi.encodePacked(uint8(1), address)`. State diagram: register() +ROLE_REGISTRAR +------------------->----------------------+ | | | renew() | renew() | +ROLE_RENEW | +ROLE_RENEW | +------+ | +------+ | | | | | | ʌ ʌ v v v | AVAILABLE --------> RESERVED -------------> REGISTERED >--+ ʌ register() v register() v | w/owner=0 | +ROLE_REGISTER_RESERVED | | +ROLE_REGISTRAR | | | | | +--------<---------+------------<------------+ unregister() +ROLE_UNREGISTER", + "version": 1 + }, + "argsData": "0x000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf94300000000000000000000000023ea712da760c4e09fc9be108f1f1da6d5d6d053000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f800100000000000000000000100001011101000000000000000000001000000100", + "transaction": { + "hash": "0x40d1ae172b85f4d75bec61e1e56dbaa7ff0cb3ea2e4659bddbb2f09baaea73d9", + "nonce": "0x1e8b", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x2388dfe5e3034d62e8fd7924f5f9d4e0ae6e4d3187a3b2406ade163aef87654c", + "blockNumber": "0xa6a800", + "transactionIndex": "0x43" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRenewerV1.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRenewerV1.json new file mode 100644 index 000000000..4fec19c59 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ETHRenewerV1.json @@ -0,0 +1,891 @@ +{ + "address": "0xb359d7d04f750e9c008a5a47bd2b64134bd180f9", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + }, + { + "internalType": "uint64", + "name": "gracePeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "bonusPeriod", + "type": "uint64" + }, + { + "internalType": "contract BaseRegistrarImplementation", + "name": "baseRegistrar", + "type": "address" + }, + { + "internalType": "address", + "name": "wrappedController", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minDuration", + "type": "uint64" + } + ], + "name": "DurationTooShort", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "NameNotRenewable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NameRenewed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + } + ], + "name": "RentPriceOracleUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "BASE_REGISTRAR", + "outputs": [ + { + "internalType": "contract BaseRegistrarImplementation", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BENEFICIARY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GRACE_PERIOD", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_RENEW_DURATION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WRAPPED_CONTROLLER", + "outputs": [ + { + "internalType": "contract IWrappedETHRegistrarController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getRemainingGracePeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRenewPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "isRenewable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rentPriceOracle", + "outputs": [ + { + "internalType": "contract IRentPriceOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + } + ], + "name": "setRentPriceOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "labels", + "type": "string[]" + } + ], + "name": "syncWrapper", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferRegistrarOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "ETHRenewerV1", + "sourceName": "src/registrar/ETHRenewerV1.sol", + "bytecode": "0x610160604052348015610010575f5ffd5b50604051611b2c380380611b2c83398101604081905261002f9161019a565b888888888883856001600160a01b03811661006357604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006c81610119565b506001600160a01b0390811660805283811660a05282811660c052600180546001600160a01b03191691831691821790556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac99060200160405180910390a1505050505083836100e19190610251565b6001600160401b0390811660e05293909316610100526001600160a01b03908116610120529091166101405250610282945050505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116811461017c575f5ffd5b50565b80516001600160401b0381168114610195575f5ffd5b919050565b5f5f5f5f5f5f5f5f5f6101208a8c0312156101b3575f5ffd5b89516101be81610168565b60208b01519099506101cf81610168565b60408b01519098506101e081610168565b60608b01519097506101f181610168565b60808b015190965061020281610168565b945061021060a08b0161017f565b935061021e60c08b0161017f565b925060e08a015161022e81610168565b6101008b015190925061024081610168565b809150509295985092959850929598565b6001600160401b03818116838216019081111561027c57634e487b7160e01b5f52601160045260245ffd5b92915050565b60805160a05160c05160e0516101005161012051610140516117db6103515f395f81816103150152818161098701528181610a120152610aeb01525f81816102ee015281816104ed015281816109af01528181610b13015261106801525f818161062e0152610d1d01525f81816102c70152818161064f015281816106de015261072f01525f81816101a2015261083201525f8181610229015281816103d90152818161055e0152818161089c0152610e6501525f8181610202015281816111d3015261123401526117db5ff3fe608060405234801561000f575f5ffd5b5060043610610149575f3560e01c8063802295ef116100c7578063c1a287e21161007d578063dba1002111610063578063dba1002114610310578063ddf0effc14610337578063f2fde38b14610358575f5ffd5b8063c1a287e2146102c2578063cd93adf5146102e9575f5ffd5b80638da5cb5b116100ad5780638da5cb5b1461028c578063a25967021461029c578063a2a11fbe146102af575f5ffd5b8063802295ef1461026657806389d779c314610279575f5ffd5b8063307a64a51161011c57806347500708116101025780634750070814610224578063715018a61461024b5780637b39ba1614610253575f5ffd5b8063307a64a5146101dc578063319c22bb146101fd575f5ffd5b806301ffc9a71461014d578063130d6f0014610175578063154fbf15146101885780632f99c6cc1461019d575b5f5ffd5b61016061015b3660046112c1565b61036b565b60405190151581526020015b60405180910390f35b61016061018336600461132d565b6103d3565b61019b610196366004611380565b6104ad565b005b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161016c565b6101e4600181565b60405167ffffffffffffffff909116815260200161016c565b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b61019b610547565b6001546101c4906001600160a01b031681565b6101e461027436600461132d565b61055a565b61019b6102873660046113b0565b61076b565b5f546001600160a01b03166101c4565b61019b6102aa36600461141b565b610957565b61019b6102bd366004611380565b610b6e565b6101e47f000000000000000000000000000000000000000000000000000000000000000081565b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b61034a61034536600461148c565b610bd7565b60405190815260200161016c565b61019b610366366004611380565b610c65565b5f6001600160e01b031982167f06aaeb320000000000000000000000000000000000000000000000000000000014806103cd57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b5f6104a67f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861044486868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cc092505050565b6040518263ffffffff1660e01b815260040161046291815260200190565b60a060405180830381865afa15801561047d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a19190611514565b610ccb565b9392505050565b6104b5610d67565b6040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f2fde38b906024015f604051808303815f87803b15801561052e575f5ffd5b505af1158015610540573d5f5f3e3d5ffd5b5050505050565b61054f610d67565b6105585f610ddd565b565b5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286105c986868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cc092505050565b6040518263ffffffff1660e01b81526004016105e791815260200190565b60a060405180830381865afa158015610602573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106269190611514565b90505f6106737f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006115b6565b60408301519091506001600160a01b03161580156106a857508067ffffffffffffffff16826020015167ffffffffffffffff16115b15610761575f8183602001516106be91906115b6565b90504267ffffffffffffffff8083169082161080159061071a57506107037f0000000000000000000000000000000000000000000000000000000000000000836115d6565b67ffffffffffffffff168167ffffffffffffffff16105b1561075e5761072982826115b6565b610753907f00000000000000000000000000000000000000000000000000000000000000006115b6565b9450505050506103cd565b50505b505f949350505050565b5f610777868686610e39565b90505f84826020015161078a91906115d6565b60015460208401516040517f3ad860830000000000000000000000000000000000000000000000000000000081529293505f926001600160a01b0390921691633ad86083916107e3918c918c918c908c9060040161161e565b602060405180830381865afa1580156107fe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610822919061166c565b905061085785610830610fca565b7f000000000000000000000000000000000000000000000000000000000000000084610fd8565b60608301516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff831660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b1580156108e5575f5ffd5b505af11580156108f7573d5f5f3e3d5ffd5b50505050610906888888611066565b8383606001517fbd0c01e5bf66003280556423db4a8bf79043c146ac57f657c30049dd433166498a8a8a878b8860405161094596959493929190611683565b60405180910390a35050505050505050565b6040517fa7fc7a070000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063a7fc7a07906024015f604051808303815f87803b1580156109f0575f5ffd5b505af1158015610a02573d5f5f3e3d5ffd5b505050505f5b81811015610aba577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663acf1a841848484818110610a5157610a516116ce565b9050602002810190610a6391906116e2565b5f6040518463ffffffff1660e01b8152600401610a8293929190611725565b5f604051808303815f87803b158015610a99575f5ffd5b505af1158015610aab573d5f5f3e3d5ffd5b50505050806001019050610a08565b506040517ff6a74ed70000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f6a74ed7906024015f604051808303815f87803b158015610b54575f5ffd5b505af1158015610b66573d5f5f3e3d5ffd5b505050505050565b610b76610d67565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac99060200160405180910390a150565b6001545f906001600160a01b0316633ad860838686610bf7828289610e39565b6020015187876040518663ffffffff1660e01b8152600401610c1d95949392919061161e565b602060405180830381865afa158015610c38573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c5c919061166c565b95945050505050565b610c6d610d67565b6001600160a01b038116610cb4576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b610cbd81610ddd565b50565b805160209091012090565b5f600182516002811115610ce157610ce1611748565b14806103cd57505f82516002811115610cfc57610cfc611748565b148015610d14575060408201516001600160a01b0316155b80156103cd57507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16826020015167ffffffffffffffff1642610d60919061175c565b1092915050565b610d6f610fca565b6001600160a01b0316610d895f546001600160a01b031690565b6001600160a01b03161461055857610d9f610fca565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610cab565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610ed086868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cc092505050565b6040518263ffffffff1660e01b8152600401610eee91815260200190565b60a060405180830381865afa158015610f09573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f2d9190611514565b9050610f3881610ccb565b610f725783836040517f1caefaa0000000000000000000000000000000000000000000000000000000008152600401610cab92919061176f565b600167ffffffffffffffff831610156104a6576040517fa096b84400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8316600482015260016024820152604401610cab565b5f610fd3611142565b905090565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261106090859061114b565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c475abff6110d385858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cc092505050565b6040516001600160e01b031960e084901b168152600481019190915267ffffffffffffffff841660248201526044016020604051808303815f875af115801561111e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611060919061166c565b5f610fd36111d0565b5f5f60205f8451602086015f885af18061116a576040513d5f823e3d81fd5b50505f513d9150811561118157806001141561118e565b6001600160a01b0384163b155b15611060576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610cab565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661120457503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015611281573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a5919061178a565b90506001600160a01b0381166112bc573391505090565b919050565b5f602082840312156112d1575f5ffd5b81356001600160e01b0319811681146104a6575f5ffd5b5f5f83601f8401126112f8575f5ffd5b50813567ffffffffffffffff81111561130f575f5ffd5b602083019150836020828501011115611326575f5ffd5b9250929050565b5f5f6020838503121561133e575f5ffd5b823567ffffffffffffffff811115611354575f5ffd5b611360858286016112e8565b90969095509350505050565b6001600160a01b0381168114610cbd575f5ffd5b5f60208284031215611390575f5ffd5b81356104a68161136c565b67ffffffffffffffff81168114610cbd575f5ffd5b5f5f5f5f5f608086880312156113c4575f5ffd5b853567ffffffffffffffff8111156113da575f5ffd5b6113e6888289016112e8565b90965094505060208601356113fa8161139b565b9250604086013561140a8161136c565b949793965091946060013592915050565b5f5f6020838503121561142c575f5ffd5b823567ffffffffffffffff811115611442575f5ffd5b8301601f81018513611452575f5ffd5b803567ffffffffffffffff811115611468575f5ffd5b8560208260051b840101111561147c575f5ffd5b6020919091019590945092505050565b5f5f5f5f6060858703121561149f575f5ffd5b843567ffffffffffffffff8111156114b5575f5ffd5b6114c1878288016112e8565b90955093505060208501356114d58161139b565b915060408501356114e58161136c565b939692955090935050565b8051600381106112bc575f5ffd5b80516112bc8161139b565b80516112bc8161136c565b5f60a0828403128015611525575f5ffd5b5060405160a0810167ffffffffffffffff8111828210171561155557634e487b7160e01b5f52604160045260245ffd5b604052611561836114f0565b815261156f602084016114fe565b602082015261158060408401611509565b6040820152606083810151908201526080928301519281019290925250919050565b634e487b7160e01b5f52601160045260245ffd5b67ffffffffffffffff82811682821603908111156103cd576103cd6115a2565b67ffffffffffffffff81811683821601908111156103cd576103cd6115a2565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b608081525f6116316080830187896115f6565b905067ffffffffffffffff8516602083015267ffffffffffffffff841660408301526001600160a01b03831660608301529695505050505050565b5f6020828403121561167c575f5ffd5b5051919050565b60a081525f61169660a08301888a6115f6565b67ffffffffffffffff96871660208401529490951660408201526001600160a01b039290921660608301526080909101529392505050565b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e198436030181126116f7575f5ffd5b83018035915067ffffffffffffffff821115611711575f5ffd5b602001915036819003821315611326575f5ffd5b604081525f6117386040830185876115f6565b9050826020830152949350505050565b634e487b7160e01b5f52602160045260245ffd5b818103818111156103cd576103cd6115a2565b602081525f6117826020830184866115f6565b949350505050565b5f6020828403121561179a575f5ffd5b81516104a68161136c56fea2646970667358221220e263d8099a3ae0f9e6eafdf198711d6b0a4e6d37ec7d51b4b91cec116ccc5b3b64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610149575f3560e01c8063802295ef116100c7578063c1a287e21161007d578063dba1002111610063578063dba1002114610310578063ddf0effc14610337578063f2fde38b14610358575f5ffd5b8063c1a287e2146102c2578063cd93adf5146102e9575f5ffd5b80638da5cb5b116100ad5780638da5cb5b1461028c578063a25967021461029c578063a2a11fbe146102af575f5ffd5b8063802295ef1461026657806389d779c314610279575f5ffd5b8063307a64a51161011c57806347500708116101025780634750070814610224578063715018a61461024b5780637b39ba1614610253575f5ffd5b8063307a64a5146101dc578063319c22bb146101fd575f5ffd5b806301ffc9a71461014d578063130d6f0014610175578063154fbf15146101885780632f99c6cc1461019d575b5f5ffd5b61016061015b3660046112c1565b61036b565b60405190151581526020015b60405180910390f35b61016061018336600461132d565b6103d3565b61019b610196366004611380565b6104ad565b005b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161016c565b6101e4600181565b60405167ffffffffffffffff909116815260200161016c565b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b61019b610547565b6001546101c4906001600160a01b031681565b6101e461027436600461132d565b61055a565b61019b6102873660046113b0565b61076b565b5f546001600160a01b03166101c4565b61019b6102aa36600461141b565b610957565b61019b6102bd366004611380565b610b6e565b6101e47f000000000000000000000000000000000000000000000000000000000000000081565b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b6101c47f000000000000000000000000000000000000000000000000000000000000000081565b61034a61034536600461148c565b610bd7565b60405190815260200161016c565b61019b610366366004611380565b610c65565b5f6001600160e01b031982167f06aaeb320000000000000000000000000000000000000000000000000000000014806103cd57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b5f6104a67f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861044486868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cc092505050565b6040518263ffffffff1660e01b815260040161046291815260200190565b60a060405180830381865afa15801561047d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104a19190611514565b610ccb565b9392505050565b6104b5610d67565b6040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f2fde38b906024015f604051808303815f87803b15801561052e575f5ffd5b505af1158015610540573d5f5f3e3d5ffd5b5050505050565b61054f610d67565b6105585f610ddd565b565b5f5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286105c986868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cc092505050565b6040518263ffffffff1660e01b81526004016105e791815260200190565b60a060405180830381865afa158015610602573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106269190611514565b90505f6106737f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006115b6565b60408301519091506001600160a01b03161580156106a857508067ffffffffffffffff16826020015167ffffffffffffffff16115b15610761575f8183602001516106be91906115b6565b90504267ffffffffffffffff8083169082161080159061071a57506107037f0000000000000000000000000000000000000000000000000000000000000000836115d6565b67ffffffffffffffff168167ffffffffffffffff16105b1561075e5761072982826115b6565b610753907f00000000000000000000000000000000000000000000000000000000000000006115b6565b9450505050506103cd565b50505b505f949350505050565b5f610777868686610e39565b90505f84826020015161078a91906115d6565b60015460208401516040517f3ad860830000000000000000000000000000000000000000000000000000000081529293505f926001600160a01b0390921691633ad86083916107e3918c918c918c908c9060040161161e565b602060405180830381865afa1580156107fe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610822919061166c565b905061085785610830610fca565b7f000000000000000000000000000000000000000000000000000000000000000084610fd8565b60608301516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff831660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b1580156108e5575f5ffd5b505af11580156108f7573d5f5f3e3d5ffd5b50505050610906888888611066565b8383606001517fbd0c01e5bf66003280556423db4a8bf79043c146ac57f657c30049dd433166498a8a8a878b8860405161094596959493929190611683565b60405180910390a35050505050505050565b6040517fa7fc7a070000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063a7fc7a07906024015f604051808303815f87803b1580156109f0575f5ffd5b505af1158015610a02573d5f5f3e3d5ffd5b505050505f5b81811015610aba577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663acf1a841848484818110610a5157610a516116ce565b9050602002810190610a6391906116e2565b5f6040518463ffffffff1660e01b8152600401610a8293929190611725565b5f604051808303815f87803b158015610a99575f5ffd5b505af1158015610aab573d5f5f3e3d5ffd5b50505050806001019050610a08565b506040517ff6a74ed70000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f6a74ed7906024015f604051808303815f87803b158015610b54575f5ffd5b505af1158015610b66573d5f5f3e3d5ffd5b505050505050565b610b76610d67565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac99060200160405180910390a150565b6001545f906001600160a01b0316633ad860838686610bf7828289610e39565b6020015187876040518663ffffffff1660e01b8152600401610c1d95949392919061161e565b602060405180830381865afa158015610c38573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c5c919061166c565b95945050505050565b610c6d610d67565b6001600160a01b038116610cb4576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b610cbd81610ddd565b50565b805160209091012090565b5f600182516002811115610ce157610ce1611748565b14806103cd57505f82516002811115610cfc57610cfc611748565b148015610d14575060408201516001600160a01b0316155b80156103cd57507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16826020015167ffffffffffffffff1642610d60919061175c565b1092915050565b610d6f610fca565b6001600160a01b0316610d895f546001600160a01b031690565b6001600160a01b03161461055857610d9f610fca565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610cab565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610ed086868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cc092505050565b6040518263ffffffff1660e01b8152600401610eee91815260200190565b60a060405180830381865afa158015610f09573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f2d9190611514565b9050610f3881610ccb565b610f725783836040517f1caefaa0000000000000000000000000000000000000000000000000000000008152600401610cab92919061176f565b600167ffffffffffffffff831610156104a6576040517fa096b84400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8316600482015260016024820152604401610cab565b5f610fd3611142565b905090565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261106090859061114b565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c475abff6110d385858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cc092505050565b6040516001600160e01b031960e084901b168152600481019190915267ffffffffffffffff841660248201526044016020604051808303815f875af115801561111e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611060919061166c565b5f610fd36111d0565b5f5f60205f8451602086015f885af18061116a576040513d5f823e3d81fd5b50505f513d9150811561118157806001141561118e565b6001600160a01b0384163b155b15611060576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610cab565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661120457503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015611281573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a5919061178a565b90506001600160a01b0381166112bc573391505090565b919050565b5f602082840312156112d1575f5ffd5b81356001600160e01b0319811681146104a6575f5ffd5b5f5f83601f8401126112f8575f5ffd5b50813567ffffffffffffffff81111561130f575f5ffd5b602083019150836020828501011115611326575f5ffd5b9250929050565b5f5f6020838503121561133e575f5ffd5b823567ffffffffffffffff811115611354575f5ffd5b611360858286016112e8565b90969095509350505050565b6001600160a01b0381168114610cbd575f5ffd5b5f60208284031215611390575f5ffd5b81356104a68161136c565b67ffffffffffffffff81168114610cbd575f5ffd5b5f5f5f5f5f608086880312156113c4575f5ffd5b853567ffffffffffffffff8111156113da575f5ffd5b6113e6888289016112e8565b90965094505060208601356113fa8161139b565b9250604086013561140a8161136c565b949793965091946060013592915050565b5f5f6020838503121561142c575f5ffd5b823567ffffffffffffffff811115611442575f5ffd5b8301601f81018513611452575f5ffd5b803567ffffffffffffffff811115611468575f5ffd5b8560208260051b840101111561147c575f5ffd5b6020919091019590945092505050565b5f5f5f5f6060858703121561149f575f5ffd5b843567ffffffffffffffff8111156114b5575f5ffd5b6114c1878288016112e8565b90955093505060208501356114d58161139b565b915060408501356114e58161136c565b939692955090935050565b8051600381106112bc575f5ffd5b80516112bc8161139b565b80516112bc8161136c565b5f60a0828403128015611525575f5ffd5b5060405160a0810167ffffffffffffffff8111828210171561155557634e487b7160e01b5f52604160045260245ffd5b604052611561836114f0565b815261156f602084016114fe565b602082015261158060408401611509565b6040820152606083810151908201526080928301519281019290925250919050565b634e487b7160e01b5f52601160045260245ffd5b67ffffffffffffffff82811682821603908111156103cd576103cd6115a2565b67ffffffffffffffff81811683821601908111156103cd576103cd6115a2565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b608081525f6116316080830187896115f6565b905067ffffffffffffffff8516602083015267ffffffffffffffff841660408301526001600160a01b03831660608301529695505050505050565b5f6020828403121561167c575f5ffd5b5051919050565b60a081525f61169660a08301888a6115f6565b67ffffffffffffffff96871660208401529490951660408201526001600160a01b039290921660608301526080909101529392505050565b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e198436030181126116f7575f5ffd5b83018035915067ffffffffffffffff821115611711575f5ffd5b602001915036819003821315611326575f5ffd5b604081525f6117386040830185876115f6565b9050826020830152949350505050565b634e487b7160e01b5f52602160045260245ffd5b818103818111156103cd576103cd6115a2565b602081525f6117826020830184866115f6565b949350505050565b5f6020828403121561179a575f5ffd5b81516104a68161136c56fea2646970667358221220e263d8099a3ae0f9e6eafdf198711d6b0a4e6d37ec7d51b4b91cec116ccc5b3b64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60111": [ + { + "length": 32, + "start": 514 + }, + { + "length": 32, + "start": 4563 + }, + { + "length": 32, + "start": 4660 + } + ], + "63497": [ + { + "length": 32, + "start": 553 + }, + { + "length": 32, + "start": 985 + }, + { + "length": 32, + "start": 1374 + }, + { + "length": 32, + "start": 2204 + }, + { + "length": 32, + "start": 3685 + } + ], + "63500": [ + { + "length": 32, + "start": 418 + }, + { + "length": 32, + "start": 2098 + } + ], + "64615": [ + { + "length": 32, + "start": 711 + }, + { + "length": 32, + "start": 1615 + }, + { + "length": 32, + "start": 1758 + }, + { + "length": 32, + "start": 1839 + } + ], + "64618": [ + { + "length": 32, + "start": 1582 + }, + { + "length": 32, + "start": 3357 + } + ], + "64622": [ + { + "length": 32, + "start": 750 + }, + { + "length": 32, + "start": 1261 + }, + { + "length": 32, + "start": 2479 + }, + { + "length": 32, + "start": 2835 + }, + { + "length": 32, + "start": 4200 + } + ], + "64626": [ + { + "length": 32, + "start": 789 + }, + { + "length": 32, + "start": 2439 + }, + { + "length": 32, + "start": 2578 + }, + { + "length": 32, + "start": 2795 + } + ] + }, + "inputSourceName": "project/src/registrar/ETHRenewerV1.sol", + "devdoc": { + "errors": { + "DurationTooShort(uint64,uint64)": [ + { + "details": "Error selector: `0xa096b844`" + } + ], + "NameNotRenewable(string)": [ + { + "details": "Error selector: `0x1caefaa0`" + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ], + "SafeERC20FailedOperation(address)": [ + { + "details": "An operation with an ERC-20 token failed." + } + ] + }, + "events": { + "NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)": { + "params": { + "amount": "The amount of `paymentToken`.", + "duration": "The duration extension, in seconds.", + "label": "The name of the renewal.", + "newExpiry": "The new expiry, in seconds.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash.", + "tokenId": "The registry token id." + } + }, + "RentPriceOracleUpdated(address)": { + "params": { + "oracle": "The new `IRentPriceOracle` contract." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "baseRegistrar": "ENSv1 `BaseRegistrarImplementation` contract.", + "beneficiary": "Address that receives payments.", + "bonusPeriod": "Duration added by premigration, in seconds.", + "ethRegistry": "ENSv2 .eth `PermissionedRegistry`.", + "gracePeriod": "Post-expiry period where renewable and not available, in seconds.", + "hcaFactory": "HCA factory.", + "oracle": "Initial oracle for registration and renewal costs.", + "owner_": "Contract owner.", + "wrappedController": "ENSv1 `ETHRegistrarController` that is a `NameWrapper` controller." + } + }, + "getRemainingGracePeriod(string)": { + "details": "Defined over `[expiry, expiry + GRACE_PERIOD)`.", + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "The remaining grace period, in seconds." + } + }, + "getRenewPrice(string,uint64,address)": { + "params": { + "duration": "The duration extension, in seconds.", + "label": "The name to renew.", + "paymentToken": "The payment token." + }, + "returns": { + "_0": "The amount of `paymentToken`." + } + }, + "isRenewable(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "`true` if renewable." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renew(string,uint64,address,bytes32)": { + "params": { + "duration": "The duration extension, in seconds.", + "label": "The name to renew.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash." + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setRentPriceOracle(address)": { + "params": { + "oracle": "The new `IRentPriceOracle` instance." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "syncWrapper(string[])": { + "params": { + "labels": "The labels to sync." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferRegistrarOwnership(address)": { + "params": { + "newOwner": "The new owner for the registrar." + } + } + }, + "stateVariables": { + "_GRACE_PERIOD_V2": { + "details": "ENSv2 `GRACE_PERIOD`." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1221400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BASE_REGISTRAR()": "infinite", + "BENEFICIARY()": "infinite", + "ETH_REGISTRY()": "infinite", + "GRACE_PERIOD()": "infinite", + "HCA_FACTORY()": "infinite", + "MIN_RENEW_DURATION()": "249", + "WRAPPED_CONTROLLER()": "infinite", + "getRemainingGracePeriod(string)": "infinite", + "getRenewPrice(string,uint64,address)": "infinite", + "isRenewable(string)": "infinite", + "owner()": "2374", + "renew(string,uint64,address,bytes32)": "infinite", + "renounceOwnership()": "infinite", + "rentPriceOracle()": "2425", + "setRentPriceOracle(address)": "infinite", + "supportsInterface(bytes4)": "435", + "syncWrapper(string[])": "infinite", + "transferOwnership(address)": "infinite", + "transferRegistrarOwnership(address)": "infinite" + }, + "internal": { + "_isRenewable(struct IPermissionedRegistry.State memory)": "infinite", + "_onRenew(string calldata,uint64)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"gracePeriod\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"bonusPeriod\",\"type\":\"uint64\"},{\"internalType\":\"contract BaseRegistrarImplementation\",\"name\":\"baseRegistrar\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"wrappedController\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minDuration\",\"type\":\"uint64\"}],\"name\":\"DurationTooShort\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"NameNotRenewable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NameRenewed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"RentPriceOracleUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_REGISTRAR\",\"outputs\":[{\"internalType\":\"contract BaseRegistrarImplementation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"BENEFICIARY\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GRACE_PERIOD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_RENEW_DURATION\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WRAPPED_CONTROLLER\",\"outputs\":[{\"internalType\":\"contract IWrappedETHRegistrarController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getRemainingGracePeriod\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRenewPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"isRenewable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rentPriceOracle\",\"outputs\":[{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"setRentPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"labels\",\"type\":\"string[]\"}],\"name\":\"syncWrapper\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferRegistrarOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DurationTooShort(uint64,uint64)\":[{\"details\":\"Error selector: `0xa096b844`\"}],\"NameNotRenewable(string)\":[{\"details\":\"Error selector: `0x1caefaa0`\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)\":{\"params\":{\"amount\":\"The amount of `paymentToken`.\",\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name of the renewal.\",\"newExpiry\":\"The new expiry, in seconds.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\",\"tokenId\":\"The registry token id.\"}},\"RentPriceOracleUpdated(address)\":{\"params\":{\"oracle\":\"The new `IRentPriceOracle` contract.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"baseRegistrar\":\"ENSv1 `BaseRegistrarImplementation` contract.\",\"beneficiary\":\"Address that receives payments.\",\"bonusPeriod\":\"Duration added by premigration, in seconds.\",\"ethRegistry\":\"ENSv2 .eth `PermissionedRegistry`.\",\"gracePeriod\":\"Post-expiry period where renewable and not available, in seconds.\",\"hcaFactory\":\"HCA factory.\",\"oracle\":\"Initial oracle for registration and renewal costs.\",\"owner_\":\"Contract owner.\",\"wrappedController\":\"ENSv1 `ETHRegistrarController` that is a `NameWrapper` controller.\"}},\"getRemainingGracePeriod(string)\":{\"details\":\"Defined over `[expiry, expiry + GRACE_PERIOD)`.\",\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"The remaining grace period, in seconds.\"}},\"getRenewPrice(string,uint64,address)\":{\"params\":{\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name to renew.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"_0\":\"The amount of `paymentToken`.\"}},\"isRenewable(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"`true` if renewable.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renew(string,uint64,address,bytes32)\":{\"params\":{\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name to renew.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setRentPriceOracle(address)\":{\"params\":{\"oracle\":\"The new `IRentPriceOracle` instance.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"syncWrapper(string[])\":{\"params\":{\"labels\":\"The labels to sync.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferRegistrarOwnership(address)\":{\"params\":{\"newOwner\":\"The new owner for the registrar.\"}}},\"stateVariables\":{\"_GRACE_PERIOD_V2\":{\"details\":\"ENSv2 `GRACE_PERIOD`.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"DurationTooShort(uint64,uint64)\":[{\"notice\":\"`duration` less than `minDuration`.\"}],\"NameNotRenewable(string)\":[{\"notice\":\"`label` cannot be renewed.\"}]},\"events\":{\"NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)\":{\"notice\":\"A name was extended by `duration`.\"},\"RentPriceOracleUpdated(address)\":{\"notice\":\"`IRentPriceOracle` was replaced.\"}},\"kind\":\"user\",\"methods\":{\"BASE_REGISTRAR()\":{\"notice\":\"ENSv1 `BaseRegistrarImplementation` contract.\"},\"BENEFICIARY()\":{\"notice\":\"Address that receives payments.\"},\"ETH_REGISTRY()\":{\"notice\":\"ENSv2 .eth `PermissionedRegistry`.\"},\"GRACE_PERIOD()\":{\"notice\":\"Post-expiry period where still renewable and not available, in seconds.\"},\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"MIN_RENEW_DURATION()\":{\"notice\":\"Minimum renew duration, in seconds.\"},\"WRAPPED_CONTROLLER()\":{\"notice\":\"ENSv1 `ETHRegistrarController` that is an active `NameWrapper` controller.\"},\"getRemainingGracePeriod(string)\":{\"notice\":\"Determine remaining grace period.\"},\"getRenewPrice(string,uint64,address)\":{\"notice\":\"Determine renew price for a name.\"},\"isRenewable(string)\":{\"notice\":\"Check if name is renewable.\"},\"renew(string,uint64,address,bytes32)\":{\"notice\":\"Renew a name.\"},\"rentPriceOracle()\":{\"notice\":\"Oracle for registration and renewal costs.\"},\"setRentPriceOracle(address)\":{\"notice\":\"Change the rent price oracle.\"},\"syncWrapper(string[])\":{\"notice\":\"Sync `NameWrapper` expiry with `BaseRegistrarImplementation` expiry.\"},\"transferRegistrarOwnership(address)\":{\"notice\":\"Transfers ownership of the registrar.\"}},\"notice\":\".eth registrar that only renews premigrated ENSv2 reservations and syncs with ENSv1. Pricing and payment are delegated to a swappable `IRentPriceOracle`. Provides a mechanism for syncing `NameWrapper` expiry.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/ETHRenewerV1.sol\":\"ETHRenewerV1\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/BaseRegistrarImplementation.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"./IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract BaseRegistrarImplementation is ERC721, IBaseRegistrar, Ownable {\\n // A map of expiry times\\n mapping(uint256 => uint256) expiries;\\n // The ENS registry\\n ENS public ens;\\n // The namehash of the TLD this registrar owns (eg, .eth)\\n bytes32 public baseNode;\\n // A map of addresses that are authorised to register and renew names.\\n mapping(address => bool) public controllers;\\n uint256 public constant GRACE_PERIOD = 90 days;\\n bytes4 private constant INTERFACE_META_ID =\\n bytes4(keccak256(\\\"supportsInterface(bytes4)\\\"));\\n bytes4 private constant ERC721_ID =\\n bytes4(\\n keccak256(\\\"balanceOf(address)\\\") ^\\n keccak256(\\\"ownerOf(uint256)\\\") ^\\n keccak256(\\\"approve(address,uint256)\\\") ^\\n keccak256(\\\"getApproved(uint256)\\\") ^\\n keccak256(\\\"setApprovalForAll(address,bool)\\\") ^\\n keccak256(\\\"isApprovedForAll(address,address)\\\") ^\\n keccak256(\\\"transferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256,bytes)\\\")\\n );\\n bytes4 private constant RECLAIM_ID =\\n bytes4(keccak256(\\\"reclaim(uint256,address)\\\"));\\n\\n /// v2.1.3 version of _isApprovedOrOwner which calls ownerOf(tokenId) and takes grace period into consideration instead of ERC721.ownerOf(tokenId);\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.1.3/contracts/token/ERC721/ERC721.sol#L187\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param spender address of the spender to query\\n /// @param tokenId uint256 ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID,\\n /// is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(\\n address spender,\\n uint256 tokenId\\n ) internal view override returns (bool) {\\n address owner = ownerOf(tokenId);\\n return (spender == owner ||\\n getApproved(tokenId) == spender ||\\n isApprovedForAll(owner, spender));\\n }\\n\\n constructor(ENS _ens, bytes32 _baseNode) ERC721(\\\"\\\", \\\"\\\") {\\n ens = _ens;\\n baseNode = _baseNode;\\n }\\n\\n modifier live() {\\n require(ens.owner(baseNode) == address(this));\\n _;\\n }\\n\\n modifier onlyController() {\\n require(controllers[msg.sender]);\\n _;\\n }\\n\\n /// @dev Gets the owner of the specified token ID. Names become unowned\\n /// when their registration expires.\\n /// @param tokenId uint256 ID of the token to query the owner of\\n /// @return address currently marked as the owner of the given token ID\\n function ownerOf(\\n uint256 tokenId\\n ) public view override(IERC721, ERC721) returns (address) {\\n require(expiries[tokenId] > block.timestamp);\\n return super.ownerOf(tokenId);\\n }\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external override onlyOwner {\\n controllers[controller] = true;\\n emit ControllerAdded(controller);\\n }\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external override onlyOwner {\\n controllers[controller] = false;\\n emit ControllerRemoved(controller);\\n }\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external override onlyOwner {\\n ens.setResolver(baseNode, resolver);\\n }\\n\\n // Returns the expiration timestamp of the specified id.\\n function nameExpires(uint256 id) external view override returns (uint256) {\\n return expiries[id];\\n }\\n\\n // Returns true iff the specified name is available for registration.\\n function available(uint256 id) public view override returns (bool) {\\n // Not available if it's registered here or in its grace period.\\n return expiries[id] + GRACE_PERIOD < block.timestamp;\\n }\\n\\n /// @dev Register a name.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external override returns (uint256) {\\n return _register(id, owner, duration, true);\\n }\\n\\n /// @dev Register a name, without modifying the registry.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function registerOnly(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256) {\\n return _register(id, owner, duration, false);\\n }\\n\\n function _register(\\n uint256 id,\\n address owner,\\n uint256 duration,\\n bool updateRegistry\\n ) internal live onlyController returns (uint256) {\\n require(available(id));\\n require(\\n block.timestamp + duration + GRACE_PERIOD >\\n block.timestamp + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] = block.timestamp + duration;\\n if (_exists(id)) {\\n // Name was previously owned, and expired\\n _burn(id);\\n }\\n _mint(owner, id);\\n if (updateRegistry) {\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n emit NameRegistered(id, owner, block.timestamp + duration);\\n\\n return block.timestamp + duration;\\n }\\n\\n function renew(\\n uint256 id,\\n uint256 duration\\n ) external override live onlyController returns (uint256) {\\n require(expiries[id] + GRACE_PERIOD >= block.timestamp); // Name must be registered here or in grace period\\n require(\\n expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] += duration;\\n emit NameRenewed(id, expiries[id]);\\n return expiries[id];\\n }\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external override live {\\n require(_isApprovedOrOwner(msg.sender, id));\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view override(ERC721, IERC165) returns (bool) {\\n return\\n interfaceID == INTERFACE_META_ID ||\\n interfaceID == ERC721_ID ||\\n interfaceID == RECLAIM_ID;\\n }\\n}\\n\",\"keccak256\":\"0xf7d55afacf1b9b2c54e2ac3603af9a8a1bcafcb9209d246a7854a28a884f1142\"},\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: address zero is not a valid owner\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _ownerOf(tokenId);\\n require(owner != address(0), \\\"ERC721: invalid token ID\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n _requireMinted(tokenId);\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not token owner or approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n _requireMinted(tokenId);\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n _safeTransfer(from, to, tokenId, data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\\n */\\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\\n return _owners[tokenId];\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _ownerOf(tokenId) != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId, 1);\\n\\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n unchecked {\\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\\n // Given that tokens are minted one by one, it is impossible in practice that\\n // this ever happens. Might change if we allow batch minting.\\n // The ERC fails to describe this case.\\n _balances[to] += 1;\\n }\\n\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n * This is an internal function that does not check if the sender is authorized to operate on the token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\\n\\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\\n owner = ERC721.ownerOf(tokenId);\\n\\n // Clear approvals\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // Cannot overflow, as that would require more tokens to be burned/transferred\\n // out than the owner initially received through minting and transferring in.\\n _balances[owner] -= 1;\\n }\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId, 1);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId, 1);\\n\\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n\\n // Clear approvals from the previous owner\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\\n // `from`'s balance is the number of token held, which is at least one before the current\\n // transfer.\\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\\n // all 2**256 token ids to be minted, which in practice is impossible.\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n }\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits an {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Reverts if the `tokenId` has not been minted yet.\\n */\\n function _requireMinted(uint256 tokenId) internal view virtual {\\n require(_exists(tokenId), \\\"ERC721: invalid token ID\\\");\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n /// @solidity memory-safe-assembly\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\\n * - When `from` is zero, the tokens will be minted for `to`.\\n * - When `to` is zero, ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\\n * - When `from` is zero, the tokens were minted for `to`.\\n * - When `to` is zero, ``from``'s tokens were burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Unsafe write access to the balances, used by extensions that \\\"mint\\\" tokens using an {ownerOf} override.\\n *\\n * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\\n * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\\n * that `ownerOf(tokenId)` is `a`.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __unsafe_increaseBalance(address account, uint256 amount) internal {\\n _balances[account] += amount;\\n }\\n}\\n\",\"keccak256\":\"0x2c309e7df9e05e6ce15bedfe74f3c61b467fc37e0fae9eab496acf5ea0bbd7ff\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\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://consensys.net/diligence/blog/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.8.0/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(address target, bytes memory data, uint256 value) 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\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.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 `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\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 /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(uint256 x, uint256 y, uint256 denominator) 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 // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\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(uint256 x, uint256 y, uint256 denominator, Rounding rounding) 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 256, 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 << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n /*\\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n * 0xb0202a11 ===\\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n */\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @param data Additional data with no specified format, sent in call to `spender`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\",\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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 /**\\n * @dev An operation with an ERC-20 token failed.\\n */\\n error SafeERC20FailedOperation(address token);\\n\\n /**\\n * @dev Indicates a failed `decreaseAllowance` request.\\n */\\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n forceApprove(token, spender, oldAllowance + value);\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n * value, non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n unchecked {\\n uint256 currentAllowance = token.allowance(address(this), spender);\\n if (currentAllowance < requestedDecrease) {\\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n }\\n forceApprove(token, spender, currentAllowance - requestedDecrease);\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n *\\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n * set here.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n safeTransfer(token, to, value);\\n } else if (!token.transferAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferFromAndCallRelaxed(\\n IERC1363 token,\\n address from,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length == 0) {\\n safeTransferFrom(token, from, to, value);\\n } else if (!token.transferFromAndCall(from, to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n * once without retrying, and relies on the returned value to be true.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n forceApprove(token, to, value);\\n } else if (!token.approveAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n // bubble errors\\n if iszero(success) {\\n let ptr := mload(0x40)\\n returndatacopy(ptr, 0, returndatasize())\\n revert(ptr, returndatasize())\\n }\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n\\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\n }\\n}\\n\",\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`.\\nabstract contract AbstractETHRegistrar is Ownable, HCAContext, ERC165, IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Minimum renew duration, in seconds.\\n uint64 public constant MIN_RENEW_DURATION = 1;\\n\\n /// @notice ENSv2 .eth `PermissionedRegistry`.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice Address that receives payments.\\n address public immutable BENEFICIARY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Oracle for registration and renewal costs.\\n IRentPriceOracle public rentPriceOracle;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `IRentPriceOracle` was replaced.\\n /// @param oracle The new `IRentPriceOracle` contract.\\n event RentPriceOracleUpdated(IRentPriceOracle oracle);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param hcaFactory HCA factory.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n constructor(\\n address owner_,\\n IHCAFactoryBasic hcaFactory,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle\\n )\\n Ownable(owner_)\\n HCAEquivalence(hcaFactory)\\n {\\n ETH_REGISTRY = ethRegistry;\\n BENEFICIARY = beneficiary;\\n\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Change the rent price oracle.\\n /// @param oracle The new `IRentPriceOracle` instance.\\n function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner {\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external\\n {\\n IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not\\n uint64 newExpiry = state.expiry + duration; // reverts if overflow\\n uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, amount); // reverts if payment failed\\n ETH_REGISTRY.renew(state.tokenId, newExpiry);\\n _onRenew(label, duration);\\n emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function isRenewable(string calldata label) external view returns (bool) {\\n return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n public\\n view\\n returns (uint256)\\n {\\n return\\n rentPriceOracle.getRenewPrice(\\n label,\\n _requireRenewable(label, duration).expiry,\\n duration,\\n paymentToken\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Callback for when a name is renewed.\\n function _onRenew(string calldata label, uint64 duration) internal virtual {}\\n\\n /// @dev Returns whether the name is renewable by this contract.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n virtual\\n returns (bool);\\n\\n /// @dev Ensure name is renewable.\\n function _requireRenewable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isRenewable(state)) {\\n revert NameNotRenewable(label);\\n }\\n if (duration < MIN_RENEW_DURATION) {\\n revert DurationTooShort(duration, MIN_RENEW_DURATION);\\n }\\n }\\n\\n /// @inheritdoc HCAContext\\n function _msgSender() internal view override(Context, HCAContext) returns (address) {\\n return super._msgSender();\\n }\\n}\\n\",\"keccak256\":\"0xb1cf6d7413558f8d257bdf8f734aaa57d4323e27854ae3ce79b7f017ff133510\",\"license\":\"MIT\"},\"project/src/registrar/ETHRenewerV1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n BaseRegistrarImplementation\\n} from \\\"@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol\\\";\\n\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {AbstractETHRegistrar} from \\\"./AbstractETHRegistrar.sol\\\";\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @notice `ETHRegistrarController.renew()` stub interface.\\n/// @dev Interface selector: `0xacf1a841`\\ninterface IWrappedETHRegistrarController {\\n /// @notice Renew an ENSv1 name.\\n /// @param label The name to renew.\\n /// @param duration The expiry extension, in seconds.\\n function renew(string calldata label, uint256 duration) external payable;\\n}\\n\\n\\n/// @notice .eth registrar that only renews premigrated ENSv2 reservations\\n/// and syncs with ENSv1.\\n///\\n/// Pricing and payment are delegated to a swappable `IRentPriceOracle`.\\n///\\n/// Provides a mechanism for syncing `NameWrapper` expiry.\\n///\\ncontract ETHRenewerV1 is AbstractETHRegistrar {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRenewer\\n uint64 public immutable GRACE_PERIOD;\\n\\n /// @dev ENSv2 `GRACE_PERIOD`.\\n uint64 internal immutable _GRACE_PERIOD_V2;\\n\\n /// @notice ENSv1 `BaseRegistrarImplementation` contract.\\n BaseRegistrarImplementation public immutable BASE_REGISTRAR;\\n\\n /// @notice ENSv1 `ETHRegistrarController` that is an active `NameWrapper` controller.\\n IWrappedETHRegistrarController public immutable WRAPPED_CONTROLLER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param hcaFactory HCA factory.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n /// @param gracePeriod Post-expiry period where renewable and not available, in seconds.\\n /// @param bonusPeriod Duration added by premigration, in seconds.\\n /// @param baseRegistrar ENSv1 `BaseRegistrarImplementation` contract.\\n /// @param wrappedController ENSv1 `ETHRegistrarController` that is a `NameWrapper` controller.\\n constructor(\\n address owner_,\\n IHCAFactoryBasic hcaFactory,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle,\\n uint64 gracePeriod,\\n uint64 bonusPeriod,\\n BaseRegistrarImplementation baseRegistrar,\\n address wrappedController\\n )\\n AbstractETHRegistrar(owner_, hcaFactory, ethRegistry, beneficiary, oracle)\\n {\\n GRACE_PERIOD = bonusPeriod + gracePeriod;\\n _GRACE_PERIOD_V2 = gracePeriod;\\n BASE_REGISTRAR = baseRegistrar;\\n WRAPPED_CONTROLLER = IWrappedETHRegistrarController(wrappedController);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Transfers ownership of the registrar.\\n /// @param newOwner The new owner for the registrar.\\n function transferRegistrarOwnership(address newOwner) external onlyOwner {\\n BASE_REGISTRAR.transferOwnership(newOwner);\\n }\\n\\n /// @notice Sync `NameWrapper` expiry with `BaseRegistrarImplementation` expiry.\\n /// @param labels The labels to sync.\\n function syncWrapper(string[] calldata labels) external {\\n BASE_REGISTRAR.addController(address(WRAPPED_CONTROLLER));\\n for (uint256 i; i < labels.length; ++i) {\\n WRAPPED_CONTROLLER.renew(labels[i], 0);\\n }\\n BASE_REGISTRAR.removeController(address(WRAPPED_CONTROLLER));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n uint64 bonusPeriod = GRACE_PERIOD - _GRACE_PERIOD_V2;\\n if (state.latestOwner == address(0) && state.expiry > bonusPeriod) {\\n uint64 expiryV1 = state.expiry - bonusPeriod;\\n uint64 t = uint64(block.timestamp);\\n if (t >= expiryV1 && t < expiryV1 + GRACE_PERIOD) {\\n return GRACE_PERIOD - (t - expiryV1);\\n }\\n }\\n return 0;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Update ENSv1 during renew.\\n function _onRenew(string calldata label, uint64 duration) internal override {\\n BASE_REGISTRAR.renew(LibLabel.id(label), duration);\\n }\\n\\n /// @dev Determine if `RESERVED` or in grace was `RESERVED`.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n override\\n returns (bool)\\n {\\n return\\n state.status == IPermissionedRegistry.Status.RESERVED ||\\n (state.status == IPermissionedRegistry.Status.AVAILABLE &&\\n state.latestOwner == address(0) &&\\n (block.timestamp - state.expiry) < _GRACE_PERIOD_V2);\\n }\\n}\\n\",\"keccak256\":\"0x8140ef069d6f805477273ad74be1f33d5b7a82f6ca42333fd3b591419baceec6\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for renewing \\\".eth\\\" names.\\n/// @dev Interface selector: `0x06aaeb32`\\ninterface IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A name was extended by `duration`.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the renewal.\\n /// @param duration The duration extension, in seconds.\\n /// @param newExpiry The new expiry, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param amount The amount of `paymentToken`.\\n event NameRenewed(\\n uint256 indexed tokenId,\\n string label,\\n uint64 duration,\\n uint64 newExpiry,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 amount\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `duration` less than `minDuration`.\\n /// @dev Error selector: `0xa096b844`\\n error DurationTooShort(uint64 duration, uint64 minDuration);\\n\\n /// @notice `label` cannot be renewed.\\n /// @dev Error selector: `0x1caefaa0`\\n error NameNotRenewable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Renew a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external;\\n\\n /// @notice Determine renew price for a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice Check if name is renewable.\\n /// @param label The name to check.\\n /// @return `true` if renewable.\\n function isRenewable(string calldata label) external view returns (bool);\\n\\n /// @notice Determine remaining grace period.\\n /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`.\\n /// @param label The name to check.\\n /// @return The remaining grace period, in seconds.\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64);\\n\\n /// @notice Post-expiry period where still renewable and not available, in seconds.\\n function GRACE_PERIOD() external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 34237, + "contract": "project/src/registrar/ETHRenewerV1.sol:ETHRenewerV1", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 63504, + "contract": "project/src/registrar/ETHRenewerV1.sol:ETHRenewerV1", + "label": "rentPriceOracle", + "offset": 0, + "slot": "1", + "type": "t_contract(IRentPriceOracle)66102" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_contract(IRentPriceOracle)66102": { + "encoding": "inplace", + "label": "contract IRentPriceOracle", + "numberOfBytes": "20" + } + } + }, + "userdoc": { + "errors": { + "DurationTooShort(uint64,uint64)": [ + { + "notice": "`duration` less than `minDuration`." + } + ], + "NameNotRenewable(string)": [ + { + "notice": "`label` cannot be renewed." + } + ] + }, + "events": { + "NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)": { + "notice": "A name was extended by `duration`." + }, + "RentPriceOracleUpdated(address)": { + "notice": "`IRentPriceOracle` was replaced." + } + }, + "kind": "user", + "methods": { + "BASE_REGISTRAR()": { + "notice": "ENSv1 `BaseRegistrarImplementation` contract." + }, + "BENEFICIARY()": { + "notice": "Address that receives payments." + }, + "ETH_REGISTRY()": { + "notice": "ENSv2 .eth `PermissionedRegistry`." + }, + "GRACE_PERIOD()": { + "notice": "Post-expiry period where still renewable and not available, in seconds." + }, + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "MIN_RENEW_DURATION()": { + "notice": "Minimum renew duration, in seconds." + }, + "WRAPPED_CONTROLLER()": { + "notice": "ENSv1 `ETHRegistrarController` that is an active `NameWrapper` controller." + }, + "getRemainingGracePeriod(string)": { + "notice": "Determine remaining grace period." + }, + "getRenewPrice(string,uint64,address)": { + "notice": "Determine renew price for a name." + }, + "isRenewable(string)": { + "notice": "Check if name is renewable." + }, + "renew(string,uint64,address,bytes32)": { + "notice": "Renew a name." + }, + "rentPriceOracle()": { + "notice": "Oracle for registration and renewal costs." + }, + "setRentPriceOracle(address)": { + "notice": "Change the rent price oracle." + }, + "syncWrapper(string[])": { + "notice": "Sync `NameWrapper` expiry with `BaseRegistrarImplementation` expiry." + }, + "transferRegistrarOwnership(address)": { + "notice": "Transfers ownership of the registrar." + } + }, + "notice": ".eth registrar that only renews premigrated ENSv2 reservations and syncs with ENSv1. Pricing and payment are delegated to a swappable `IRentPriceOracle`. Provides a mechanism for syncing `NameWrapper` expiry.", + "version": 1 + }, + "argsData": "0x000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf943000000000000000000000000dedb92913a25abe1f7bcdd85d8a344a43b398b67000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80000000000000000000000000e19d37839f42f7d2694d8c5712f412c66a218161000000000000000000000000000000000000000000000000000000000024ea00000000000000000000000000000000000000000000000000000000000051bd0100000000000000000000000057f1887a8bf19b14fc0df6fd9b2acc9af147ea85000000000000000000000000fed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", + "transaction": { + "hash": "0x8bb5982c90a84bb0f66c5d1de39cd42453345111ff01cbaad0313dae035076f7", + "nonce": "0x2169", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x55c357db75611a52d61722a4a087836c994931d8896ceb47da39e0984a07c803", + "blockNumber": "0xa6d528", + "transactionIndex": "0xc9" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/Graveyard.json b/contracts/deployments/sepolia-official-v1-20260525-r2/Graveyard.json new file mode 100644 index 000000000..c7e22ad64 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/Graveyard.json @@ -0,0 +1,411 @@ +{ + "address": "0x802453f2f077d5a0c3d0f9a6eb2a36dcfa3c6e0d", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [], + "name": "NameNotClearable", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "names", + "type": "bytes[]" + } + ], + "name": "clear", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "Graveyard", + "sourceName": "src/migration/Graveyard.sol", + "bytecode": "0x610120604052348015610010575f5ffd5b5060405161151338038061151383398101604081905261002f916101a8565b6001600160a01b03808216608052821660a081905260408051633f15457f60e01b81529051633f15457f916004808201926020929091908290030181865afa15801561007d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a191906101e0565b6001600160a01b031660c0816001600160a01b031681525050816001600160a01b0316632b20e3976040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061011a91906101e0565b6001600160a01b031660e0819052604080516360d143f160e11b8152905163c1a287e2916004808201926020929091908290030181865afa158015610161573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101859190610202565b61010052506102199050565b6001600160a01b03811681146101a5575f5ffd5b50565b5f5f604083850312156101b9575f5ffd5b82516101c481610191565b60208401519092506101d581610191565b809150509250929050565b5f602082840312156101f0575f5ffd5b81516101fb81610191565b9392505050565b5f60208284031215610212575f5ffd5b5051919050565b60805160a05160c05160e0516101005161128561028e5f395f61068101525f61065801525f81816104eb0152818161076a0152818161081601526108e901525f8181610106015281816105950152818161097001528181610a2e0152610b1201525f8181610145015261024a01526112855ff3fe608060405234801561000f575f5ffd5b5060043610610085575f3560e01c80636f3ff726116100585780636f3ff72614610167578063bc197c811461017a578063d62f4d37146101b2578063f23a6e61146101c7575f5ffd5b806301ffc9a714610089578063150b7a02146100b1578063192cf07d1461010157806348ee1bcc14610140575b5f5ffd5b61009c610097366004610c68565b6101ff565b60405190151581526020015b60405180910390f35b6100e86100bf366004610d5e565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040516001600160e01b031990911681526020016100a8565b6101287f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a8565b6101287f000000000000000000000000000000000000000000000000000000000000000081565b61009c610175366004610dc6565b610229565b6100e8610188366004610e61565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b6101c56101c0366004610f14565b6102b5565b005b6100e86101d5366004610f85565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b5f6001600160e01b0319821663379ffb9360e11b14806102235750610223826102fb565b92915050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610291573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610fdd565b5f5b818110156102f6576102ec8383838181106102d4576102d4610ffc565b90506020028101906102e69190611010565b5f61031f565b50506001016102b7565b505050565b5f6001600160e01b0319821663379ffb9360e11b1480610223575061022382610b51565b5f8080808561032f866001611067565b108015610355575086868681811061034957610349610ffc565b919091013560f81c1590505b156103bd57610365856021611067565b905085811061039457868660405163ba4adc2360e01b815260040161038b9291906110a2565b60405180910390fd5b86866103a1876001611067565b6103ad928492906110bd565b6103b6916110e4565b9150610415565b6103fd87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250899250610bb7915050565b90925090508161041557505f9250829150610b499050565b5f5f61042289898561031f565b9150915061043982855f9182526020526040902090565b95505f81600381111561044e5761044e611101565b036104a1577f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae86146104935760405163acae6b3b60e01b815260040160405180910390fd5b5060019350610b4992505050565b60018160038111156104b5576104b5611101565b03610887576040517f02571be3000000000000000000000000000000000000000000000000000000008152600481018790525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610538573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061055c9190611115565b9050306001600160a01b0382160361057d575060029450610b499350505050565b604051630178fe3f60e01b8152600481018890525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156105e2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106069190611130565b509092509050600181161561064e576001600160a01b038216301461063e5760405163acae6b3b60e01b815260040160405180910390fd5b5060039550610b49945050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663fca247ac87307f00000000000000000000000000000000000000000000000000000000000000006106b24267ffffffffffffffff61118e565b6106bc919061118e565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b03909116602483015260448201526064016020604051808303815f875af115801561070c573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073091906111a1565b506040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018990525f906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630178b8bf90602401602060405180830381865afa1580156107af573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d39190611115565b6001600160a01b031614610877576040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018990525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015b5f604051808303815f87803b158015610860575f5ffd5b505af1158015610872573d5f5f3e3d5ffd5b505050505b5060029550610b49945050505050565b600281600381111561089b5761089b611101565b03610956576040517f5ef2c7f000000000000000000000000000000000000000000000000000000000815260048101839052602481018590523060448201525f6064820181905260848201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635ef2c7f09060a4015f604051808303815f87803b158015610932575f5ffd5b505af1158015610944573d5f5f3e3d5ffd5b5060029750610b499650505050505050565b604051630178fe3f60e01b8152600481018790525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156109bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e19190611130565b509092509050306001600160a01b03831603610a15576001811615610a10575060039550610b49945050505050565b610877565b6001600160a01b03821615610877576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166324c1af44858d8d610a618e6001611067565b610a6d928b92906110bd565b305f5f5f5f6040518963ffffffff1660e01b8152600401610a959897969594939291906111b8565b6020604051808303815f875af1158015610ab1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad591906111a1565b506040517fd8c9921a00000000000000000000000000000000000000000000000000000000815260048101859052602481018790523060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d8c9921a90606401610849565b935093915050565b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061022357507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610223565b5f5f5f610bc48585610be4565b9250905060ff811615610bdc57806021858701012092505b509250929050565b5f5f83518310610c09578360405163ba4adc2360e01b815260040161038b919061121a565b838381518110610c1b57610c1b610ffc565b016020015160f81c91505081810160010181610c3b578351811415610c41565b83518110155b15610c61578360405163ba4adc2360e01b815260040161038b919061121a565b9250929050565b5f60208284031215610c78575f5ffd5b81356001600160e01b031981168114610c8f575f5ffd5b9392505050565b6001600160a01b0381168114610caa575f5ffd5b50565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610cea57610cea610cad565b604052919050565b5f82601f830112610d01575f5ffd5b813567ffffffffffffffff811115610d1b57610d1b610cad565b610d2e601f8201601f1916602001610cc1565b818152846020838601011115610d42575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215610d71575f5ffd5b8435610d7c81610c96565b93506020850135610d8c81610c96565b925060408501359150606085013567ffffffffffffffff811115610dae575f5ffd5b610dba87828801610cf2565b91505092959194509250565b5f60208284031215610dd6575f5ffd5b8135610c8f81610c96565b5f82601f830112610df0575f5ffd5b813567ffffffffffffffff811115610e0a57610e0a610cad565b8060051b610e1a60208201610cc1565b91825260208185018101929081019086841115610e35575f5ffd5b6020860192505b83831015610e57578235825260209283019290910190610e3c565b9695505050505050565b5f5f5f5f5f60a08688031215610e75575f5ffd5b8535610e8081610c96565b94506020860135610e9081610c96565b9350604086013567ffffffffffffffff811115610eab575f5ffd5b610eb788828901610de1565b935050606086013567ffffffffffffffff811115610ed3575f5ffd5b610edf88828901610de1565b925050608086013567ffffffffffffffff811115610efb575f5ffd5b610f0788828901610cf2565b9150509295509295909350565b5f5f60208385031215610f25575f5ffd5b823567ffffffffffffffff811115610f3b575f5ffd5b8301601f81018513610f4b575f5ffd5b803567ffffffffffffffff811115610f61575f5ffd5b8560208260051b8401011115610f75575f5ffd5b6020919091019590945092505050565b5f5f5f5f5f60a08688031215610f99575f5ffd5b8535610fa481610c96565b94506020860135610fb481610c96565b93506040860135925060608601359150608086013567ffffffffffffffff811115610efb575f5ffd5b5f60208284031215610fed575f5ffd5b81518015158114610c8f575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e19843603018112611025575f5ffd5b83018035915067ffffffffffffffff82111561103f575f5ffd5b602001915036819003821315610c61575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561022357610223611053565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f6110b560208301848661107a565b949350505050565b5f5f858511156110cb575f5ffd5b838611156110d7575f5ffd5b5050820193919092039150565b80356020831015610223575f19602084900360031b1b1692915050565b634e487b7160e01b5f52602160045260245ffd5b5f60208284031215611125575f5ffd5b8151610c8f81610c96565b5f5f5f60608486031215611142575f5ffd5b835161114d81610c96565b602085015190935063ffffffff81168114611166575f5ffd5b604085015190925067ffffffffffffffff81168114611183575f5ffd5b809150509250925092565b8181038181111561022357610223611053565b5f602082840312156111b1575f5ffd5b5051919050565b88815260e060208201525f6111d160e08301898b61107a565b6001600160a01b03978816604084015295909616606082015267ffffffffffffffff938416608082015263ffffffff9290921660a083015290911660c090910152949350505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fea264697066735822122082fbca3300199672dd64e36b4a8aa76a0762784ed6809bc18bc686151430e58e64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610085575f3560e01c80636f3ff726116100585780636f3ff72614610167578063bc197c811461017a578063d62f4d37146101b2578063f23a6e61146101c7575f5ffd5b806301ffc9a714610089578063150b7a02146100b1578063192cf07d1461010157806348ee1bcc14610140575b5f5ffd5b61009c610097366004610c68565b6101ff565b60405190151581526020015b60405180910390f35b6100e86100bf366004610d5e565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040516001600160e01b031990911681526020016100a8565b6101287f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a8565b6101287f000000000000000000000000000000000000000000000000000000000000000081565b61009c610175366004610dc6565b610229565b6100e8610188366004610e61565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b6101c56101c0366004610f14565b6102b5565b005b6100e86101d5366004610f85565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b5f6001600160e01b0319821663379ffb9360e11b14806102235750610223826102fb565b92915050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610291573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610fdd565b5f5b818110156102f6576102ec8383838181106102d4576102d4610ffc565b90506020028101906102e69190611010565b5f61031f565b50506001016102b7565b505050565b5f6001600160e01b0319821663379ffb9360e11b1480610223575061022382610b51565b5f8080808561032f866001611067565b108015610355575086868681811061034957610349610ffc565b919091013560f81c1590505b156103bd57610365856021611067565b905085811061039457868660405163ba4adc2360e01b815260040161038b9291906110a2565b60405180910390fd5b86866103a1876001611067565b6103ad928492906110bd565b6103b6916110e4565b9150610415565b6103fd87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250899250610bb7915050565b90925090508161041557505f9250829150610b499050565b5f5f61042289898561031f565b9150915061043982855f9182526020526040902090565b95505f81600381111561044e5761044e611101565b036104a1577f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae86146104935760405163acae6b3b60e01b815260040160405180910390fd5b5060019350610b4992505050565b60018160038111156104b5576104b5611101565b03610887576040517f02571be3000000000000000000000000000000000000000000000000000000008152600481018790525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa158015610538573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061055c9190611115565b9050306001600160a01b0382160361057d575060029450610b499350505050565b604051630178fe3f60e01b8152600481018890525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156105e2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106069190611130565b509092509050600181161561064e576001600160a01b038216301461063e5760405163acae6b3b60e01b815260040160405180910390fd5b5060039550610b49945050505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663fca247ac87307f00000000000000000000000000000000000000000000000000000000000000006106b24267ffffffffffffffff61118e565b6106bc919061118e565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b03909116602483015260448201526064016020604051808303815f875af115801561070c573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073091906111a1565b506040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018990525f906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630178b8bf90602401602060405180830381865afa1580156107af573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d39190611115565b6001600160a01b031614610877576040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018990525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015b5f604051808303815f87803b158015610860575f5ffd5b505af1158015610872573d5f5f3e3d5ffd5b505050505b5060029550610b49945050505050565b600281600381111561089b5761089b611101565b03610956576040517f5ef2c7f000000000000000000000000000000000000000000000000000000000815260048101839052602481018590523060448201525f6064820181905260848201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635ef2c7f09060a4015f604051808303815f87803b158015610932575f5ffd5b505af1158015610944573d5f5f3e3d5ffd5b5060029750610b499650505050505050565b604051630178fe3f60e01b8152600481018790525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156109bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e19190611130565b509092509050306001600160a01b03831603610a15576001811615610a10575060039550610b49945050505050565b610877565b6001600160a01b03821615610877576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166324c1af44858d8d610a618e6001611067565b610a6d928b92906110bd565b305f5f5f5f6040518963ffffffff1660e01b8152600401610a959897969594939291906111b8565b6020604051808303815f875af1158015610ab1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad591906111a1565b506040517fd8c9921a00000000000000000000000000000000000000000000000000000000815260048101859052602481018790523060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d8c9921a90606401610849565b935093915050565b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061022357507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610223565b5f5f5f610bc48585610be4565b9250905060ff811615610bdc57806021858701012092505b509250929050565b5f5f83518310610c09578360405163ba4adc2360e01b815260040161038b919061121a565b838381518110610c1b57610c1b610ffc565b016020015160f81c91505081810160010181610c3b578351811415610c41565b83518110155b15610c61578360405163ba4adc2360e01b815260040161038b919061121a565b9250929050565b5f60208284031215610c78575f5ffd5b81356001600160e01b031981168114610c8f575f5ffd5b9392505050565b6001600160a01b0381168114610caa575f5ffd5b50565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610cea57610cea610cad565b604052919050565b5f82601f830112610d01575f5ffd5b813567ffffffffffffffff811115610d1b57610d1b610cad565b610d2e601f8201601f1916602001610cc1565b818152846020838601011115610d42575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f60808587031215610d71575f5ffd5b8435610d7c81610c96565b93506020850135610d8c81610c96565b925060408501359150606085013567ffffffffffffffff811115610dae575f5ffd5b610dba87828801610cf2565b91505092959194509250565b5f60208284031215610dd6575f5ffd5b8135610c8f81610c96565b5f82601f830112610df0575f5ffd5b813567ffffffffffffffff811115610e0a57610e0a610cad565b8060051b610e1a60208201610cc1565b91825260208185018101929081019086841115610e35575f5ffd5b6020860192505b83831015610e57578235825260209283019290910190610e3c565b9695505050505050565b5f5f5f5f5f60a08688031215610e75575f5ffd5b8535610e8081610c96565b94506020860135610e9081610c96565b9350604086013567ffffffffffffffff811115610eab575f5ffd5b610eb788828901610de1565b935050606086013567ffffffffffffffff811115610ed3575f5ffd5b610edf88828901610de1565b925050608086013567ffffffffffffffff811115610efb575f5ffd5b610f0788828901610cf2565b9150509295509295909350565b5f5f60208385031215610f25575f5ffd5b823567ffffffffffffffff811115610f3b575f5ffd5b8301601f81018513610f4b575f5ffd5b803567ffffffffffffffff811115610f61575f5ffd5b8560208260051b8401011115610f75575f5ffd5b6020919091019590945092505050565b5f5f5f5f5f60a08688031215610f99575f5ffd5b8535610fa481610c96565b94506020860135610fb481610c96565b93506040860135925060608601359150608086013567ffffffffffffffff811115610efb575f5ffd5b5f60208284031215610fed575f5ffd5b81518015158114610c8f575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f5f8335601e19843603018112611025575f5ffd5b83018035915067ffffffffffffffff82111561103f575f5ffd5b602001915036819003821315610c61575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561022357610223611053565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f6110b560208301848661107a565b949350505050565b5f5f858511156110cb575f5ffd5b838611156110d7575f5ffd5b5050820193919092039150565b80356020831015610223575f19602084900360031b1b1692915050565b634e487b7160e01b5f52602160045260245ffd5b5f60208284031215611125575f5ffd5b8151610c8f81610c96565b5f5f5f60608486031215611142575f5ffd5b835161114d81610c96565b602085015190935063ffffffff81168114611166575f5ffd5b604085015190925067ffffffffffffffff81168114611183575f5ffd5b809150509250925092565b8181038181111561022357610223611053565b5f602082840312156111b1575f5ffd5b5051919050565b88815260e060208201525f6111d160e08301898b61107a565b6001600160a01b03978816604084015295909616606082015267ffffffffffffffff938416608082015263ffffffff9290921660a083015290911660c090910152949350505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fea264697066735822122082fbca3300199672dd64e36b4a8aa76a0762784ed6809bc18bc686151430e58e64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "61303": [ + { + "length": 32, + "start": 262 + }, + { + "length": 32, + "start": 1429 + }, + { + "length": 32, + "start": 2416 + }, + { + "length": 32, + "start": 2606 + }, + { + "length": 32, + "start": 2834 + } + ], + "61307": [ + { + "length": 32, + "start": 1259 + }, + { + "length": 32, + "start": 1898 + }, + { + "length": 32, + "start": 2070 + }, + { + "length": 32, + "start": 2281 + } + ], + "61311": [ + { + "length": 32, + "start": 1624 + } + ], + "61314": [ + { + "length": 32, + "start": 1665 + } + ], + "75212": [ + { + "length": 32, + "start": 325 + }, + { + "length": 32, + "start": 586 + } + ] + }, + "inputSourceName": "project/src/migration/Graveyard.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "NameNotClearable()": [ + { + "details": "Error selector: `0xacae6b3b`" + } + ] + }, + "kind": "dev", + "methods": { + "clear(bytes[])": { + "params": { + "names": "The array of names to clear." + } + }, + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "nameWrapper": "The ENSv1 `NameWrapper` contract." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "onERC721Received(address,address,uint256,bytes)": { + "details": "See {IERC721Receiver-onERC721Received}. Always returns `IERC721Receiver.onERC721Received.selector`." + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + } + }, + "stateVariables": { + "_BASE_REGISTRAR": { + "details": "The ENSv1 `BaseRegistrar` contract." + }, + "_GRACE_PERIOD": { + "details": "Same as `BaseRegistrarImplementation.GRACE_PERIOD()`." + }, + "_REGISTRY_V1": { + "details": "The ENSv1 `ENSRegistry` contract." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "948200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "NAME_WRAPPER()": "infinite", + "clear(bytes[])": "infinite", + "isContractNamer(address)": "infinite", + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": "infinite", + "onERC1155Received(address,address,uint256,uint256,bytes)": "infinite", + "onERC721Received(address,address,uint256,bytes)": "infinite", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_clear(bytes calldata,uint256)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NameNotClearable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"names\",\"type\":\"bytes[]\"}],\"name\":\"clear\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"NameNotClearable()\":[{\"details\":\"Error selector: `0xacae6b3b`\"}]},\"kind\":\"dev\",\"methods\":{\"clear(bytes[])\":{\"params\":{\"names\":\"The array of names to clear.\"}},\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"nameWrapper\":\"The ENSv1 `NameWrapper` contract.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}. Always returns `IERC721Receiver.onERC721Received.selector`.\"},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"stateVariables\":{\"_BASE_REGISTRAR\":{\"details\":\"The ENSv1 `BaseRegistrar` contract.\"},\"_GRACE_PERIOD\":{\"details\":\"Same as `BaseRegistrarImplementation.GRACE_PERIOD()`.\"},\"_REGISTRY_V1\":{\"details\":\"The ENSv1 `ENSRegistry` contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract.\"},\"clear(bytes[])\":{\"notice\":\"Clear registry for migrated names.\"},\"constructor\":{\"notice\":\"Create a graveyard.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"}},\"notice\":\"The ENSv1 ETHRegistrarController for ENSv2 launch which becomes the burn address for migrated tokens. 1. Claim any expired ENSv1 name and assign ownership to this contract. 2. Clear the registry for any owned token.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/migration/Graveyard.sol\":\"Graveyard\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/BaseRegistrarImplementation.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"./IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract BaseRegistrarImplementation is ERC721, IBaseRegistrar, Ownable {\\n // A map of expiry times\\n mapping(uint256 => uint256) expiries;\\n // The ENS registry\\n ENS public ens;\\n // The namehash of the TLD this registrar owns (eg, .eth)\\n bytes32 public baseNode;\\n // A map of addresses that are authorised to register and renew names.\\n mapping(address => bool) public controllers;\\n uint256 public constant GRACE_PERIOD = 90 days;\\n bytes4 private constant INTERFACE_META_ID =\\n bytes4(keccak256(\\\"supportsInterface(bytes4)\\\"));\\n bytes4 private constant ERC721_ID =\\n bytes4(\\n keccak256(\\\"balanceOf(address)\\\") ^\\n keccak256(\\\"ownerOf(uint256)\\\") ^\\n keccak256(\\\"approve(address,uint256)\\\") ^\\n keccak256(\\\"getApproved(uint256)\\\") ^\\n keccak256(\\\"setApprovalForAll(address,bool)\\\") ^\\n keccak256(\\\"isApprovedForAll(address,address)\\\") ^\\n keccak256(\\\"transferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256,bytes)\\\")\\n );\\n bytes4 private constant RECLAIM_ID =\\n bytes4(keccak256(\\\"reclaim(uint256,address)\\\"));\\n\\n /// v2.1.3 version of _isApprovedOrOwner which calls ownerOf(tokenId) and takes grace period into consideration instead of ERC721.ownerOf(tokenId);\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.1.3/contracts/token/ERC721/ERC721.sol#L187\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param spender address of the spender to query\\n /// @param tokenId uint256 ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID,\\n /// is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(\\n address spender,\\n uint256 tokenId\\n ) internal view override returns (bool) {\\n address owner = ownerOf(tokenId);\\n return (spender == owner ||\\n getApproved(tokenId) == spender ||\\n isApprovedForAll(owner, spender));\\n }\\n\\n constructor(ENS _ens, bytes32 _baseNode) ERC721(\\\"\\\", \\\"\\\") {\\n ens = _ens;\\n baseNode = _baseNode;\\n }\\n\\n modifier live() {\\n require(ens.owner(baseNode) == address(this));\\n _;\\n }\\n\\n modifier onlyController() {\\n require(controllers[msg.sender]);\\n _;\\n }\\n\\n /// @dev Gets the owner of the specified token ID. Names become unowned\\n /// when their registration expires.\\n /// @param tokenId uint256 ID of the token to query the owner of\\n /// @return address currently marked as the owner of the given token ID\\n function ownerOf(\\n uint256 tokenId\\n ) public view override(IERC721, ERC721) returns (address) {\\n require(expiries[tokenId] > block.timestamp);\\n return super.ownerOf(tokenId);\\n }\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external override onlyOwner {\\n controllers[controller] = true;\\n emit ControllerAdded(controller);\\n }\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external override onlyOwner {\\n controllers[controller] = false;\\n emit ControllerRemoved(controller);\\n }\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external override onlyOwner {\\n ens.setResolver(baseNode, resolver);\\n }\\n\\n // Returns the expiration timestamp of the specified id.\\n function nameExpires(uint256 id) external view override returns (uint256) {\\n return expiries[id];\\n }\\n\\n // Returns true iff the specified name is available for registration.\\n function available(uint256 id) public view override returns (bool) {\\n // Not available if it's registered here or in its grace period.\\n return expiries[id] + GRACE_PERIOD < block.timestamp;\\n }\\n\\n /// @dev Register a name.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external override returns (uint256) {\\n return _register(id, owner, duration, true);\\n }\\n\\n /// @dev Register a name, without modifying the registry.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function registerOnly(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256) {\\n return _register(id, owner, duration, false);\\n }\\n\\n function _register(\\n uint256 id,\\n address owner,\\n uint256 duration,\\n bool updateRegistry\\n ) internal live onlyController returns (uint256) {\\n require(available(id));\\n require(\\n block.timestamp + duration + GRACE_PERIOD >\\n block.timestamp + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] = block.timestamp + duration;\\n if (_exists(id)) {\\n // Name was previously owned, and expired\\n _burn(id);\\n }\\n _mint(owner, id);\\n if (updateRegistry) {\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n emit NameRegistered(id, owner, block.timestamp + duration);\\n\\n return block.timestamp + duration;\\n }\\n\\n function renew(\\n uint256 id,\\n uint256 duration\\n ) external override live onlyController returns (uint256) {\\n require(expiries[id] + GRACE_PERIOD >= block.timestamp); // Name must be registered here or in grace period\\n require(\\n expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] += duration;\\n emit NameRenewed(id, expiries[id]);\\n return expiries[id];\\n }\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external override live {\\n require(_isApprovedOrOwner(msg.sender, id));\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view override(ERC721, IERC165) returns (bool) {\\n return\\n interfaceID == INTERFACE_META_ID ||\\n interfaceID == ERC721_ID ||\\n interfaceID == RECLAIM_ID;\\n }\\n}\\n\",\"keccak256\":\"0xf7d55afacf1b9b2c54e2ac3603af9a8a1bcafcb9209d246a7854a28a884f1142\"},\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: address zero is not a valid owner\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _ownerOf(tokenId);\\n require(owner != address(0), \\\"ERC721: invalid token ID\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n _requireMinted(tokenId);\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not token owner or approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n _requireMinted(tokenId);\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n _safeTransfer(from, to, tokenId, data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\\n */\\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\\n return _owners[tokenId];\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _ownerOf(tokenId) != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId, 1);\\n\\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n unchecked {\\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\\n // Given that tokens are minted one by one, it is impossible in practice that\\n // this ever happens. Might change if we allow batch minting.\\n // The ERC fails to describe this case.\\n _balances[to] += 1;\\n }\\n\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n * This is an internal function that does not check if the sender is authorized to operate on the token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\\n\\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\\n owner = ERC721.ownerOf(tokenId);\\n\\n // Clear approvals\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // Cannot overflow, as that would require more tokens to be burned/transferred\\n // out than the owner initially received through minting and transferring in.\\n _balances[owner] -= 1;\\n }\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId, 1);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId, 1);\\n\\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n\\n // Clear approvals from the previous owner\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\\n // `from`'s balance is the number of token held, which is at least one before the current\\n // transfer.\\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\\n // all 2**256 token ids to be minted, which in practice is impossible.\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n }\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits an {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Reverts if the `tokenId` has not been minted yet.\\n */\\n function _requireMinted(uint256 tokenId) internal view virtual {\\n require(_exists(tokenId), \\\"ERC721: invalid token ID\\\");\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n /// @solidity memory-safe-assembly\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\\n * - When `from` is zero, the tokens will be minted for `to`.\\n * - When `to` is zero, ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\\n * - When `from` is zero, the tokens were minted for `to`.\\n * - When `to` is zero, ``from``'s tokens were burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Unsafe write access to the balances, used by extensions that \\\"mint\\\" tokens using an {ownerOf} override.\\n *\\n * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\\n * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\\n * that `ownerOf(tokenId)` is `a`.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __unsafe_increaseBalance(address account, uint256 amount) internal {\\n _balances[account] += amount;\\n }\\n}\\n\",\"keccak256\":\"0x2c309e7df9e05e6ce15bedfe74f3c61b467fc37e0fae9eab496acf5ea0bbd7ff\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\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://consensys.net/diligence/blog/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.8.0/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(address target, bytes memory data, uint256 value) 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\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.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 `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\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 /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(uint256 x, uint256 y, uint256 denominator) 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 // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\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(uint256 x, uint256 y, uint256 denominator, Rounding rounding) 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 256, 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 << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Holder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165, ERC165} from \\\"../../../utils/introspection/ERC165.sol\\\";\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\n\\n/**\\n * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.\\n *\\n * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be\\n * stuck.\\n */\\nabstract contract ERC1155Holder is ERC165, IERC1155Receiver {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xe103e95f854ef0cd1bba5f469175f67cd332f5c2561941f165e3dd65cee94d6d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @title ERC-721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC-721 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\\n * 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\":\"0xb5afb8e8eebc4d1c6404df2f5e1e6d2c3d24fd01e5dfc855314951ecfaae462d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC721Receiver} from \\\"../IERC721Receiver.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC721Receiver} interface.\\n *\\n * Accepts all token transfers.\\n * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or\\n * {IERC721-setApprovalForAll}.\\n */\\nabstract contract ERC721Holder is IERC721Receiver {\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n *\\n * Always returns `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n}\\n\",\"keccak256\":\"0xaad20f8713b5cd98114278482d5d91b9758f9727048527d582e8e88fd4901fd8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/migration/Graveyard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n BaseRegistrarImplementation\\n} from \\\"@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol\\\";\\nimport {IBaseRegistrar} from \\\"@ens/contracts/ethregistrar/IBaseRegistrar.sol\\\";\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {ERC1155Holder} from \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol\\\";\\nimport {ERC721Holder} from \\\"@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @notice The ENSv1 ETHRegistrarController for ENSv2 launch which becomes the burn address for migrated tokens.\\n///\\n/// 1. Claim any expired ENSv1 name and assign ownership to this contract.\\n/// 2. Clear the registry for any owned token.\\n///\\ncontract Graveyard is ERC721Holder, ERC1155Holder, DelegatedContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The internal states of registry ownership.\\n enum State {\\n ROOT,\\n ETH,\\n OWNED,\\n LOCKED\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @dev The ENSv1 `ENSRegistry` contract.\\n ENS internal immutable _REGISTRY_V1;\\n\\n /// @dev The ENSv1 `BaseRegistrar` contract.\\n IBaseRegistrar internal immutable _BASE_REGISTRAR;\\n\\n /// @dev Same as `BaseRegistrarImplementation.GRACE_PERIOD()`.\\n uint256 internal immutable _GRACE_PERIOD;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0xacae6b3b`\\n error NameNotClearable();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Create a graveyard.\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param contractNamer Delegated contract namer.\\n constructor(INameWrapper nameWrapper, IContractNamer contractNamer)\\n DelegatedContractNamer(contractNamer)\\n {\\n NAME_WRAPPER = nameWrapper;\\n _REGISTRY_V1 = nameWrapper.ens();\\n _BASE_REGISTRAR = nameWrapper.registrar();\\n _GRACE_PERIOD = BaseRegistrarImplementation(address(_BASE_REGISTRAR)).GRACE_PERIOD();\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n override(ERC1155Holder, DelegatedContractNamer)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Clear registry for migrated names.\\n /// @param names The array of names to clear.\\n function clear(bytes[] calldata names) external {\\n for (uint256 i; i < names.length; ++i) {\\n _clear(names[i], 0);\\n }\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Recursively clear ancestor namespace.\\n ///\\n /// Wrapped labels are 1-255 bytes and always have a preimage.\\n /// see: V1Fixture.t.sol: `test_nameWrapper_labelTooShort` and `test_nameWrapper_labelTooLong`\\n /// see: https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/NameWrapper.sol#L865-L876\\n ///\\n /// This function supports a modified DNS-encoding where zero-length labels\\n /// in the middle of name must be followed with exactly 32 bytes of labelhash.\\n ///\\n /// This is safe because zero-length non-terminating labels normally revert.\\n ///\\n function _clear(bytes calldata name, uint256 offset) internal returns (bytes32 node, State) {\\n bytes32 labelHash;\\n uint256 nextOffset;\\n // modified DNS-encoding: interpret zero-length labels differently\\n if (offset + 1 < name.length && uint8(name[offset]) == 0) {\\n nextOffset = offset + 33; // skip length and ensure next 32 bytes exist\\n if (nextOffset >= name.length) {\\n revert NameCoder.DNSDecodingFailed(name);\\n }\\n labelHash = bytes32(name[offset + 1:nextOffset]); // cast as literal bytes32\\n } else {\\n (labelHash, nextOffset) = NameCoder.readLabel(name, offset); // use standard logic\\n if (labelHash == bytes32(0)) {\\n return (bytes32(0), State.ROOT);\\n }\\n }\\n (bytes32 parentNode, State parentState) = _clear(name, nextOffset);\\n node = NameCoder.namehash(parentNode, labelHash);\\n if (parentState == State.ROOT) {\\n if (node != NameCoder.ETH_NODE) {\\n revert NameNotClearable();\\n }\\n return (node, State.ETH);\\n } else if (parentState == State.ETH) {\\n address owner = _REGISTRY_V1.owner(node);\\n if (owner == address(this)) {\\n // resolver is cleared by migration\\n return (node, State.OWNED);\\n }\\n uint32 fuses;\\n (owner, fuses, ) = NAME_WRAPPER.getData(uint256(node));\\n if (LibMigration.isLocked(fuses)) {\\n if (owner != address(this)) {\\n revert NameNotClearable();\\n }\\n // resolver is cleared by migration\\n return (node, State.LOCKED);\\n }\\n _BASE_REGISTRAR.register(\\n uint256(labelHash),\\n address(this),\\n type(uint64).max - block.timestamp - _GRACE_PERIOD // max duration?\\n );\\n // lock expired? so clear it\\n if (_REGISTRY_V1.resolver(node) != address(0)) {\\n _REGISTRY_V1.setResolver(node, address(0));\\n }\\n return (node, State.OWNED);\\n } else if (parentState == State.OWNED) {\\n _REGISTRY_V1.setSubnodeRecord(parentNode, labelHash, address(this), address(0), 0);\\n return (node, State.OWNED);\\n } else {\\n (address owner, uint32 fuses, ) = NAME_WRAPPER.getData(uint256(node));\\n if (owner == address(this)) {\\n // resolver is cleared by migration\\n if (LibMigration.isLocked(fuses)) {\\n return (node, State.LOCKED);\\n }\\n // } else if (LibMigration.isEmancipatedChild(fuses)) {\\n // return (node, State.OWNED);\\n // }\\n } else if (owner != address(0)) {\\n NAME_WRAPPER.setSubnodeRecord(\\n parentNode,\\n string(name[offset + 1:nextOffset]),\\n address(this), // owner\\n address(0), // resolver\\n 0, // ttl\\n 0, // fuses\\n 0 // expiry (uses min)\\n ); // reverts if not migrated\\n NAME_WRAPPER.unwrap(parentNode, labelHash, address(this));\\n }\\n return (node, State.OWNED);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd3734939fe1471b07e4d100cd5e367125e5bfe4f132034933526a4f84d0a7d04\",\"license\":\"MIT\"},\"project/src/migration/libraries/LibMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n CANNOT_BURN_FUSES,\\n CANNOT_UNWRAP,\\n IS_DOT_ETH,\\n PARENT_CANNOT_CONTROL\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Primitives for migration.\\nlibrary LibMigration {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Typed arguments for migration via transfer payload.\\n struct Data {\\n /// @dev Subdomain being migrated.\\n string label;\\n /// @dev Address that will own the name in the v2 registry.\\n address owner;\\n /// @dev Address of the child registry.\\n /// Ignored by locked migration.\\n IRegistry subregistry;\\n /// @dev Resolver address to set for the migrated name.\\n /// Ignored if locked and `CANNOT_SET_RESOLVER`.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Minimum size of `abi.encode(Data({...}))`.\\n uint256 internal constant MIN_DATA_SIZE = 7 * 32;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be registered because unmigrated NameWrapper token exists.\\n /// @dev Error selector: `0x408fa1b8`\\n error NameRequiresMigration();\\n\\n /// @notice NameWrapper token is unlocked.\\n /// @dev Error selector: `0x1bfe8f0a`\\n error NameNotLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper token is locked.\\n /// @dev Error selector: `0xe7c290e2`\\n error NameIsLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper or BaseRegistrar token does not match supplied data.\\n /// @dev Error selector: `0xedec3569`\\n error NameDataMismatch(uint256 tokenId);\\n\\n /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\\n /// @dev Error selector: `0xa4f07713`\\n error FrozenTokenApproval(uint256 tokenId);\\n\\n /// @notice The encoded data is invalid.\\n /// @dev Error selector: `0x5cb045db`\\n error InvalidData();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns `true` if the NameWrapper token is locked.\\n function isLocked(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient\\n // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()`\\n return (fuses & CANNOT_UNWRAP) != 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token fuses are not frozen.\\n function notFrozen(uint32 fuses) internal pure returns (bool) {\\n return (fuses & CANNOT_BURN_FUSES) == 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth.\\n function isEmancipatedChild(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL must be set for the entire ancestory.\\n // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()`\\n return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL;\\n }\\n}\\n\",\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract." + }, + "clear(bytes[])": { + "notice": "Clear registry for migrated names." + }, + "constructor": { + "notice": "Create a graveyard." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + } + }, + "notice": "The ENSv1 ETHRegistrarController for ENSv2 launch which becomes the burn address for migrated tokens. 1. Claim any expired ENSv1 name and assign ownership to this contract. 2. Clear the registry for any owned token.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce8000000000000000000000000fc8bf9234969d6b85729b756fa9e14bb84a06754", + "transaction": { + "hash": "0x2927c8f580608f661c5aa005e0c8a19fe6de72d043742dc240788e6dcd8a5db9", + "nonce": "0x1e92", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xc7cf941bf6717b907a7c67cd09164de489bffa121535c75a29bb06d1b1741e01", + "blockNumber": "0xa6a807", + "transactionIndex": "0x43" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/HCAFactory.json b/contracts/deployments/sepolia-official-v1-20260525-r2/HCAFactory.json new file mode 100644 index 000000000..3141edc45 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/HCAFactory.json @@ -0,0 +1,688 @@ +{ + "address": "0x358680728dedb552adaa9f5eb5d4395b291cf943", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "contract IHCAInitDataParser", + "name": "initDataParser_", + "type": "address" + }, + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EthTransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "HCAImplementationNotSelectable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "hcaOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "hca", + "type": "address" + } + ], + "name": "AccountCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "AccountImplementationSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "accountImplementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "initDataParser", + "type": "address" + } + ], + "name": "NewHCAImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "DEFERRED_IMPLEMENTATION", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "accountHCAOf", + "outputs": [ + { + "internalType": "address", + "name": "hca", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "accountImplementationOf", + "outputs": [ + { + "internalType": "address", + "name": "accountImplementation", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "computeAccountAddress", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initData", + "type": "bytes" + } + ], + "name": "createAccount", + "outputs": [ + { + "internalType": "address payable", + "name": "hca", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "hca", + "type": "address" + } + ], + "name": "getAccountOwner", + "outputs": [ + { + "internalType": "address", + "name": "hcaOwner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initData", + "type": "bytes" + } + ], + "name": "getOwnerFromHCAInitdata", + "outputs": [ + { + "internalType": "address", + "name": "hcaOwner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initDataParser", + "outputs": [ + { + "internalType": "contract IHCAInitDataParser", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accountImplementation", + "type": "address" + } + ], + "name": "setAccountImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + }, + { + "internalType": "contract IHCAInitDataParser", + "name": "initDataParser_", + "type": "address" + } + ], + "name": "setImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "HCAFactory", + "sourceName": "src/hca/HCAFactory.sol", + "bytecode": "0x60a060405234801561000f575f5ffd5b5060405161155c38038061155c83398101604081905261002e91610156565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b610065816100e3565b50600180546001600160a01b038086166001600160a01b031992831617909255600280549285169290911691909117905560405130906100a490610132565b6001600160a01b039091168152602001604051809103905ff0801580156100cd573d5f5f3e3d5ffd5b506001600160a01b0316608052506101a0915050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6104e58061107783390190565b6001600160a01b0381168114610153575f5ffd5b50565b5f5f5f60608486031215610168575f5ffd5b83516101738161013f565b60208501519093506101848161013f565b60408501519092506101958161013f565b809150509250925092565b608051610eb16101c65f395f81816101f6015281816104b001526106960152610eb15ff3fe6080604052600436106100d9575f3560e01c80638f8fbab41161007c578063cade6a5d11610057578063cade6a5d1461022b578063d2f308f71461024a578063eaeae2e014610281578063f2fde38b146102a0575f5ffd5b80638f8fbab4146101c6578063a73d253b146101e5578063a9ea858f14610218575f5ffd5b806351df58b6116100b757806351df58b6146101585780635c60da1b14610177578063715018a6146101965780638da5cb5b146101aa575f5ffd5b806309766da2146100dd578063128af67c146100fe578063442b172c14610139575b5f5ffd5b3480156100e8575f5ffd5b506100fc6100f7366004610b0f565b6102bf565b005b348015610109575f5ffd5b5061011d610118366004610b2a565b61032b565b6040516001600160a01b03909116815260200160405180910390f35b348015610144575f5ffd5b5061011d610153366004610b0f565b6103bc565b348015610163575f5ffd5b5060025461011d906001600160a01b031681565b348015610182575f5ffd5b5060015461011d906001600160a01b031681565b3480156101a1575f5ffd5b506100fc61040e565b3480156101b5575f5ffd5b505f546001600160a01b031661011d565b3480156101d1575f5ffd5b506100fc6101e0366004610b98565b610421565b3480156101f0575f5ffd5b5061011d7f000000000000000000000000000000000000000000000000000000000000000081565b61011d610226366004610b2a565b610493565b348015610236575f5ffd5b5061011d610245366004610b0f565b6105b0565b348015610255575f5ffd5b5061011d610264366004610b0f565b6001600160a01b039081165f908152600460205260409020541690565b34801561028c575f5ffd5b5061011d61029b366004610b0f565b6105c0565b3480156102ab575f5ffd5b506100fc6102ba366004610b0f565b61060c565b6102c881610667565b335f81815260046020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03861690811790915590519092917f95e97e89102832f2ee5f59162c972c394da5c44eba158043aa5d227ea27ea5ae91a350565b6002546040517ff9660ea10000000000000000000000000000000000000000000000000000000081525f916001600160a01b03169063f9660ea1906103769086908690600401610bcf565b602060405180830381865afa158015610391573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103b59190610bfd565b9392505050565b6001600160a01b038082165f90815260036020526040902054168015806103fd5750816001600160a01b03166103f182610722565b6001600160a01b031614155b1561040957505f919050565b919050565b61041661073f565b61041f5f610784565b565b61042961073f565b6001805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03858116918217909355600280549092169284169283179091556040517f608e8e3695b40b0624fa99fb9ddc5d031b73505828e0a23810d212f26aebe558905f90a35050565b5f5f61049f848461032b565b90505f6104ab826107e0565b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036104fa576104f18284610810565b9450905061053f565b61053a828488888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061083692505050565b945090505b806105a7576001600160a01b038481165f81815260036020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169488169485179055519192917fac631f3001b55ea1509cf3d7e74898f85392a61a76e8149181ae1259622dabc89190a35b50505092915050565b5f6105ba82610722565b92915050565b5f6001600160a01b0382166105d657505f919050565b6105df82610722565b6001600160a01b038181165f9081526003602052604090205491925083811691161461040957505f919050565b61061461073f565b6001600160a01b03811661065b576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b61066481610784565b50565b6001546001600160a01b03828116911614801561068c57506001600160a01b03811615155b156106945750565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03161480156106dd57506001600160a01b03811615155b156106e55750565b6040517fbf4480a40000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610652565b5f6105ba606083901b6bffffffffffffffffffffffff19166108b8565b5f546001600160a01b0316331461041f576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610652565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038082165f9081526004602052604090205416806104095750506001546001600160a01b031690565b5f5f61082b848460405180602001604052805f8152506108c3565b915091509250929050565b5f5f6108ab85858560405160240161084e9190610c18565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4b6a1419000000000000000000000000000000000000000000000000000000001790526108c3565b915091505b935093915050565b5f6105ba82306109a3565b5f5f6108ce84610722565b90505f816001600160a01b03163b119150816109115761090b346108f287866109fa565b606087901b6bffffffffffffffffffffffff1916610a92565b506108b0565b5f816001600160a01b0316346040515f6040518083038185875af1925050503d805f811461095a576040519150601f19603f3d011682016040523d82523d5f602084013e61095f565b606091505b505090508061099a576040517f6d963f8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50935093915050565b5f604051825f5260ff600b53836020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b20601452806040525061d6945f52600160345350506017601e20919050565b606081515f03610a48576040518060e0016040528060b88152602001610cc260b891398360601b604051602001610a32929190610c64565b60405160208183030381529060405290506105ba565b6040518061014001604052806101028152602001610d7a61010291398360601b83604051602001610a7b93929190610c8d565b604051602081830303815290604052905092915050565b5f6f67363d3d37363d34f03d5260086018f35f52816010805ff580610abe5763301164255f526004601cfd5b8060145261d6945f5260016034536017601e2091505f5f85516020870188855af1823b02610af35763301164255f526004601cfd5b509392505050565b6001600160a01b0381168114610664575f5ffd5b5f60208284031215610b1f575f5ffd5b81356103b581610afb565b5f5f60208385031215610b3b575f5ffd5b823567ffffffffffffffff811115610b51575f5ffd5b8301601f81018513610b61575f5ffd5b803567ffffffffffffffff811115610b77575f5ffd5b856020828401011115610b88575f5ffd5b6020919091019590945092505050565b5f5f60408385031215610ba9575f5ffd5b8235610bb481610afb565b91506020830135610bc481610afb565b809150509250929050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f60208284031215610c0d575f5ffd5b81516103b581610afb565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f81518060208401855e5f93019283525090919050565b5f610c6f8285610c4d565b6bffffffffffffffffffffffff199390931683525050601401919050565b5f610c988286610c4d565b6bffffffffffffffffffffffff1985168152610cb76014820185610c4d565b969550505050505056fe607660426014828201600c395f5191823b156062578282937f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a25f395ff35b82634c9c8ce360e01b5f5260045260245ffdfe3615604057365f80375f8036817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d5f803e15603c573d5ff35b3d5ffd5b0060426100c0818101601481600c395f5190813b1560ac5760145f8381949382947f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55817fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a260017f90b772c2cb8a51aa7a8a65fc23543c6d022d5b3f8e2b92eed79fba7eef8293005d601319813803019384910183395af43d5f803e1560a85781905f395ff35b3d5ffd5b50634c9c8ce360e01b5f5260045260245ffdfe3615604057365f80375f8036817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d5f803e15603c573d5ff35b3d5ffd5b00a2646970667358221220ccf07aaffe3a782a26f10d43239e1493fa3b1a104f0ea0b4f6803087f29beb7964736f6c634300081b003360a0604052348015600e575f5ffd5b506040516104e53803806104e5833981016040819052602b916061565b6001600160a01b03811660515760405163420eb10160e11b815260040160405180910390fd5b6001600160a01b0316608052608c565b5f602082840312156070575f5ffd5b81516001600160a01b03811681146085575f5ffd5b9392505050565b60805161043c6100a95f395f8181603d015260c0015261043c5ff3fe608060405260043610610028575f3560e01c8063319c22bb1461002c5780634f1ef2861461007b575b5f5ffd5b348015610037575f5ffd5b5061005f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61008e610089366004610355565b610090565b005b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa15801561010d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013191906103d5565b90506001600160a01b038116610173576040517fd815aa7d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b038216146101cb576040517f633d83ce0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03821660248201526044015b60405180910390fd5b836001600160a01b03163b5f03610219576040517f1e1228950000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016101c2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386169081179091556040517fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a25f8290036102a45750505050565b5f846001600160a01b031684846040516102bf9291906103f7565b5f60405180830381855af49150503d805f81146102f7576040519150601f19603f3d011682016040523d82523d5f602084013e6102fc565b606091505b5050905080610337576040517f107fd27400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6001600160a01b0381168114610352575f5ffd5b50565b5f5f5f60408486031215610367575f5ffd5b83356103728161033e565b9250602084013567ffffffffffffffff81111561038d575f5ffd5b8401601f8101861361039d575f5ffd5b803567ffffffffffffffff8111156103b3575f5ffd5b8660208284010111156103c4575f5ffd5b939660209190910195509293505050565b5f602082840312156103e5575f5ffd5b81516103f08161033e565b9392505050565b818382375f910190815291905056fea2646970667358221220b691fa0ff58a82add9194235591310228bb81fde4de3e7c3299de2ce8d4c7d8664736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106100d9575f3560e01c80638f8fbab41161007c578063cade6a5d11610057578063cade6a5d1461022b578063d2f308f71461024a578063eaeae2e014610281578063f2fde38b146102a0575f5ffd5b80638f8fbab4146101c6578063a73d253b146101e5578063a9ea858f14610218575f5ffd5b806351df58b6116100b757806351df58b6146101585780635c60da1b14610177578063715018a6146101965780638da5cb5b146101aa575f5ffd5b806309766da2146100dd578063128af67c146100fe578063442b172c14610139575b5f5ffd5b3480156100e8575f5ffd5b506100fc6100f7366004610b0f565b6102bf565b005b348015610109575f5ffd5b5061011d610118366004610b2a565b61032b565b6040516001600160a01b03909116815260200160405180910390f35b348015610144575f5ffd5b5061011d610153366004610b0f565b6103bc565b348015610163575f5ffd5b5060025461011d906001600160a01b031681565b348015610182575f5ffd5b5060015461011d906001600160a01b031681565b3480156101a1575f5ffd5b506100fc61040e565b3480156101b5575f5ffd5b505f546001600160a01b031661011d565b3480156101d1575f5ffd5b506100fc6101e0366004610b98565b610421565b3480156101f0575f5ffd5b5061011d7f000000000000000000000000000000000000000000000000000000000000000081565b61011d610226366004610b2a565b610493565b348015610236575f5ffd5b5061011d610245366004610b0f565b6105b0565b348015610255575f5ffd5b5061011d610264366004610b0f565b6001600160a01b039081165f908152600460205260409020541690565b34801561028c575f5ffd5b5061011d61029b366004610b0f565b6105c0565b3480156102ab575f5ffd5b506100fc6102ba366004610b0f565b61060c565b6102c881610667565b335f81815260046020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03861690811790915590519092917f95e97e89102832f2ee5f59162c972c394da5c44eba158043aa5d227ea27ea5ae91a350565b6002546040517ff9660ea10000000000000000000000000000000000000000000000000000000081525f916001600160a01b03169063f9660ea1906103769086908690600401610bcf565b602060405180830381865afa158015610391573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103b59190610bfd565b9392505050565b6001600160a01b038082165f90815260036020526040902054168015806103fd5750816001600160a01b03166103f182610722565b6001600160a01b031614155b1561040957505f919050565b919050565b61041661073f565b61041f5f610784565b565b61042961073f565b6001805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03858116918217909355600280549092169284169283179091556040517f608e8e3695b40b0624fa99fb9ddc5d031b73505828e0a23810d212f26aebe558905f90a35050565b5f5f61049f848461032b565b90505f6104ab826107e0565b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316036104fa576104f18284610810565b9450905061053f565b61053a828488888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061083692505050565b945090505b806105a7576001600160a01b038481165f81815260036020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169488169485179055519192917fac631f3001b55ea1509cf3d7e74898f85392a61a76e8149181ae1259622dabc89190a35b50505092915050565b5f6105ba82610722565b92915050565b5f6001600160a01b0382166105d657505f919050565b6105df82610722565b6001600160a01b038181165f9081526003602052604090205491925083811691161461040957505f919050565b61061461073f565b6001600160a01b03811661065b576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b61066481610784565b50565b6001546001600160a01b03828116911614801561068c57506001600160a01b03811615155b156106945750565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03161480156106dd57506001600160a01b03811615155b156106e55750565b6040517fbf4480a40000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610652565b5f6105ba606083901b6bffffffffffffffffffffffff19166108b8565b5f546001600160a01b0316331461041f576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610652565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038082165f9081526004602052604090205416806104095750506001546001600160a01b031690565b5f5f61082b848460405180602001604052805f8152506108c3565b915091509250929050565b5f5f6108ab85858560405160240161084e9190610c18565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4b6a1419000000000000000000000000000000000000000000000000000000001790526108c3565b915091505b935093915050565b5f6105ba82306109a3565b5f5f6108ce84610722565b90505f816001600160a01b03163b119150816109115761090b346108f287866109fa565b606087901b6bffffffffffffffffffffffff1916610a92565b506108b0565b5f816001600160a01b0316346040515f6040518083038185875af1925050503d805f811461095a576040519150601f19603f3d011682016040523d82523d5f602084013e61095f565b606091505b505090508061099a576040517f6d963f8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50935093915050565b5f604051825f5260ff600b53836020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b20601452806040525061d6945f52600160345350506017601e20919050565b606081515f03610a48576040518060e0016040528060b88152602001610cc260b891398360601b604051602001610a32929190610c64565b60405160208183030381529060405290506105ba565b6040518061014001604052806101028152602001610d7a61010291398360601b83604051602001610a7b93929190610c8d565b604051602081830303815290604052905092915050565b5f6f67363d3d37363d34f03d5260086018f35f52816010805ff580610abe5763301164255f526004601cfd5b8060145261d6945f5260016034536017601e2091505f5f85516020870188855af1823b02610af35763301164255f526004601cfd5b509392505050565b6001600160a01b0381168114610664575f5ffd5b5f60208284031215610b1f575f5ffd5b81356103b581610afb565b5f5f60208385031215610b3b575f5ffd5b823567ffffffffffffffff811115610b51575f5ffd5b8301601f81018513610b61575f5ffd5b803567ffffffffffffffff811115610b77575f5ffd5b856020828401011115610b88575f5ffd5b6020919091019590945092505050565b5f5f60408385031215610ba9575f5ffd5b8235610bb481610afb565b91506020830135610bc481610afb565b809150509250929050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f60208284031215610c0d575f5ffd5b81516103b581610afb565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f81518060208401855e5f93019283525090919050565b5f610c6f8285610c4d565b6bffffffffffffffffffffffff199390931683525050601401919050565b5f610c988286610c4d565b6bffffffffffffffffffffffff1985168152610cb76014820185610c4d565b969550505050505056fe607660426014828201600c395f5191823b156062578282937f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a25f395ff35b82634c9c8ce360e01b5f5260045260245ffdfe3615604057365f80375f8036817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d5f803e15603c573d5ff35b3d5ffd5b0060426100c0818101601481600c395f5190813b1560ac5760145f8381949382947f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55817fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a260017f90b772c2cb8a51aa7a8a65fc23543c6d022d5b3f8e2b92eed79fba7eef8293005d601319813803019384910183395af43d5f803e1560a85781905f395ff35b3d5ffd5b50634c9c8ce360e01b5f5260045260245ffdfe3615604057365f80375f8036817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d5f803e15603c573d5ff35b3d5ffd5b00a2646970667358221220ccf07aaffe3a782a26f10d43239e1493fa3b1a104f0ea0b4f6803087f29beb7964736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60188": [ + { + "length": 32, + "start": 502 + }, + { + "length": 32, + "start": 1200 + }, + { + "length": 32, + "start": 1686 + } + ] + }, + "inputSourceName": "project/src/hca/HCAFactory.sol", + "devdoc": { + "details": "HCA-aware protocol calls resolve deployed HCAs after the deterministic account is recorded for its owner.", + "errors": { + "EthTransferFailed()": [ + { + "details": "Error selector: `0x6d963f88`" + } + ], + "HCAImplementationNotSelectable(address)": [ + { + "details": "Error selector: `0xbf4480a4`", + "params": { + "implementation": "The rejected implementation address." + } + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "events": { + "AccountCreated(address,address)": { + "params": { + "hca": "The address of the deployed HCA proxy.", + "hcaOwner": "The owner of the newly created account." + } + }, + "AccountImplementationSet(address,address)": { + "params": { + "account": "The account selecting the implementation.", + "implementation": "The selected implementation." + } + }, + "NewHCAImplementation(address,address)": { + "params": { + "accountImplementation": "The implementation contract selectable for newly deployed HCA proxies.", + "initDataParser": "The parser used to extract account ownership from initialization data." + } + } + }, + "kind": "dev", + "methods": { + "accountHCAOf(address)": { + "params": { + "account": "The account to inspect." + }, + "returns": { + "hca": "The recorded HCA address." + } + }, + "accountImplementationOf(address)": { + "params": { + "account": "The account to inspect." + }, + "returns": { + "accountImplementation": "The selected implementation." + } + }, + "computeAccountAddress(address)": { + "params": { + "owner": "The owner whose HCA address to predict." + }, + "returns": { + "_0": "The deterministic proxy address." + } + }, + "constructor": { + "params": { + "implementation_": "The HCA implementation contract to proxy to.", + "initDataParser_": "The parser used to parse account-specific init data.", + "owner_": "The owner of this factory." + } + }, + "createAccount(bytes)": { + "details": "Uses the owner's selected implementation when set, otherwise the current implementation.", + "params": { + "initData": "The initialization data used to initialize the HCA proxy and identify its owner." + }, + "returns": { + "hca": "The deployed or existing HCA proxy address." + } + }, + "getAccountOwner(address)": { + "details": "Returns zero for non-HCA callers and for HCAs that are not recorded for their owner.", + "params": { + "hca": "The HCA or caller address to look up." + }, + "returns": { + "hcaOwner": "The recorded HCA owner, or zero when the caller has no recorded HCA mapping." + } + }, + "getOwnerFromHCAInitdata(bytes)": { + "params": { + "initData": "The initialization data to parse." + }, + "returns": { + "hcaOwner": "The owner encoded in the initialization data." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setAccountImplementation(address)": { + "params": { + "accountImplementation": "The implementation to select." + } + }, + "setImplementation(address,address)": { + "params": { + "implementation_": "The new implementation address.", + "initDataParser_": "The new parser used to extract account ownership from initialization data." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "stateVariables": { + "_accountImplementations": { + "details": "Maps an account to the implementation selected for its deterministic HCA." + }, + "_hcaOwners": { + "details": "Maps each deployed HCA proxy address to its owner." + } + }, + "title": "HCAFactory", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "752200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "DEFERRED_IMPLEMENTATION()": "infinite", + "accountHCAOf(address)": "infinite", + "accountImplementationOf(address)": "2590", + "computeAccountAddress(address)": "infinite", + "createAccount(bytes)": "infinite", + "getAccountOwner(address)": "infinite", + "getOwnerFromHCAInitdata(bytes)": "infinite", + "implementation()": "2369", + "initDataParser()": "2347", + "owner()": "2406", + "renounceOwnership()": "infinite", + "setAccountImplementation(address)": "infinite", + "setImplementation(address,address)": "infinite", + "transferOwnership(address)": "infinite" + }, + "internal": { + "_deploymentImplementationOf(address)": "4354", + "_requireSelectableImplementation(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"},{\"internalType\":\"contract IHCAInitDataParser\",\"name\":\"initDataParser_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"EthTransferFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"HCAImplementationNotSelectable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"hcaOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"hca\",\"type\":\"address\"}],\"name\":\"AccountCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"AccountImplementationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"accountImplementation\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"initDataParser\",\"type\":\"address\"}],\"name\":\"NewHCAImplementation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFERRED_IMPLEMENTATION\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"accountHCAOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"hca\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"accountImplementationOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"accountImplementation\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"computeAccountAddress\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initData\",\"type\":\"bytes\"}],\"name\":\"createAccount\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"hca\",\"type\":\"address\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"hca\",\"type\":\"address\"}],\"name\":\"getAccountOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"hcaOwner\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initData\",\"type\":\"bytes\"}],\"name\":\"getOwnerFromHCAInitdata\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"hcaOwner\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initDataParser\",\"outputs\":[{\"internalType\":\"contract IHCAInitDataParser\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accountImplementation\",\"type\":\"address\"}],\"name\":\"setAccountImplementation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"},{\"internalType\":\"contract IHCAInitDataParser\",\"name\":\"initDataParser_\",\"type\":\"address\"}],\"name\":\"setImplementation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"HCA-aware protocol calls resolve deployed HCAs after the deterministic account is recorded for its owner.\",\"errors\":{\"EthTransferFailed()\":[{\"details\":\"Error selector: `0x6d963f88`\"}],\"HCAImplementationNotSelectable(address)\":[{\"details\":\"Error selector: `0xbf4480a4`\",\"params\":{\"implementation\":\"The rejected implementation address.\"}}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"AccountCreated(address,address)\":{\"params\":{\"hca\":\"The address of the deployed HCA proxy.\",\"hcaOwner\":\"The owner of the newly created account.\"}},\"AccountImplementationSet(address,address)\":{\"params\":{\"account\":\"The account selecting the implementation.\",\"implementation\":\"The selected implementation.\"}},\"NewHCAImplementation(address,address)\":{\"params\":{\"accountImplementation\":\"The implementation contract selectable for newly deployed HCA proxies.\",\"initDataParser\":\"The parser used to extract account ownership from initialization data.\"}}},\"kind\":\"dev\",\"methods\":{\"accountHCAOf(address)\":{\"params\":{\"account\":\"The account to inspect.\"},\"returns\":{\"hca\":\"The recorded HCA address.\"}},\"accountImplementationOf(address)\":{\"params\":{\"account\":\"The account to inspect.\"},\"returns\":{\"accountImplementation\":\"The selected implementation.\"}},\"computeAccountAddress(address)\":{\"params\":{\"owner\":\"The owner whose HCA address to predict.\"},\"returns\":{\"_0\":\"The deterministic proxy address.\"}},\"constructor\":{\"params\":{\"implementation_\":\"The HCA implementation contract to proxy to.\",\"initDataParser_\":\"The parser used to parse account-specific init data.\",\"owner_\":\"The owner of this factory.\"}},\"createAccount(bytes)\":{\"details\":\"Uses the owner's selected implementation when set, otherwise the current implementation.\",\"params\":{\"initData\":\"The initialization data used to initialize the HCA proxy and identify its owner.\"},\"returns\":{\"hca\":\"The deployed or existing HCA proxy address.\"}},\"getAccountOwner(address)\":{\"details\":\"Returns zero for non-HCA callers and for HCAs that are not recorded for their owner.\",\"params\":{\"hca\":\"The HCA or caller address to look up.\"},\"returns\":{\"hcaOwner\":\"The recorded HCA owner, or zero when the caller has no recorded HCA mapping.\"}},\"getOwnerFromHCAInitdata(bytes)\":{\"params\":{\"initData\":\"The initialization data to parse.\"},\"returns\":{\"hcaOwner\":\"The owner encoded in the initialization data.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccountImplementation(address)\":{\"params\":{\"accountImplementation\":\"The implementation to select.\"}},\"setImplementation(address,address)\":{\"params\":{\"implementation_\":\"The new implementation address.\",\"initDataParser_\":\"The new parser used to extract account ownership from initialization data.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"stateVariables\":{\"_accountImplementations\":{\"details\":\"Maps an account to the implementation selected for its deterministic HCA.\"},\"_hcaOwners\":{\"details\":\"Maps each deployed HCA proxy address to its owner.\"}},\"title\":\"HCAFactory\",\"version\":1},\"userdoc\":{\"errors\":{\"EthTransferFailed()\":[{\"notice\":\"Thrown when ETH forwarding to an existing proxy fails.\"}],\"HCAImplementationNotSelectable(address)\":[{\"notice\":\"Thrown when an account selects an unsupported implementation.\"}]},\"events\":{\"AccountCreated(address,address)\":{\"notice\":\"Emitted when a new HCA is deployed.\"},\"AccountImplementationSet(address,address)\":{\"notice\":\"Emitted when an account selects its HCA implementation.\"},\"NewHCAImplementation(address,address)\":{\"notice\":\"Emitted when the implementation and init data parser selectable for new HCA proxies change.\"}},\"kind\":\"user\",\"methods\":{\"DEFERRED_IMPLEMENTATION()\":{\"notice\":\"The implementation that lets an HCA owner defer the final account upgrade target.\"},\"accountHCAOf(address)\":{\"notice\":\"Returns the deterministic HCA address recorded for an account.\"},\"accountImplementationOf(address)\":{\"notice\":\"Returns the implementation explicitly selected by an account.\"},\"computeAccountAddress(address)\":{\"notice\":\"Computes the deterministic HCA proxy address for an owner.\"},\"constructor\":{\"notice\":\"Initializes the factory with an implementation, init data parser, owner, and deferred implementation.\"},\"createAccount(bytes)\":{\"notice\":\"Deploys a new HCA proxy for the owner encoded in the initialization data, or forwards ETH if already deployed.\"},\"getAccountOwner(address)\":{\"notice\":\"Returns the owner recorded for a deployed HCA proxy.\"},\"getOwnerFromHCAInitdata(bytes)\":{\"notice\":\"Extracts the HCA owner from initialization data.\"},\"implementation()\":{\"notice\":\"The current HCA implementation contract selectable by accounts.\"},\"initDataParser()\":{\"notice\":\"The parser contract that extracts account ownership from HCA initialization data.\"},\"setAccountImplementation(address)\":{\"notice\":\"Selects the implementation used when deploying the sender's deterministic HCA.\"},\"setImplementation(address,address)\":{\"notice\":\"Updates the implementation and init data parser selectable for new HCA proxies.\"}},\"notice\":\"Factory for deploying Hidden Contract Accounts as deterministic ERC-1967 proxies.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/hca/HCAFactory.sol\":\"HCAFactory\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/solady/src/utils/CREATE3.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Deterministic deployments agnostic to the initialization code.\\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/CREATE3.sol)\\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol)\\n/// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol)\\nlibrary CREATE3 {\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* CUSTOM ERRORS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Unable to deploy the contract.\\n error DeploymentFailed();\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* BYTECODE CONSTANTS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /**\\n * -------------------------------------------------------------------+\\n * Opcode | Mnemonic | Stack | Memory |\\n * -------------------------------------------------------------------|\\n * 36 | CALLDATASIZE | cds | |\\n * 3d | RETURNDATASIZE | 0 cds | |\\n * 3d | RETURNDATASIZE | 0 0 cds | |\\n * 37 | CALLDATACOPY | | [0..cds): calldata |\\n * 36 | CALLDATASIZE | cds | [0..cds): calldata |\\n * 3d | RETURNDATASIZE | 0 cds | [0..cds): calldata |\\n * 34 | CALLVALUE | value 0 cds | [0..cds): calldata |\\n * f0 | CREATE | newContract | [0..cds): calldata |\\n * -------------------------------------------------------------------|\\n * Opcode | Mnemonic | Stack | Memory |\\n * -------------------------------------------------------------------|\\n * 67 bytecode | PUSH8 bytecode | bytecode | |\\n * 3d | RETURNDATASIZE | 0 bytecode | |\\n * 52 | MSTORE | | [0..8): bytecode |\\n * 60 0x08 | PUSH1 0x08 | 0x08 | [0..8): bytecode |\\n * 60 0x18 | PUSH1 0x18 | 0x18 0x08 | [0..8): bytecode |\\n * f3 | RETURN | | [0..8): bytecode |\\n * -------------------------------------------------------------------+\\n */\\n\\n /// @dev The proxy initialization code.\\n uint256 private constant _PROXY_INITCODE = 0x67363d3d37363d34f03d5260086018f3;\\n\\n /// @dev Hash of the `_PROXY_INITCODE`.\\n /// Equivalent to `keccak256(abi.encodePacked(hex\\\"67363d3d37363d34f03d5260086018f3\\\"))`.\\n bytes32 internal constant PROXY_INITCODE_HASH =\\n 0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f;\\n\\n /*\\u00b4:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0\\u2022.*\\u2022\\u00b4.*:\\u02da.\\u00b0*.\\u02da\\u2022\\u00b4.\\u00b0:\\u00b0\\u2022.\\u00b0+.*\\u2022\\u00b4.*:*/\\n /* CREATE3 OPERATIONS */\\n /*.\\u2022\\u00b0:\\u00b0.\\u00b4+\\u02da.*\\u00b0.\\u02da:*.\\u00b4\\u2022*.+\\u00b0.\\u2022\\u00b0:\\u00b4*.\\u00b4\\u2022*.\\u2022\\u00b0.\\u2022\\u00b0:\\u00b0.\\u00b4:\\u2022\\u02da\\u00b0.*\\u00b0.\\u02da:*.\\u00b4+\\u00b0.\\u2022*/\\n\\n /// @dev Deploys `initCode` deterministically with a `salt`.\\n /// Returns the deterministic address of the deployed contract,\\n /// which solely depends on `salt`.\\n function deployDeterministic(bytes memory initCode, bytes32 salt)\\n internal\\n returns (address deployed)\\n {\\n deployed = deployDeterministic(0, initCode, salt);\\n }\\n\\n /// @dev Deploys `initCode` deterministically with a `salt`.\\n /// The deployed contract is funded with `value` (in wei) ETH.\\n /// Returns the deterministic address of the deployed contract,\\n /// which solely depends on `salt`.\\n function deployDeterministic(uint256 value, bytes memory initCode, bytes32 salt)\\n internal\\n returns (address deployed)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, _PROXY_INITCODE) // Store the `_PROXY_INITCODE`.\\n let proxy := create2(0, 0x10, 0x10, salt)\\n if iszero(proxy) {\\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x14, proxy) // Store the proxy's address.\\n // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01).\\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex).\\n mstore(0x00, 0xd694)\\n mstore8(0x34, 0x01) // Nonce of the proxy contract (1).\\n deployed := keccak256(0x1e, 0x17)\\n if iszero(\\n mul( // The arguments of `mul` are evaluated last to first.\\n extcodesize(deployed),\\n call(gas(), proxy, value, add(initCode, 0x20), mload(initCode), 0x00, 0x00)\\n )\\n ) {\\n mstore(0x00, 0x30116425) // `DeploymentFailed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n\\n /// @dev Returns the deterministic address for `salt`.\\n function predictDeterministicAddress(bytes32 salt) internal view returns (address deployed) {\\n deployed = predictDeterministicAddress(salt, address(this));\\n }\\n\\n /// @dev Returns the deterministic address for `salt` with `deployer`.\\n function predictDeterministicAddress(bytes32 salt, address deployer)\\n internal\\n pure\\n returns (address deployed)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x00, deployer) // Store `deployer`.\\n mstore8(0x0b, 0xff) // Store the prefix.\\n mstore(0x20, salt) // Store the salt.\\n mstore(0x40, PROXY_INITCODE_HASH) // Store the bytecode hash.\\n\\n mstore(0x14, keccak256(0x0b, 0x55)) // Store the proxy's address.\\n mstore(0x40, m) // Restore the free memory pointer.\\n // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01).\\n // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex).\\n mstore(0x00, 0xd694)\\n mstore8(0x34, 0x01) // Nonce of the proxy contract (1).\\n deployed := keccak256(0x1e, 0x17)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c5f5a0bd6f3cfa30101ed769ac090e54e1235d412d2859ea11c5de8f00a094d\",\"license\":\"MIT\"},\"project/src/hca/HCADeferredImplementation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IERC1967} from \\\"@openzeppelin/contracts/interfaces/IERC1967.sol\\\";\\nimport {StorageSlot} from \\\"@openzeppelin/contracts/utils/StorageSlot.sol\\\";\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @title HCADeferredImplementation\\n/// @notice Minimal implementation for HCAs whose owner has deferred the final account implementation.\\n/// @dev Calls are expected to arrive through an ERC-1967 proxy registered in the HCA factory.\\ncontract HCADeferredImplementation is IERC1967 {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev ERC-1967 implementation slot.\\n bytes32 internal constant IMPLEMENTATION_SLOT =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @notice The HCA factory used to authorize owner upgrades.\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Thrown when the HCA factory is the zero address.\\n /// @dev Error selector: `0x841d6202`\\n error HCAFactoryCannotBeZero();\\n\\n /// @notice Thrown when a caller is not the registered HCA owner.\\n /// @param caller The unauthorized caller.\\n /// @param owner The registered HCA owner.\\n /// @dev Error selector: `0x633d83ce`\\n error HCADeferredUpgradeUnauthorized(address caller, address owner);\\n\\n /// @notice Thrown when the HCA factory has no owner registered for the proxy.\\n /// @dev Error selector: `0xd815aa7d`\\n error HCADeferredOwnerNotSet();\\n\\n /// @notice Thrown when the target implementation has no contract code.\\n /// @param implementation The rejected implementation address.\\n /// @dev Error selector: `0x1e122895`\\n error HCADeferredImplementationHasNoCode(address implementation);\\n\\n /// @notice Thrown when the post-upgrade delegatecall fails.\\n /// @dev Error selector: `0x107fd274`\\n error HCADeferredInitializationFailed();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory used for ownership lookup.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n if (address(hcaFactory) == address(0))\\n revert HCAFactoryCannotBeZero();\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Upgrades the proxy to a final implementation and optionally initializes it.\\n /// @param newImplementation The implementation to install in the proxy.\\n /// @param data Optional initialization call data delegated to the new implementation.\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable {\\n address owner = HCA_FACTORY.getAccountOwner(address(this));\\n if (owner == address(0))\\n revert HCADeferredOwnerNotSet();\\n if (msg.sender != owner)\\n revert HCADeferredUpgradeUnauthorized(msg.sender, owner);\\n if (newImplementation.code.length == 0)\\n revert HCADeferredImplementationHasNoCode(newImplementation);\\n\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n emit Upgraded(newImplementation);\\n\\n if (data.length == 0)\\n return;\\n\\n (bool success, ) = newImplementation.delegatecall(data);\\n if (!success)\\n revert HCADeferredInitializationFailed();\\n }\\n}\\n\",\"keccak256\":\"0xe25ae415c16a4491968d62096aade8886475c3608335bdfbe684fff1da0b21d9\",\"license\":\"MIT\"},\"project/src/hca/HCAFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.27;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {HCADeferredImplementation} from \\\"./HCADeferredImplementation.sol\\\";\\nimport {IHCAFactory} from \\\"./interfaces/IHCAFactory.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IHCAInitDataParser} from \\\"./interfaces/IHCAInitDataParser.sol\\\";\\nimport {ProxyLib} from \\\"./ProxyLib.sol\\\";\\n\\n/// @title HCAFactory\\n/// @notice Factory for deploying Hidden Contract Accounts as deterministic ERC-1967 proxies.\\n/// @dev HCA-aware protocol calls resolve deployed HCAs after the deterministic account is recorded\\n/// for its owner.\\ncontract HCAFactory is Ownable, IHCAFactory {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The implementation that lets an HCA owner defer the final account upgrade target.\\n address public immutable DEFERRED_IMPLEMENTATION;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The current HCA implementation contract selectable by accounts.\\n address public implementation;\\n\\n /// @notice The parser contract that extracts account ownership from HCA initialization data.\\n IHCAInitDataParser public initDataParser;\\n\\n /// @dev Maps each deployed HCA proxy address to its owner.\\n mapping(address hca => address owner) internal _hcaOwners;\\n\\n /// @dev Maps an account to the implementation selected for its deterministic HCA.\\n mapping(address account => address implementation) internal _accountImplementations;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when a new HCA is deployed.\\n /// @param hcaOwner The owner of the newly created account.\\n /// @param hca The address of the deployed HCA proxy.\\n event AccountCreated(address indexed hcaOwner, address indexed hca);\\n\\n /// @notice Emitted when the implementation and init data parser selectable for new HCA proxies change.\\n /// @param accountImplementation The implementation contract selectable for newly deployed HCA proxies.\\n /// @param initDataParser The parser used to extract account ownership from initialization data.\\n event NewHCAImplementation(\\n address indexed accountImplementation,\\n address indexed initDataParser\\n );\\n\\n /// @notice Emitted when an account selects its HCA implementation.\\n /// @param account The account selecting the implementation.\\n /// @param implementation The selected implementation.\\n event AccountImplementationSet(address indexed account, address indexed implementation);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Thrown when an account selects an unsupported implementation.\\n /// @param implementation The rejected implementation address.\\n /// @dev Error selector: `0xbf4480a4`\\n error HCAImplementationNotSelectable(address implementation);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Initializes the factory with an implementation, init data parser, owner, and deferred implementation.\\n /// @param implementation_ The HCA implementation contract to proxy to.\\n /// @param initDataParser_ The parser used to parse account-specific init data.\\n /// @param owner_ The owner of this factory.\\n constructor(address implementation_, IHCAInitDataParser initDataParser_, address owner_)\\n Ownable(owner_)\\n {\\n implementation = implementation_;\\n initDataParser = initDataParser_;\\n DEFERRED_IMPLEMENTATION = address(\\n new HCADeferredImplementation(IHCAFactoryBasic(address(this)))\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Updates the implementation and init data parser selectable for new HCA proxies.\\n /// @param implementation_ The new implementation address.\\n /// @param initDataParser_ The new parser used to extract account ownership from initialization data.\\n function setImplementation(address implementation_, IHCAInitDataParser initDataParser_)\\n external\\n onlyOwner\\n {\\n implementation = implementation_;\\n initDataParser = initDataParser_;\\n emit NewHCAImplementation(implementation_, address(initDataParser_));\\n }\\n\\n /// @notice Selects the implementation used when deploying the sender's deterministic HCA.\\n /// @param accountImplementation The implementation to select.\\n function setAccountImplementation(address accountImplementation) external {\\n _requireSelectableImplementation(accountImplementation);\\n _accountImplementations[msg.sender] = accountImplementation;\\n emit AccountImplementationSet(msg.sender, accountImplementation);\\n }\\n\\n /// @notice Deploys a new HCA proxy for the owner encoded in the initialization data, or forwards ETH if already deployed.\\n /// @dev Uses the owner's selected implementation when set, otherwise the current implementation.\\n /// @param initData The initialization data used to initialize the HCA proxy and identify its owner.\\n /// @return hca The deployed or existing HCA proxy address.\\n function createAccount(bytes calldata initData) external payable returns (address payable hca) {\\n address hcaOwner = getOwnerFromHCAInitdata(initData);\\n address accountImplementation = _deploymentImplementationOf(hcaOwner);\\n bool alreadyDeployed;\\n if (accountImplementation == DEFERRED_IMPLEMENTATION) {\\n (alreadyDeployed, hca) = ProxyLib.deployProxyWithoutInitialization(\\n accountImplementation,\\n hcaOwner\\n );\\n } else {\\n (alreadyDeployed, hca) = ProxyLib.deployProxy(accountImplementation, hcaOwner, initData);\\n }\\n if (!alreadyDeployed) {\\n _hcaOwners[hca] = hcaOwner;\\n emit AccountCreated(hcaOwner, hca);\\n }\\n }\\n\\n /// @notice Returns the owner recorded for a deployed HCA proxy.\\n /// @dev Returns zero for non-HCA callers and for HCAs that are not recorded for their owner.\\n /// @param hca The HCA or caller address to look up.\\n /// @return hcaOwner The recorded HCA owner, or zero when the caller has no recorded HCA mapping.\\n function getAccountOwner(address hca) external view returns (address hcaOwner) {\\n hcaOwner = _hcaOwners[hca];\\n if (hcaOwner == address(0) || ProxyLib.predictProxyAddress(hcaOwner) != hca) {\\n return address(0);\\n }\\n }\\n\\n /// @inheritdoc IHCAFactory\\n function accountHCAOf(address account) external view returns (address hca) {\\n if (account == address(0)) {\\n return address(0);\\n }\\n hca = ProxyLib.predictProxyAddress(account);\\n if (_hcaOwners[hca] != account) {\\n return address(0);\\n }\\n }\\n\\n /// @inheritdoc IHCAFactory\\n function accountImplementationOf(address account)\\n external\\n view\\n returns (address accountImplementation)\\n {\\n accountImplementation = _accountImplementations[account];\\n }\\n\\n /// @inheritdoc IHCAFactory\\n function computeAccountAddress(address owner) external view returns (address payable) {\\n return ProxyLib.predictProxyAddress(owner);\\n }\\n\\n /// @inheritdoc IHCAFactory\\n function getOwnerFromHCAInitdata(bytes calldata initData)\\n public\\n view\\n returns (address hcaOwner)\\n {\\n hcaOwner = initDataParser.getOwnerFromInitData(initData);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns an account's selected implementation, or the current implementation when unset.\\n function _deploymentImplementationOf(address account)\\n internal\\n view\\n returns (address accountImplementation)\\n {\\n accountImplementation = _accountImplementations[account];\\n if (accountImplementation == address(0)) {\\n accountImplementation = implementation;\\n }\\n }\\n\\n /// @dev Reverts unless the implementation is selectable by this factory.\\n function _requireSelectableImplementation(address accountImplementation) internal view {\\n if (accountImplementation == implementation && accountImplementation != address(0)) {\\n return;\\n }\\n if (accountImplementation == DEFERRED_IMPLEMENTATION && accountImplementation != address(0)) {\\n return;\\n }\\n revert HCAImplementationNotSelectable(accountImplementation);\\n }\\n}\\n\",\"keccak256\":\"0x1cf573fb4447067f5f63fbd18c6d689b4ee9b623456101b88a07cdc66d99a410\",\"license\":\"MIT\"},\"project/src/hca/ProxyLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.27;\\n\\nimport {CREATE3} from \\\"solady/utils/CREATE3.sol\\\";\\n\\n/// @notice Minimal initializer interface for HCA account implementations.\\n/// @dev Interface selector: `0x4b6a1419`\\ninterface IHCAAccountInitializer {\\n /// @notice Initializes the account with implementation-specific data.\\n /// @param initData Encoded account initialization data.\\n function initializeAccount(bytes calldata initData) external payable;\\n}\\n\\n\\n/// @title ProxyLib\\n/// @notice Deploys deterministic HCA proxy accounts using CREATE3 and owner-derived salts.\\n/// @dev Existing proxy addresses receive any attached ETH instead of being redeployed.\\nlibrary ProxyLib {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Init-code prefix compiled from `src/hca/HCAProxyInitCode.yul`.\\n /// Regenerate with `FOUNDRY_PROFILE=yul forge inspect src/hca/HCAProxyInitCode.yul:HCAProxyInitCode bytecode`.\\n bytes internal constant INITIALIZED_HCA_PROXY_INIT_CODE_PREFIX =\\n hex\\\"60426100c0818101601481600c395f5190813b1560ac5760145f8381949382947f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55817fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8480a260017f90b772c2cb8a51aa7a8a65fc23543c6d022d5b3f8e2b92eed79fba7eef8293005d601319813803019384910183395af43d5f803e1560a85781905f395ff35b3d5ffd5b50634c9c8ce360e01b5f5260045260245ffdfe3615604057365f80375f8036817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d5f803e15603c573d5ff35b3d5ffd5b00\\\";\\n\\n /// @dev Init-code prefix compiled from `src/hca/HCAProxyNoInitCode.yul`.\\n /// Regenerate with `FOUNDRY_PROFILE=yul forge inspect src/hca/HCAProxyNoInitCode.yul:HCAProxyNoInitCode bytecode`.\\n bytes internal constant UNINITIALIZED_HCA_PROXY_INIT_CODE_PREFIX =\\n hex\\\"607660426014828201600c395f5191823b156062578282937f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a25f395ff35b82634c9c8ce360e01b5f5260045260245ffdfe3615604057365f80375f8036817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d5f803e15603c573d5ff35b3d5ffd5b00\\\";\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Thrown when ETH forwarding to an existing proxy fails.\\n /// @dev Error selector: `0x6d963f88`\\n error EthTransferFailed();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Deploys an initialized deterministic HCA proxy or funds the existing proxy.\\n /// @dev Encodes the account initializer call for fresh deployments.\\n /// @param implementation The implementation stored in the proxy.\\n /// @param owner The owner used to derive the proxy address.\\n /// @param initData The data passed to the account initializer.\\n /// @return alreadyDeployed Whether the proxy already existed.\\n /// @return account The deployed or existing proxy address.\\n function deployProxy(address implementation, address owner, bytes memory initData)\\n internal\\n returns (bool alreadyDeployed, address payable account)\\n {\\n return\\n _deployProxy({implementation: implementation, owner: owner, initializationData: abi.encodeCall(\\n IHCAAccountInitializer.initializeAccount,\\n initData\\n )});\\n }\\n\\n /// @notice Deploys an uninitialized deterministic HCA proxy or funds the existing proxy.\\n /// @dev Used for implementations that intentionally expose no initialization function.\\n /// @param implementation The implementation stored in the proxy.\\n /// @param owner The owner used to derive the proxy address.\\n /// @return alreadyDeployed Whether the proxy already existed.\\n /// @return account The deployed or existing proxy address.\\n function deployProxyWithoutInitialization(address implementation, address owner)\\n internal\\n returns (bool alreadyDeployed, address payable account)\\n {\\n return _deployProxy({implementation: implementation, owner: owner, initializationData: \\\"\\\"});\\n }\\n\\n /// @notice Predicts the deterministic HCA proxy address for an owner.\\n /// @dev Uses the current contract address as the CREATE3 deployer.\\n /// @param owner The owner used to derive the proxy address.\\n /// @return predictedAddress The deterministic proxy address.\\n function predictProxyAddress(address owner)\\n internal\\n view\\n returns (address payable predictedAddress)\\n {\\n predictedAddress = payable(CREATE3.predictDeterministicAddress(_getSalt(owner)));\\n }\\n\\n /// @dev Returns the Yul-derived init-code prefix for initialized proxy deployment.\\n function initializedHCAProxyInitCodePrefix() internal pure returns (bytes memory) {\\n return INITIALIZED_HCA_PROXY_INIT_CODE_PREFIX;\\n }\\n\\n /// @dev Returns the Yul-derived init-code prefix for uninitialized proxy deployment.\\n function uninitializedHCAProxyInitCodePrefix() internal pure returns (bytes memory) {\\n return UNINITIALIZED_HCA_PROXY_INIT_CODE_PREFIX;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Deploys a proxy if absent. Existing proxies receive any attached ETH.\\n function _deployProxy(address implementation, address owner, bytes memory initializationData)\\n private\\n returns (bool alreadyDeployed, address payable account)\\n {\\n account = predictProxyAddress(owner);\\n alreadyDeployed = account.code.length > 0;\\n if (!alreadyDeployed) {\\n CREATE3.deployDeterministic(\\n msg.value,\\n _proxyInitCode(implementation, initializationData),\\n _getSalt(owner)\\n );\\n } else {\\n // solgrid-disable-next-line security/arbitrary-send-eth\\n (bool success, ) = account.call{value: msg.value}(\\\"\\\");\\n require(success, EthTransferFailed());\\n }\\n }\\n\\n /// @dev Converts an owner address into the deterministic CREATE3 salt used for that owner's proxy.\\n function _getSalt(address owner) private pure returns (bytes32) {\\n return bytes32(bytes20(owner));\\n }\\n\\n /// @dev Builds CREATE3 init code for a constructor-initialized ERC-1967 HCA proxy.\\n function _proxyInitCode(address implementation, bytes memory initializationData)\\n private\\n pure\\n returns (bytes memory initCode)\\n {\\n if (initializationData.length == 0) {\\n return bytes.concat(UNINITIALIZED_HCA_PROXY_INIT_CODE_PREFIX, bytes20(implementation));\\n }\\n return\\n bytes.concat(\\n INITIALIZED_HCA_PROXY_INIT_CODE_PREFIX,\\n bytes20(implementation),\\n initializationData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x2315f5accdff73012f1bb967b8b628eba4209809417785b33d494296eade4543\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.27;\\n\\nimport {IHCAFactoryBasic} from \\\"./IHCAFactoryBasic.sol\\\";\\nimport {IHCAInitDataParser} from \\\"./IHCAInitDataParser.sol\\\";\\n\\n/// @title IHCAFactory\\n/// @notice Full interface for deterministic Hidden Contract Account deployment and lookup.\\n/// @dev Interface selector: `0x65dc8339`\\ninterface IHCAFactory is IHCAFactoryBasic {\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Deploys or funds the deterministic HCA for the owner encoded in `initData`.\\n /// @dev Deploys with the owner's selected implementation when present, otherwise with the current implementation.\\n /// @param initData Initialization data used to identify and initialize the HCA owner.\\n /// @return hca The deployed or existing HCA proxy address.\\n function createAccount(bytes calldata initData) external payable returns (address payable hca);\\n\\n /// @notice Selects the implementation used when deploying this account's HCA.\\n /// @param accountImplementation The implementation to select.\\n function setAccountImplementation(address accountImplementation) external;\\n\\n /// @notice Updates the implementation and init data parser selectable for new HCA proxies.\\n /// @param implementation_ The new implementation address.\\n /// @param initDataParser_ The parser used to extract account ownership from initialization data.\\n function setImplementation(address implementation_, IHCAInitDataParser initDataParser_)\\n external;\\n\\n /// @notice Returns the implementation selectable for newly deployed HCA proxies.\\n function implementation() external view returns (address);\\n\\n /// @notice Returns the parser used to extract account ownership from initialization data.\\n function initDataParser() external view returns (IHCAInitDataParser);\\n\\n /// @notice Returns the immutable implementation that lets an owner defer their HCA upgrade target.\\n function DEFERRED_IMPLEMENTATION() external view returns (address);\\n\\n /// @notice Returns the implementation explicitly selected by an account.\\n /// @param account The account to inspect.\\n /// @return implementation The selected implementation.\\n function accountImplementationOf(address account)\\n external\\n view\\n returns (address implementation);\\n\\n /// @notice Returns the deterministic HCA address recorded for an account.\\n /// @param account The account to inspect.\\n /// @return hca The recorded HCA address.\\n function accountHCAOf(address account) external view returns (address hca);\\n\\n /// @notice Computes the deterministic HCA proxy address for an owner.\\n /// @param owner The owner whose HCA address to predict.\\n /// @return hca The deterministic proxy address.\\n function computeAccountAddress(address owner) external view returns (address payable hca);\\n\\n /// @notice Extracts the HCA owner from initialization data.\\n /// @param initData The initialization data to parse.\\n /// @return hcaOwner The owner encoded in the initialization data.\\n function getOwnerFromHCAInitdata(bytes calldata initData)\\n external\\n view\\n returns (address hcaOwner);\\n}\\n\",\"keccak256\":\"0x8aa87104f06533de48c351f678bade92eaf2f7f5d4aa11c80d9cd3305ef2241f\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAInitDataParser.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.27;\\n\\n/// @title IHCAInitDataParser\\n/// @notice Extracts Hidden Contract Account ownership from account initialization data.\\n/// @dev Interface selector: `0xf9660ea1`\\ninterface IHCAInitDataParser {\\n /// @notice Extracts the HCA owner from initialization data.\\n /// @param initData The initialization data to parse.\\n /// @return hcaOwner The owner encoded in the initialization data.\\n function getOwnerFromInitData(bytes calldata initData) external view returns (address hcaOwner);\\n}\\n\",\"keccak256\":\"0x7e04b480fb10b2c9be0956b61c3aa3d231f9a66b90a883d925ab3d34b6f5aded\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 34237, + "contract": "project/src/hca/HCAFactory.sol:HCAFactory", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 60191, + "contract": "project/src/hca/HCAFactory.sol:HCAFactory", + "label": "implementation", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 60195, + "contract": "project/src/hca/HCAFactory.sol:HCAFactory", + "label": "initDataParser", + "offset": 0, + "slot": "2", + "type": "t_contract(IHCAInitDataParser)60910" + }, + { + "astId": 60200, + "contract": "project/src/hca/HCAFactory.sol:HCAFactory", + "label": "_hcaOwners", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 60205, + "contract": "project/src/hca/HCAFactory.sol:HCAFactory", + "label": "_accountImplementations", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_address,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_contract(IHCAInitDataParser)60910": { + "encoding": "inplace", + "label": "contract IHCAInitDataParser", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + } + } + }, + "userdoc": { + "errors": { + "EthTransferFailed()": [ + { + "notice": "Thrown when ETH forwarding to an existing proxy fails." + } + ], + "HCAImplementationNotSelectable(address)": [ + { + "notice": "Thrown when an account selects an unsupported implementation." + } + ] + }, + "events": { + "AccountCreated(address,address)": { + "notice": "Emitted when a new HCA is deployed." + }, + "AccountImplementationSet(address,address)": { + "notice": "Emitted when an account selects its HCA implementation." + }, + "NewHCAImplementation(address,address)": { + "notice": "Emitted when the implementation and init data parser selectable for new HCA proxies change." + } + }, + "kind": "user", + "methods": { + "DEFERRED_IMPLEMENTATION()": { + "notice": "The implementation that lets an HCA owner defer the final account upgrade target." + }, + "accountHCAOf(address)": { + "notice": "Returns the deterministic HCA address recorded for an account." + }, + "accountImplementationOf(address)": { + "notice": "Returns the implementation explicitly selected by an account." + }, + "computeAccountAddress(address)": { + "notice": "Computes the deterministic HCA proxy address for an owner." + }, + "constructor": { + "notice": "Initializes the factory with an implementation, init data parser, owner, and deferred implementation." + }, + "createAccount(bytes)": { + "notice": "Deploys a new HCA proxy for the owner encoded in the initialization data, or forwards ETH if already deployed." + }, + "getAccountOwner(address)": { + "notice": "Returns the owner recorded for a deployed HCA proxy." + }, + "getOwnerFromHCAInitdata(bytes)": { + "notice": "Extracts the HCA owner from initialization data." + }, + "implementation()": { + "notice": "The current HCA implementation contract selectable by accounts." + }, + "initDataParser()": { + "notice": "The parser contract that extracts account ownership from HCA initialization data." + }, + "setAccountImplementation(address)": { + "notice": "Selects the implementation used when deploying the sender's deterministic HCA." + }, + "setImplementation(address,address)": { + "notice": "Updates the implementation and init data parser selectable for new HCA proxies." + } + }, + "notice": "Factory for deploying Hidden Contract Accounts as deterministic ERC-1967 proxies.", + "version": 1 + }, + "argsData": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80", + "transaction": { + "hash": "0xb3bd3ddbda9a50c1130cada000dca7bfe917619ebefad19ad7a1bda4be7034db", + "nonce": "0x1e4b", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xda2d75d5ef8f3faaad9017a3ed644bfcc9d0533524b8deef6858a51cbcef8ec6", + "blockNumber": "0xa6a7be", + "transactionIndex": "0x4c" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/LabelStore.json b/contracts/deployments/sepolia-official-v1-20260525-r2/LabelStore.json new file mode 100644 index 000000000..27447f08f --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/LabelStore.json @@ -0,0 +1,299 @@ +{ + "address": "0x23ea712da760c4e09fc9be108f1f1da6d5d6d053", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "LabelIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelIsTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "Label", + "type": "event" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getLabel", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setLabel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "LabelStore", + "sourceName": "src/utils/LabelStore.sol", + "bytecode": "0x60a0604052348015600e575f5ffd5b50604051610810380380610810833981016040819052602b91603b565b6001600160a01b03166080526066565b5f60208284031215604a575f5ffd5b81516001600160a01b0381168114605f575f5ffd5b9392505050565b60805161078c6100845f395f818160950152610195015261078c5ff3fe608060405234801561000f575f5ffd5b5060043610610064575f3560e01c80636f3ff7261161004d5780636f3ff726146100dc578063b21bf7fa146100ef578063bf5309691461010f575f5ffd5b806301ffc9a71461006857806348ee1bcc14610090575b5f5ffd5b61007b61007636600461049c565b610124565b60405190151581526020015b60405180910390f35b6100b77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610087565b61007b6100ea3660046104ca565b610167565b6101026100fd3660046104fd565b610200565b6040516100879190610514565b61012261011d366004610549565b6102a8565b005b5f6001600160e01b031982167f0d48fe930000000000000000000000000000000000000000000000000000000014806101615750610161826103b2565b92915050565b60405163379ffb9360e11b815273ffffffffffffffffffffffffffffffffffffffff82811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa1580156101dc573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016191906105b7565b60605f5f61020d846103ff565b81526020019081526020015f208054610225906105d6565b80601f0160208091040260200160405190810160405280929190818152602001828054610251906105d6565b801561029c5780601f106102735761010080835404028352916020019161029c565b820191905f5260205f20905b81548152906001019060200180831161027f57829003601f168201915b50505050509050919050565b6102e682828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061040e92505050565b505f61032683838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049192505050565b90505f610332826103ff565b5f81815260208190526040902080549192509061034e906105d6565b90505f036103ac575f81815260208190526040902061036e84868361066e565b50815f1b7f4acabfe38b19342d926f219b03cae7c02831d64c4449ccd3d6726b8ef1f9963085856040516103a3929190610728565b60405180910390a25b50505050565b5f6001600160e01b0319821663379ffb9360e11b148061016157507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610161565b5f63ffffffff82168218610161565b80515f9080820361044b576040517fbf9a274000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff81111561016157826040517fdab6c73c0000000000000000000000000000000000000000000000000000000081526004016104889190610514565b60405180910390fd5b805160209091012090565b5f602082840312156104ac575f5ffd5b81356001600160e01b0319811681146104c3575f5ffd5b9392505050565b5f602082840312156104da575f5ffd5b813573ffffffffffffffffffffffffffffffffffffffff811681146104c3575f5ffd5b5f6020828403121561050d575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f6020838503121561055a575f5ffd5b823567ffffffffffffffff811115610570575f5ffd5b8301601f81018513610580575f5ffd5b803567ffffffffffffffff811115610596575f5ffd5b8560208284010111156105a7575f5ffd5b6020919091019590945092505050565b5f602082840312156105c7575f5ffd5b815180151581146104c3575f5ffd5b600181811c908216806105ea57607f821691505b60208210810361060857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52604160045260245ffd5b601f82111561066957805f5260205f20601f840160051c810160208510156106475750805b601f840160051c820191505b81811015610666575f8155600101610653565b50505b505050565b67ffffffffffffffff8311156106865761068661060e565b61069a8361069483546105d6565b83610622565b5f601f8411600181146106cb575f85156106b45750838201355b5f19600387901b1c1916600186901b178355610666565b5f83815260208120601f198716915b828110156106fa57868501358255602094850194600190920191016106da565b5086821015610716575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f1916010191905056fea2646970667358221220871a9d0e95440d247e44b1a5b4bd1779b460d213efef23515b201d638cef80e764736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610064575f3560e01c80636f3ff7261161004d5780636f3ff726146100dc578063b21bf7fa146100ef578063bf5309691461010f575f5ffd5b806301ffc9a71461006857806348ee1bcc14610090575b5f5ffd5b61007b61007636600461049c565b610124565b60405190151581526020015b60405180910390f35b6100b77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610087565b61007b6100ea3660046104ca565b610167565b6101026100fd3660046104fd565b610200565b6040516100879190610514565b61012261011d366004610549565b6102a8565b005b5f6001600160e01b031982167f0d48fe930000000000000000000000000000000000000000000000000000000014806101615750610161826103b2565b92915050565b60405163379ffb9360e11b815273ffffffffffffffffffffffffffffffffffffffff82811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa1580156101dc573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016191906105b7565b60605f5f61020d846103ff565b81526020019081526020015f208054610225906105d6565b80601f0160208091040260200160405190810160405280929190818152602001828054610251906105d6565b801561029c5780601f106102735761010080835404028352916020019161029c565b820191905f5260205f20905b81548152906001019060200180831161027f57829003601f168201915b50505050509050919050565b6102e682828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061040e92505050565b505f61032683838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049192505050565b90505f610332826103ff565b5f81815260208190526040902080549192509061034e906105d6565b90505f036103ac575f81815260208190526040902061036e84868361066e565b50815f1b7f4acabfe38b19342d926f219b03cae7c02831d64c4449ccd3d6726b8ef1f9963085856040516103a3929190610728565b60405180910390a25b50505050565b5f6001600160e01b0319821663379ffb9360e11b148061016157507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610161565b5f63ffffffff82168218610161565b80515f9080820361044b576040517fbf9a274000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff81111561016157826040517fdab6c73c0000000000000000000000000000000000000000000000000000000081526004016104889190610514565b60405180910390fd5b805160209091012090565b5f602082840312156104ac575f5ffd5b81356001600160e01b0319811681146104c3575f5ffd5b9392505050565b5f602082840312156104da575f5ffd5b813573ffffffffffffffffffffffffffffffffffffffff811681146104c3575f5ffd5b5f6020828403121561050d575f5ffd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f6020838503121561055a575f5ffd5b823567ffffffffffffffff811115610570575f5ffd5b8301601f81018513610580575f5ffd5b803567ffffffffffffffff811115610596575f5ffd5b8560208284010111156105a7575f5ffd5b6020919091019590945092505050565b5f602082840312156105c7575f5ffd5b815180151581146104c3575f5ffd5b600181811c908216806105ea57607f821691505b60208210810361060857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52604160045260245ffd5b601f82111561066957805f5260205f20601f840160051c810160208510156106475750805b601f840160051c820191505b81811015610666575f8155600101610653565b50505b505050565b67ffffffffffffffff8311156106865761068661060e565b61069a8361069483546105d6565b83610622565b5f601f8411600181146106cb575f85156106b45750838201355b5f19600387901b1c1916600186901b178355610666565b5f83815260208120601f198716915b828110156106fa57868501358255602094850194600190920191016106da565b5086821015610716575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f1916010191905056fea2646970667358221220871a9d0e95440d247e44b1a5b4bd1779b460d213efef23515b201d638cef80e764736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "75212": [ + { + "length": 32, + "start": 149 + }, + { + "length": 32, + "start": 405 + } + ] + }, + "inputSourceName": "project/src/utils/LabelStore.sol", + "devdoc": { + "errors": { + "LabelIsEmpty()": [ + { + "details": "The label was empty. Error selector: `0xbf9a2740`" + } + ], + "LabelIsTooLong(string)": [ + { + "details": "The label was more than 255 bytes. Error selector: `0xdab6c73c`" + } + ] + }, + "events": { + "Label(bytes32,string)": { + "params": { + "label": "The recorded label.", + "labelHash": "The hash of `label`." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "contractNamer": "Delegated contract namer." + } + }, + "getLabel(uint256)": { + "params": { + "anyId": "The truncated labelhash." + }, + "returns": { + "_0": "The label or null if unknown." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "setLabel(string)": { + "params": { + "label": "The label." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "stateVariables": { + "_labels": { + "details": "The truncated labelhash to label mapping." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "386400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "getLabel(uint256)": "infinite", + "isContractNamer(address)": "infinite", + "setLabel(string)": "infinite", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_storageId(uint256)": "48" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"LabelIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelIsTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"Label\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getLabel\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setLabel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"LabelIsEmpty()\":[{\"details\":\"The label was empty. Error selector: `0xbf9a2740`\"}],\"LabelIsTooLong(string)\":[{\"details\":\"The label was more than 255 bytes. Error selector: `0xdab6c73c`\"}]},\"events\":{\"Label(bytes32,string)\":{\"params\":{\"label\":\"The recorded label.\",\"labelHash\":\"The hash of `label`.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\"}},\"getLabel(uint256)\":{\"params\":{\"anyId\":\"The truncated labelhash.\"},\"returns\":{\"_0\":\"The label or null if unknown.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"setLabel(string)\":{\"params\":{\"label\":\"The label.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"_labels\":{\"details\":\"The truncated labelhash to label mapping.\"}},\"version\":1},\"userdoc\":{\"events\":{\"Label(bytes32,string)\":{\"notice\":\"A label was recorded.\"}},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"getLabel(uint256)\":{\"notice\":\"Invert `anyId` to the corresponding label.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"setLabel(string)\":{\"notice\":\"Ensure `label` can be inverted from `anyId`.\"}},\"notice\":\"Shared label database.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/utils/LabelStore.sol\":\"LabelStore\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"},\"project/src/utils/LabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {DelegatedContractNamer} from \\\"./DelegatedContractNamer.sol\\\";\\nimport {ILabelStore} from \\\"./interfaces/ILabelStore.sol\\\";\\nimport {LibLabel} from \\\"./LibLabel.sol\\\";\\n\\n/// @notice Shared label database.\\ncontract LabelStore is DelegatedContractNamer, ILabelStore {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The truncated labelhash to label mapping.\\n mapping(uint256 storageId => string label) internal _labels;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) DelegatedContractNamer(contractNamer) {}\\n\\n /// @inheritdoc DelegatedContractNamer\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return interfaceId == type(ILabelStore).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ILabelStore\\n function setLabel(string calldata label) external {\\n NameCoder.assertLabelSize(label);\\n uint256 labelId = LibLabel.id(label);\\n uint256 storageId = _storageId(labelId);\\n if (bytes(_labels[storageId]).length == 0) {\\n _labels[storageId] = label;\\n emit Label(bytes32(labelId), label);\\n }\\n }\\n\\n /// @inheritdoc ILabelStore\\n function getLabel(uint256 anyId) public view returns (string memory) {\\n return _labels[_storageId(anyId)];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Convert `anyId` to `storageId`.\\n function _storageId(uint256 anyId) internal pure returns (uint256) {\\n return LibLabel.withVersion(anyId, 0);\\n }\\n}\\n\",\"keccak256\":\"0x2f9cb8449c35bde2bcadc6735e271e9d1cd6998f62681cffe5344fb8e5c76178\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/interfaces/ILabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @notice Interface for a shared label database.\\n/// @dev Interface selector: `0x0d48fe93`\\ninterface ILabelStore {\\n /// @notice A label was recorded.\\n /// @param labelHash The hash of `label`.\\n /// @param label The recorded label.\\n event Label(bytes32 indexed labelHash, string label);\\n\\n /// @notice Ensure `label` can be inverted from `anyId`.\\n /// @param label The label.\\n function setLabel(string calldata label) external;\\n\\n /// @notice Invert `anyId` to the corresponding label.\\n /// @param anyId The truncated labelhash.\\n /// @return The label or null if unknown.\\n function getLabel(uint256 anyId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 75283, + "contract": "project/src/utils/LabelStore.sol:LabelStore", + "label": "_labels", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_string_storage)" + } + ], + "types": { + "t_mapping(t_uint256,t_string_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + }, + "userdoc": { + "events": { + "Label(bytes32,string)": { + "notice": "A label was recorded." + } + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "getLabel(uint256)": { + "notice": "Invert `anyId` to the corresponding label." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "setLabel(string)": { + "notice": "Ensure `label` can be inverted from `anyId`." + } + }, + "notice": "Shared label database.", + "version": 1 + }, + "argsData": "0x000000000000000000000000fc8bf9234969d6b85729b756fa9e14bb84a06754", + "transaction": { + "hash": "0xc0f3c254bf1bbf43ee712ab9823009cffa1cae887eb1aa2c39b4f735a8874c19", + "nonce": "0x1e4c", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x6d4b068f4c83f68512d9c35f7c10126ebf900efea208290a90663b6f601feff5", + "blockNumber": "0xa6a7bf", + "transactionIndex": "0x3c" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/LockedMigrationController.json b/contracts/deployments/sepolia-official-v1-20260525-r2/LockedMigrationController.json new file mode 100644 index 000000000..224e85def --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/LockedMigrationController.json @@ -0,0 +1,754 @@ +{ + "address": "0xf91c34ed840889ed96f806f882fd50506a336edb", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "address", + "name": "graveyard", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry", + "type": "address" + }, + { + "internalType": "contract VerifiableFactory", + "name": "verifiableFactory", + "type": "address" + }, + { + "internalType": "address", + "name": "wrapperRegistryImpl", + "type": "address" + }, + { + "internalType": "contract IAddressSet", + "name": "publicResolverSet", + "type": "address" + }, + { + "internalType": "address", + "name": "publicResolver", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "FrozenTokenApproval", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameDataMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameNotLocked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GRAVEYARD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_RESOLVER_SET", + "outputs": [ + { + "internalType": "contract IAddressSet", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERIFIABLE_FACTORY", + "outputs": [ + { + "internalType": "contract IVerifiableFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WRAPPER_REGISTRY_IMPL", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[]", + "name": "mds", + "type": "tuple[]" + } + ], + "name": "finishERC1155Migration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedName", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNode", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "LockedMigrationController", + "sourceName": "src/migration/LockedMigrationController.sol", + "bytecode": "0x6101a0604052348015610010575f5ffd5b5060405161216638038061216683398101604081905261002f9161012a565b808888878787878585816001600160a01b03166080816001600160a01b031681525050806001600160a01b031660a0816001600160a01b031681525050816001600160a01b0316633f15457f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100a8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100cc91906101d5565b6001600160a01b0390811660c05295861660e0525050918316610100528216610120528116610140529283166101605250509590951661018052506101f795505050505050565b6001600160a01b0381168114610127575f5ffd5b50565b5f5f5f5f5f5f5f5f610100898b031215610142575f5ffd5b885161014d81610113565b60208a015190985061015e81610113565b60408a015190975061016f81610113565b60608a015190965061018081610113565b60808a015190955061019181610113565b60a08a01519094506101a281610113565b60c08a01519093506101b381610113565b60e08a01519092506101c481610113565b809150509295985092959890939650565b5f602082840312156101e5575f5ffd5b81516101f081610113565b9392505050565b60805160a05160c05160e0516101005161012051610140516101605161018051611e8c6102da5f395f8181610187015281816108d701526112e201525f81816101ae01526103c301525f81816102f40152610d9701525f81816102cd0152610d2501525f81816101d50152610ebb01525f81816101210152610e8c01525f610c7901525f81816101fc01528181610def015261109501525f81816101600152818161047f01528181610503015281816106b201528181610a4401528181610b1101528181610be601528181610e3201528181610ffa01526110bd0152611e8c5ff3fe608060405234801561000f575f5ffd5b50600436106100f0575f3560e01c80635d05f04911610093578063bc197c8111610063578063bc197c8114610289578063f23a6e61146102b5578063f923b685146102c8578063ffeb4a30146102ef575f5ffd5b80635d05f0491461021e5780636e7a2116146102335780636f3ff726146102615780639b224b1d14610274575f5ffd5b806347500708116100ce578063475007081461018257806348ee1bcc146101a9578063547c9d2d146101d05780635c1a6b68146101f7575f5ffd5b806301ffc9a7146100f457806318ad9b711461011c578063192cf07d1461015b575b5f5ffd5b6101076101023660046114ff565b610316565b60405190151581526020015b60405180910390f35b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610113565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b61023161022c366004611575565b610326565b005b6040517f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae8152602001610113565b61010761026f366004611603565b6103a2565b61027c61042e565b604051610113919061164c565b61029c61029736600461169c565b6104f7565b6040516001600160e01b03199091168152602001610113565b61029c6102c336600461175f565b6106a6565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b5f610320826108b1565b92915050565b33301461034d5760405163d86ad9cf60e01b81523360048201526024015b60405180910390fd5b828114610390576040517f5b0599910000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610344565b61039c848484846108d5565b50505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561040a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032091906117d6565b6040517f20c38e2b0000000000000000000000000000000000000000000000000000000081527f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae60048201526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906320c38e2b906024015f60405180830381865afa1580156104cb573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104f2919081019061188a565b905090565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610579576040513360248201526105799063d86ad9cf60e01b906044015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261119a565b828261058660e089611918565b61059190604061192f565b808210156105cb576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b1790526105cb9061119a565b5f6105d8868801886119f5565b604051635d05f04960e01b81529091503090635d05f04990610602908e908e908690600401611b47565b5f604051808303815f87803b158015610619575f5ffd5b505af192505050801561062a575060015b61066c573d808015610657576040519150601f19603f3d011682016040523d82523d5f602084013e61065c565b606091505b506106668161119a565b50610695565b507fbc197c81000000000000000000000000000000000000000000000000000000009350610697565b505b50505098975050505050505050565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106f5576040513360248201526106f59063d86ad9cf60e01b90604401610542565b828260e080821015610733576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b1790526107339061119a565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f1990920191018161076b57905050905089825f815181106107b3576107b3611bae565b60209081029190910101526107ca87890189611bc2565b815f815181106107dc576107dc611bae565b6020908102919091010152604051635d05f04960e01b81523090635d05f0499061080c9085908590600401611bfc565b5f604051808303815f87803b158015610823575f5ffd5b505af1925050508015610834575060015b610876573d808015610861576040519150601f19603f3d011682016040523d82523d5f602084013e610866565b606091505b506108708161119a565b506108a1565b507ff23a6e610000000000000000000000000000000000000000000000000000000094506108a49050565b50505b5050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b14806103205750610320826111ad565b7f00000000000000000000000000000000000000000000000000000000000000007f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae5f5b85811015611191575f85858381811061093457610934611bae565b90506020028101906109469190611c49565b61094f90611c67565b60208101519091506001600160a01b0316610996576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8888848181106109a9576109a9611bae565b845180516020918201209102929092013592506109d1905085825f9182526020526040902090565b8214610a0c576040517fedec356900000000000000000000000000000000000000000000000000000000815260048101839052602401610344565b60608301516040517f0178fe3f000000000000000000000000000000000000000000000000000000008152600481018490525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015610a91573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab59190611c72565b9250925050610ac682600116151590565b15610fcf576040821615801590610b8657506040517f081812fc000000000000000000000000000000000000000000000000000000008152600481018690525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063081812fc90602401602060405180830381865afa158015610b56573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b7a9190611cd0565b6001600160a01b031614155b15610bc0576040517fa4f0771300000000000000000000000000000000000000000000000000000000815260048101869052602401610344565b600882165f03610c4a57604051630c4b7b8560e11b8152600481018690525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015610c2f575f5ffd5b505af1158015610c41573d5f5f3e3d5ffd5b50505050610db9565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178b8bf90602401602060405180830381865afa158015610cc6573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cea9190611cd0565b6040517f1aedefda0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529194507f000000000000000000000000000000000000000000000000000000000000000090911690631aedefda90602401602060405180830381865afa158015610d6c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d9091906117d6565b15610db9577f000000000000000000000000000000000000000000000000000000000000000092505b6040517ff242432a0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526001606483015260a060848301525f60a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c4015f604051808303815f87803b158015610e73575f5ffd5b505af1158015610e85573d5f5f3e3d5ffd5b505050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d84121a7f0000000000000000000000000000000000000000000000000000000000000000885f1c898e8c5f01518d60200151610ef18b611213565b604051602401610f05959493929190611ceb565b60408051601f198184030181529181526020820180516001600160e01b03167f9e77193200000000000000000000000000000000000000000000000000000000179052516001600160e01b031960e086901b168152610f6993929190600401611d2f565b6020604051808303815f875af1158015610f85573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fa99190611cd0565b9050610fc8875f015188602001518387610fc288611258565b876112b0565b5050611180565b620100006203000083160361114b57604051630c4b7b8560e11b8152600481018690525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015611043575f5ffd5b505af1158015611055573d5f5f3e3d5ffd5b50506040517fd8c9921a000000000000000000000000000000000000000000000000000000008152600481018b9052602481018790526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448301527f000000000000000000000000000000000000000000000000000000000000000016925063d8c9921a91506064015f604051808303815f87803b158015611100575f5ffd5b505af1158015611112573d5f5f3e3d5ffd5b50508751602089015160408a015161114594509192509086731110000000000000000000000000000001100000866112b0565b50611180565b6040517f1bfe8f0a00000000000000000000000000000000000000000000000000000000815260048101869052602401610344565b505050505050806001019050610919565b50505050505050565b6111a38161136c565b9050805160208201fd5b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061032057507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610320565b5f602082168103611222576001175b6002821661123157608081901b175b7f110000000000000000000000000100001100000000000000000000000001000017919050565b5f6204000082161561126a5762010000175b600882165f0361127b576301000000175b6002821661128a57608081901b175b600482165f036112ab57731000000000000000000000000000000000000000175b919050565b6040517f85f3e6430000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385f3e64390611321908a908a908a908a908a908990600401611d5f565b6020604051808303815f875af115801561133d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113619190611dc1565b979650505050505050565b60605f8251118015611396575062461bcd60e51b61138983611dd8565b6001600160e01b03191614155b1561142f5762461bcd60e51b7f577261707065644572726f723a3a3078000000000000000000000000000000006113cc84611433565b6040516020016113dd929190611e14565b60408051601f19818403018152908290526113fa9160240161164c565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b805160609060011b8067ffffffffffffffff811115611454576114546117f5565b6040519080825280601f01601f19166020018201604052801561147e576020820181803683370190505b509150602083810190830161149482828561149c565b505050919050565b8181015b8083101561039c5783516101005b82851080156114bc57505f81115b156114f25760031901600f82821c16600a81106114dc57806057016114e1565b806030015b9050808653506001909401936114ae565b50506020840193506114a0565b5f6020828403121561150f575f5ffd5b81356001600160e01b031981168114611526575f5ffd5b9392505050565b5f5f83601f84011261153d575f5ffd5b50813567ffffffffffffffff811115611554575f5ffd5b6020830191508360208260051b850101111561156e575f5ffd5b9250929050565b5f5f5f5f60408587031215611588575f5ffd5b843567ffffffffffffffff81111561159e575f5ffd5b6115aa8782880161152d565b909550935050602085013567ffffffffffffffff8111156115c9575f5ffd5b6115d58782880161152d565b95989497509550505050565b6001600160a01b03811681146115f5575f5ffd5b50565b80356112ab816115e1565b5f60208284031215611613575f5ffd5b8135611526816115e1565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611526602083018461161e565b5f5f83601f84011261166e575f5ffd5b50813567ffffffffffffffff811115611685575f5ffd5b60208301915083602082850101111561156e575f5ffd5b5f5f5f5f5f5f5f5f60a0898b0312156116b3575f5ffd5b88356116be816115e1565b975060208901356116ce816115e1565b9650604089013567ffffffffffffffff8111156116e9575f5ffd5b6116f58b828c0161152d565b909750955050606089013567ffffffffffffffff811115611714575f5ffd5b6117208b828c0161152d565b909550935050608089013567ffffffffffffffff81111561173f575f5ffd5b61174b8b828c0161165e565b999c989b5096995094979396929594505050565b5f5f5f5f5f5f60a08789031215611774575f5ffd5b863561177f816115e1565b9550602087013561178f816115e1565b94506040870135935060608701359250608087013567ffffffffffffffff8111156117b8575f5ffd5b6117c489828a0161165e565b979a9699509497509295939492505050565b5f602082840312156117e6575f5ffd5b81518015158114611526575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff8111828210171561182c5761182c6117f5565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561185b5761185b6117f5565b604052919050565b5f67ffffffffffffffff82111561187c5761187c6117f5565b50601f01601f191660200190565b5f6020828403121561189a575f5ffd5b815167ffffffffffffffff8111156118b0575f5ffd5b8201601f810184136118c0575f5ffd5b80516118d36118ce82611863565b611832565b8181528560208385010111156118e7575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761032057610320611904565b8082018082111561032057610320611904565b5f60808284031215611952575f5ffd5b61195a611809565b9050813567ffffffffffffffff811115611972575f5ffd5b8201601f81018413611982575f5ffd5b80356119906118ce82611863565b8181528560208385010111156119a4575f5ffd5b816020840160208301375f602083830101528084525050506119c8602083016115f8565b60208201526119d9604083016115f8565b60408201526119ea606083016115f8565b606082015292915050565b5f60208284031215611a05575f5ffd5b813567ffffffffffffffff811115611a1b575f5ffd5b8201601f81018413611a2b575f5ffd5b803567ffffffffffffffff811115611a4557611a456117f5565b8060051b611a5560208201611832565b91825260208184018101929081019087841115611a70575f5ffd5b6020850192505b8383101561136157823567ffffffffffffffff811115611a95575f5ffd5b611aa489602083890101611942565b83525060209283019290910190611a77565b5f82825180855260208501945060208160051b830101602085015f5b83811015611b3b57601f198584030188528151805160808552611af8608086018261161e565b6020838101516001600160a01b03908116888301526040808601518216908901526060948501511693909601929092525097830197929190910190600101611ad2565b50909695505050505050565b604081528260408201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841115611b7e575f5ffd5b8360051b80866060850137820182810360609081016020850152611ba490820185611ab6565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611bd2575f5ffd5b813567ffffffffffffffff811115611be8575f5ffd5b611bf484828501611942565b949350505050565b604080825283519082018190525f9060208501906060840190835b81811015611c35578351835260209384019390920191600101611c17565b50508381036020850152611ba48186611ab6565b5f8235607e19833603018112611c5d575f5ffd5b9190910192915050565b5f6103203683611942565b5f5f5f60608486031215611c84575f5ffd5b8351611c8f816115e1565b602085015190935063ffffffff81168114611ca8575f5ffd5b604085015190925067ffffffffffffffff81168114611cc5575f5ffd5b809150509250925092565b5f60208284031215611ce0575f5ffd5b8151611526816115e1565b8581526001600160a01b038516602082015260a060408201525f611d1260a083018661161e565b6001600160a01b0394909416606083015250608001529392505050565b6001600160a01b0384168152826020820152606060408201525f611d56606083018461161e565b95945050505050565b60c081525f611d7160c083018961161e565b90506001600160a01b03871660208301526001600160a01b03861660408301526001600160a01b038516606083015283608083015267ffffffffffffffff831660a0830152979650505050505050565b5f60208284031215611dd1575f5ffd5b5051919050565b805160208201516001600160e01b0319811691906004821015611e0d576001600160e01b0319808360040360031b1b82161692505b5050919050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000831681525f82518060208501601085015e5f9201601001918252509291505056fea264697066735822122076c8e6c41b327064b66fd1fb1c19895ac0751b01e50c9cefd0e3368b752962b764736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100f0575f3560e01c80635d05f04911610093578063bc197c8111610063578063bc197c8114610289578063f23a6e61146102b5578063f923b685146102c8578063ffeb4a30146102ef575f5ffd5b80635d05f0491461021e5780636e7a2116146102335780636f3ff726146102615780639b224b1d14610274575f5ffd5b806347500708116100ce578063475007081461018257806348ee1bcc146101a9578063547c9d2d146101d05780635c1a6b68146101f7575f5ffd5b806301ffc9a7146100f457806318ad9b711461011c578063192cf07d1461015b575b5f5ffd5b6101076101023660046114ff565b610316565b60405190151581526020015b60405180910390f35b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610113565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b61023161022c366004611575565b610326565b005b6040517f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae8152602001610113565b61010761026f366004611603565b6103a2565b61027c61042e565b604051610113919061164c565b61029c61029736600461169c565b6104f7565b6040516001600160e01b03199091168152602001610113565b61029c6102c336600461175f565b6106a6565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b5f610320826108b1565b92915050565b33301461034d5760405163d86ad9cf60e01b81523360048201526024015b60405180910390fd5b828114610390576040517f5b0599910000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610344565b61039c848484846108d5565b50505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561040a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032091906117d6565b6040517f20c38e2b0000000000000000000000000000000000000000000000000000000081527f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae60048201526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906320c38e2b906024015f60405180830381865afa1580156104cb573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104f2919081019061188a565b905090565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610579576040513360248201526105799063d86ad9cf60e01b906044015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261119a565b828261058660e089611918565b61059190604061192f565b808210156105cb576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b1790526105cb9061119a565b5f6105d8868801886119f5565b604051635d05f04960e01b81529091503090635d05f04990610602908e908e908690600401611b47565b5f604051808303815f87803b158015610619575f5ffd5b505af192505050801561062a575060015b61066c573d808015610657576040519150601f19603f3d011682016040523d82523d5f602084013e61065c565b606091505b506106668161119a565b50610695565b507fbc197c81000000000000000000000000000000000000000000000000000000009350610697565b505b50505098975050505050505050565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106f5576040513360248201526106f59063d86ad9cf60e01b90604401610542565b828260e080821015610733576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b1790526107339061119a565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f1990920191018161076b57905050905089825f815181106107b3576107b3611bae565b60209081029190910101526107ca87890189611bc2565b815f815181106107dc576107dc611bae565b6020908102919091010152604051635d05f04960e01b81523090635d05f0499061080c9085908590600401611bfc565b5f604051808303815f87803b158015610823575f5ffd5b505af1925050508015610834575060015b610876573d808015610861576040519150601f19603f3d011682016040523d82523d5f602084013e610866565b606091505b506108708161119a565b506108a1565b507ff23a6e610000000000000000000000000000000000000000000000000000000094506108a49050565b50505b5050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b14806103205750610320826111ad565b7f00000000000000000000000000000000000000000000000000000000000000007f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae5f5b85811015611191575f85858381811061093457610934611bae565b90506020028101906109469190611c49565b61094f90611c67565b60208101519091506001600160a01b0316610996576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8888848181106109a9576109a9611bae565b845180516020918201209102929092013592506109d1905085825f9182526020526040902090565b8214610a0c576040517fedec356900000000000000000000000000000000000000000000000000000000815260048101839052602401610344565b60608301516040517f0178fe3f000000000000000000000000000000000000000000000000000000008152600481018490525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015610a91573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab59190611c72565b9250925050610ac682600116151590565b15610fcf576040821615801590610b8657506040517f081812fc000000000000000000000000000000000000000000000000000000008152600481018690525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063081812fc90602401602060405180830381865afa158015610b56573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b7a9190611cd0565b6001600160a01b031614155b15610bc0576040517fa4f0771300000000000000000000000000000000000000000000000000000000815260048101869052602401610344565b600882165f03610c4a57604051630c4b7b8560e11b8152600481018690525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015610c2f575f5ffd5b505af1158015610c41573d5f5f3e3d5ffd5b50505050610db9565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178b8bf90602401602060405180830381865afa158015610cc6573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cea9190611cd0565b6040517f1aedefda0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529194507f000000000000000000000000000000000000000000000000000000000000000090911690631aedefda90602401602060405180830381865afa158015610d6c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d9091906117d6565b15610db9577f000000000000000000000000000000000000000000000000000000000000000092505b6040517ff242432a0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526001606483015260a060848301525f60a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c4015f604051808303815f87803b158015610e73575f5ffd5b505af1158015610e85573d5f5f3e3d5ffd5b505050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d84121a7f0000000000000000000000000000000000000000000000000000000000000000885f1c898e8c5f01518d60200151610ef18b611213565b604051602401610f05959493929190611ceb565b60408051601f198184030181529181526020820180516001600160e01b03167f9e77193200000000000000000000000000000000000000000000000000000000179052516001600160e01b031960e086901b168152610f6993929190600401611d2f565b6020604051808303815f875af1158015610f85573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fa99190611cd0565b9050610fc8875f015188602001518387610fc288611258565b876112b0565b5050611180565b620100006203000083160361114b57604051630c4b7b8560e11b8152600481018690525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015611043575f5ffd5b505af1158015611055573d5f5f3e3d5ffd5b50506040517fd8c9921a000000000000000000000000000000000000000000000000000000008152600481018b9052602481018790526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448301527f000000000000000000000000000000000000000000000000000000000000000016925063d8c9921a91506064015f604051808303815f87803b158015611100575f5ffd5b505af1158015611112573d5f5f3e3d5ffd5b50508751602089015160408a015161114594509192509086731110000000000000000000000000000001100000866112b0565b50611180565b6040517f1bfe8f0a00000000000000000000000000000000000000000000000000000000815260048101869052602401610344565b505050505050806001019050610919565b50505050505050565b6111a38161136c565b9050805160208201fd5b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061032057507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610320565b5f602082168103611222576001175b6002821661123157608081901b175b7f110000000000000000000000000100001100000000000000000000000001000017919050565b5f6204000082161561126a5762010000175b600882165f0361127b576301000000175b6002821661128a57608081901b175b600482165f036112ab57731000000000000000000000000000000000000000175b919050565b6040517f85f3e6430000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385f3e64390611321908a908a908a908a908a908990600401611d5f565b6020604051808303815f875af115801561133d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113619190611dc1565b979650505050505050565b60605f8251118015611396575062461bcd60e51b61138983611dd8565b6001600160e01b03191614155b1561142f5762461bcd60e51b7f577261707065644572726f723a3a3078000000000000000000000000000000006113cc84611433565b6040516020016113dd929190611e14565b60408051601f19818403018152908290526113fa9160240161164c565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b805160609060011b8067ffffffffffffffff811115611454576114546117f5565b6040519080825280601f01601f19166020018201604052801561147e576020820181803683370190505b509150602083810190830161149482828561149c565b505050919050565b8181015b8083101561039c5783516101005b82851080156114bc57505f81115b156114f25760031901600f82821c16600a81106114dc57806057016114e1565b806030015b9050808653506001909401936114ae565b50506020840193506114a0565b5f6020828403121561150f575f5ffd5b81356001600160e01b031981168114611526575f5ffd5b9392505050565b5f5f83601f84011261153d575f5ffd5b50813567ffffffffffffffff811115611554575f5ffd5b6020830191508360208260051b850101111561156e575f5ffd5b9250929050565b5f5f5f5f60408587031215611588575f5ffd5b843567ffffffffffffffff81111561159e575f5ffd5b6115aa8782880161152d565b909550935050602085013567ffffffffffffffff8111156115c9575f5ffd5b6115d58782880161152d565b95989497509550505050565b6001600160a01b03811681146115f5575f5ffd5b50565b80356112ab816115e1565b5f60208284031215611613575f5ffd5b8135611526816115e1565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611526602083018461161e565b5f5f83601f84011261166e575f5ffd5b50813567ffffffffffffffff811115611685575f5ffd5b60208301915083602082850101111561156e575f5ffd5b5f5f5f5f5f5f5f5f60a0898b0312156116b3575f5ffd5b88356116be816115e1565b975060208901356116ce816115e1565b9650604089013567ffffffffffffffff8111156116e9575f5ffd5b6116f58b828c0161152d565b909750955050606089013567ffffffffffffffff811115611714575f5ffd5b6117208b828c0161152d565b909550935050608089013567ffffffffffffffff81111561173f575f5ffd5b61174b8b828c0161165e565b999c989b5096995094979396929594505050565b5f5f5f5f5f5f60a08789031215611774575f5ffd5b863561177f816115e1565b9550602087013561178f816115e1565b94506040870135935060608701359250608087013567ffffffffffffffff8111156117b8575f5ffd5b6117c489828a0161165e565b979a9699509497509295939492505050565b5f602082840312156117e6575f5ffd5b81518015158114611526575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff8111828210171561182c5761182c6117f5565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561185b5761185b6117f5565b604052919050565b5f67ffffffffffffffff82111561187c5761187c6117f5565b50601f01601f191660200190565b5f6020828403121561189a575f5ffd5b815167ffffffffffffffff8111156118b0575f5ffd5b8201601f810184136118c0575f5ffd5b80516118d36118ce82611863565b611832565b8181528560208385010111156118e7575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761032057610320611904565b8082018082111561032057610320611904565b5f60808284031215611952575f5ffd5b61195a611809565b9050813567ffffffffffffffff811115611972575f5ffd5b8201601f81018413611982575f5ffd5b80356119906118ce82611863565b8181528560208385010111156119a4575f5ffd5b816020840160208301375f602083830101528084525050506119c8602083016115f8565b60208201526119d9604083016115f8565b60408201526119ea606083016115f8565b606082015292915050565b5f60208284031215611a05575f5ffd5b813567ffffffffffffffff811115611a1b575f5ffd5b8201601f81018413611a2b575f5ffd5b803567ffffffffffffffff811115611a4557611a456117f5565b8060051b611a5560208201611832565b91825260208184018101929081019087841115611a70575f5ffd5b6020850192505b8383101561136157823567ffffffffffffffff811115611a95575f5ffd5b611aa489602083890101611942565b83525060209283019290910190611a77565b5f82825180855260208501945060208160051b830101602085015f5b83811015611b3b57601f198584030188528151805160808552611af8608086018261161e565b6020838101516001600160a01b03908116888301526040808601518216908901526060948501511693909601929092525097830197929190910190600101611ad2565b50909695505050505050565b604081528260408201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841115611b7e575f5ffd5b8360051b80866060850137820182810360609081016020850152611ba490820185611ab6565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611bd2575f5ffd5b813567ffffffffffffffff811115611be8575f5ffd5b611bf484828501611942565b949350505050565b604080825283519082018190525f9060208501906060840190835b81811015611c35578351835260209384019390920191600101611c17565b50508381036020850152611ba48186611ab6565b5f8235607e19833603018112611c5d575f5ffd5b9190910192915050565b5f6103203683611942565b5f5f5f60608486031215611c84575f5ffd5b8351611c8f816115e1565b602085015190935063ffffffff81168114611ca8575f5ffd5b604085015190925067ffffffffffffffff81168114611cc5575f5ffd5b809150509250925092565b5f60208284031215611ce0575f5ffd5b8151611526816115e1565b8581526001600160a01b038516602082015260a060408201525f611d1260a083018661161e565b6001600160a01b0394909416606083015250608001529392505050565b6001600160a01b0384168152826020820152606060408201525f611d56606083018461161e565b95945050505050565b60c081525f611d7160c083018961161e565b90506001600160a01b03871660208301526001600160a01b03861660408301526001600160a01b038516606083015283608083015267ffffffffffffffff831660a0830152979650505050505050565b5f60208284031215611dd1575f5ffd5b5051919050565b805160208201516001600160e01b0319811691906004821015611e0d576001600160e01b0319808360040360031b1b82161692505b5050919050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000831681525f82518060208501601085015e5f9201601001918252509291505056fea264697066735822122076c8e6c41b327064b66fd1fb1c19895ac0751b01e50c9cefd0e3368b752962b764736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60938": [ + { + "length": 32, + "start": 352 + }, + { + "length": 32, + "start": 1151 + }, + { + "length": 32, + "start": 1283 + }, + { + "length": 32, + "start": 1714 + }, + { + "length": 32, + "start": 2628 + }, + { + "length": 32, + "start": 2833 + }, + { + "length": 32, + "start": 3046 + }, + { + "length": 32, + "start": 3634 + }, + { + "length": 32, + "start": 4090 + }, + { + "length": 32, + "start": 4285 + } + ], + "60941": [ + { + "length": 32, + "start": 508 + }, + { + "length": 32, + "start": 3567 + }, + { + "length": 32, + "start": 4245 + } + ], + "60945": [ + { + "length": 32, + "start": 3193 + } + ], + "61794": [ + { + "length": 32, + "start": 391 + }, + { + "length": 32, + "start": 2263 + }, + { + "length": 32, + "start": 4834 + } + ], + "61942": [ + { + "length": 32, + "start": 289 + }, + { + "length": 32, + "start": 3724 + } + ], + "61945": [ + { + "length": 32, + "start": 469 + }, + { + "length": 32, + "start": 3771 + } + ], + "61949": [ + { + "length": 32, + "start": 717 + }, + { + "length": 32, + "start": 3365 + } + ], + "61952": [ + { + "length": 32, + "start": 756 + }, + { + "length": 32, + "start": 3479 + } + ], + "75212": [ + { + "length": 32, + "start": 430 + }, + { + "length": 32, + "start": 963 + } + ] + }, + "inputSourceName": "project/src/migration/LockedMigrationController.sol", + "devdoc": { + "errors": { + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "FrozenTokenApproval(uint256)": [ + { + "details": "Error selector: `0xa4f07713`" + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "NameDataMismatch(uint256)": [ + { + "details": "Error selector: `0xedec3569`" + } + ], + "NameNotLocked(uint256)": [ + { + "details": "Error selector: `0x1bfe8f0a`" + } + ], + "UnauthorizedCaller(address)": [ + { + "details": "Error selector: `0xd86ad9cf`", + "params": { + "caller": "The address that attempted the unauthorized operation" + } + } + ] + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "ethRegistry": "The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.", + "graveyard": "The ENSv1 `BaseRegistrar` token graveyard.", + "nameWrapper": "The ENSv1 `NameWrapper` contract.", + "publicResolver": "The replacement `PublicResolver`.", + "publicResolverSet": "The list of `PublicResolver` contracts that require replacement.", + "verifiableFactory": "The shared factory for verifiable deployments.", + "wrapperRegistryImpl": "The `WrapperRegistry` implementation contract." + } + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "details": "Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts", + "params": { + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated.", + "mds": "The migration parameters for each name, indexed in parallel with `ids`." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.", + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed" + } + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data` struct containing migration parameters.", + "id": "The NameWrapper token ID (namehash) of the name being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed" + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1564000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "ETH_REGISTRY()": "infinite", + "GRAVEYARD()": "infinite", + "NAME_WRAPPER()": "infinite", + "PUBLIC_RESOLVER()": "infinite", + "PUBLIC_RESOLVER_SET()": "infinite", + "VERIFIABLE_FACTORY()": "infinite", + "WRAPPER_REGISTRY_IMPL()": "infinite", + "finishERC1155Migration(uint256[],(string,address,address,address)[])": "infinite", + "getWrappedName()": "infinite", + "getWrappedNode()": "221", + "isContractNamer(address)": "infinite", + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": "infinite", + "onERC1155Received(address,address,uint256,uint256,bytes)": "infinite", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_getRegistry()": "infinite", + "_inject(string memory,address,contract IRegistry,address,uint256,uint64)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"graveyard\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry\",\"type\":\"address\"},{\"internalType\":\"contract VerifiableFactory\",\"name\":\"verifiableFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"wrapperRegistryImpl\",\"type\":\"address\"},{\"internalType\":\"contract IAddressSet\",\"name\":\"publicResolverSet\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"publicResolver\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"FrozenTokenApproval\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameNotLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GRAVEYARD\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PUBLIC_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PUBLIC_RESOLVER_SET\",\"outputs\":[{\"internalType\":\"contract IAddressSet\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERIFIABLE_FACTORY\",\"outputs\":[{\"internalType\":\"contract IVerifiableFactory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WRAPPER_REGISTRY_IMPL\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[]\",\"name\":\"mds\",\"type\":\"tuple[]\"}],\"name\":\"finishERC1155Migration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedName\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNode\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"FrozenTokenApproval(uint256)\":[{\"details\":\"Error selector: `0xa4f07713`\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"NameDataMismatch(uint256)\":[{\"details\":\"Error selector: `0xedec3569`\"}],\"NameNotLocked(uint256)\":[{\"details\":\"Error selector: `0x1bfe8f0a`\"}],\"UnauthorizedCaller(address)\":[{\"details\":\"Error selector: `0xd86ad9cf`\",\"params\":{\"caller\":\"The address that attempted the unauthorized operation\"}}]},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"ethRegistry\":\"The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\",\"graveyard\":\"The ENSv1 `BaseRegistrar` token graveyard.\",\"nameWrapper\":\"The ENSv1 `NameWrapper` contract.\",\"publicResolver\":\"The replacement `PublicResolver`.\",\"publicResolverSet\":\"The list of `PublicResolver` contracts that require replacement.\",\"verifiableFactory\":\"The shared factory for verifiable deployments.\",\"wrapperRegistryImpl\":\"The `WrapperRegistry` implementation contract.\"}},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"details\":\"Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts\",\"params\":{\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\",\"mds\":\"The migration parameters for each name, indexed in parallel with `ids`.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\",\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\"}},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data` struct containing migration parameters.\",\"id\":\"The NameWrapper token ID (namehash) of the name being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"FrozenTokenApproval(uint256)\":[{\"notice\":\"NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"NameDataMismatch(uint256)\":[{\"notice\":\"NameWrapper or BaseRegistrar token does not match supplied data.\"}],\"NameNotLocked(uint256)\":[{\"notice\":\"NameWrapper token is unlocked.\"}],\"UnauthorizedCaller(address)\":[{\"notice\":\"Thrown when a caller is not authorized to perform the requested operation\"}]},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"ETH_REGISTRY()\":{\"notice\":\"The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\"},\"GRAVEYARD()\":{\"notice\":\"The ENSv1 `BaseRegistrar` token graveyard.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\"},\"PUBLIC_RESOLVER()\":{\"notice\":\"The replacement `PublicResolver`.\"},\"PUBLIC_RESOLVER_SET()\":{\"notice\":\"The list of `PublicResolver` contracts that require replacement.\"},\"VERIFIABLE_FACTORY()\":{\"notice\":\"The shared factory for verifiable deployments.\"},\"WRAPPER_REGISTRY_IMPL()\":{\"notice\":\"The `WrapperRegistry` implementation contract.\"},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"notice\":\"Convert NameWrapper tokens to their equivalent ENSv2 form.\"},\"getWrappedName()\":{\"notice\":\"Returns the DNS-encoded name for this registry.\"},\"getWrappedNode()\":{\"notice\":\"Returns the DNS-encoded name for \\\"eth\\\".\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"notice\":\"Migrate one NameWrapper token via `safeTransferFrom()`.\"}},\"notice\":\"Migration controller for handling locked .eth names. Assumes premigration has `RESERVED` existing ENSv1 names. Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/migration/LockedMigrationController.sol\":\"LockedMigrationController\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n /*\\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n * 0xb0202a11 ===\\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n */\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @param data Additional data with no specified format, sent in call to `spender`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\",\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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 /**\\n * @dev An operation with an ERC-20 token failed.\\n */\\n error SafeERC20FailedOperation(address token);\\n\\n /**\\n * @dev Indicates a failed `decreaseAllowance` request.\\n */\\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n forceApprove(token, spender, oldAllowance + value);\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n * value, non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n unchecked {\\n uint256 currentAllowance = token.allowance(address(this), spender);\\n if (currentAllowance < requestedDecrease) {\\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n }\\n forceApprove(token, spender, currentAllowance - requestedDecrease);\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n *\\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n * set here.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n safeTransfer(token, to, value);\\n } else if (!token.transferAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferFromAndCallRelaxed(\\n IERC1363 token,\\n address from,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length == 0) {\\n safeTransferFrom(token, from, to, value);\\n } else if (!token.transferFromAndCall(from, to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n * once without retrying, and relies on the returned value to be true.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n forceApprove(token, to, value);\\n } else if (!token.approveAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n // bubble errors\\n if iszero(success) {\\n let ptr := mload(0x40)\\n returndatacopy(ptr, 0, returndatasize())\\n revert(ptr, returndatasize())\\n }\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n\\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\n }\\n}\\n\",\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\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 There's no code to deploy.\\n */\\n error Create2EmptyBytecode();\\n\\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(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n if (bytecode.length == 0) {\\n revert Create2EmptyBytecode();\\n }\\n assembly (\\\"memory-safe\\\") {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n // if no address was created, and returndata is not empty, bubble revert\\n if and(iszero(addr), not(iszero(returndatasize()))) {\\n let p := mload(0x40)\\n returndatacopy(p, 0, returndatasize())\\n revert(p, returndatasize())\\n }\\n }\\n if (addr == address(0)) {\\n revert Errors.FailedDeployment();\\n }\\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(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {\\n assembly (\\\"memory-safe\\\") {\\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 := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xbb7e8401583d26268ea9103013bcdcd90866a7718bd91105ebd21c9bf11f4f06\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/CloneProxyBytecode.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nlibrary CloneProxyBytecode {\\n // EIP-1167 minimal proxy creation/runtime code:\\n // https://eips.ethereum.org/EIPS/eip-1167\\n //\\n // Standard runtime is 45 bytes:\\n // 363d3d373d3d3d363d73<20-byte implementation>5af43d82803e903d91602b57fd5bf3\\n //\\n // We append a 32-byte salt to the runtime and make the creation stub return 77 bytes\\n // instead of the standard 45. The proxy still executes the same minimal-proxy logic;\\n // UUPSProxyLogic reads the appended salt with extcodecopy().\\n uint256 internal constant CREATION_CODE_LENGTH = 0x57;\\n\\n function creationCode(address logic, bytes32 salt) internal pure returns (bytes memory code) {\\n code = new bytes(CREATION_CODE_LENGTH);\\n\\n assembly (\\\"memory-safe\\\") {\\n let ptr := add(code, 0x20)\\n\\n // Creation stub plus runtime prefix. The creation stub returns 77 bytes:\\n // 45 bytes of EIP-1167 runtime plus our appended 32-byte salt.\\n mstore(ptr, 0x3d604d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n // Fill the EIP-1167 PUSH20 slot with the shared proxy logic address.\\n mstore(add(ptr, 0x14), shl(0x60, logic))\\n // Runtime suffix: delegatecall to `logic`, copy returndata, then return or revert.\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n // Append salt after the executable minimal-proxy runtime for extcodecopy().\\n mstore(add(ptr, 0x37), salt)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2973c5070195e3c2806b59f1dc7a9da5aa1efa4a30867d9715def848bd51780f\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IProxyAuthorization {\\n function canUpgradeFrom(address previousImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IUUPSProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IUUPSProxy {\\n error ImplementationCannotBeZeroAddress();\\n\\n error AlreadyInitialized();\\n\\n error ImplementationNotSet();\\n\\n error InvalidUpgradeTarget(address currentImplementation, address newImplementation);\\n\\n error UpgradeNotAllowedInContext();\\n\\n function initialize(address implementation, bytes calldata data) external payable;\\n\\n function getVerifiableProxyData() external view returns (bytes32 salt, address implementation);\\n\\n function verifiableProxyFactory() external view returns (address);\\n}\\n\",\"keccak256\":\"0xf0b7151951532e69f98ded4b36a6994921a9636e70e369ef9714d38ce8264060\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IVerifiableFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IVerifiableFactory {\\n event ProxyDeployed(address indexed sender, address indexed proxyAddress, uint256 salt, address implementation);\\n\\n function deployProxy(address implementation, uint256 salt, bytes memory data) external returns (address);\\n\\n function verifyContract(address proxy, address expectedImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x00499139966665152ce90dddf24ae3047c6fb07d3e045b1e4d77ec9e86dc4eef\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/UUPSProxyLogic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport {IProxyAuthorization} from \\\"./IProxyAuthorization.sol\\\";\\nimport {IUUPSProxy} from \\\"./IUUPSProxy.sol\\\";\\n\\ncontract UUPSProxyLogic is IUUPSProxy {\\n /// @dev `keccak256(bytes(\\\"eip1967.proxy.implementation\\\")) - 1`.\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ImplementationCannotBeZeroAddress()\\\")))`.\\n uint256 internal constant _IMPLEMENTATION_CANNOT_BE_ZERO_ADDRESS_ERROR_SELECTOR = 0x0760838f;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"AlreadyInitialized()\\\")))`.\\n uint256 internal constant _ALREADY_INITIALIZED_ERROR_SELECTOR = 0x0dc149f0;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"UpgradeNotAllowedInContext()\\\")))`.\\n uint256 internal constant _UPGRADE_NOT_ALLOWED_IN_CONTEXT_ERROR_SELECTOR = 0x784cf700;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ERC1967InvalidImplementation(address)\\\")))`.\\n uint256 internal constant _ERC1967_INVALID_IMPLEMENTATION_ERROR_SELECTOR = 0x4c9c8ce3;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ERC1967NonPayable()\\\")))`.\\n uint256 internal constant _ERC1967_NON_PAYABLE_ERROR_SELECTOR = 0xb398979f;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"Upgraded(address)\\\")))`.\\n uint256 internal constant _UPGRADED_EVENT_SELECTOR =\\n 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;\\n\\n address public immutable verifiableProxyFactory;\\n\\n constructor() {\\n verifiableProxyFactory = msg.sender;\\n }\\n\\n function initialize(address implementation, bytes calldata data) external payable {\\n assembly {\\n if eq(implementation, 0) {\\n mstore(0, _IMPLEMENTATION_CANNOT_BE_ZERO_ADDRESS_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n if iszero(eq(sload(_IMPLEMENTATION_SLOT), 0)) {\\n mstore(0, _ALREADY_INITIALIZED_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n if iszero(extcodesize(implementation)) {\\n mstore(0, _ERC1967_INVALID_IMPLEMENTATION_ERROR_SELECTOR)\\n mstore(0x20, implementation)\\n revert(0x1c, 0x24)\\n }\\n sstore(_IMPLEMENTATION_SLOT, implementation)\\n log2(0, 0, _UPGRADED_EVENT_SELECTOR, implementation)\\n\\n let dlength := data.length\\n switch dlength\\n case 0 {\\n if callvalue() {\\n mstore(0, _ERC1967_NON_PAYABLE_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n }\\n default {\\n calldatacopy(0, data.offset, dlength)\\n let result := delegatecall(gas(), implementation, 0, dlength, 0, 0)\\n if iszero(result) {\\n returndatacopy(0, 0, returndatasize())\\n revert(0, returndatasize())\\n }\\n }\\n }\\n }\\n\\n function getVerifiableProxyData() public view returns (bytes32 salt, address implementation) {\\n assembly {\\n extcodecopy(address(), 0, sub(extcodesize(address()), 0x20), 0x20)\\n salt := mload(0)\\n implementation := sload(_IMPLEMENTATION_SLOT)\\n }\\n }\\n\\n function upgradeToAndCall(address newImplementation, bytes calldata) external payable {\\n if (newImplementation == address(0)) revert ImplementationCannotBeZeroAddress();\\n\\n address implementation = _implementation();\\n if (implementation == address(0)) revert ImplementationNotSet();\\n\\n IProxyAuthorization newImpl = IProxyAuthorization(newImplementation);\\n if (!newImpl.canUpgradeFrom(implementation)) {\\n revert InvalidUpgradeTarget(implementation, newImplementation);\\n }\\n\\n _delegate(implementation, false);\\n }\\n\\n function _implementation() internal view returns (address impl) {\\n assembly {\\n impl := sload(_IMPLEMENTATION_SLOT)\\n }\\n }\\n\\n function _delegate(address implementation, bool checkImplementation) internal {\\n assembly {\\n calldatacopy(0, 0, calldatasize())\\n\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n if checkImplementation {\\n if iszero(eq(implementation, sload(_IMPLEMENTATION_SLOT))) {\\n mstore(0, _UPGRADE_NOT_ALLOWED_IN_CONTEXT_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n }\\n\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n fallback() external payable {\\n _delegate(_implementation(), true);\\n }\\n}\\n\",\"keccak256\":\"0x3633e240557a6ee77fb29b913f6cc5aa6a8b546cc6a9e927458e93fa0622c07f\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/VerifiableFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport {Create2} from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\nimport {CloneProxyBytecode} from \\\"./CloneProxyBytecode.sol\\\";\\nimport {UUPSProxyLogic} from \\\"./UUPSProxyLogic.sol\\\";\\nimport {IUUPSProxy} from \\\"./IUUPSProxy.sol\\\";\\nimport {IVerifiableFactory} from \\\"./IVerifiableFactory.sol\\\";\\n\\ncontract VerifiableFactory is IVerifiableFactory {\\n address public immutable proxyLogic;\\n\\n constructor() {\\n proxyLogic = address(new UUPSProxyLogic());\\n }\\n\\n /**\\n * @dev Deploys a new verifiable proxy clone at a deterministic address.\\n *\\n * The deployed proxy is an EIP-1167-style clone that delegates proxy mechanics to the\\n * factory's `proxyLogic` contract. The clone runtime also appends the derived salt so the\\n * factory can later verify the proxy's CREATE2 address.\\n *\\n * The CREATE2 salt is `keccak256(abi.encode(msg.sender, salt))`, so two callers can reuse\\n * the same user salt without colliding.\\n *\\n * @param implementation The address of the contract implementation the proxy will delegate calls to.\\n * @param salt A value provided by the caller to ensure uniqueness of the proxy address.\\n * @return proxy The address of the deployed proxy clone.\\n */\\n function deployProxy(address implementation, uint256 salt, bytes memory data) external returns (address proxy) {\\n bytes32 outerSalt = keccak256(abi.encode(msg.sender, salt));\\n bytes memory executableBytecode = _proxyCreationCode(outerSalt);\\n\\n assembly {\\n proxy := create2(0, add(executableBytecode, 0x20), mload(executableBytecode), outerSalt)\\n if iszero(proxy) {\\n revert(0, 0)\\n }\\n }\\n\\n IUUPSProxy(proxy).initialize(implementation, data);\\n\\n emit ProxyDeployed(msg.sender, proxy, salt, implementation);\\n }\\n\\n /**\\n * @dev Initiates verification of a proxy contract.\\n *\\n * This function attempts to validate a proxy contract by retrieving its salt\\n * and reconstructing the address to ensure it was correctly deployed by the\\n * current factory.\\n *\\n * @param proxy The address of the proxy contract being verified.\\n * @return A boolean indicating whether the verification succeeded.\\n */\\n function verifyContract(address proxy, address expectedImplementation) public view returns (bool) {\\n if (!isContract(proxy)) return false;\\n\\n try IUUPSProxy(proxy).getVerifiableProxyData() returns (bytes32 salt, address actualImplementation) {\\n if (actualImplementation != expectedImplementation) return false;\\n return _verifyContract(proxy, salt);\\n } catch {}\\n return false;\\n }\\n\\n function _verifyContract(address proxy, bytes32 salt) private view returns (bool) {\\n bytes memory proxyBytecode = _proxyCreationCode(salt);\\n\\n address expectedProxyAddress = Create2.computeAddress(salt, keccak256(proxyBytecode), address(this));\\n\\n return expectedProxyAddress == proxy;\\n }\\n\\n function _proxyCreationCode(bytes32 salt) private view returns (bytes memory creationCode) {\\n creationCode = CloneProxyBytecode.creationCode(proxyLogic, salt);\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n}\\n\",\"keccak256\":\"0xb59ebead19f6c9f00645c1290acd3c627b40389b14c959347fe08b89e1ce074e\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/migration/AbstractWrapperReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {IERC1155Receiver} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport {ERC165, IERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {UnauthorizedCaller} from \\\"../CommonErrors.sol\\\";\\nimport {WrappedErrorLib} from \\\"../utils/WrappedErrorLib.sol\\\";\\n\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title AbstractWrapperReceiver\\n/// @dev Abstract IERC1155Receiver which handles NameWrapper token migration via transfer.\\n///\\n/// NameWrapper only allows `Error(string)` exceptions during transfer and squelches typed errors.\\n/// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L317-L335\\n/// This contract, with the aid of WrappedErrorLib, embeds errors that occur during migration into `Error(string)`.\\n///\\n/// There are (2) AbstractWrapperReceiver implementations:\\n/// 1. UnlockedMigrationController accepts unlocked tokens.\\n/// 2. LockedWrapperReceiver accepts locked tokens.\\n///\\n/// `LibMigration.isLocked()` determines lock status.\\n///\\nabstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice The ENSv1 `BaseRegistrar` token graveyard.\\n address public immutable GRAVEYARD;\\n\\n /// @dev The ENSv1 `ENSRegistry` contract.\\n ENS internal immutable _REGISTRY_V1;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Restrict `msg.sender` to NameWrapper.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier onlyWrapper() {\\n if (msg.sender != address(NAME_WRAPPER)) {\\n WrappedErrorLib.wrapAndRevert(\\n abi.encodeWithSelector(UnauthorizedCaller.selector, msg.sender)\\n );\\n }\\n _;\\n }\\n\\n /// @dev Avoid `abi.decode()` failure for obviously invalid data.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier withData(bytes calldata data, uint256 minimumSize) {\\n if (data.length < minimumSize) {\\n WrappedErrorLib.wrapAndRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector));\\n }\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n constructor(INameWrapper nameWrapper, address graveyard) {\\n NAME_WRAPPER = nameWrapper;\\n GRAVEYARD = graveyard;\\n _REGISTRY_V1 = nameWrapper.ens();\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate one NameWrapper token via `safeTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param id The NameWrapper token ID (namehash) of the name being migrated.\\n /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters.\\n function onERC1155Received(\\n address /*operator*/,\\n address /*from*/,\\n uint256 id,\\n uint256 /*amount*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (amount != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L293\\n uint256[] memory ids = new uint256[](1);\\n LibMigration.Data[] memory mds = new LibMigration.Data[](1);\\n ids[0] = id;\\n mds[0] = abi.decode(data, (LibMigration.Data)); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155Received.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param data ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\\n function onERC1155BatchReceived(\\n address /*operator*/,\\n address /*from*/,\\n uint256[] calldata ids,\\n uint256[] calldata /*amounts*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, 64 + ids.length * LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (ids.length != amounts.length) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L162\\n // if (amounts[i] != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L182\\n LibMigration.Data[] memory mds = abi.decode(data, (LibMigration.Data[])); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155BatchReceived.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @notice Convert NameWrapper tokens to their equivalent ENSv2 form.\\n /// @dev Only callable by ourself and invoked by our `IERC1155Receiver` handlers.\\n ///\\n /// TODO: gas analysis and optimization\\n /// NOTE: converting this to an internal call requires catching many reverts\\n ///\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param mds The migration parameters for each name, indexed in parallel with `ids`.\\n function finishERC1155Migration(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n external\\n {\\n if (msg.sender != address(this)) {\\n revert UnauthorizedCaller(msg.sender);\\n }\\n if (ids.length != mds.length) {\\n revert IERC1155Errors.ERC1155InvalidArrayLength(ids.length, mds.length);\\n }\\n _migrateWrapped(ids, mds);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Migrate received NameWrapper tokens.\\n /// Token owner is this contract.\\n /// Token is not expired.\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n virtual;\\n}\\n\",\"keccak256\":\"0x0c15f9f657ba58bf5081cbff88c385c9e673ba87aed2032397ec2c5448d7fe1a\",\"license\":\"MIT\"},\"project/src/migration/LockedMigrationController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {VerifiableFactory} from \\\"@ensdomains/verifiable-factory/VerifiableFactory.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\nimport {IAddressSet} from \\\"../utils/interfaces/IAddressSet.sol\\\";\\n\\nimport {AbstractWrapperReceiver} from \\\"./AbstractWrapperReceiver.sol\\\";\\nimport {LockedWrapperReceiver} from \\\"./LockedWrapperReceiver.sol\\\";\\n\\n/// @notice Migration controller for handling locked .eth names.\\n///\\n/// Assumes premigration has `RESERVED` existing ENSv1 names.\\n/// Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration.\\n///\\ncontract LockedMigrationController is LockedWrapperReceiver, DelegatedContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n /// @param ethRegistry The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\\n /// @param verifiableFactory The shared factory for verifiable deployments.\\n /// @param wrapperRegistryImpl The `WrapperRegistry` implementation contract.\\n /// @param publicResolverSet The list of `PublicResolver` contracts that require replacement.\\n /// @param publicResolver The replacement `PublicResolver`.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n INameWrapper nameWrapper,\\n address graveyard,\\n IPermissionedRegistry ethRegistry,\\n VerifiableFactory verifiableFactory,\\n address wrapperRegistryImpl,\\n IAddressSet publicResolverSet,\\n address publicResolver,\\n IContractNamer contractNamer\\n )\\n LockedWrapperReceiver(\\n nameWrapper,\\n graveyard,\\n verifiableFactory,\\n wrapperRegistryImpl,\\n publicResolverSet,\\n publicResolver\\n )\\n DelegatedContractNamer(contractNamer)\\n {\\n ETH_REGISTRY = ethRegistry;\\n }\\n\\n /// @inheritdoc DelegatedContractNamer\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(AbstractWrapperReceiver, DelegatedContractNamer)\\n returns (bool)\\n {\\n return super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Returns the DNS-encoded name for \\\"eth\\\".\\n function getWrappedNode() public pure override returns (bytes32) {\\n return NameCoder.ETH_NODE;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Register `RESERVED` .eth token.\\n function _inject(\\n string memory label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 /*expiry*/\\n )\\n internal\\n override\\n returns (uint256 tokenId)\\n {\\n return\\n ETH_REGISTRY.register(\\n label,\\n owner,\\n subregistry,\\n resolver,\\n roleBitmap,\\n 0 // use reserved expiry\\n ); // reverts if not RESERVED\\n }\\n\\n /// @inheritdoc LockedWrapperReceiver\\n function _getRegistry() internal view override returns (IRegistry) {\\n return ETH_REGISTRY;\\n }\\n}\\n\",\"keccak256\":\"0xfeaf28aa17111f758e8957ee898ef7cc48c0410716b4bac412c0795543c6e664\",\"license\":\"MIT\"},\"project/src/migration/LockedWrapperReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {\\n INameWrapper,\\n CAN_EXTEND_EXPIRY,\\n CANNOT_APPROVE,\\n CANNOT_CREATE_SUBDOMAIN,\\n CANNOT_SET_RESOLVER,\\n CANNOT_TRANSFER\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IVerifiableFactory} from \\\"@ensdomains/verifiable-factory/IVerifiableFactory.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {REGISTRATION_ROLE_BITMAP} from \\\"../registrar/ETHRegistrar.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {IWrapperRegistry} from \\\"../registry/interfaces/IWrapperRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"../registry/libraries/RegistryRolesLib.sol\\\";\\nimport {IAddressSet} from \\\"../utils/interfaces/IAddressSet.sol\\\";\\n\\nimport {AbstractWrapperReceiver} from \\\"./AbstractWrapperReceiver.sol\\\";\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title LockedWrappedReceiver\\n/// @dev AbstractWrapperReceiver for locked NameWrapper tokens.\\n///\\n/// There are (2) LockedWrapperReceiver implementations:\\n/// 1. LockedMigrationController only accepts .eth 2LD tokens.\\n/// 2. WrapperRegistry only accepts emancipated (N+1)-LD children with a matching N-LD parent node.\\n///\\n/// eg. transfer(\\\"nick.eth\\\") => LockedMigrationController\\n/// \\u21aa ETHRegistry.subregistry(\\\"nick\\\") = WrapperRegistry(\\\"nick.eth\\\")\\n/// transfer(\\\"sub.nick.eth\\\") => WrapperRegistry(\\\"nick.eth\\\")\\n/// \\u21aa WrapperRegistry(\\\"nick.eth\\\").subregistry(\\\"sub\\\") = WrapperRegistry(\\\"sub.nick.eth\\\")\\n/// transfer(\\\"abc.sub.nick.eth\\\") => WrapperRegistry(\\\"sub.nick.eth\\\")\\n/// \\u21aa WrapperRegistry(\\\"sub.nick.eth\\\").subregistry(\\\"abc\\\") = WrapperRegistry(\\\"abc.sub.nick.eth\\\")\\n///\\n/// Upon successful migration:\\n/// * subregistry is bound to a WrapperRegistry (does not have `ROLE_SET_SUBREGISTRY`)\\n/// * subregistry is canonical (does not have `ROLE_SET_PARENT`) and knows its name\\n/// * subregistry migrates emancipated children with the same parent\\n///\\nabstract contract LockedWrapperReceiver is AbstractWrapperReceiver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The shared factory for verifiable deployments.\\n IVerifiableFactory public immutable VERIFIABLE_FACTORY;\\n\\n /// @notice The `WrapperRegistry` implementation contract.\\n address public immutable WRAPPER_REGISTRY_IMPL;\\n\\n /// @notice The list of `PublicResolver` contracts that require replacement.\\n IAddressSet public immutable PUBLIC_RESOLVER_SET;\\n\\n /// @notice The replacement `PublicResolver`.\\n address public immutable PUBLIC_RESOLVER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n /// @param verifiableFactory The shared factory for verifiable deployments.\\n /// @param wrapperRegistryImpl The `WrapperRegistry` implementation contract.\\n /// @param publicResolverSet The list of `PublicResolver` contracts that require replacement.\\n /// @param publicResolver The replacement `PublicResolver`.\\n constructor(\\n INameWrapper nameWrapper,\\n address graveyard,\\n IVerifiableFactory verifiableFactory,\\n address wrapperRegistryImpl,\\n IAddressSet publicResolverSet,\\n address publicResolver\\n )\\n AbstractWrapperReceiver(nameWrapper, graveyard)\\n {\\n VERIFIABLE_FACTORY = verifiableFactory;\\n WRAPPER_REGISTRY_IMPL = wrapperRegistryImpl;\\n PUBLIC_RESOLVER_SET = publicResolverSet;\\n PUBLIC_RESOLVER = publicResolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Returns the DNS-encoded name for this registry.\\n function getWrappedName() public view virtual returns (bytes memory) {\\n return NAME_WRAPPER.names(getWrappedNode());\\n }\\n\\n /// @notice Returns the NameWrapper node (namehash).\\n function getWrappedNode() public view virtual returns (bytes32);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc AbstractWrapperReceiver\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n override\\n {\\n IRegistry parentRegistry = _getRegistry();\\n bytes32 parentNode = getWrappedNode();\\n for (uint256 i; i < ids.length; ++i) {\\n LibMigration.Data memory md = mds[i];\\n if (md.owner == address(0)) {\\n revert InvalidOwner();\\n }\\n bytes32 node = bytes32(ids[i]);\\n bytes32 labelHash = keccak256(bytes(md.label));\\n if (node != NameCoder.namehash(parentNode, labelHash)) {\\n revert LibMigration.NameDataMismatch(uint256(node));\\n }\\n\\n // by construction: 1 <= length(label) <= 255\\n // same as NameCoder.assertLabelSize()\\n // see: V1Fixture.t.sol: `test_nameWrapper_labelTooShort()` and `test_nameWrapper_labelTooLong()`.\\n\\n address resolver = md.resolver;\\n (, uint32 fuses, uint64 expiry) = NAME_WRAPPER.getData(uint256(node));\\n if (LibMigration.isLocked(fuses)) {\\n if (\\n (fuses & CANNOT_APPROVE) != 0 &&\\n NAME_WRAPPER.getApproved(uint256(node)) != address(0)\\n ) {\\n revert LibMigration.FrozenTokenApproval(uint256(node));\\n }\\n\\n if ((fuses & CANNOT_SET_RESOLVER) == 0) {\\n NAME_WRAPPER.setResolver(node, address(0)); // clear ENSv1 resolver\\n } else {\\n resolver = _REGISTRY_V1.resolver(node); // replace with ENSv1 resolver\\n if (PUBLIC_RESOLVER_SET.includes(resolver)) {\\n resolver = PUBLIC_RESOLVER; // replace with new PublicResolver\\n }\\n }\\n\\n NAME_WRAPPER.safeTransferFrom(address(this), GRAVEYARD, uint256(node), 1, \\\"\\\"); // transfer to graveyard\\n\\n // create subregistry\\n IRegistry subregistry =\\n IRegistry(\\n VERIFIABLE_FACTORY.deployProxy(\\n WRAPPER_REGISTRY_IMPL,\\n uint256(node),\\n abi.encodeCall(\\n IWrapperRegistry.initialize,\\n (\\n node,\\n parentRegistry,\\n md.label,\\n md.owner,\\n _subregistryRoleBitmapFromFuses(fuses)\\n )\\n )\\n )\\n );\\n\\n // add name to ENSv2\\n // PermissionedRegistry._register() => CannotSetPastExpiry :: see expiry check\\n // PermissionedRegistry._register() => LabelAlreadyRegistered :: only have ROLE_REGISTER_RESERVED\\n // ERC1155._safeTransferFrom() => ERC1155InvalidReceiver :: see owner check\\n _inject(\\n md.label,\\n md.owner,\\n subregistry,\\n resolver,\\n _tokenRoleBitmapFromFuses(fuses),\\n expiry\\n );\\n } else if (LibMigration.isEmancipatedChild(fuses)) {\\n NAME_WRAPPER.setResolver(node, address(0)); // clear ENSv1 resolver\\n NAME_WRAPPER.unwrap(parentNode, labelHash, GRAVEYARD); // unwrap and transfer to graveyard\\n\\n // add name to ENSv2 (same as UnlockedMigrationController)\\n _inject(\\n md.label,\\n md.owner,\\n md.subregistry,\\n resolver,\\n REGISTRATION_ROLE_BITMAP,\\n expiry\\n );\\n } else {\\n revert LibMigration.NameNotLocked(uint256(node));\\n }\\n }\\n }\\n\\n /// @dev Register a locked name.\\n function _inject(\\n string memory label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n internal\\n virtual\\n returns (uint256 tokenId);\\n\\n /// @dev The ENSv2 registry being migrated to.\\n function _getRegistry() internal view virtual returns (IRegistry);\\n\\n /// @dev Convert fuses to equivalent subregistry root roles.\\n function _subregistryRoleBitmapFromFuses(uint32 fuses)\\n internal\\n pure\\n returns (uint256 roleBitmap)\\n {\\n if ((fuses & CANNOT_CREATE_SUBDOMAIN) == 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_REGISTRAR;\\n }\\n if (LibMigration.notFrozen(fuses)) {\\n roleBitmap |= roleBitmap << 128; // give admin\\n }\\n roleBitmap |=\\n RegistryRolesLib.ROLE_RENEW |\\n RegistryRolesLib.ROLE_RENEW_ADMIN |\\n RegistryRolesLib.ROLE_UPGRADE |\\n RegistryRolesLib.ROLE_UPGRADE_ADMIN |\\n RegistryRolesLib.ROLE_CAN_NAME |\\n RegistryRolesLib.ROLE_CAN_NAME_ADMIN;\\n }\\n\\n /// @dev Convert fuses to equivalent token roles.\\n function _tokenRoleBitmapFromFuses(uint32 fuses) internal pure returns (uint256 roleBitmap) {\\n if ((fuses & CAN_EXTEND_EXPIRY) != 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_RENEW;\\n }\\n if ((fuses & CANNOT_SET_RESOLVER) == 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_SET_RESOLVER;\\n }\\n if (LibMigration.notFrozen(fuses)) {\\n roleBitmap |= roleBitmap << 128; // give admin\\n }\\n if ((fuses & CANNOT_TRANSFER) == 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfdd9a054e4bb46a6908503af4af181db9ccc1dbdd7625f488fc9a8d4811b3b35\",\"license\":\"MIT\"},\"project/src/migration/libraries/LibMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n CANNOT_BURN_FUSES,\\n CANNOT_UNWRAP,\\n IS_DOT_ETH,\\n PARENT_CANNOT_CONTROL\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Primitives for migration.\\nlibrary LibMigration {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Typed arguments for migration via transfer payload.\\n struct Data {\\n /// @dev Subdomain being migrated.\\n string label;\\n /// @dev Address that will own the name in the v2 registry.\\n address owner;\\n /// @dev Address of the child registry.\\n /// Ignored by locked migration.\\n IRegistry subregistry;\\n /// @dev Resolver address to set for the migrated name.\\n /// Ignored if locked and `CANNOT_SET_RESOLVER`.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Minimum size of `abi.encode(Data({...}))`.\\n uint256 internal constant MIN_DATA_SIZE = 7 * 32;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be registered because unmigrated NameWrapper token exists.\\n /// @dev Error selector: `0x408fa1b8`\\n error NameRequiresMigration();\\n\\n /// @notice NameWrapper token is unlocked.\\n /// @dev Error selector: `0x1bfe8f0a`\\n error NameNotLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper token is locked.\\n /// @dev Error selector: `0xe7c290e2`\\n error NameIsLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper or BaseRegistrar token does not match supplied data.\\n /// @dev Error selector: `0xedec3569`\\n error NameDataMismatch(uint256 tokenId);\\n\\n /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\\n /// @dev Error selector: `0xa4f07713`\\n error FrozenTokenApproval(uint256 tokenId);\\n\\n /// @notice The encoded data is invalid.\\n /// @dev Error selector: `0x5cb045db`\\n error InvalidData();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns `true` if the NameWrapper token is locked.\\n function isLocked(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient\\n // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()`\\n return (fuses & CANNOT_UNWRAP) != 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token fuses are not frozen.\\n function notFrozen(uint32 fuses) internal pure returns (bool) {\\n return (fuses & CANNOT_BURN_FUSES) == 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth.\\n function isEmancipatedChild(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL must be set for the entire ancestory.\\n // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()`\\n return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL;\\n }\\n}\\n\",\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\"},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`.\\nabstract contract AbstractETHRegistrar is Ownable, HCAContext, ERC165, IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Minimum renew duration, in seconds.\\n uint64 public constant MIN_RENEW_DURATION = 1;\\n\\n /// @notice ENSv2 .eth `PermissionedRegistry`.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice Address that receives payments.\\n address public immutable BENEFICIARY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Oracle for registration and renewal costs.\\n IRentPriceOracle public rentPriceOracle;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `IRentPriceOracle` was replaced.\\n /// @param oracle The new `IRentPriceOracle` contract.\\n event RentPriceOracleUpdated(IRentPriceOracle oracle);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param hcaFactory HCA factory.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n constructor(\\n address owner_,\\n IHCAFactoryBasic hcaFactory,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle\\n )\\n Ownable(owner_)\\n HCAEquivalence(hcaFactory)\\n {\\n ETH_REGISTRY = ethRegistry;\\n BENEFICIARY = beneficiary;\\n\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Change the rent price oracle.\\n /// @param oracle The new `IRentPriceOracle` instance.\\n function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner {\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external\\n {\\n IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not\\n uint64 newExpiry = state.expiry + duration; // reverts if overflow\\n uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, amount); // reverts if payment failed\\n ETH_REGISTRY.renew(state.tokenId, newExpiry);\\n _onRenew(label, duration);\\n emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function isRenewable(string calldata label) external view returns (bool) {\\n return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n public\\n view\\n returns (uint256)\\n {\\n return\\n rentPriceOracle.getRenewPrice(\\n label,\\n _requireRenewable(label, duration).expiry,\\n duration,\\n paymentToken\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Callback for when a name is renewed.\\n function _onRenew(string calldata label, uint64 duration) internal virtual {}\\n\\n /// @dev Returns whether the name is renewable by this contract.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n virtual\\n returns (bool);\\n\\n /// @dev Ensure name is renewable.\\n function _requireRenewable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isRenewable(state)) {\\n revert NameNotRenewable(label);\\n }\\n if (duration < MIN_RENEW_DURATION) {\\n revert DurationTooShort(duration, MIN_RENEW_DURATION);\\n }\\n }\\n\\n /// @inheritdoc HCAContext\\n function _msgSender() internal view override(Context, HCAContext) returns (address) {\\n return super._msgSender();\\n }\\n}\\n\",\"keccak256\":\"0xb1cf6d7413558f8d257bdf8f734aaa57d4323e27854ae3ce79b7f017ff133510\",\"license\":\"MIT\"},\"project/src/registrar/ETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"../registry/libraries/RegistryRolesLib.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {AbstractETHRegistrar} from \\\"./AbstractETHRegistrar.sol\\\";\\nimport {IETHRegistrar} from \\\"./interfaces/IETHRegistrar.sol\\\";\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Roles assigned to owners at registration. Includes set-subregistry, set-resolver, and can-transfer (with admin variants).\\nuint256 constant REGISTRATION_ROLE_BITMAP =\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY |\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN |\\n RegistryRolesLib.ROLE_SET_RESOLVER |\\n RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN |\\n RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN;\\n\\n/// @notice Commit-reveal registrar for .eth names. Registration requires two transactions: first\\n/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment\\n/// age but before the maximum commitment age has elapsed. The commitment hash binds all\\n/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer)\\n/// to prevent front-running.\\n///\\n/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed\\n/// set of roles (set subregistry, set resolver, and transfer \\u2014 each with their admin\\n/// counterpart).\\n///\\n/// Pricing and payment are delegated to a swappable `IRentPriceOracle`.\\n///\\ncontract ETHRegistrar is AbstractETHRegistrar, IETHRegistrar {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRenewer\\n uint64 public immutable GRACE_PERIOD;\\n\\n /// @notice Minimum seconds a commitment must age before registration can proceed.\\n /// @dev If zero, front-running protection is disabled.\\n uint64 public immutable MIN_COMMITMENT_AGE;\\n\\n /// @notice Maximum seconds a commitment remains valid; expired commitments are rejected.\\n uint64 public immutable MAX_COMMITMENT_AGE;\\n\\n /// @notice Minimum register duration, in seconds.\\n uint64 public immutable MIN_REGISTER_DURATION;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n mapping(bytes32 commitment => uint64 commitTime) public commitmentAt;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`.\\n /// @dev Error selector: `0x3e5aa838`\\n error MaxCommitmentAgeTooLow();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param hcaFactory HCA factory.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n /// @param gracePeriod Post-expiry period where still renewable and not available, in seconds.\\n /// @param minCommitmentAge Minimum seconds a commitment must age before registration can proceed.\\n /// @param maxCommitmentAge Maximum seconds a commitment remains valid; expired commitments are rejected.\\n /// @param minRegisterDuration Minimum register duration, in seconds.\\n constructor(\\n address owner_,\\n IHCAFactoryBasic hcaFactory,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle,\\n uint64 gracePeriod,\\n uint64 minCommitmentAge,\\n uint64 maxCommitmentAge,\\n uint64 minRegisterDuration\\n )\\n AbstractETHRegistrar(owner_, hcaFactory, ethRegistry, beneficiary, oracle)\\n {\\n if (maxCommitmentAge <= minCommitmentAge) {\\n revert MaxCommitmentAgeTooLow();\\n }\\n GRACE_PERIOD = gracePeriod;\\n MIN_COMMITMENT_AGE = minCommitmentAge;\\n MAX_COMMITMENT_AGE = maxCommitmentAge;\\n MIN_REGISTER_DURATION = minRegisterDuration;\\n }\\n\\n /// @inheritdoc AbstractETHRegistrar\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return\\n interfaceId == type(IETHRegistrar).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n function commit(bytes32 commitment) external {\\n if (commitmentAt[commitment] + MAX_COMMITMENT_AGE > block.timestamp) {\\n revert UnexpiredCommitmentExists(commitment);\\n }\\n commitmentAt[commitment] = uint64(block.timestamp);\\n emit CommitmentMade(commitment);\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function register(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256 tokenId)\\n {\\n if (owner == address(0)) {\\n revert InvalidOwner();\\n }\\n _consumeCommitment(\\n makeCommitment(label, owner, secret, subregistry, resolver, duration, referrer)\\n ); // reverts if no commitment\\n IPermissionedRegistry.State memory state = _requireAvailable(label, duration); // reverts if not\\n (uint256 base, uint256 premium) =\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(state.expiry),\\n duration,\\n paymentToken\\n ); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, base + premium); // reverts if payment failed\\n tokenId = ETH_REGISTRY.register(\\n label,\\n owner,\\n subregistry,\\n resolver,\\n REGISTRATION_ROLE_BITMAP,\\n uint64(block.timestamp) + duration // new expiry\\n ); // should not revert\\n emit NameRegistered(\\n tokenId,\\n label,\\n owner,\\n subregistry,\\n resolver,\\n duration,\\n paymentToken,\\n referrer,\\n base,\\n premium\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function isAvailable(string calldata label) external view returns (bool) {\\n return _isAvailable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 bae, uint256 premium)\\n {\\n return\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(_requireAvailable(label, duration).expiry),\\n duration,\\n paymentToken\\n );\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n return\\n uint64(\\n _isRenewableGrace(state)\\n ? GRACE_PERIOD - (block.timestamp - state.expiry)\\n : 0\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n public\\n pure\\n override\\n returns (bytes32)\\n {\\n return\\n keccak256(abi.encode(label, owner, secret, subregistry, resolver, duration, referrer));\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates that the given `commitment` was recorded within the allowed time window\\n /// (between minimum and maximum commitment age), then deletes it so it cannot be reused.\\n /// @param commitment The commitment hash to validate and consume.\\n function _consumeCommitment(bytes32 commitment) internal {\\n uint64 t = uint64(block.timestamp);\\n uint64 t0 = commitmentAt[commitment];\\n uint64 tMin = t0 + MIN_COMMITMENT_AGE;\\n if (t < tMin) {\\n revert CommitmentTooNew(commitment, tMin, t);\\n }\\n uint64 tMax = t0 + MAX_COMMITMENT_AGE;\\n if (t >= tMax) {\\n revert CommitmentTooOld(commitment, tMax, t);\\n }\\n delete commitmentAt[commitment];\\n }\\n\\n /// @dev Ensure name is registerable.\\n function _requireAvailable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isAvailable(state)) {\\n revert NameNotAvailable(label);\\n }\\n if (duration < MIN_REGISTER_DURATION) {\\n revert DurationTooShort(duration, MIN_REGISTER_DURATION);\\n }\\n }\\n\\n /// @dev Determine if `AVAILABLE` and not in grace.\\n function _isAvailable(IPermissionedRegistry.State memory state) internal view returns (bool) {\\n return _checkGrace(state, false);\\n }\\n\\n /// @dev Determine if `REGISTERED` or in grace was `REGISTERED`.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n override\\n returns (bool)\\n {\\n return state.status == IPermissionedRegistry.Status.REGISTERED || _isRenewableGrace(state);\\n }\\n\\n /// @dev Determine if was `REGISTERED` and in grace.\\n function _isRenewableGrace(IPermissionedRegistry.State memory state)\\n internal\\n view\\n returns (bool)\\n {\\n return state.latestOwner != address(0) && _checkGrace(state, true);\\n }\\n\\n /// @dev Check if `AVAILABLE` and conditionally in grace.\\n function _checkGrace(IPermissionedRegistry.State memory state, bool grace)\\n internal\\n view\\n returns (bool)\\n {\\n return\\n state.status == IPermissionedRegistry.Status.AVAILABLE &&\\n (grace == (block.timestamp - state.expiry) < GRACE_PERIOD);\\n }\\n\\n /// @dev Determine duration name has been available.\\n function _availablePeriod(uint64 expiry) internal view returns (uint64) {\\n uint64 t = uint64(block.timestamp);\\n if (expiry == 0) {\\n return t; // never registered\\n }\\n expiry += GRACE_PERIOD;\\n return t > expiry ? t - expiry : 0;\\n }\\n}\\n\",\"keccak256\":\"0x98448c1cb629eec852d9e6ba65ab8b1d46b68f813c2687b0c84d115fbc84b91c\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./IETHRenewer.sol\\\";\\n\\n/// @notice Interface for registering \\\".eth\\\" names.\\n/// @dev Interface selector: `0xc1401b80`\\ninterface IETHRegistrar is IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` was recorded onchain at `block.timestamp`.\\n /// @param commitment The commitment hash from `makeCommitment()`.\\n event CommitmentMade(bytes32 commitment);\\n\\n /// @notice A name was registered.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the registration.\\n /// @param owner The owner address.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param base The amount of `paymentToken` for the registration.\\n /// @param premium The amount of `paymentToken` due to premium.\\n event NameRegistered(\\n uint256 indexed tokenId,\\n string label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 base,\\n uint256 premium\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` is still usable for registration.\\n /// @dev Error selector: `0x0a059d71`\\n error UnexpiredCommitmentExists(bytes32 commitment);\\n\\n /// @notice `commitment` cannot be consumed yet.\\n /// @dev Error selector: `0x6be614e3`\\n error CommitmentTooNew(bytes32 commitment, uint64 validFrom, uint64 blockTimestamp);\\n\\n /// @notice `commitment` has expired.\\n /// @dev Error selector: `0x0cb9df3f`\\n error CommitmentTooOld(bytes32 commitment, uint64 validTo, uint64 blockTimestamp);\\n\\n /// @notice `label` cannot be registered.\\n /// @dev Error selector: `0x477707e8`\\n error NameNotAvailable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registration step #1: record intent to register without revealing any information.\\n /// @dev Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.\\n /// @param commitment The commitment hash.\\n function commit(bytes32 commitment) external;\\n\\n /// @notice Register a name.\\n /// @param label The name from commitment.\\n /// @param owner The owner from commitment.\\n /// @param secret The secret from commitment.\\n /// @param subregistry The registry from commitment.\\n /// @param resolver The resolver from commitment.\\n /// @param duration The registration from commitment.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @return The registered token ID.\\n function register(\\n string memory label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256);\\n\\n /// @notice Get timestamp of a prior commitment.\\n /// @param commitment The commitment hash.\\n /// @return The commitment time, in seconds, or 0 if unknown.\\n function commitmentAt(bytes32 commitment) external view returns (uint64);\\n\\n /// @notice Determine register price for a name.\\n /// @param label The name to register.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Check if name is available.\\n /// @param label The name to check.\\n /// @return `true` if registerable.\\n function isAvailable(string memory label) external view returns (bool);\\n\\n /// @notice Compute hash of registration parameters.\\n /// @param label The name to register.\\n /// @param owner The owner address.\\n /// @param secret The secret for the registration.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param referrer The referrer hash.\\n /// @return The commitment hash.\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n external\\n pure\\n returns (bytes32);\\n}\\n\",\"keccak256\":\"0x7e824c5019f8eb7d7a283451700234716353e01d649c811b5ced5cf58b476289\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for renewing \\\".eth\\\" names.\\n/// @dev Interface selector: `0x06aaeb32`\\ninterface IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A name was extended by `duration`.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the renewal.\\n /// @param duration The duration extension, in seconds.\\n /// @param newExpiry The new expiry, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param amount The amount of `paymentToken`.\\n event NameRenewed(\\n uint256 indexed tokenId,\\n string label,\\n uint64 duration,\\n uint64 newExpiry,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 amount\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `duration` less than `minDuration`.\\n /// @dev Error selector: `0xa096b844`\\n error DurationTooShort(uint64 duration, uint64 minDuration);\\n\\n /// @notice `label` cannot be renewed.\\n /// @dev Error selector: `0x1caefaa0`\\n error NameNotRenewable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Renew a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external;\\n\\n /// @notice Determine renew price for a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice Check if name is renewable.\\n /// @param label The name to check.\\n /// @return `true` if renewable.\\n function isRenewable(string calldata label) external view returns (bool);\\n\\n /// @notice Determine remaining grace period.\\n /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`.\\n /// @param label The name to check.\\n /// @return The remaining grace period, in seconds.\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64);\\n\\n /// @notice Post-expiry period where still renewable and not available, in seconds.\\n function GRACE_PERIOD() external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IWrapperRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IPermissionedRegistry} from \\\"./IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Interface for a registry that manages a locked NameWrapper name.\\n/// @dev Interface selector: `0x6b2f7339`\\ninterface IWrapperRegistry is IPermissionedRegistry {\\n /// @notice Initializes WrapperRegistry.\\n /// @param node Namehash of this registry.\\n /// @param parentRegistry The parent of this registry.\\n /// @param childLabel The subdomain for this registry.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n function initialize(\\n bytes32 node,\\n IRegistry parentRegistry,\\n string calldata childLabel,\\n address rootAccount,\\n uint256 roleBitmap\\n )\\n external;\\n\\n /// @notice Returns the DNS-encoded name for this registry.\\n function getWrappedName() external view returns (bytes memory);\\n\\n /// @notice Returns the NameWrapper node (namehash).\\n function getWrappedNode() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xfc002c3302da346dbe758ecdcf33ef4fbdcefd2e693971a85c31f2c4c86676cd\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 7: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x6bd37001025ec90ffe9b852fcfdf68be81a9f70f8777d80136bea1c04da30041\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/WrappedErrorLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {HexUtils} from \\\"@ens/contracts/utils/HexUtils.sol\\\";\\n\\n/// @dev Library to wrap and unwrap typed error data inside of `Error(string)`.\\n/// Uses hex to embed arbitrary data and avoid invalid unicode.\\nlibrary WrappedErrorLib {\\n /// @dev Error selector for `Error(string)`.\\n bytes4 internal constant ERROR_STRING_SELECTOR = 0x08c379a0;\\n\\n /// @dev The detectable human-readable error prefix.\\n /// Must be exactly 16 bytes.\\n bytes16 internal constant WRAPPED_ERROR_PREFIX = \\\"WrappedError::0x\\\";\\n\\n /// @dev Wrap an error and then revert.\\n function wrapAndRevert(bytes memory err) internal pure {\\n err = wrap(err);\\n assembly {\\n revert(add(err, 32), mload(err))\\n }\\n }\\n\\n /// @dev Embed a typed error into `Error(string)`.\\n /// Does nothing if already `Error(string)`.\\n /// For detection, `WRAPPED_ERROR_PREFIX` is leading bytes the error string.\\n function wrap(bytes memory err) internal pure returns (bytes memory) {\\n if (err.length > 0 && bytes4(err) != ERROR_STRING_SELECTOR) {\\n // assert((err.length & 31) == 4);\\n err = abi.encodeWithSelector(\\n ERROR_STRING_SELECTOR,\\n abi.encodePacked(WRAPPED_ERROR_PREFIX, HexUtils.bytesToHex(err))\\n );\\n }\\n return err;\\n }\\n\\n /// @dev Unwrap a typed error from `Error(string)`.\\n /// Does nothing if detection and extracton fails.\\n /// @param err The error data to unwrap.\\n /// @return The unwrapped error data, or unmodified if not wrapped.\\n function unwrap(bytes memory err) internal pure returns (bytes memory) {\\n if (bytes4(err) == ERROR_STRING_SELECTOR) {\\n bytes memory v;\\n assembly {\\n v := add(err, 4) // skip selector\\n }\\n v = abi.decode(v, (bytes));\\n if (bytes16(v) == WRAPPED_ERROR_PREFIX) {\\n (bytes memory inner, bool ok) = HexUtils.hexToBytes(v, 16, v.length);\\n if (ok) {\\n return inner;\\n }\\n }\\n }\\n return err;\\n }\\n}\\n\",\"keccak256\":\"0xf92862b6509cf553bd542925617318a2509bfdc6457e8b5d102c8e9658c610e4\",\"license\":\"MIT\"},\"project/src/utils/interfaces/IAddressSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x1aedefda`\\ninterface IAddressSet {\\n /// @notice Check if `addr` is included in the set.\\n /// @param addr The address to check.\\n /// @return `true` if included.\\n function includes(address addr) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcb4f9c6364c1cf8a737591088f488ede7a7c6bc9d7d87f2dbdac731b492bd862\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "FrozenTokenApproval(uint256)": [ + { + "notice": "NameWrapper token has existing approval and burned `CANNOT_APPROVE`." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "NameDataMismatch(uint256)": [ + { + "notice": "NameWrapper or BaseRegistrar token does not match supplied data." + } + ], + "NameNotLocked(uint256)": [ + { + "notice": "NameWrapper token is unlocked." + } + ], + "UnauthorizedCaller(address)": [ + { + "notice": "Thrown when a caller is not authorized to perform the requested operation" + } + ] + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "ETH_REGISTRY()": { + "notice": "The ENSv2 .eth `PermissionedRegistry` where migrated names are registered." + }, + "GRAVEYARD()": { + "notice": "The ENSv1 `BaseRegistrar` token graveyard." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens." + }, + "PUBLIC_RESOLVER()": { + "notice": "The replacement `PublicResolver`." + }, + "PUBLIC_RESOLVER_SET()": { + "notice": "The list of `PublicResolver` contracts that require replacement." + }, + "VERIFIABLE_FACTORY()": { + "notice": "The shared factory for verifiable deployments." + }, + "WRAPPER_REGISTRY_IMPL()": { + "notice": "The `WrapperRegistry` implementation contract." + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "notice": "Convert NameWrapper tokens to their equivalent ENSv2 form." + }, + "getWrappedName()": { + "notice": "Returns the DNS-encoded name for this registry." + }, + "getWrappedNode()": { + "notice": "Returns the DNS-encoded name for \"eth\"." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "notice": "Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "notice": "Migrate one NameWrapper token via `safeTransferFrom()`." + } + }, + "notice": "Migration controller for handling locked .eth names. Assumes premigration has `RESERVED` existing ENSv1 names. Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce8000000000000000000000000802453f2f077d5a0c3d0f9a6eb2a36dcfa3c6e0d000000000000000000000000dedb92913a25abe1f7bcdd85d8a344a43b398b67000000000000000000000000d2a632d8a8b67c2c4398c255cbd7af8dd72361980000000000000000000000009d9d230d9b894d3cc14fc7801031f45cd5007f18000000000000000000000000fef98bae02b882b00efa02f3d7b379bee6cda86b0000000000000000000000005239a812ec9a62f46dbb5de8f346c8efe7553a9f000000000000000000000000fc8bf9234969d6b85729b756fa9e14bb84a06754", + "transaction": { + "hash": "0xb9a7512943536ea366e36c799e4434ef216d84f468e46323ce67bc5432b5ed12", + "nonce": "0x1e9d", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x147da58fdb9f984bfdcb992abc0b8218123cd101933a00632c1e299117056305", + "blockNumber": "0xa6a812", + "transactionIndex": "0x3c" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/ManagedUniversalResolverProxy.json b/contracts/deployments/sepolia-official-v1-20260525-r2/ManagedUniversalResolverProxy.json new file mode 100644 index 000000000..9ea48fcb9 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/ManagedUniversalResolverProxy.json @@ -0,0 +1,326 @@ +{ + "address": "0x6d80f2172cfdec5730fe683860c33d26fc42e6f1", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidImplementation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [], + "name": "SameImplementation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "AdminRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "UpgradableUniversalResolverProxy", + "sourceName": "src/universalResolver/UpgradableUniversalResolverProxy.sol", + "bytecode": "0x608060405234801561000f575f5ffd5b50604051610c4d380380610c4d83398101604081905261002e9161019b565b6100378161006e565b5f516020610c2d5f395f51905f5280546001600160a01b0319166001600160a01b038316179055610067826100e6565b50506101cc565b6001600160a01b038116158061008c57506001600160a01b0381163b155b156100aa5760405163340aafcd60e11b815260040160405180910390fd5b6001600160a01b0381166100bc61014d565b6001600160a01b0316036100e357604051634c3b76bf60e01b815260040160405180910390fd5b50565b5f6100ef61016c565b9050815f516020610c0d5f395f51905f5280546001600160a01b0319166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b5f5f516020610c2d5f395f51905f525b546001600160a01b0316919050565b5f5f516020610c0d5f395f51905f5261015d565b80516001600160a01b0381168114610196575f5ffd5b919050565b5f5f604083850312156101ac575f5ffd5b6101b583610180565b91506101c360208401610180565b90509250929050565b610a34806101d95f395ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f5f6100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610698565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106df565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079f565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107ba565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610892565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109eb565b6105a4565b6104308361041d83856109eb565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b805160208201516001600160e01b031981169190600482101561067d576001600160e01b0319808360040360031b1b82161692505b5050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106ab576106ab610684565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b038816835260a0602084015280875180835260c08501915060c08160051b8601019250602089015f5b828110156107455760bf198786030184526107308583516106b1565b94506020938401939190910190600101610714565b50505050828103604084015261075b81876106b1565b6001600160e01b0319861660608501529050828103608084015261077f81856106b1565b98975050505050505050565b6001600160a01b038116811461051a575f5ffd5b5f602082840312156107af575f5ffd5b81356102448161078b565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f7576107f76107ba565b604052919050565b5f5f67ffffffffffffffff841115610819576108196107ba565b50601f8301601f191660200161082e816107ce565b915050828152838383011115610842575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f830112610867575f5ffd5b610244838351602085016107ff565b80516001600160e01b03198116811461088d575f5ffd5b919050565b5f5f5f5f5f60a086880312156108a6575f5ffd5b85516108b18161078b565b602087015190955067ffffffffffffffff8111156108cd575f5ffd5b8601601f810188136108dd575f5ffd5b805167ffffffffffffffff8111156108f7576108f76107ba565b8060051b610907602082016107ce565b9182526020818401810192908101908b841115610922575f5ffd5b6020850192505b8383101561097b57825167ffffffffffffffff811115610947575f5ffd5b8501603f81018d13610957575f5ffd5b6109698d6020830151604084016107ff565b83525060209283019290910190610929565b8098505050505050604086015167ffffffffffffffff81111561099c575f5ffd5b6109a888828901610858565b9350506109b760608701610876565b9150608086015167ffffffffffffffff8111156109d2575f5ffd5b6109de88828901610858565b9150509295509295909350565b808201808211156106ab576106ab61068456fea2646970667358221220279d9d6797af016644e3ccab38510ac50a266b554e0ccfc76c6215c485dcca4264736f6c634300081b0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f5f6100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610698565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106df565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079f565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107ba565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610892565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109eb565b6105a4565b6104308361041d83856109eb565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b805160208201516001600160e01b031981169190600482101561067d576001600160e01b0319808360040360031b1b82161692505b5050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106ab576106ab610684565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b038816835260a0602084015280875180835260c08501915060c08160051b8601019250602089015f5b828110156107455760bf198786030184526107308583516106b1565b94506020938401939190910190600101610714565b50505050828103604084015261075b81876106b1565b6001600160e01b0319861660608501529050828103608084015261077f81856106b1565b98975050505050505050565b6001600160a01b038116811461051a575f5ffd5b5f602082840312156107af575f5ffd5b81356102448161078b565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f7576107f76107ba565b604052919050565b5f5f67ffffffffffffffff841115610819576108196107ba565b50601f8301601f191660200161082e816107ce565b915050828152838383011115610842575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f830112610867575f5ffd5b610244838351602085016107ff565b80516001600160e01b03198116811461088d575f5ffd5b919050565b5f5f5f5f5f60a086880312156108a6575f5ffd5b85516108b18161078b565b602087015190955067ffffffffffffffff8111156108cd575f5ffd5b8601601f810188136108dd575f5ffd5b805167ffffffffffffffff8111156108f7576108f76107ba565b8060051b610907602082016107ce565b9182526020818401810192908101908b841115610922575f5ffd5b6020850192505b8383101561097b57825167ffffffffffffffff811115610947575f5ffd5b8501603f81018d13610957575f5ffd5b6109698d6020830151604084016107ff565b83525060209283019290910190610929565b8098505050505050604086015167ffffffffffffffff81111561099c575f5ffd5b6109a888828901610858565b9350506109b760608701610876565b9150608086015167ffffffffffffffff8111156109d2575f5ffd5b6109de88828901610858565b9150509295509295909350565b808201808211156106ab576106ab61068456fea2646970667358221220279d9d6797af016644e3ccab38510ac50a266b554e0ccfc76c6215c485dcca4264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/src/universalResolver/UpgradableUniversalResolverProxy.sol", + "devdoc": { + "errors": { + "CallerNotAdmin()": [ + { + "details": "Error selector: `0x06d919f2`" + } + ], + "InvalidImplementation()": [ + { + "details": "Error selector: `0x68155f9a`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "SameImplementation()": [ + { + "details": "Error selector: `0x4c3b76bf`" + } + ] + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new admin address", + "previousAdmin": "The previous admin address" + } + }, + "AdminRemoved(address)": { + "params": { + "admin": "The admin address that was removed" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The new implementation address" + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "admin_": "The address of the admin", + "implementation_": "The address of the implementation" + } + }, + "upgradeTo(address)": { + "params": { + "newImplementation": "Address of the new implementation" + } + } + }, + "stateVariables": { + "_ADMIN_SLOT": { + "details": "Storage slot for admin (EIP-1967 compatible)" + }, + "_IMPLEMENTATION_SLOT": { + "details": "Storage slot for implementation address (EIP-1967 compatible)" + } + }, + "title": "UpgradableUniversalResolverProxy", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "522400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "": "infinite", + "admin()": "2430", + "implementation()": "2375", + "renounceAdmin()": "infinite", + "upgradeTo(address)": "infinite" + }, + "internal": { + "_getAdmin()": "2152", + "_getImplementation()": "2141", + "_setAdmin(address)": "27982", + "_setImplementation(address)": "infinite", + "_validateImplementation(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CallerNotAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SameImplementation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"AdminRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CallerNotAdmin()\":[{\"details\":\"Error selector: `0x06d919f2`\"}],\"InvalidImplementation()\":[{\"details\":\"Error selector: `0x68155f9a`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"SameImplementation()\":[{\"details\":\"Error selector: `0x4c3b76bf`\"}]},\"events\":{\"AdminChanged(address,address)\":{\"params\":{\"newAdmin\":\"The new admin address\",\"previousAdmin\":\"The previous admin address\"}},\"AdminRemoved(address)\":{\"params\":{\"admin\":\"The admin address that was removed\"}},\"Upgraded(address)\":{\"params\":{\"implementation\":\"The new implementation address\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"admin_\":\"The address of the admin\",\"implementation_\":\"The address of the implementation\"}},\"upgradeTo(address)\":{\"params\":{\"newImplementation\":\"Address of the new implementation\"}}},\"stateVariables\":{\"_ADMIN_SLOT\":{\"details\":\"Storage slot for admin (EIP-1967 compatible)\"},\"_IMPLEMENTATION_SLOT\":{\"details\":\"Storage slot for implementation address (EIP-1967 compatible)\"}},\"title\":\"UpgradableUniversalResolverProxy\",\"version\":1},\"userdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"notice\":\"Event emitted when the admin is changed.\"},\"AdminRemoved(address)\":{\"notice\":\"Event emitted when the admin is removed.\"},\"Upgraded(address)\":{\"notice\":\"Event emitted when the implementation is upgraded.\"}},\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Returns the current admin address.\"},\"implementation()\":{\"notice\":\"Returns the current implementation address.\"},\"renounceAdmin()\":{\"notice\":\"Allows admin to revoke their admin rights by setting admin to address(0).\"},\"upgradeTo(address)\":{\"notice\":\"Upgrades to a new implementation.\"}},\"notice\":\"A specialized proxy for UniversalResolver that forwards method calls and properly handles CCIP-Read reverts. Admin can upgrade the implementation.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/universalResolver/UpgradableUniversalResolverProxy.sol\":\"UpgradableUniversalResolverProxy\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/src/universalResolver/UpgradableUniversalResolverProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EIP3668, OffchainLookup} from \\\"@ens/contracts/ccipRead/EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"@ens/contracts/utils/BytesUtils.sol\\\";\\nimport {StorageSlot} from \\\"@openzeppelin/contracts/utils/StorageSlot.sol\\\";\\n\\n/// @title UpgradableUniversalResolverProxy\\n/// @notice A specialized proxy for UniversalResolver that forwards method calls\\n/// and properly handles CCIP-Read reverts. Admin can upgrade the implementation.\\ncontract UpgradableUniversalResolverProxy {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Storage slot for implementation address (EIP-1967 compatible)\\n bytes32 private constant _IMPLEMENTATION_SLOT =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @dev Storage slot for admin (EIP-1967 compatible)\\n bytes32 private constant _ADMIN_SLOT =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Event emitted when the implementation is upgraded.\\n /// @param implementation The new implementation address\\n event Upgraded(address indexed implementation);\\n\\n /// @notice Event emitted when the admin is changed.\\n /// @param previousAdmin The previous admin address\\n /// @param newAdmin The new admin address\\n event AdminChanged(address indexed previousAdmin, address indexed newAdmin);\\n\\n /// @notice Event emitted when the admin is removed.\\n /// @param admin The admin address that was removed\\n event AdminRemoved(address indexed admin);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x06d919f2`\\n error CallerNotAdmin();\\n\\n /// @dev Error selector: `0x68155f9a`\\n error InvalidImplementation();\\n\\n /// @dev Error selector: `0x4c3b76bf`\\n error SameImplementation();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier restricting a function to the admin.\\n modifier onlyAdmin() {\\n if (msg.sender != _getAdmin())\\n revert CallerNotAdmin();\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param admin_ The address of the admin\\n /// @param implementation_ The address of the implementation\\n constructor(address admin_, address implementation_) {\\n _validateImplementation(implementation_);\\n _setImplementation(implementation_);\\n _setAdmin(admin_);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Fallback function that handles forwarding calls to the implementation\\n /// and properly manages CCIP-Read reverts.\\n fallback() external {\\n (bool ok, bytes memory v) = _getImplementation().staticcall(msg.data);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n EIP3668.Params memory p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n if (p.sender == _getImplementation()) {\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n p.callbackFunction,\\n p.extraData\\n );\\n }\\n }\\n\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @notice Upgrades to a new implementation.\\n /// @param newImplementation Address of the new implementation\\n function upgradeTo(address newImplementation) external onlyAdmin {\\n _validateImplementation(newImplementation);\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /// @notice Allows admin to revoke their admin rights by setting admin to address(0).\\n function renounceAdmin() external onlyAdmin {\\n address currentAdmin = _getAdmin();\\n _setAdmin(address(0));\\n emit AdminRemoved(currentAdmin);\\n }\\n\\n /// @notice Returns the current implementation address.\\n function implementation() external view returns (address) {\\n return _getImplementation();\\n }\\n\\n /// @notice Returns the current admin address.\\n function admin() external view returns (address) {\\n return _getAdmin();\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates if the implementation is valid.\\n function _validateImplementation(address newImplementation) internal view {\\n if (newImplementation == address(0) || newImplementation.code.length == 0) {\\n revert InvalidImplementation();\\n }\\n if (_getImplementation() == newImplementation) {\\n revert SameImplementation();\\n }\\n }\\n\\n /// @dev Gets the current implementation address from storage.\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /// @dev Gets the current admin address from storage.\\n function _getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Sets the implementation address in storage.\\n function _setImplementation(address newImplementation) private {\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /// @dev Sets the admin address in storage.\\n function _setAdmin(address newAdmin) private {\\n address previousAdmin = _getAdmin();\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n emit AdminChanged(previousAdmin, newAdmin);\\n }\\n}\\n\",\"keccak256\":\"0x12df288b00cb10a4e94697b04af4203300f5592cf32ab27735d0682078fb6110\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "events": { + "AdminChanged(address,address)": { + "notice": "Event emitted when the admin is changed." + }, + "AdminRemoved(address)": { + "notice": "Event emitted when the admin is removed." + }, + "Upgraded(address)": { + "notice": "Event emitted when the implementation is upgraded." + } + }, + "kind": "user", + "methods": { + "admin()": { + "notice": "Returns the current admin address." + }, + "implementation()": { + "notice": "Returns the current implementation address." + }, + "renounceAdmin()": { + "notice": "Allows admin to revoke their admin rights by setting admin to address(0)." + }, + "upgradeTo(address)": { + "notice": "Upgrades to a new implementation." + } + }, + "notice": "A specialized proxy for UniversalResolver that forwards method calls and properly handles CCIP-Read reverts. Admin can upgrade the implementation.", + "version": 1 + }, + "argsData": "0x000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f800000000000000000000000003c85752a5d47dd09d677c645ff2a938b38fbfeba", + "transaction": { + "hash": "0xaa61fc98451c1fcc271e0184a3c016fb940e90402a0c812d917591916199ab37", + "nonce": "0x1ea3", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x34682982fcc1074345b7f298848ec0a3569cfb845f29d57e4ec85e5232598d61", + "blockNumber": "0xa6a818", + "transactionIndex": "0x6d" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/MigrationHelper.json b/contracts/deployments/sepolia-official-v1-20260525-r2/MigrationHelper.json new file mode 100644 index 000000000..b319569d3 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/MigrationHelper.json @@ -0,0 +1,498 @@ +{ + "address": "0x11cfa7e034dafb7439cc1cc8b6e547f5c82ad021", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "rootRegistry", + "type": "address" + }, + { + "internalType": "contract AbstractWrapperReceiver", + "name": "unlockedController", + "type": "address" + }, + { + "internalType": "contract AbstractWrapperReceiver", + "name": "lockedController", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "nft", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "NotApprovedOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "ParentNotMigrated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "WrappedOwnerMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LOCKED_CONTROLLER", + "outputs": [ + { + "internalType": "contract AbstractWrapperReceiver", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_REGISTRY", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNLOCKED_CONTROLLER", + "outputs": [ + { + "internalType": "contract AbstractWrapperReceiver", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[]", + "name": "unwrapped", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[][]", + "name": "unlockedGroups", + "type": "tuple[][]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[][]", + "name": "lockedGroups", + "type": "tuple[][]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "parentName", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[][]", + "name": "groups", + "type": "tuple[][]" + } + ], + "internalType": "struct LockedChildren[]", + "name": "lockedChildrenGroups", + "type": "tuple[]" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "MigrationHelper", + "sourceName": "src/migration/MigrationHelper.sol", + "bytecode": "0x610140604052348015610010575f5ffd5b5060405161184d38038061184d83398101604081905261002f91610148565b6001600160a01b0380851660805283811660a05282811660c081905290821660e0526040805163192cf07d60e01b8152905163192cf07d916004808201926020929091908290030181865afa15801561008a573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100ae91906101a4565b6001600160a01b031661010081905260408051632b20e39760e01b81529051632b20e397916004808201926020929091908290030181865afa1580156100f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061011a91906101a4565b6001600160a01b031661012052506101c692505050565b6001600160a01b0381168114610145575f5ffd5b50565b5f5f5f5f6080858703121561015b575f5ffd5b845161016681610131565b602086015190945061017781610131565b604086015190935061018881610131565b606086015190925061019981610131565b939692955090935050565b5f602082840312156101b4575f5ffd5b81516101bf81610131565b9392505050565b60805160a05160c05160e05161010051610120516115ef61025e5f395f81816101f50152818161026d015261029501525f818160bb0152818161098f01528181610a0901528181610ac40152610c1401525f8181607801526103d401525f818161011e015281816102c5015261038701525f8181610145015261043101525f818160e2015281816107d1015261083201526115ef5ff3fe608060405234801561000f575f5ffd5b506004361061006f575f3560e01c8063476e8b711161004d578063476e8b71146101045780634ee4a14214610119578063c92cc49a14610140575f5ffd5b8063141b1a4c14610073578063192cf07d146100b6578063319c22bb146100dd575b5f5ffd5b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b610117610112366004610e76565b610167565b005b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b5f61017061055d565b90505f5b8881101561035f57368a8a8381811061018f5761018f610f44565b90506020028101906101a19190610f58565b90505f6101ae8280610f76565b6040516101bc929190610fb9565b6040519081900381207f6352211e0000000000000000000000000000000000000000000000000000000082526004820181905291505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610242573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102669190610fdf565b90506102937f0000000000000000000000000000000000000000000000000000000000000000828761056b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b88d4fde827f000000000000000000000000000000000000000000000000000000000000000085876040516020016102f6919061102d565b6040516020818303038152906040526040518563ffffffff1660e01b81526004016103249493929190611110565b5f604051808303815f87803b15801561033b575f5ffd5b505af115801561034d573d5f5f3e3d5ffd5b50505050505050806001019050610174565b506103ad817f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae7f00000000000000000000000000000000000000000000000000000000000000008a8a610662565b6103fa817f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae7f00000000000000000000000000000000000000000000000000000000000000008888610662565b5f5b82811015610551573684848381811061041757610417610f44565b90506020028101906104299190611150565b90505f6104937f000000000000000000000000000000000000000000000000000000000000000061045a8480610f76565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506106b4915050565b90506001600160a01b0381166104ea576104ad8280610f76565b6040517f83d435f10000000000000000000000000000000000000000000000000000000081526004016104e1929190611164565b60405180910390fd5b610547846105346104fb8580610f76565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250610794915050565b83610542602087018761117f565b610662565b50506001016103fc565b50505050505050505050565b5f6105666107ce565b905090565b806001600160a01b0316826001600160a01b03161415801561061357506040517fe985e9c50000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152828116602483015284169063e985e9c590604401602060405180830381865afa1580156105ed573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061061191906111c5565b155b1561065d576040517f1cf8fdfe0000000000000000000000000000000000000000000000000000000081526001600160a01b038085166004830152831660248201526044016104e1565b505050565b5f5b818110156106ac576106a486868686868681811061068457610684610f44565b9050602002810190610696919061117f565b61069f91611252565b6108bf565b600101610664565b505050505050565b5f5f5f6106c18585610cbe565b9092509050816106d557859250505061078d565b5f6106e18787846106b4565b90506001600160a01b03811615610789575f6106fd8787610ceb565b506040517f35af62160000000000000000000000000000000000000000000000000000000081529091506001600160a01b038316906335af621690610746908490600401611398565b602060405180830381865afa158015610761573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107859190610fdf565b9450505b5050505b9392505050565b5f61079f8383610cbe565b9250905080156107c8576107c56107b68484610794565b825f9182526020526040902090565b90505b92915050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661080257503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa15801561087f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a39190610fdf565b90506001600160a01b0381166108ba573391505090565b919050565b80515f8190036108cf5750610cb8565b5f5f8267ffffffffffffffff8111156108ea576108ea6111e4565b604051908082528060200260200182016040528015610913578160200160208202803683370190505b5090505f5b83811015610ab9575f85828151811061093357610933610f44565b602002602001015190505f61095b89835f0151805190602001205f9182526020526040902090565b6040517f0178fe3f000000000000000000000000000000000000000000000000000000008152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156109dc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0091906113aa565b50509050610a2f7f0000000000000000000000000000000000000000000000000000000000000000828d61056b565b835f03610a3e57809550610a8c565b806001600160a01b0316866001600160a01b031614610a8c576040517fd04374c0000000000000000000000000000000000000000000000000000000008152600481018390526024016104e1565b81858581518110610a9f57610a9f610f44565b602002602001018181525050505050806001019050610918565b5082600103610b9a577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f242432a8387845f81518110610b0557610b05610f44565b60200260200101516001895f81518110610b2157610b21610f44565b6020026020010151604051602001610b399190611461565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610b68959493929190611473565b5f604051808303815f87803b158015610b7f575f5ffd5b505af1158015610b91573d5f5f3e3d5ffd5b50505050610cb4565b5f8367ffffffffffffffff811115610bb457610bb46111e4565b604051908082528060200260200182016040528015610bdd578160200160208202803683370190505b5090505f5b84811015610c11576001828281518110610bfe57610bfe610f44565b6020908102919091010152600101610be2565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632eb2c2d6848885858a604051602001610c5691906114ba565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610c85959493929190611557565b5f604051808303815f87803b158015610c9c575f5ffd5b505af1158015610cae573d5f5f3e3d5ffd5b50505050505b5050505b50505050565b5f5f5f610ccb8585610d68565b9250905060ff811615610ce357806021858701012092505b509250929050565b60605f5f610cf98585610d68565b925090505f60ff821667ffffffffffffffff811115610d1a57610d1a6111e4565b6040519080825280601f01601f191660200182016040528015610d44576020820181803683370190505b509050610d5d6020820160218888010160ff8516610dec565b959194509092505050565b5f5f83518310610d8d578360405163ba4adc2360e01b81526004016104e19190611398565b838381518110610d9f57610d9f610f44565b016020015160f81c91505081810160010181610dbf578351811415610dc5565b83518110155b15610de5578360405163ba4adc2360e01b81526004016104e19190611398565b9250929050565b5b601f811115610e0d578151835260209283019290910190601f1901610ded565b801561065d5790518251600160209390930360031b9290921b5f190180199091169116179052565b5f5f83601f840112610e45575f5ffd5b50813567ffffffffffffffff811115610e5c575f5ffd5b6020830191508360208260051b8501011115610de5575f5ffd5b5f5f5f5f5f5f5f5f6080898b031215610e8d575f5ffd5b883567ffffffffffffffff811115610ea3575f5ffd5b610eaf8b828c01610e35565b909950975050602089013567ffffffffffffffff811115610ece575f5ffd5b610eda8b828c01610e35565b909750955050604089013567ffffffffffffffff811115610ef9575f5ffd5b610f058b828c01610e35565b909550935050606089013567ffffffffffffffff811115610f24575f5ffd5b610f308b828c01610e35565b999c989b5096995094979396929594505050565b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112610f6c575f5ffd5b9190910192915050565b5f5f8335601e19843603018112610f8b575f5ffd5b83018035915067ffffffffffffffff821115610fa5575f5ffd5b602001915036819003821315610de5575f5ffd5b818382375f9101908152919050565b6001600160a01b0381168114610fdc575f5ffd5b50565b5f60208284031215610fef575f5ffd5b815161078d81610fc8565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b80356108ba81610fc8565b602081525f8235601e19843603018112611045575f5ffd5b830160208101903567ffffffffffffffff811115611061575f5ffd5b80360382131561106f575f5ffd5b6080602085015261108460a085018284610ffa565b91505061109360208501611022565b6001600160a01b0381166040850152506110af60408501611022565b6001600160a01b0381166060850152506110cb60608501611022565b6001600160a01b0381166080850152509392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f61114660808301846110e2565b9695505050505050565b5f8235603e19833603018112610f6c575f5ffd5b602081525f611177602083018486610ffa565b949350505050565b5f5f8335601e19843603018112611194575f5ffd5b83018035915067ffffffffffffffff8211156111ae575f5ffd5b6020019150600581901b3603821315610de5575f5ffd5b5f602082840312156111d5575f5ffd5b8151801515811461078d575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff8111828210171561121b5761121b6111e4565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561124a5761124a6111e4565b604052919050565b5f67ffffffffffffffff83111561126b5761126b6111e4565b8260051b61127b60208201611221565b84815290830190602081019036831115611293575f5ffd5b845b8381101561138e57803567ffffffffffffffff8111156112b3575f5ffd5b860160803682900312156112c5575f5ffd5b6112cd6111f8565b813567ffffffffffffffff8111156112e3575f5ffd5b820136601f8201126112f3575f5ffd5b803567ffffffffffffffff81111561130d5761130d6111e4565b611320601f8201601f1916602001611221565b818152366020838501011115611334575f5ffd5b816020840160208301375f6020838301015280845250505061135860208301611022565b602082015261136960408301611022565b604082015261137a60608301611022565b606082015284525060209283019201611295565b5095945050505050565b602081525f6107c560208301846110e2565b5f5f5f606084860312156113bc575f5ffd5b83516113c781610fc8565b602085015190935063ffffffff811681146113e0575f5ffd5b604085015190925067ffffffffffffffff811681146113fd575f5ffd5b809150509250925092565b5f81516080845261141c60808501826110e2565b90506001600160a01b0360208401511660208501526001600160a01b0360408401511660408501526001600160a01b0360608401511660608501528091505092915050565b602081525f6107c56020830184611408565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a060808201525f6114af60a08301846110e2565b979650505050505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561151157603f198786030184526114fc858351611408565b945060209384019391909101906001016114e0565b50929695505050505050565b5f8151808452602084019350602083015f5b8281101561154d57815186526020958601959091019060010161152f565b5093949350505050565b6001600160a01b03861681526001600160a01b038516602082015260a060408201525f61158760a083018661151d565b8281036060840152611599818661151d565b905082810360808401526115ad81856110e2565b9897505050505050505056fea264697066735822122003ec8138856440ca21fd07cae164858e12922b65ac8ae6b302200d748ea961c764736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061006f575f3560e01c8063476e8b711161004d578063476e8b71146101045780634ee4a14214610119578063c92cc49a14610140575f5ffd5b8063141b1a4c14610073578063192cf07d146100b6578063319c22bb146100dd575b5f5ffd5b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b610117610112366004610e76565b610167565b005b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b61009a7f000000000000000000000000000000000000000000000000000000000000000081565b5f61017061055d565b90505f5b8881101561035f57368a8a8381811061018f5761018f610f44565b90506020028101906101a19190610f58565b90505f6101ae8280610f76565b6040516101bc929190610fb9565b6040519081900381207f6352211e0000000000000000000000000000000000000000000000000000000082526004820181905291505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610242573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102669190610fdf565b90506102937f0000000000000000000000000000000000000000000000000000000000000000828761056b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b88d4fde827f000000000000000000000000000000000000000000000000000000000000000085876040516020016102f6919061102d565b6040516020818303038152906040526040518563ffffffff1660e01b81526004016103249493929190611110565b5f604051808303815f87803b15801561033b575f5ffd5b505af115801561034d573d5f5f3e3d5ffd5b50505050505050806001019050610174565b506103ad817f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae7f00000000000000000000000000000000000000000000000000000000000000008a8a610662565b6103fa817f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae7f00000000000000000000000000000000000000000000000000000000000000008888610662565b5f5b82811015610551573684848381811061041757610417610f44565b90506020028101906104299190611150565b90505f6104937f000000000000000000000000000000000000000000000000000000000000000061045a8480610f76565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506106b4915050565b90506001600160a01b0381166104ea576104ad8280610f76565b6040517f83d435f10000000000000000000000000000000000000000000000000000000081526004016104e1929190611164565b60405180910390fd5b610547846105346104fb8580610f76565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250610794915050565b83610542602087018761117f565b610662565b50506001016103fc565b50505050505050505050565b5f6105666107ce565b905090565b806001600160a01b0316826001600160a01b03161415801561061357506040517fe985e9c50000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152828116602483015284169063e985e9c590604401602060405180830381865afa1580156105ed573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061061191906111c5565b155b1561065d576040517f1cf8fdfe0000000000000000000000000000000000000000000000000000000081526001600160a01b038085166004830152831660248201526044016104e1565b505050565b5f5b818110156106ac576106a486868686868681811061068457610684610f44565b9050602002810190610696919061117f565b61069f91611252565b6108bf565b600101610664565b505050505050565b5f5f5f6106c18585610cbe565b9092509050816106d557859250505061078d565b5f6106e18787846106b4565b90506001600160a01b03811615610789575f6106fd8787610ceb565b506040517f35af62160000000000000000000000000000000000000000000000000000000081529091506001600160a01b038316906335af621690610746908490600401611398565b602060405180830381865afa158015610761573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107859190610fdf565b9450505b5050505b9392505050565b5f61079f8383610cbe565b9250905080156107c8576107c56107b68484610794565b825f9182526020526040902090565b90505b92915050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661080257503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa15801561087f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108a39190610fdf565b90506001600160a01b0381166108ba573391505090565b919050565b80515f8190036108cf5750610cb8565b5f5f8267ffffffffffffffff8111156108ea576108ea6111e4565b604051908082528060200260200182016040528015610913578160200160208202803683370190505b5090505f5b83811015610ab9575f85828151811061093357610933610f44565b602002602001015190505f61095b89835f0151805190602001205f9182526020526040902090565b6040517f0178fe3f000000000000000000000000000000000000000000000000000000008152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156109dc573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0091906113aa565b50509050610a2f7f0000000000000000000000000000000000000000000000000000000000000000828d61056b565b835f03610a3e57809550610a8c565b806001600160a01b0316866001600160a01b031614610a8c576040517fd04374c0000000000000000000000000000000000000000000000000000000008152600481018390526024016104e1565b81858581518110610a9f57610a9f610f44565b602002602001018181525050505050806001019050610918565b5082600103610b9a577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f242432a8387845f81518110610b0557610b05610f44565b60200260200101516001895f81518110610b2157610b21610f44565b6020026020010151604051602001610b399190611461565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610b68959493929190611473565b5f604051808303815f87803b158015610b7f575f5ffd5b505af1158015610b91573d5f5f3e3d5ffd5b50505050610cb4565b5f8367ffffffffffffffff811115610bb457610bb46111e4565b604051908082528060200260200182016040528015610bdd578160200160208202803683370190505b5090505f5b84811015610c11576001828281518110610bfe57610bfe610f44565b6020908102919091010152600101610be2565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632eb2c2d6848885858a604051602001610c5691906114ba565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610c85959493929190611557565b5f604051808303815f87803b158015610c9c575f5ffd5b505af1158015610cae573d5f5f3e3d5ffd5b50505050505b5050505b50505050565b5f5f5f610ccb8585610d68565b9250905060ff811615610ce357806021858701012092505b509250929050565b60605f5f610cf98585610d68565b925090505f60ff821667ffffffffffffffff811115610d1a57610d1a6111e4565b6040519080825280601f01601f191660200182016040528015610d44576020820181803683370190505b509050610d5d6020820160218888010160ff8516610dec565b959194509092505050565b5f5f83518310610d8d578360405163ba4adc2360e01b81526004016104e19190611398565b838381518110610d9f57610d9f610f44565b016020015160f81c91505081810160010181610dbf578351811415610dc5565b83518110155b15610de5578360405163ba4adc2360e01b81526004016104e19190611398565b9250929050565b5b601f811115610e0d578151835260209283019290910190601f1901610ded565b801561065d5790518251600160209390930360031b9290921b5f190180199091169116179052565b5f5f83601f840112610e45575f5ffd5b50813567ffffffffffffffff811115610e5c575f5ffd5b6020830191508360208260051b8501011115610de5575f5ffd5b5f5f5f5f5f5f5f5f6080898b031215610e8d575f5ffd5b883567ffffffffffffffff811115610ea3575f5ffd5b610eaf8b828c01610e35565b909950975050602089013567ffffffffffffffff811115610ece575f5ffd5b610eda8b828c01610e35565b909750955050604089013567ffffffffffffffff811115610ef9575f5ffd5b610f058b828c01610e35565b909550935050606089013567ffffffffffffffff811115610f24575f5ffd5b610f308b828c01610e35565b999c989b5096995094979396929594505050565b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112610f6c575f5ffd5b9190910192915050565b5f5f8335601e19843603018112610f8b575f5ffd5b83018035915067ffffffffffffffff821115610fa5575f5ffd5b602001915036819003821315610de5575f5ffd5b818382375f9101908152919050565b6001600160a01b0381168114610fdc575f5ffd5b50565b5f60208284031215610fef575f5ffd5b815161078d81610fc8565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b80356108ba81610fc8565b602081525f8235601e19843603018112611045575f5ffd5b830160208101903567ffffffffffffffff811115611061575f5ffd5b80360382131561106f575f5ffd5b6080602085015261108460a085018284610ffa565b91505061109360208501611022565b6001600160a01b0381166040850152506110af60408501611022565b6001600160a01b0381166060850152506110cb60608501611022565b6001600160a01b0381166080850152509392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03851681526001600160a01b0384166020820152826040820152608060608201525f61114660808301846110e2565b9695505050505050565b5f8235603e19833603018112610f6c575f5ffd5b602081525f611177602083018486610ffa565b949350505050565b5f5f8335601e19843603018112611194575f5ffd5b83018035915067ffffffffffffffff8211156111ae575f5ffd5b6020019150600581901b3603821315610de5575f5ffd5b5f602082840312156111d5575f5ffd5b8151801515811461078d575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff8111828210171561121b5761121b6111e4565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561124a5761124a6111e4565b604052919050565b5f67ffffffffffffffff83111561126b5761126b6111e4565b8260051b61127b60208201611221565b84815290830190602081019036831115611293575f5ffd5b845b8381101561138e57803567ffffffffffffffff8111156112b3575f5ffd5b860160803682900312156112c5575f5ffd5b6112cd6111f8565b813567ffffffffffffffff8111156112e3575f5ffd5b820136601f8201126112f3575f5ffd5b803567ffffffffffffffff81111561130d5761130d6111e4565b611320601f8201601f1916602001611221565b818152366020838501011115611334575f5ffd5b816020840160208301375f6020838301015280845250505061135860208301611022565b602082015261136960408301611022565b604082015261137a60608301611022565b606082015284525060209283019201611295565b5095945050505050565b602081525f6107c560208301846110e2565b5f5f5f606084860312156113bc575f5ffd5b83516113c781610fc8565b602085015190935063ffffffff811681146113e0575f5ffd5b604085015190925067ffffffffffffffff811681146113fd575f5ffd5b809150509250925092565b5f81516080845261141c60808501826110e2565b90506001600160a01b0360208401511660208501526001600160a01b0360408401511660408501526001600160a01b0360608401511660608501528091505092915050565b602081525f6107c56020830184611408565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a060808201525f6114af60a08301846110e2565b979650505050505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561151157603f198786030184526114fc858351611408565b945060209384019391909101906001016114e0565b50929695505050505050565b5f8151808452602084019350602083015f5b8281101561154d57815186526020958601959091019060010161152f565b5093949350505050565b6001600160a01b03861681526001600160a01b038516602082015260a060408201525f61158760a083018661151d565b8281036060840152611599818661151d565b905082810360808401526115ad81856110e2565b9897505050505050505056fea264697066735822122003ec8138856440ca21fd07cae164858e12922b65ac8ae6b302200d748ea961c764736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60111": [ + { + "length": 32, + "start": 226 + }, + { + "length": 32, + "start": 2001 + }, + { + "length": 32, + "start": 2098 + } + ], + "62479": [ + { + "length": 32, + "start": 325 + }, + { + "length": 32, + "start": 1073 + } + ], + "62483": [ + { + "length": 32, + "start": 286 + }, + { + "length": 32, + "start": 709 + }, + { + "length": 32, + "start": 903 + } + ], + "62487": [ + { + "length": 32, + "start": 120 + }, + { + "length": 32, + "start": 980 + } + ], + "62491": [ + { + "length": 32, + "start": 187 + }, + { + "length": 32, + "start": 2447 + }, + { + "length": 32, + "start": 2569 + }, + { + "length": 32, + "start": 2756 + }, + { + "length": 32, + "start": 3092 + } + ], + "62495": [ + { + "length": 32, + "start": 501 + }, + { + "length": 32, + "start": 621 + }, + { + "length": 32, + "start": 661 + } + ] + }, + "inputSourceName": "project/src/migration/MigrationHelper.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "NotApprovedOperator(address,address)": [ + { + "details": "Error selector: `0x1cf8fdfe`" + } + ], + "ParentNotMigrated(bytes)": [ + { + "details": "Error selector: `0x83d435f1`" + } + ], + "WrappedOwnerMismatch(uint256)": [ + { + "details": "Error selector: `0xd04374c0`" + } + ] + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "hcaFactory": "The HCA factory to use.", + "lockedController": "The ENSv2 `LockedMigrationController`.", + "rootRegistry": "The root registry.", + "unlockedController": "The ENSv2 `UnlockedMigrationController`." + } + }, + "migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])": { + "params": { + "lockedChildrenGroups": "Array of `LockedChildren` for 3LD+ tokens.", + "lockedGroups": "Array of Groups of `LibMigration.Data` for locked 2LD tokens with a common owner.", + "unlockedGroups": "Array of Groups of `LibMigration.Data` for unlocked 2LD tokens with a common owner.", + "unwrapped": "Array of `LibMigration.Data` for unwrapped tokens." + } + } + }, + "stateVariables": { + "_BASE_REGISTRAR": { + "details": "The ENSv1 `BaseRegistrar` contract." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1123000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "HCA_FACTORY()": "infinite", + "LOCKED_CONTROLLER()": "infinite", + "NAME_WRAPPER()": "infinite", + "ROOT_REGISTRY()": "infinite", + "UNLOCKED_CONTROLLER()": "infinite", + "migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])": "infinite" + }, + "internal": { + "_requireOperatorApproval(address,address,address)": "infinite", + "_transferWrapped(address,bytes32,address,struct LibMigration.Data memory[] memory)": "infinite", + "_transferWrappedGroups(address,bytes32,address,struct LibMigration.Data calldata[] calldata[] calldata)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"rootRegistry\",\"type\":\"address\"},{\"internalType\":\"contract AbstractWrapperReceiver\",\"name\":\"unlockedController\",\"type\":\"address\"},{\"internalType\":\"contract AbstractWrapperReceiver\",\"name\":\"lockedController\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"nft\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NotApprovedOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"ParentNotMigrated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"WrappedOwnerMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LOCKED_CONTROLLER\",\"outputs\":[{\"internalType\":\"contract AbstractWrapperReceiver\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNLOCKED_CONTROLLER\",\"outputs\":[{\"internalType\":\"contract AbstractWrapperReceiver\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[]\",\"name\":\"unwrapped\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[][]\",\"name\":\"unlockedGroups\",\"type\":\"tuple[][]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[][]\",\"name\":\"lockedGroups\",\"type\":\"tuple[][]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"parentName\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[][]\",\"name\":\"groups\",\"type\":\"tuple[][]\"}],\"internalType\":\"struct LockedChildren[]\",\"name\":\"lockedChildrenGroups\",\"type\":\"tuple[]\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"NotApprovedOperator(address,address)\":[{\"details\":\"Error selector: `0x1cf8fdfe`\"}],\"ParentNotMigrated(bytes)\":[{\"details\":\"Error selector: `0x83d435f1`\"}],\"WrappedOwnerMismatch(uint256)\":[{\"details\":\"Error selector: `0xd04374c0`\"}]},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"hcaFactory\":\"The HCA factory to use.\",\"lockedController\":\"The ENSv2 `LockedMigrationController`.\",\"rootRegistry\":\"The root registry.\",\"unlockedController\":\"The ENSv2 `UnlockedMigrationController`.\"}},\"migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])\":{\"params\":{\"lockedChildrenGroups\":\"Array of `LockedChildren` for 3LD+ tokens.\",\"lockedGroups\":\"Array of Groups of `LibMigration.Data` for locked 2LD tokens with a common owner.\",\"unlockedGroups\":\"Array of Groups of `LibMigration.Data` for unlocked 2LD tokens with a common owner.\",\"unwrapped\":\"Array of `LibMigration.Data` for unwrapped tokens.\"}}},\"stateVariables\":{\"_BASE_REGISTRAR\":{\"details\":\"The ENSv1 `BaseRegistrar` contract.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"NotApprovedOperator(address,address)\":[{\"notice\":\"Caller is not an approved operator by `owner` on `nft`.\"}],\"ParentNotMigrated(bytes)\":[{\"notice\":\"A parent has not been migrated yet.\"}],\"WrappedOwnerMismatch(uint256)\":[{\"notice\":\"A group has multiple owners.\"}]},\"kind\":\"user\",\"methods\":{\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"LOCKED_CONTROLLER()\":{\"notice\":\"The ENSv2 `LockedMigrationController` contract.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract.\"},\"ROOT_REGISTRY()\":{\"notice\":\"The ENSv2 root registry.\"},\"UNLOCKED_CONTROLLER()\":{\"notice\":\"The ENSv2 `UnlockedMigrationController` contract.\"},\"constructor\":{\"notice\":\"Initializes `MigrationHelper`.\"},\"migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])\":{\"notice\":\"Optimized batch migration helper.\"}},\"notice\":\"Migration helper for mixed (ERC-721 and ERC-1155) batch migration using approval.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/migration/MigrationHelper.sol\":\"MigrationHelper\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/migration/AbstractWrapperReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {IERC1155Receiver} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport {ERC165, IERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {UnauthorizedCaller} from \\\"../CommonErrors.sol\\\";\\nimport {WrappedErrorLib} from \\\"../utils/WrappedErrorLib.sol\\\";\\n\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title AbstractWrapperReceiver\\n/// @dev Abstract IERC1155Receiver which handles NameWrapper token migration via transfer.\\n///\\n/// NameWrapper only allows `Error(string)` exceptions during transfer and squelches typed errors.\\n/// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L317-L335\\n/// This contract, with the aid of WrappedErrorLib, embeds errors that occur during migration into `Error(string)`.\\n///\\n/// There are (2) AbstractWrapperReceiver implementations:\\n/// 1. UnlockedMigrationController accepts unlocked tokens.\\n/// 2. LockedWrapperReceiver accepts locked tokens.\\n///\\n/// `LibMigration.isLocked()` determines lock status.\\n///\\nabstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice The ENSv1 `BaseRegistrar` token graveyard.\\n address public immutable GRAVEYARD;\\n\\n /// @dev The ENSv1 `ENSRegistry` contract.\\n ENS internal immutable _REGISTRY_V1;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Restrict `msg.sender` to NameWrapper.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier onlyWrapper() {\\n if (msg.sender != address(NAME_WRAPPER)) {\\n WrappedErrorLib.wrapAndRevert(\\n abi.encodeWithSelector(UnauthorizedCaller.selector, msg.sender)\\n );\\n }\\n _;\\n }\\n\\n /// @dev Avoid `abi.decode()` failure for obviously invalid data.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier withData(bytes calldata data, uint256 minimumSize) {\\n if (data.length < minimumSize) {\\n WrappedErrorLib.wrapAndRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector));\\n }\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n constructor(INameWrapper nameWrapper, address graveyard) {\\n NAME_WRAPPER = nameWrapper;\\n GRAVEYARD = graveyard;\\n _REGISTRY_V1 = nameWrapper.ens();\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate one NameWrapper token via `safeTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param id The NameWrapper token ID (namehash) of the name being migrated.\\n /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters.\\n function onERC1155Received(\\n address /*operator*/,\\n address /*from*/,\\n uint256 id,\\n uint256 /*amount*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (amount != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L293\\n uint256[] memory ids = new uint256[](1);\\n LibMigration.Data[] memory mds = new LibMigration.Data[](1);\\n ids[0] = id;\\n mds[0] = abi.decode(data, (LibMigration.Data)); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155Received.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param data ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\\n function onERC1155BatchReceived(\\n address /*operator*/,\\n address /*from*/,\\n uint256[] calldata ids,\\n uint256[] calldata /*amounts*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, 64 + ids.length * LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (ids.length != amounts.length) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L162\\n // if (amounts[i] != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L182\\n LibMigration.Data[] memory mds = abi.decode(data, (LibMigration.Data[])); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155BatchReceived.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @notice Convert NameWrapper tokens to their equivalent ENSv2 form.\\n /// @dev Only callable by ourself and invoked by our `IERC1155Receiver` handlers.\\n ///\\n /// TODO: gas analysis and optimization\\n /// NOTE: converting this to an internal call requires catching many reverts\\n ///\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param mds The migration parameters for each name, indexed in parallel with `ids`.\\n function finishERC1155Migration(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n external\\n {\\n if (msg.sender != address(this)) {\\n revert UnauthorizedCaller(msg.sender);\\n }\\n if (ids.length != mds.length) {\\n revert IERC1155Errors.ERC1155InvalidArrayLength(ids.length, mds.length);\\n }\\n _migrateWrapped(ids, mds);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Migrate received NameWrapper tokens.\\n /// Token owner is this contract.\\n /// Token is not expired.\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n virtual;\\n}\\n\",\"keccak256\":\"0x0c15f9f657ba58bf5081cbff88c385c9e673ba87aed2032397ec2c5448d7fe1a\",\"license\":\"MIT\"},\"project/src/migration/MigrationHelper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IBaseRegistrar} from \\\"@ens/contracts/ethregistrar/IBaseRegistrar.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {LibRegistry} from \\\"../universalResolver/libraries/LibRegistry.sol\\\";\\n\\nimport {AbstractWrapperReceiver} from \\\"./AbstractWrapperReceiver.sol\\\";\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @dev Struct for migrating locked 3LD+ tokens.\\nstruct LockedChildren {\\n /// @param parentName The parent name.\\n bytes parentName;\\n /// @param groups Array of Groups of `LibMigration.Data` for locked tokens with a common owner.\\n LibMigration.Data[][] groups;\\n}\\n\\n/// @notice Migration helper for mixed (ERC-721 and ERC-1155) batch migration using approval.\\ncontract MigrationHelper is HCAContext {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 root registry.\\n IRegistry public immutable ROOT_REGISTRY;\\n\\n /// @notice The ENSv2 `UnlockedMigrationController` contract.\\n AbstractWrapperReceiver public immutable UNLOCKED_CONTROLLER;\\n\\n /// @notice The ENSv2 `LockedMigrationController` contract.\\n AbstractWrapperReceiver public immutable LOCKED_CONTROLLER;\\n\\n /// @notice The ENSv1 `NameWrapper` contract.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @dev The ENSv1 `BaseRegistrar` contract.\\n IBaseRegistrar internal immutable _BASE_REGISTRAR;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A group has multiple owners.\\n /// @dev Error selector: `0xd04374c0`\\n error WrappedOwnerMismatch(uint256 tokenId);\\n\\n /// @notice A parent has not been migrated yet.\\n /// @dev Error selector: `0x83d435f1`\\n error ParentNotMigrated(bytes name);\\n\\n /// @notice Caller is not an approved operator by `owner` on `nft`.\\n /// @dev Error selector: `0x1cf8fdfe`\\n error NotApprovedOperator(address nft, address owner);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Initializes `MigrationHelper`.\\n /// @param hcaFactory The HCA factory to use.\\n /// @param rootRegistry The root registry.\\n /// @param unlockedController The ENSv2 `UnlockedMigrationController`.\\n /// @param lockedController The ENSv2 `LockedMigrationController`.\\n constructor(\\n IHCAFactoryBasic hcaFactory,\\n IRegistry rootRegistry,\\n AbstractWrapperReceiver unlockedController,\\n AbstractWrapperReceiver lockedController\\n )\\n HCAEquivalence(hcaFactory)\\n {\\n ROOT_REGISTRY = rootRegistry;\\n UNLOCKED_CONTROLLER = unlockedController;\\n LOCKED_CONTROLLER = lockedController;\\n\\n NAME_WRAPPER = unlockedController.NAME_WRAPPER();\\n _BASE_REGISTRAR = NAME_WRAPPER.registrar();\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Optimized batch migration helper.\\n /// @param unwrapped Array of `LibMigration.Data` for unwrapped tokens.\\n /// @param unlockedGroups Array of Groups of `LibMigration.Data` for unlocked 2LD tokens with a common owner.\\n /// @param lockedGroups Array of Groups of `LibMigration.Data` for locked 2LD tokens with a common owner.\\n /// @param lockedChildrenGroups Array of `LockedChildren` for 3LD+ tokens.\\n function migrate(\\n LibMigration.Data[] calldata unwrapped,\\n LibMigration.Data[][] calldata unlockedGroups,\\n LibMigration.Data[][] calldata lockedGroups,\\n LockedChildren[] calldata lockedChildrenGroups\\n )\\n external\\n {\\n address sender = _msgSender();\\n for (uint256 i; i < unwrapped.length; ++i) {\\n LibMigration.Data calldata md = unwrapped[i];\\n uint256 tokenId = uint256(keccak256(bytes(md.label)));\\n address owner = _BASE_REGISTRAR.ownerOf(tokenId);\\n _requireOperatorApproval(address(_BASE_REGISTRAR), owner, sender);\\n _BASE_REGISTRAR.safeTransferFrom(\\n owner,\\n address(UNLOCKED_CONTROLLER),\\n tokenId,\\n abi.encode(md)\\n );\\n }\\n _transferWrappedGroups(\\n sender,\\n NameCoder.ETH_NODE,\\n address(UNLOCKED_CONTROLLER),\\n unlockedGroups\\n );\\n _transferWrappedGroups(sender, NameCoder.ETH_NODE, address(LOCKED_CONTROLLER), lockedGroups);\\n for (uint256 j; j < lockedChildrenGroups.length; ++j) {\\n LockedChildren calldata lc = lockedChildrenGroups[j];\\n IRegistry registry = LibRegistry.findExactRegistry(ROOT_REGISTRY, lc.parentName, 0);\\n if (address(registry) == address(0)) {\\n revert ParentNotMigrated(lc.parentName);\\n }\\n _transferWrappedGroups(\\n sender,\\n NameCoder.namehash(lc.parentName, 0),\\n address(registry),\\n lc.groups\\n );\\n }\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Batch transfer groups of NameWrapper tokens.\\n function _transferWrappedGroups(\\n address sender,\\n bytes32 parentNode,\\n address receiver,\\n LibMigration.Data[][] calldata groups\\n )\\n internal\\n {\\n for (uint256 i; i < groups.length; ++i) {\\n _transferWrapped(sender, parentNode, receiver, groups[i]);\\n }\\n }\\n\\n /// @dev Batch transfer NameWrapper tokens.\\n function _transferWrapped(\\n address sender,\\n bytes32 parentNode,\\n address receiver,\\n LibMigration.Data[] memory mds\\n )\\n internal\\n {\\n uint256 n = mds.length;\\n if (n == 0) {\\n return;\\n }\\n address from;\\n uint256[] memory ids = new uint256[](n);\\n for (uint256 i; i < n; ++i) {\\n LibMigration.Data memory md = mds[i];\\n uint256 id = uint256(NameCoder.namehash(parentNode, keccak256(bytes(md.label))));\\n (address owner, , ) = NAME_WRAPPER.getData(id);\\n _requireOperatorApproval(address(NAME_WRAPPER), owner, sender);\\n if (i == 0) {\\n from = owner;\\n } else if (from != owner) {\\n revert WrappedOwnerMismatch(id);\\n }\\n ids[i] = id;\\n }\\n if (n == 1) {\\n NAME_WRAPPER.safeTransferFrom(from, receiver, ids[0], 1, abi.encode(mds[0]));\\n } else {\\n uint256[] memory amounts = new uint256[](n);\\n for (uint256 i; i < n; ++i) {\\n amounts[i] = 1;\\n }\\n NAME_WRAPPER.safeBatchTransferFrom(from, receiver, ids, amounts, abi.encode(mds));\\n }\\n }\\n\\n /// @dev Ensure operator is owner or approved by owner.\\n function _requireOperatorApproval(address nft, address owner, address operator) internal view {\\n // transfer() will check if from is approved by this contract\\n // note: both IBaseRegistrar and INameWrapper implement isApprovedForAll()\\n if (owner != operator && !INameWrapper(nft).isApprovedForAll(owner, operator)) {\\n revert NotApprovedOperator(nft, owner);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa74df3251aca219d511247197ea164c9f7abd0c8587394720b70b8c4d7534683\",\"license\":\"MIT\"},\"project/src/migration/libraries/LibMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n CANNOT_BURN_FUSES,\\n CANNOT_UNWRAP,\\n IS_DOT_ETH,\\n PARENT_CANNOT_CONTROL\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Primitives for migration.\\nlibrary LibMigration {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Typed arguments for migration via transfer payload.\\n struct Data {\\n /// @dev Subdomain being migrated.\\n string label;\\n /// @dev Address that will own the name in the v2 registry.\\n address owner;\\n /// @dev Address of the child registry.\\n /// Ignored by locked migration.\\n IRegistry subregistry;\\n /// @dev Resolver address to set for the migrated name.\\n /// Ignored if locked and `CANNOT_SET_RESOLVER`.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Minimum size of `abi.encode(Data({...}))`.\\n uint256 internal constant MIN_DATA_SIZE = 7 * 32;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be registered because unmigrated NameWrapper token exists.\\n /// @dev Error selector: `0x408fa1b8`\\n error NameRequiresMigration();\\n\\n /// @notice NameWrapper token is unlocked.\\n /// @dev Error selector: `0x1bfe8f0a`\\n error NameNotLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper token is locked.\\n /// @dev Error selector: `0xe7c290e2`\\n error NameIsLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper or BaseRegistrar token does not match supplied data.\\n /// @dev Error selector: `0xedec3569`\\n error NameDataMismatch(uint256 tokenId);\\n\\n /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\\n /// @dev Error selector: `0xa4f07713`\\n error FrozenTokenApproval(uint256 tokenId);\\n\\n /// @notice The encoded data is invalid.\\n /// @dev Error selector: `0x5cb045db`\\n error InvalidData();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns `true` if the NameWrapper token is locked.\\n function isLocked(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient\\n // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()`\\n return (fuses & CANNOT_UNWRAP) != 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token fuses are not frozen.\\n function notFrozen(uint32 fuses) internal pure returns (bool) {\\n return (fuses & CANNOT_BURN_FUSES) == 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth.\\n function isEmancipatedChild(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL must be set for the entire ancestory.\\n // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()`\\n return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL;\\n }\\n}\\n\",\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/universalResolver/libraries/LibRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"../../registry/interfaces/IOwnedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Recursive traversal helpers for the namechain registry tree \\u2014 resolver lookup, registry\\n/// discovery, canonical name construction, and ancestry enumeration.\\nlibrary LibRegistry {\\n /// @dev Find the resolver address for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return exactRegistry The exact registry or null if not exact.\\n /// @return resolver The resolver or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n // supply if end of name\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return (rootRegistry, address(0), bytes32(0), offset);\\n }\\n // lookup parent name\\n (exactRegistry, resolver, node, resolverOffset) = findResolver(rootRegistry, name, next);\\n // if there was a parent registry...\\n if (address(exactRegistry) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n // remember the resolver (if it exists)\\n address res = exactRegistry.getResolver(label);\\n if (res != address(0)) {\\n resolver = res;\\n resolverOffset = offset;\\n }\\n exactRegistry = exactRegistry.getSubregistry(label);\\n }\\n node = NameCoder.namehash(node, labelHash); // update namehash\\n }\\n\\n /// @dev Find the owner for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return owner The owner address or null if unowned or not found.\\n function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (address owner)\\n {\\n IRegistry registry = findParentRegistry(rootRegistry, name, offset);\\n if (\\n address(registry) != address(0) &&\\n ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId)\\n ) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n owner = IOwnedRegistry(address(registry)).findOwner(label);\\n }\\n }\\n\\n /// @dev Construct the canonical name for `registry`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param registry The registry to name.\\n /// @return name The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry rootRegistry, IRegistry registry)\\n internal\\n view\\n returns (bytes memory name)\\n {\\n if (address(registry) == address(0)) {\\n return \\\"\\\";\\n }\\n for (;;) {\\n if (address(registry) == address(rootRegistry)) {\\n return abi.encodePacked(name, uint8(0)); // add terminator\\n }\\n (IRegistry parent, string memory label) = registry.getParent();\\n if (address(parent) == address(0)) {\\n return \\\"\\\"; // no canonical parent\\n }\\n IRegistry child = parent.getSubregistry(label);\\n if (address(child) != address(registry)) {\\n return \\\"\\\"; // wrong canonical child\\n }\\n name = abi.encodePacked(name, NameCoder.assertLabelSize(label), label); // reverts if invalid label\\n registry = parent;\\n }\\n }\\n\\n /// @dev Find the registry for `name` and return it iff it is canonical for that name.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name)\\n internal\\n view\\n returns (IRegistry)\\n {\\n IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0);\\n return\\n address(registry) != address(0) &&\\n keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) ==\\n keccak256(name)\\n ? registry\\n : IRegistry(address(0));\\n }\\n\\n /// @dev Find the exact registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return exactRegistry The exact registry or null if not found.\\n function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return rootRegistry;\\n }\\n IRegistry parent = findExactRegistry(rootRegistry, name, next);\\n if (address(parent) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n exactRegistry = parent.getSubregistry(label);\\n }\\n }\\n\\n /// @dev Find the parent registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return parentRegistry The parent registry or null if not found.\\n function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry parentRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n parentRegistry = findExactRegistry(rootRegistry, name, next);\\n }\\n }\\n\\n /// @dev Find all registries in the ancestry of `name`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return registries Array of registries in label-order.\\n function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry[] memory registries)\\n {\\n registries = new IRegistry[](1 + NameCoder.countLabels(name, offset));\\n registries[registries.length - 1] = rootRegistry;\\n _findRegistries(name, offset, registries, 0);\\n }\\n\\n /// @dev Recursive function for building ancestry.\\n function _findRegistries(\\n bytes memory name,\\n uint256 offset,\\n IRegistry[] memory registries,\\n uint256 index\\n )\\n private\\n view\\n returns (IRegistry registry)\\n {\\n (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset);\\n if (bytes(label).length == 0) {\\n return registries[registries.length - 1];\\n }\\n registry = _findRegistries(name, nextOffset, registries, index + 1);\\n if (address(registry) != address(0)) {\\n registry = registry.getSubregistry(label);\\n registries[index] = registry;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0b5f34bcc76ee3e49d300444fbcbe1ed152faee49a91c87eaea5f6d61ce6fb0b\",\"license\":\"MIT\"},\"project/src/utils/WrappedErrorLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {HexUtils} from \\\"@ens/contracts/utils/HexUtils.sol\\\";\\n\\n/// @dev Library to wrap and unwrap typed error data inside of `Error(string)`.\\n/// Uses hex to embed arbitrary data and avoid invalid unicode.\\nlibrary WrappedErrorLib {\\n /// @dev Error selector for `Error(string)`.\\n bytes4 internal constant ERROR_STRING_SELECTOR = 0x08c379a0;\\n\\n /// @dev The detectable human-readable error prefix.\\n /// Must be exactly 16 bytes.\\n bytes16 internal constant WRAPPED_ERROR_PREFIX = \\\"WrappedError::0x\\\";\\n\\n /// @dev Wrap an error and then revert.\\n function wrapAndRevert(bytes memory err) internal pure {\\n err = wrap(err);\\n assembly {\\n revert(add(err, 32), mload(err))\\n }\\n }\\n\\n /// @dev Embed a typed error into `Error(string)`.\\n /// Does nothing if already `Error(string)`.\\n /// For detection, `WRAPPED_ERROR_PREFIX` is leading bytes the error string.\\n function wrap(bytes memory err) internal pure returns (bytes memory) {\\n if (err.length > 0 && bytes4(err) != ERROR_STRING_SELECTOR) {\\n // assert((err.length & 31) == 4);\\n err = abi.encodeWithSelector(\\n ERROR_STRING_SELECTOR,\\n abi.encodePacked(WRAPPED_ERROR_PREFIX, HexUtils.bytesToHex(err))\\n );\\n }\\n return err;\\n }\\n\\n /// @dev Unwrap a typed error from `Error(string)`.\\n /// Does nothing if detection and extracton fails.\\n /// @param err The error data to unwrap.\\n /// @return The unwrapped error data, or unmodified if not wrapped.\\n function unwrap(bytes memory err) internal pure returns (bytes memory) {\\n if (bytes4(err) == ERROR_STRING_SELECTOR) {\\n bytes memory v;\\n assembly {\\n v := add(err, 4) // skip selector\\n }\\n v = abi.decode(v, (bytes));\\n if (bytes16(v) == WRAPPED_ERROR_PREFIX) {\\n (bytes memory inner, bool ok) = HexUtils.hexToBytes(v, 16, v.length);\\n if (ok) {\\n return inner;\\n }\\n }\\n }\\n return err;\\n }\\n}\\n\",\"keccak256\":\"0xf92862b6509cf553bd542925617318a2509bfdc6457e8b5d102c8e9658c610e4\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "NotApprovedOperator(address,address)": [ + { + "notice": "Caller is not an approved operator by `owner` on `nft`." + } + ], + "ParentNotMigrated(bytes)": [ + { + "notice": "A parent has not been migrated yet." + } + ], + "WrappedOwnerMismatch(uint256)": [ + { + "notice": "A group has multiple owners." + } + ] + }, + "kind": "user", + "methods": { + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "LOCKED_CONTROLLER()": { + "notice": "The ENSv2 `LockedMigrationController` contract." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract." + }, + "ROOT_REGISTRY()": { + "notice": "The ENSv2 root registry." + }, + "UNLOCKED_CONTROLLER()": { + "notice": "The ENSv2 `UnlockedMigrationController` contract." + }, + "constructor": { + "notice": "Initializes `MigrationHelper`." + }, + "migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])": { + "notice": "Optimized batch migration helper." + } + }, + "notice": "Migration helper for mixed (ERC-721 and ERC-1155) batch migration using approval.", + "version": 1 + }, + "argsData": "0x000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf943000000000000000000000000c960f7217d3643b525ef36bec8adf86953cd9ab8000000000000000000000000056138ef5660f7113a3b0adc08ac3683310e7fbc000000000000000000000000f91c34ed840889ed96f806f882fd50506a336edb", + "transaction": { + "hash": "0x9dea0196d80a7d2478d4e932d1973814f378645ae22d4d132e5acad881a300b5", + "nonce": "0x1e9f", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xe7e30d49c8adb48956561e116d7cc843221a221df1f4721695eac6e0445a0a20", + "blockNumber": "0xa6a814", + "transactionIndex": "0x18" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/MockDAI.json b/contracts/deployments/sepolia-official-v1-20260525-r2/MockDAI.json new file mode 100644 index 000000000..69fa28315 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/MockDAI.json @@ -0,0 +1,916 @@ +{ + "address": "0x2922bcd677af690fcd1ecc699519e4bfabc73ff8", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "ERC2612ExpiredSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC2612InvalidSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nuke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "MockERC20", + "sourceName": "test/mocks/MockERC20.sol", + "bytecode": "0x610160604052348015610010575f80fd5b5060405161155238038061155283398101604081905261002f916101d6565b6040805180820190915260018152603160f81b602082015282908190818060036100598282610315565b5060046100668282610315565b5061007691508390506005610135565b61012052610085816006610135565b61014052815160208084019190912060e052815190820120610100524660a05261011160e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c052506008805460ff191660ff929092169190911790555061042c565b5f6020835110156101505761014983610167565b9050610161565b8161015b8482610315565b5060ff90505b92915050565b5f80829050601f8151111561019a578260405163305a27a960e01b815260040161019191906103d4565b60405180910390fd5b80516101a582610409565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b805160ff811681146101d1575f80fd5b919050565b5f80604083850312156101e7575f80fd5b82516001600160401b03808211156101fd575f80fd5b818501915085601f830112610210575f80fd5b815181811115610222576102226101ad565b604051601f8201601f19908116603f0116810190838211818310171561024a5761024a6101ad565b81604052828152886020848701011115610262575f80fd5b8260208601602083015e5f602084830101528096505050505050610288602084016101c1565b90509250929050565b600181811c908216806102a557607f821691505b6020821081036102c357634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561031057805f5260205f20601f840160051c810160208510156102ee5750805b601f840160051c820191505b8181101561030d575f81556001016102fa565b50505b505050565b81516001600160401b0381111561032e5761032e6101ad565b6103428161033c8454610291565b846102c9565b602080601f831160018114610375575f841561035e5750858301515b5f19600386901b1c1916600185901b1785556103cc565b5f85815260208120601f198616915b828110156103a357888601518255948401946001909101908401610384565b50858210156103c057878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b805160208083015191908110156102c3575f1960209190910360031b1b16919050565b60805160a05160c05160e0516101005161012051610140516110d561047d5f395f61080601525f6107d901525f61074e01525f61072601525f61068101525f6106ab01525f6106d501526110d55ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806370a0823111610093578063a9059cbb11610063578063a9059cbb146101ea578063cade97aa146101fd578063d505accf14610210578063dd62ed3e14610223575f80fd5b806370a082311461018c5780637ecebe00146101b457806384b0196e146101c757806395d89b41146101e2575f80fd5b806323b872dd116100ce57806323b872dd14610147578063313ce5671461015a5780633644e5151461016f57806340c10f1914610177575f80fd5b806306fdde03146100f4578063095ea7b31461011257806318160ddd14610135575b5f80fd5b6100fc61025b565b6040516101099190610e35565b60405180910390f35b610125610120366004610e69565b6102eb565b6040519015158152602001610109565b6002545b604051908152602001610109565b610125610155366004610e91565b610304565b60085460405160ff9091168152602001610109565b610139610327565b61018a610185366004610e69565b610335565b005b61013961019a366004610eca565b6001600160a01b03165f9081526020819052604090205490565b6101396101c2366004610eca565b610343565b6101cf610360565b6040516101099796959493929190610ee3565b6100fc6103be565b6101256101f8366004610e69565b6103cd565b61018a61020b366004610eca565b6103da565b61018a61021e366004610f96565b610404565b610139610231366004611003565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b60606003805461026a90611034565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611034565b80156102e15780601f106102b8576101008083540402835291602001916102e1565b820191905f5260205f20905b8154815290600101906020018083116102c457829003601f168201915b5050505050905090565b5f336102f8818585610571565b60019150505b92915050565b5f33610311858285610583565b61031c858585610618565b506001949350505050565b5f610330610675565b905090565b61033f828261079e565b5050565b6001600160a01b0381165f908152600760205260408120546102fe565b5f6060805f805f60606103716107d2565b6103796107ff565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b60606004805461026a90611034565b5f336102f8818585610618565b610401816103fc836001600160a01b03165f9081526020819052604090205490565b61082c565b50565b83421115610446576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886104918c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f6104eb82610860565b90505f6104fa828787876108a7565b9050896001600160a01b0316816001600160a01b03161461055a576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b16602482015260440161043d565b6105658a8a8a610571565b50505050505050505050565b61057e83838360016108d3565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106125781811015610604576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044810183905260640161043d565b61061284848484035f6108d3565b50505050565b6001600160a01b03831661064157604051634b637e8f60e11b81525f600482015260240161043d565b6001600160a01b03821661066a5760405163ec442f0560e01b81525f600482015260240161043d565b61057e8383836109d7565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156106cd57507f000000000000000000000000000000000000000000000000000000000000000046145b156106f757507f000000000000000000000000000000000000000000000000000000000000000090565b610330604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166107c75760405163ec442f0560e01b81525f600482015260240161043d565b61033f5f83836109d7565b60606103307f00000000000000000000000000000000000000000000000000000000000000006005610b16565b60606103307f00000000000000000000000000000000000000000000000000000000000000006006610b16565b6001600160a01b03821661085557604051634b637e8f60e11b81525f600482015260240161043d565b61033f825f836109d7565b5f6102fe61086c610675565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f805f806108b788888888610bbf565b9250925092506108c78282610c87565b50909695505050505050565b6001600160a01b038416610915576040517fe602df050000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038316610957576040517f94280d620000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561061257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109c991815260200190565b60405180910390a350505050565b6001600160a01b038316610a01578060025f8282546109f6919061106c565b90915550610a8a9050565b6001600160a01b0383165f9081526020819052604090205481811015610a6c576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602481018290526044810183905260640161043d565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610aa657600280548290039055610ac4565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610b0991815260200190565b60405180910390a3505050565b606060ff8314610b3057610b2983610d8a565b90506102fe565b818054610b3c90611034565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6890611034565b8015610bb35780601f10610b8a57610100808354040283529160200191610bb3565b820191905f5260205f20905b815481529060010190602001808311610b9657829003601f168201915b505050505090506102fe565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610bf857505f91506003905082610c7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610c49573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610c7457505f925060019150829050610c7d565b92505f91508190505b9450945094915050565b5f826003811115610c9a57610c9a61108b565b03610ca3575050565b6001826003811115610cb757610cb761108b565b03610cee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610d0257610d0261108b565b03610d3c576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b6003826003811115610d5057610d5061108b565b0361033f576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b60605f610d9683610dc7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f8111156102fe576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e476020830184610e07565b9392505050565b80356001600160a01b0381168114610e64575f80fd5b919050565b5f8060408385031215610e7a575f80fd5b610e8383610e4e565b946020939093013593505050565b5f805f60608486031215610ea3575f80fd5b610eac84610e4e565b9250610eba60208501610e4e565b9150604084013590509250925092565b5f60208284031215610eda575f80fd5b610e4782610e4e565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e06020840152610f1f60e084018a610e07565b8381036040850152610f31818a610e07565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b81811015610f8457835183529284019291840191600101610f68565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a031215610fac575f80fd5b610fb588610e4e565b9650610fc360208901610e4e565b95506040880135945060608801359350608088013560ff81168114610fe6575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611014575f80fd5b61101d83610e4e565b915061102b60208401610e4e565b90509250929050565b600181811c9082168061104857607f821691505b60208210810361106657634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102fe57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220cdc2566732702bdfff4697695617b2f6b1e00e79e3174e5aaad85856d16daf8764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806370a0823111610093578063a9059cbb11610063578063a9059cbb146101ea578063cade97aa146101fd578063d505accf14610210578063dd62ed3e14610223575f80fd5b806370a082311461018c5780637ecebe00146101b457806384b0196e146101c757806395d89b41146101e2575f80fd5b806323b872dd116100ce57806323b872dd14610147578063313ce5671461015a5780633644e5151461016f57806340c10f1914610177575f80fd5b806306fdde03146100f4578063095ea7b31461011257806318160ddd14610135575b5f80fd5b6100fc61025b565b6040516101099190610e35565b60405180910390f35b610125610120366004610e69565b6102eb565b6040519015158152602001610109565b6002545b604051908152602001610109565b610125610155366004610e91565b610304565b60085460405160ff9091168152602001610109565b610139610327565b61018a610185366004610e69565b610335565b005b61013961019a366004610eca565b6001600160a01b03165f9081526020819052604090205490565b6101396101c2366004610eca565b610343565b6101cf610360565b6040516101099796959493929190610ee3565b6100fc6103be565b6101256101f8366004610e69565b6103cd565b61018a61020b366004610eca565b6103da565b61018a61021e366004610f96565b610404565b610139610231366004611003565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b60606003805461026a90611034565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611034565b80156102e15780601f106102b8576101008083540402835291602001916102e1565b820191905f5260205f20905b8154815290600101906020018083116102c457829003601f168201915b5050505050905090565b5f336102f8818585610571565b60019150505b92915050565b5f33610311858285610583565b61031c858585610618565b506001949350505050565b5f610330610675565b905090565b61033f828261079e565b5050565b6001600160a01b0381165f908152600760205260408120546102fe565b5f6060805f805f60606103716107d2565b6103796107ff565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b60606004805461026a90611034565b5f336102f8818585610618565b610401816103fc836001600160a01b03165f9081526020819052604090205490565b61082c565b50565b83421115610446576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886104918c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f6104eb82610860565b90505f6104fa828787876108a7565b9050896001600160a01b0316816001600160a01b03161461055a576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b16602482015260440161043d565b6105658a8a8a610571565b50505050505050505050565b61057e83838360016108d3565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106125781811015610604576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044810183905260640161043d565b61061284848484035f6108d3565b50505050565b6001600160a01b03831661064157604051634b637e8f60e11b81525f600482015260240161043d565b6001600160a01b03821661066a5760405163ec442f0560e01b81525f600482015260240161043d565b61057e8383836109d7565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156106cd57507f000000000000000000000000000000000000000000000000000000000000000046145b156106f757507f000000000000000000000000000000000000000000000000000000000000000090565b610330604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166107c75760405163ec442f0560e01b81525f600482015260240161043d565b61033f5f83836109d7565b60606103307f00000000000000000000000000000000000000000000000000000000000000006005610b16565b60606103307f00000000000000000000000000000000000000000000000000000000000000006006610b16565b6001600160a01b03821661085557604051634b637e8f60e11b81525f600482015260240161043d565b61033f825f836109d7565b5f6102fe61086c610675565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f805f806108b788888888610bbf565b9250925092506108c78282610c87565b50909695505050505050565b6001600160a01b038416610915576040517fe602df050000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038316610957576040517f94280d620000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561061257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109c991815260200190565b60405180910390a350505050565b6001600160a01b038316610a01578060025f8282546109f6919061106c565b90915550610a8a9050565b6001600160a01b0383165f9081526020819052604090205481811015610a6c576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602481018290526044810183905260640161043d565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610aa657600280548290039055610ac4565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610b0991815260200190565b60405180910390a3505050565b606060ff8314610b3057610b2983610d8a565b90506102fe565b818054610b3c90611034565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6890611034565b8015610bb35780601f10610b8a57610100808354040283529160200191610bb3565b820191905f5260205f20905b815481529060010190602001808311610b9657829003601f168201915b505050505090506102fe565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610bf857505f91506003905082610c7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610c49573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610c7457505f925060019150829050610c7d565b92505f91508190505b9450945094915050565b5f826003811115610c9a57610c9a61108b565b03610ca3575050565b6001826003811115610cb757610cb761108b565b03610cee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610d0257610d0261108b565b03610d3c576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b6003826003811115610d5057610d5061108b565b0361033f576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b60605f610d9683610dc7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f8111156102fe576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e476020830184610e07565b9392505050565b80356001600160a01b0381168114610e64575f80fd5b919050565b5f8060408385031215610e7a575f80fd5b610e8383610e4e565b946020939093013593505050565b5f805f60608486031215610ea3575f80fd5b610eac84610e4e565b9250610eba60208501610e4e565b9150604084013590509250925092565b5f60208284031215610eda575f80fd5b610e4782610e4e565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e06020840152610f1f60e084018a610e07565b8381036040850152610f31818a610e07565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b81811015610f8457835183529284019291840191600101610f68565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a031215610fac575f80fd5b610fb588610e4e565b9650610fc360208901610e4e565b95506040880135945060608801359350608088013560ff81168114610fe6575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611014575f80fd5b61101d83610e4e565b915061102b60208401610e4e565b90509250929050565b600181811c9082168061104857607f821691505b60208210810361106657634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102fe57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220cdc2566732702bdfff4697695617b2f6b1e00e79e3174e5aaad85856d16daf8764736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "45206": [ + { + "length": 32, + "start": 1749 + } + ], + "45208": [ + { + "length": 32, + "start": 1707 + } + ], + "45210": [ + { + "length": 32, + "start": 1665 + } + ], + "45212": [ + { + "length": 32, + "start": 1830 + } + ], + "45214": [ + { + "length": 32, + "start": 1870 + } + ], + "45217": [ + { + "length": 32, + "start": 2009 + } + ], + "45220": [ + { + "length": 32, + "start": 2054 + } + ] + }, + "inputSourceName": "project/test/mocks/MockERC20.sol", + "devdoc": { + "errors": { + "ECDSAInvalidSignature()": [ + { + "details": "The signature derives the `address(0)`." + } + ], + "ECDSAInvalidSignatureLength(uint256)": [ + { + "details": "The signature has an invalid length." + } + ], + "ECDSAInvalidSignatureS(bytes32)": [ + { + "details": "The signature has an S value that is in the upper half order." + } + ], + "ERC20InsufficientAllowance(address,uint256,uint256)": [ + { + "details": "Indicates a failure with the `spender`’s `allowance`. Used in transfers.", + "params": { + "allowance": "Amount of tokens a `spender` is allowed to operate with.", + "needed": "Minimum amount required to perform a transfer.", + "spender": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC20InsufficientBalance(address,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC20InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC20InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC20InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC20InvalidSpender(address)": [ + { + "details": "Indicates a failure with the `spender` to be approved. Used in approvals.", + "params": { + "spender": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC2612ExpiredSignature(uint256)": [ + { + "details": "Permit deadline has expired." + } + ], + "ERC2612InvalidSigner(address,address)": [ + { + "details": "Mismatched signature." + } + ], + "InvalidAccountNonce(address,uint256)": [ + { + "details": "The nonce used for an `account` is not the expected current nonce." + } + ] + }, + "events": { + "Approval(address,address,uint256)": { + "details": "Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance." + }, + "EIP712DomainChanged()": { + "details": "MAY be emitted to signal that the domain could have changed." + }, + "Transfer(address,address,uint256)": { + "details": "Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero." + } + }, + "kind": "dev", + "methods": { + "DOMAIN_SEPARATOR()": { + "details": "Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}." + }, + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "eip712Domain()": { + "details": "returns the fields and values that describe the domain separator used by this contract for EIP-712 signature." + }, + "name()": { + "details": "Returns the name of the token." + }, + "nonces(address)": { + "details": "Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times." + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "861800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "DOMAIN_SEPARATOR()": "infinite", + "allowance(address,address)": "infinite", + "approve(address,uint256)": "24758", + "balanceOf(address)": "2560", + "decimals()": "2333", + "eip712Domain()": "infinite", + "mint(address,uint256)": "infinite", + "name()": "infinite", + "nonces(address)": "2613", + "nuke(address)": "53133", + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": "infinite", + "symbol()": "infinite", + "totalSupply()": "2348", + "transfer(address,uint256)": "51238", + "transferFrom(address,address,uint256)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"allowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSpender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"ERC2612ExpiredSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC2612InvalidSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentNonce\",\"type\":\"uint256\"}],\"name\":\"InvalidAccountNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortString\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"str\",\"type\":\"string\"}],\"name\":\"StringTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EIP712DomainChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eip712Domain\",\"outputs\":[{\"internalType\":\"bytes1\",\"name\":\"fields\",\"type\":\"bytes1\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"verifyingContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"extensions\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nuke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ECDSAInvalidSignature()\":[{\"details\":\"The signature derives the `address(0)`.\"}],\"ECDSAInvalidSignatureLength(uint256)\":[{\"details\":\"The signature has an invalid length.\"}],\"ECDSAInvalidSignatureS(bytes32)\":[{\"details\":\"The signature has an S value that is in the upper half order.\"}],\"ERC20InsufficientAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\",\"params\":{\"allowance\":\"Amount of tokens a `spender` is allowed to operate with.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC20InsufficientBalance(address,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC20InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC20InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidSpender(address)\":[{\"details\":\"Indicates a failure with the `spender` to be approved. Used in approvals.\",\"params\":{\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC2612ExpiredSignature(uint256)\":[{\"details\":\"Permit deadline has expired.\"}],\"ERC2612InvalidSigner(address,address)\":[{\"details\":\"Mismatched signature.\"}],\"InvalidAccountNonce(address,uint256)\":[{\"details\":\"The nonce used for an `account` is not the expected current nonce.\"}]},\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"EIP712DomainChanged()\":{\"details\":\"MAY be emitted to signal that the domain could have changed.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"eip712Domain()\":{\"details\":\"returns the fields and values that describe the domain separator used by this contract for EIP-712 signature.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/test/mocks/MockERC20.sol\":\"MockERC20\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)\\n\\npragma solidity ^0.8.20;\\n\\ninterface IERC5267 {\\n /**\\n * @dev MAY be emitted to signal that the domain could have changed.\\n */\\n event EIP712DomainChanged();\\n\\n /**\\n * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\\n * signature.\\n */\\n function eip712Domain()\\n external\\n view\\n returns (\\n bytes1 fields,\\n string memory name,\\n string memory version,\\n uint256 chainId,\\n address verifyingContract,\\n bytes32 salt,\\n uint256[] memory extensions\\n );\\n}\\n\",\"keccak256\":\"0x92aa1df62dc3d33f1656d63bede0923e0df0b706ad4137c8b10b0a8fe549fd92\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC20Metadata} from \\\"./extensions/IERC20Metadata.sol\\\";\\nimport {Context} from \\\"../../utils/Context.sol\\\";\\nimport {IERC20Errors} from \\\"../../interfaces/draft-IERC6093.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 *\\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 * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\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 ERC-20\\n * applications.\\n */\\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\\n mapping(address account => uint256) private _balances;\\n\\n mapping(address account => mapping(address spender => 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 * Both values are immutable: they can only be set once during 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 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 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 default value returned by this function, unless\\n * it's 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 returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual 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 `value`.\\n */\\n function transfer(address to, uint256 value) public virtual returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, value);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `value` 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 value) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, value);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Skips emitting an {Approval} event indicating an allowance update. This is not\\n * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\\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 `value`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `value`.\\n */\\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, value);\\n _transfer(from, to, value);\\n return true;\\n }\\n\\n /**\\n * @dev Moves a `value` 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 * NOTE: This function is not virtual, {_update} should be overridden instead.\\n */\\n function _transfer(address from, address to, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC20InvalidSender(address(0));\\n }\\n if (to == address(0)) {\\n revert ERC20InvalidReceiver(address(0));\\n }\\n _update(from, to, value);\\n }\\n\\n /**\\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\\n * this function.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _update(address from, address to, uint256 value) internal virtual {\\n if (from == address(0)) {\\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\\n _totalSupply += value;\\n } else {\\n uint256 fromBalance = _balances[from];\\n if (fromBalance < value) {\\n revert ERC20InsufficientBalance(from, fromBalance, value);\\n }\\n unchecked {\\n // Overflow not possible: value <= fromBalance <= totalSupply.\\n _balances[from] = fromBalance - value;\\n }\\n }\\n\\n if (to == address(0)) {\\n unchecked {\\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\\n _totalSupply -= value;\\n }\\n } else {\\n unchecked {\\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\\n _balances[to] += value;\\n }\\n }\\n\\n emit Transfer(from, to, value);\\n }\\n\\n /**\\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\\n * Relies on the `_update` mechanism\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * NOTE: This function is not virtual, {_update} should be overridden instead.\\n */\\n function _mint(address account, uint256 value) internal {\\n if (account == address(0)) {\\n revert ERC20InvalidReceiver(address(0));\\n }\\n _update(address(0), account, value);\\n }\\n\\n /**\\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\\n * Relies on the `_update` mechanism.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * NOTE: This function is not virtual, {_update} should be overridden instead\\n */\\n function _burn(address account, uint256 value) internal {\\n if (account == address(0)) {\\n revert ERC20InvalidSender(address(0));\\n }\\n _update(account, address(0), value);\\n }\\n\\n /**\\n * @dev Sets `value` 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 * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\\n */\\n function _approve(address owner, address spender, uint256 value) internal {\\n _approve(owner, spender, value, true);\\n }\\n\\n /**\\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\\n *\\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\\n * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\\n * `Approval` event during `transferFrom` operations.\\n *\\n * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\\n * true using the following override:\\n *\\n * ```solidity\\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\\n * super._approve(owner, spender, value, true);\\n * }\\n * ```\\n *\\n * Requirements are the same as {_approve}.\\n */\\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\\n if (owner == address(0)) {\\n revert ERC20InvalidApprover(address(0));\\n }\\n if (spender == address(0)) {\\n revert ERC20InvalidSpender(address(0));\\n }\\n _allowances[owner][spender] = value;\\n if (emitEvent) {\\n emit Approval(owner, spender, value);\\n }\\n }\\n\\n /**\\n * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\\n *\\n * Does not update the allowance value in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Does not emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance < type(uint256).max) {\\n if (currentAllowance < value) {\\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\\n }\\n unchecked {\\n _approve(owner, spender, currentAllowance - value, false);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x41f6b3b9e030561e7896dbef372b499cc8d418a80c3884a4d65a68f2fdc7493a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Permit.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20Permit} from \\\"./IERC20Permit.sol\\\";\\nimport {ERC20} from \\\"../ERC20.sol\\\";\\nimport {ECDSA} from \\\"../../../utils/cryptography/ECDSA.sol\\\";\\nimport {EIP712} from \\\"../../../utils/cryptography/EIP712.sol\\\";\\nimport {Nonces} from \\\"../../../utils/Nonces.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC-20 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 */\\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {\\n bytes32 private constant PERMIT_TYPEHASH =\\n keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n /**\\n * @dev Permit deadline has expired.\\n */\\n error ERC2612ExpiredSignature(uint256 deadline);\\n\\n /**\\n * @dev Mismatched signature.\\n */\\n error ERC2612InvalidSigner(address signer, address owner);\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC-20 token name.\\n */\\n constructor(string memory name) EIP712(name, \\\"1\\\") {}\\n\\n /**\\n * @inheritdoc IERC20Permit\\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 ) public virtual {\\n if (block.timestamp > deadline) {\\n revert ERC2612ExpiredSignature(deadline);\\n }\\n\\n bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSA.recover(hash, v, r, s);\\n if (signer != owner) {\\n revert ERC2612InvalidSigner(signer, owner);\\n }\\n\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @inheritdoc IERC20Permit\\n */\\n function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) {\\n return super.nonces(owner);\\n }\\n\\n /**\\n * @inheritdoc IERC20Permit\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n}\\n\",\"keccak256\":\"0xaa7f0646f49ebe2606eeca169f85c56451bbaeeeb06265fa076a03369a25d1d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\\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\",\"keccak256\":\"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC-20 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 *\\n * ==== Security Considerations\\n *\\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\\n * generally recommended is:\\n *\\n * ```solidity\\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\\n * doThing(..., value);\\n * }\\n *\\n * function doThing(..., uint256 value) public {\\n * token.safeTransferFrom(msg.sender, address(this), value);\\n * ...\\n * }\\n * ```\\n *\\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\\n * {SafeERC20-safeTransferFrom}).\\n *\\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\\n * contracts should have entry points that don't rely on permit.\\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 * CAUTION: See Security Considerations above.\\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\",\"keccak256\":\"0x27dbc90e5136ffe46c04f7596fc2dbcc3acebd8d504da3d93fdb8496e6de04f6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Nonces.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides tracking nonces for addresses. Nonces will only increment.\\n */\\nabstract contract Nonces {\\n /**\\n * @dev The nonce used for an `account` is not the expected current nonce.\\n */\\n error InvalidAccountNonce(address account, uint256 currentNonce);\\n\\n mapping(address account => uint256) private _nonces;\\n\\n /**\\n * @dev Returns the next unused nonce for an address.\\n */\\n function nonces(address owner) public view virtual returns (uint256) {\\n return _nonces[owner];\\n }\\n\\n /**\\n * @dev Consumes a nonce.\\n *\\n * Returns the current value and increments nonce.\\n */\\n function _useNonce(address owner) internal virtual returns (uint256) {\\n // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be\\n // decremented or reset. This guarantees that the nonce never overflows.\\n unchecked {\\n // It is important to do x++ and not ++x here.\\n return _nonces[owner]++;\\n }\\n }\\n\\n /**\\n * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.\\n */\\n function _useCheckedNonce(address owner, uint256 nonce) internal virtual {\\n uint256 current = _useNonce(owner);\\n if (nonce != current) {\\n revert InvalidAccountNonce(owner, current);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0082767004fca261c332e9ad100868327a863a88ef724e844857128845ab350f\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\n\\n// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |\\n// | length | 0x BB |\\ntype ShortString is bytes32;\\n\\n/**\\n * @dev This library provides functions to convert short memory strings\\n * into a `ShortString` type that can be used as an immutable variable.\\n *\\n * Strings of arbitrary length can be optimized using this library if\\n * they are short enough (up to 31 bytes) by packing them with their\\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\\n * fallback mechanism can be used for every other case.\\n *\\n * Usage example:\\n *\\n * ```solidity\\n * contract Named {\\n * using ShortStrings for *;\\n *\\n * ShortString private immutable _name;\\n * string private _nameFallback;\\n *\\n * constructor(string memory contractName) {\\n * _name = contractName.toShortStringWithFallback(_nameFallback);\\n * }\\n *\\n * function name() external view returns (string memory) {\\n * return _name.toStringWithFallback(_nameFallback);\\n * }\\n * }\\n * ```\\n */\\nlibrary ShortStrings {\\n // Used as an identifier for strings longer than 31 bytes.\\n bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\\n\\n error StringTooLong(string str);\\n error InvalidShortString();\\n\\n /**\\n * @dev Encode a string of at most 31 chars into a `ShortString`.\\n *\\n * This will trigger a `StringTooLong` error is the input string is too long.\\n */\\n function toShortString(string memory str) internal pure returns (ShortString) {\\n bytes memory bstr = bytes(str);\\n if (bstr.length > 31) {\\n revert StringTooLong(str);\\n }\\n return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\\n }\\n\\n /**\\n * @dev Decode a `ShortString` back to a \\\"normal\\\" string.\\n */\\n function toString(ShortString sstr) internal pure returns (string memory) {\\n uint256 len = byteLength(sstr);\\n // using `new string(len)` would work locally but is not memory safe.\\n string memory str = new string(32);\\n assembly (\\\"memory-safe\\\") {\\n mstore(str, len)\\n mstore(add(str, 0x20), sstr)\\n }\\n return str;\\n }\\n\\n /**\\n * @dev Return the length of a `ShortString`.\\n */\\n function byteLength(ShortString sstr) internal pure returns (uint256) {\\n uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\\n if (result > 31) {\\n revert InvalidShortString();\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\\n */\\n function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\\n if (bytes(value).length < 32) {\\n return toShortString(value);\\n } else {\\n StorageSlot.getStringSlot(store).value = value;\\n return ShortString.wrap(FALLBACK_SENTINEL);\\n }\\n }\\n\\n /**\\n * @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}.\\n */\\n function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\\n return toString(value);\\n } else {\\n return store;\\n }\\n }\\n\\n /**\\n * @dev Return the length of a string that was encoded to `ShortString` or written to storage using\\n * {toShortStringWithFallback}.\\n *\\n * WARNING: This will return the \\\"byte length\\\" of the string. This may not reflect the actual length in terms of\\n * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\\n */\\n function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\\n return byteLength(value);\\n } else {\\n return bytes(store).length;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1fcf8cceb1a67e6c8512267e780933c4a3f63ef44756e6c818fda79be51c8402\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Math} from \\\"./math/Math.sol\\\";\\nimport {SafeCast} from \\\"./math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n using SafeCast for *;\\n\\n bytes16 private constant HEX_DIGITS = \\\"0123456789abcdef\\\";\\n uint8 private constant ADDRESS_LENGTH = 20;\\n uint256 private constant SPECIAL_CHARS_LOOKUP =\\n (1 << 0x08) | // backspace\\n (1 << 0x09) | // tab\\n (1 << 0x0a) | // newline\\n (1 << 0x0c) | // form feed\\n (1 << 0x0d) | // carriage return\\n (1 << 0x22) | // double quote\\n (1 << 0x5c); // backslash\\n\\n /**\\n * @dev The `value` string doesn't fit in the specified `length`.\\n */\\n error StringsInsufficientHexLength(uint256 value, uint256 length);\\n\\n /**\\n * @dev The string being parsed contains characters that are not in scope of the given base.\\n */\\n error StringsInvalidChar();\\n\\n /**\\n * @dev The string being parsed is not a properly formatted address.\\n */\\n error StringsInvalidAddressFormat();\\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 assembly (\\\"memory-safe\\\") {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n assembly (\\\"memory-safe\\\") {\\n mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toStringSigned(int256 value) internal pure returns (string memory) {\\n return string.concat(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value)));\\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 uint256 localValue = value;\\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] = HEX_DIGITS[localValue & 0xf];\\n localValue >>= 4;\\n }\\n if (localValue != 0) {\\n revert StringsInsufficientHexLength(value, length);\\n }\\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\\n * representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\\n * representation, according to EIP-55.\\n */\\n function toChecksumHexString(address addr) internal pure returns (string memory) {\\n bytes memory buffer = bytes(toHexString(addr));\\n\\n // hash the hex part of buffer (skip length + 2 bytes, length 40)\\n uint256 hashValue;\\n assembly (\\\"memory-safe\\\") {\\n hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\\n }\\n\\n for (uint256 i = 41; i > 1; --i) {\\n // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\\n if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\\n // case shift by xoring with 0x20\\n buffer[i] ^= 0x20;\\n }\\n hashValue >>= 4;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input) internal pure returns (uint256) {\\n return parseUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n uint256 result = 0;\\n for (uint256 i = begin; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 9) return (false, 0);\\n result *= 10;\\n result += chr;\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `int256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input) internal pure returns (int256) {\\n return parseInt(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\\n (bool success, int256 value) = tryParseInt(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\\n * the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\\n return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n uint256 private constant ABS_MIN_INT256 = 2 ** 255;\\n\\n /**\\n * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character or if the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, int256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseIntUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseIntUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, int256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // Check presence of a negative sign.\\n bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n bool positiveSign = sign == bytes1(\\\"+\\\");\\n bool negativeSign = sign == bytes1(\\\"-\\\");\\n uint256 offset = (positiveSign || negativeSign).toUint();\\n\\n (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\\n\\n if (absSuccess && absValue < ABS_MIN_INT256) {\\n return (true, negativeSign ? -int256(absValue) : int256(absValue));\\n } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\\n return (true, type(int256).min);\\n } else return (false, 0);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input) internal pure returns (uint256) {\\n return parseHexUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseHexUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\\n * invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseHexUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseHexUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // skip 0x prefix if present\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 offset = hasPrefix.toUint() * 2;\\n\\n uint256 result = 0;\\n for (uint256 i = begin + offset; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 15) return (false, 0);\\n result *= 16;\\n unchecked {\\n // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\\n // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.\\n result += chr;\\n }\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as an `address`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input) internal pure returns (address) {\\n return parseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\\n (bool success, address value) = tryParseAddress(input, begin, end);\\n if (!success) revert StringsInvalidAddressFormat();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\\n * formatted address. See {parseAddress-string} requirements.\\n */\\n function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\\n return tryParseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\\n * formatted address. See {parseAddress-string-uint256-uint256} requirements.\\n */\\n function tryParseAddress(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, address value) {\\n if (end > bytes(input).length || begin > end) return (false, address(0));\\n\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\\n\\n // check that input is the correct length\\n if (end - begin == expectedLength) {\\n // length guarantees that this does not overflow, and value is at most type(uint160).max\\n (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\\n return (s, address(uint160(v)));\\n } else {\\n return (false, address(0));\\n }\\n }\\n\\n function _tryParseChr(bytes1 chr) private pure returns (uint8) {\\n uint8 value = uint8(chr);\\n\\n // Try to parse `chr`:\\n // - Case 1: [0-9]\\n // - Case 2: [a-f]\\n // - Case 3: [A-F]\\n // - otherwise not supported\\n unchecked {\\n if (value > 47 && value < 58) value -= 48;\\n else if (value > 96 && value < 103) value -= 87;\\n else if (value > 64 && value < 71) value -= 55;\\n else return type(uint8).max;\\n }\\n\\n return value;\\n }\\n\\n /**\\n * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.\\n *\\n * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.\\n *\\n * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of\\n * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode\\n * characters that are not in this range, but other tooling may provide different results.\\n */\\n function escapeJSON(string memory input) internal pure returns (string memory) {\\n bytes memory buffer = bytes(input);\\n bytes memory output = new bytes(2 * buffer.length); // worst case scenario\\n uint256 outputLength = 0;\\n\\n for (uint256 i; i < buffer.length; ++i) {\\n bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));\\n if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {\\n output[outputLength++] = \\\"\\\\\\\\\\\";\\n if (char == 0x08) output[outputLength++] = \\\"b\\\";\\n else if (char == 0x09) output[outputLength++] = \\\"t\\\";\\n else if (char == 0x0a) output[outputLength++] = \\\"n\\\";\\n else if (char == 0x0c) output[outputLength++] = \\\"f\\\";\\n else if (char == 0x0d) output[outputLength++] = \\\"r\\\";\\n else if (char == 0x5c) output[outputLength++] = \\\"\\\\\\\\\\\";\\n else if (char == 0x22) {\\n // solhint-disable-next-line quotes\\n output[outputLength++] = '\\\"';\\n }\\n } else {\\n output[outputLength++] = char;\\n }\\n }\\n // write the actual length and deallocate unused memory\\n assembly (\\\"memory-safe\\\") {\\n mstore(output, outputLength)\\n mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))\\n }\\n\\n return string(output);\\n }\\n\\n /**\\n * @dev Reads a bytes32 from a bytes array without bounds checking.\\n *\\n * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\\n * assembly block as such would prevent some optimizations.\\n */\\n function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\\n // This is not memory safe in the general case, but all calls to this private function are within bounds.\\n assembly (\\\"memory-safe\\\") {\\n value := mload(add(buffer, add(0x20, offset)))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x81c274a60a7ae232ae3dc9ff3a4011b4849a853c13b0832cd3351bb1bb2f0dae\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.20;\\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 }\\n\\n /**\\n * @dev The signature derives the `address(0)`.\\n */\\n error ECDSAInvalidSignature();\\n\\n /**\\n * @dev The signature has an invalid length.\\n */\\n error ECDSAInvalidSignatureLength(uint256 length);\\n\\n /**\\n * @dev The signature has an S value that is in the upper half order.\\n */\\n error ECDSAInvalidSignatureS(bytes32 s);\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\\n * return address(0) without also returning an error description. Errors are documented using an enum (error type)\\n * and a bytes32 providing additional information about the error.\\n *\\n * If no error is returned, then the address can be used for verification purposes.\\n *\\n * The `ecrecover` EVM precompile 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 {MessageHashUtils-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 function tryRecover(\\n bytes32 hash,\\n bytes memory signature\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\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 assembly (\\\"memory-safe\\\") {\\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, bytes32(signature.length));\\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 precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\\n _throwError(error, errorArg);\\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[ERC-2098 short signatures]\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n unchecked {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n // We do not check for an overflow here since the shift operation results in 0 or 1.\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\\n _throwError(error, errorArg);\\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 function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\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, s);\\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, bytes32(0));\\n }\\n\\n return (signer, RecoverError.NoError, bytes32(0));\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\\n */\\n function _throwError(RecoverError error, bytes32 errorArg) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert ECDSAInvalidSignature();\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert ECDSAInvalidSignatureLength(uint256(errorArg));\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert ECDSAInvalidSignatureS(errorArg);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x69f54c02b7d81d505910ec198c11ed4c6a728418a868b906b4a0cf29946fda84\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {MessageHashUtils} from \\\"./MessageHashUtils.sol\\\";\\nimport {ShortStrings, ShortString} from \\\"../ShortStrings.sol\\\";\\nimport {IERC5267} from \\\"../../interfaces/IERC5267.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose\\n * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract\\n * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to\\n * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\\n * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the\\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\\n *\\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n */\\nabstract contract EIP712 is IERC5267 {\\n using ShortStrings for *;\\n\\n bytes32 private constant TYPE_HASH =\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _cachedDomainSeparator;\\n uint256 private immutable _cachedChainId;\\n address private immutable _cachedThis;\\n\\n bytes32 private immutable _hashedName;\\n bytes32 private immutable _hashedVersion;\\n\\n ShortString private immutable _name;\\n ShortString private immutable _version;\\n // slither-disable-next-line constable-states\\n string private _nameFallback;\\n // slither-disable-next-line constable-states\\n string private _versionFallback;\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n _name = name.toShortStringWithFallback(_nameFallback);\\n _version = version.toShortStringWithFallback(_versionFallback);\\n _hashedName = keccak256(bytes(name));\\n _hashedVersion = keccak256(bytes(version));\\n\\n _cachedChainId = block.chainid;\\n _cachedDomainSeparator = _buildDomainSeparator();\\n _cachedThis = address(this);\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\\n return _cachedDomainSeparator;\\n } else {\\n return _buildDomainSeparator();\\n }\\n }\\n\\n function _buildDomainSeparator() private view returns (bytes32) {\\n return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n\\n /**\\n * @inheritdoc IERC5267\\n */\\n function eip712Domain()\\n public\\n view\\n virtual\\n returns (\\n bytes1 fields,\\n string memory name,\\n string memory version,\\n uint256 chainId,\\n address verifyingContract,\\n bytes32 salt,\\n uint256[] memory extensions\\n )\\n {\\n return (\\n hex\\\"0f\\\", // 01111\\n _EIP712Name(),\\n _EIP712Version(),\\n block.chainid,\\n address(this),\\n bytes32(0),\\n new uint256[](0)\\n );\\n }\\n\\n /**\\n * @dev The name parameter for the EIP712 domain.\\n *\\n * NOTE: By default this function reads _name which is an immutable value.\\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function _EIP712Name() internal view returns (string memory) {\\n return _name.toStringWithFallback(_nameFallback);\\n }\\n\\n /**\\n * @dev The version parameter for the EIP712 domain.\\n *\\n * NOTE: By default this function reads _version which is an immutable value.\\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function _EIP712Version() internal view returns (string memory) {\\n return _version.toStringWithFallback(_versionFallback);\\n }\\n}\\n\",\"keccak256\":\"0x0c60057e7351874f086db8dc9291b7ada9ad62cb7725befd2991430d04a74572\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Strings} from \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\\n *\\n * The library provides methods for generating a hash of a message that conforms to the\\n * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\\n * specifications.\\n */\\nlibrary MessageHashUtils {\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x45` (`personal_sign` messages).\\n *\\n * The digest is calculated by prefixing a bytes32 `messageHash` with\\n * `\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\"` and hashing the result. It corresponds with the\\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\\n *\\n * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\\n * keccak256, although any bytes32 value can be safely used because the final digest will\\n * be re-hashed.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\") // 32 is the bytes-length of messageHash\\n mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\\n digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\\n }\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x45` (`personal_sign` messages).\\n *\\n * The digest is calculated by prefixing an arbitrary `message` with\\n * `\\\"\\\\x19Ethereum Signed Message:\\\\n\\\" + len(message)` and hashing the result. It corresponds with the\\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\\n return\\n keccak256(bytes.concat(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", bytes(Strings.toString(message.length)), message));\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x00` (data with intended validator).\\n *\\n * The digest is calculated by prefixing an arbitrary `data` with `\\\"\\\\x19\\\\x00\\\"` and the intended\\n * `validator` address. Then hashing the result.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(hex\\\"19_00\\\", validator, data));\\n }\\n\\n /**\\n * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.\\n */\\n function toDataWithIntendedValidatorHash(\\n address validator,\\n bytes32 messageHash\\n ) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, hex\\\"19_00\\\")\\n mstore(0x02, shl(96, validator))\\n mstore(0x16, messageHash)\\n digest := keccak256(0x00, 0x36)\\n }\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).\\n *\\n * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\\n * `\\\\x19\\\\x01` and hashing the result. It corresponds to the hash signed by the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n mstore(ptr, hex\\\"19_01\\\")\\n mstore(add(ptr, 0x02), domainSeparator)\\n mstore(add(ptr, 0x22), structHash)\\n digest := keccak256(ptr, 0x42)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x26670fef37d4adf55570ba78815eec5f31cb017e708f61886add4fc4da665631\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\\n }\\n }\\n\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a > b, a, b);\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a < b, a, b);\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // Formula from the \\\"Bit Twiddling Hacks\\\" by Sean Eron Anderson.\\n // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\\n // taking advantage of the most significant (or \\\"sign\\\" bit) in two's complement representation.\\n // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\\n // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\\n int256 mask = n >> 255;\\n\\n // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\\n return uint256((n + mask) ^ mask);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\"},\"project/test/mocks/MockERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {ERC20Permit} from \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol\\\";\\n\\ncontract MockERC20 is ERC20Permit {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n uint8 private _decimals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor(string memory symbol, uint8 decimals_) ERC20(symbol, symbol) ERC20Permit(symbol) {\\n _decimals = decimals_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function mint(address to, uint256 amount) external {\\n _mint(to, amount);\\n }\\n\\n function nuke(address owner) external {\\n _burn(owner, balanceOf(owner));\\n }\\n\\n function decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\\n\\ncontract MockERC20Blacklist is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n mapping(address account => bool isBlacklisted) public isBlacklisted;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n error Blacklisted(address);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"BLACK\\\", 6) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function setBlacklisted(address account, bool blacklisted) external {\\n isBlacklisted[account] = blacklisted;\\n }\\n\\n function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\\n _checkBlacklist(from);\\n _checkBlacklist(to);\\n return super.transferFrom(from, to, amount);\\n }\\n\\n function _checkBlacklist(address addr) internal view {\\n if (isBlacklisted[addr]) {\\n revert Blacklisted(addr);\\n }\\n }\\n}\\n\\n\\ncontract MockERC20VoidReturn is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"VOID\\\", 11) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\\n super.transferFrom(from, to, amount);\\n assembly {\\n return(0, 0) // return void\\n }\\n }\\n}\\n\\n\\ncontract MockERC20FalseReturn is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"FALSE\\\", 13) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function transferFrom(address, address, uint256) public pure override returns (bool) {\\n return false; // return false instead of revert\\n }\\n}\\n\",\"keccak256\":\"0xf418c9e3b57c817e2ae0085dacf3b79d531ff5e4c5d51634c09d0981d834472b\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 37501, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 37507, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 37509, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 37511, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 37513, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + }, + { + "astId": 45222, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_nameFallback", + "offset": 0, + "slot": "5", + "type": "t_string_storage" + }, + { + "astId": 45224, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_versionFallback", + "offset": 0, + "slot": "6", + "type": "t_string_storage" + }, + { + "astId": 42750, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_nonces", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 74928, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_decimals", + "offset": 0, + "slot": "8", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "argsData": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000034441490000000000000000000000000000000000000000000000000000000000", + "transaction": { + "nonce": "0x2174", + "hash": "0xd1ef0f2bd2cc1724c2d7692188de18c7a0ecfc8696b1df8b3c5ef198a1742ea9", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x1ad9a396e3cd7048222fbf095cf99e7195e511c3359f846f6596087a579bfd95", + "blockNumber": "0xa7c6b0", + "transactionIndex": "0x114" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/MockUSDC.json b/contracts/deployments/sepolia-official-v1-20260525-r2/MockUSDC.json new file mode 100644 index 000000000..08fd9bc0a --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/MockUSDC.json @@ -0,0 +1,916 @@ +{ + "address": "0xba11ebdb3f9a2c5946d8629517f06364e53a2e10", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "ERC2612ExpiredSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC2612InvalidSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nuke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "MockERC20", + "sourceName": "test/mocks/MockERC20.sol", + "bytecode": "0x610160604052348015610010575f80fd5b5060405161155238038061155283398101604081905261002f916101d6565b6040805180820190915260018152603160f81b602082015282908190818060036100598282610315565b5060046100668282610315565b5061007691508390506005610135565b61012052610085816006610135565b61014052815160208084019190912060e052815190820120610100524660a05261011160e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c052506008805460ff191660ff929092169190911790555061042c565b5f6020835110156101505761014983610167565b9050610161565b8161015b8482610315565b5060ff90505b92915050565b5f80829050601f8151111561019a578260405163305a27a960e01b815260040161019191906103d4565b60405180910390fd5b80516101a582610409565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b805160ff811681146101d1575f80fd5b919050565b5f80604083850312156101e7575f80fd5b82516001600160401b03808211156101fd575f80fd5b818501915085601f830112610210575f80fd5b815181811115610222576102226101ad565b604051601f8201601f19908116603f0116810190838211818310171561024a5761024a6101ad565b81604052828152886020848701011115610262575f80fd5b8260208601602083015e5f602084830101528096505050505050610288602084016101c1565b90509250929050565b600181811c908216806102a557607f821691505b6020821081036102c357634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561031057805f5260205f20601f840160051c810160208510156102ee5750805b601f840160051c820191505b8181101561030d575f81556001016102fa565b50505b505050565b81516001600160401b0381111561032e5761032e6101ad565b6103428161033c8454610291565b846102c9565b602080601f831160018114610375575f841561035e5750858301515b5f19600386901b1c1916600185901b1785556103cc565b5f85815260208120601f198616915b828110156103a357888601518255948401946001909101908401610384565b50858210156103c057878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b805160208083015191908110156102c3575f1960209190910360031b1b16919050565b60805160a05160c05160e0516101005161012051610140516110d561047d5f395f61080601525f6107d901525f61074e01525f61072601525f61068101525f6106ab01525f6106d501526110d55ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806370a0823111610093578063a9059cbb11610063578063a9059cbb146101ea578063cade97aa146101fd578063d505accf14610210578063dd62ed3e14610223575f80fd5b806370a082311461018c5780637ecebe00146101b457806384b0196e146101c757806395d89b41146101e2575f80fd5b806323b872dd116100ce57806323b872dd14610147578063313ce5671461015a5780633644e5151461016f57806340c10f1914610177575f80fd5b806306fdde03146100f4578063095ea7b31461011257806318160ddd14610135575b5f80fd5b6100fc61025b565b6040516101099190610e35565b60405180910390f35b610125610120366004610e69565b6102eb565b6040519015158152602001610109565b6002545b604051908152602001610109565b610125610155366004610e91565b610304565b60085460405160ff9091168152602001610109565b610139610327565b61018a610185366004610e69565b610335565b005b61013961019a366004610eca565b6001600160a01b03165f9081526020819052604090205490565b6101396101c2366004610eca565b610343565b6101cf610360565b6040516101099796959493929190610ee3565b6100fc6103be565b6101256101f8366004610e69565b6103cd565b61018a61020b366004610eca565b6103da565b61018a61021e366004610f96565b610404565b610139610231366004611003565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b60606003805461026a90611034565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611034565b80156102e15780601f106102b8576101008083540402835291602001916102e1565b820191905f5260205f20905b8154815290600101906020018083116102c457829003601f168201915b5050505050905090565b5f336102f8818585610571565b60019150505b92915050565b5f33610311858285610583565b61031c858585610618565b506001949350505050565b5f610330610675565b905090565b61033f828261079e565b5050565b6001600160a01b0381165f908152600760205260408120546102fe565b5f6060805f805f60606103716107d2565b6103796107ff565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b60606004805461026a90611034565b5f336102f8818585610618565b610401816103fc836001600160a01b03165f9081526020819052604090205490565b61082c565b50565b83421115610446576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886104918c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f6104eb82610860565b90505f6104fa828787876108a7565b9050896001600160a01b0316816001600160a01b03161461055a576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b16602482015260440161043d565b6105658a8a8a610571565b50505050505050505050565b61057e83838360016108d3565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106125781811015610604576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044810183905260640161043d565b61061284848484035f6108d3565b50505050565b6001600160a01b03831661064157604051634b637e8f60e11b81525f600482015260240161043d565b6001600160a01b03821661066a5760405163ec442f0560e01b81525f600482015260240161043d565b61057e8383836109d7565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156106cd57507f000000000000000000000000000000000000000000000000000000000000000046145b156106f757507f000000000000000000000000000000000000000000000000000000000000000090565b610330604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166107c75760405163ec442f0560e01b81525f600482015260240161043d565b61033f5f83836109d7565b60606103307f00000000000000000000000000000000000000000000000000000000000000006005610b16565b60606103307f00000000000000000000000000000000000000000000000000000000000000006006610b16565b6001600160a01b03821661085557604051634b637e8f60e11b81525f600482015260240161043d565b61033f825f836109d7565b5f6102fe61086c610675565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f805f806108b788888888610bbf565b9250925092506108c78282610c87565b50909695505050505050565b6001600160a01b038416610915576040517fe602df050000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038316610957576040517f94280d620000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561061257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109c991815260200190565b60405180910390a350505050565b6001600160a01b038316610a01578060025f8282546109f6919061106c565b90915550610a8a9050565b6001600160a01b0383165f9081526020819052604090205481811015610a6c576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602481018290526044810183905260640161043d565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610aa657600280548290039055610ac4565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610b0991815260200190565b60405180910390a3505050565b606060ff8314610b3057610b2983610d8a565b90506102fe565b818054610b3c90611034565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6890611034565b8015610bb35780601f10610b8a57610100808354040283529160200191610bb3565b820191905f5260205f20905b815481529060010190602001808311610b9657829003601f168201915b505050505090506102fe565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610bf857505f91506003905082610c7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610c49573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610c7457505f925060019150829050610c7d565b92505f91508190505b9450945094915050565b5f826003811115610c9a57610c9a61108b565b03610ca3575050565b6001826003811115610cb757610cb761108b565b03610cee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610d0257610d0261108b565b03610d3c576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b6003826003811115610d5057610d5061108b565b0361033f576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b60605f610d9683610dc7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f8111156102fe576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e476020830184610e07565b9392505050565b80356001600160a01b0381168114610e64575f80fd5b919050565b5f8060408385031215610e7a575f80fd5b610e8383610e4e565b946020939093013593505050565b5f805f60608486031215610ea3575f80fd5b610eac84610e4e565b9250610eba60208501610e4e565b9150604084013590509250925092565b5f60208284031215610eda575f80fd5b610e4782610e4e565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e06020840152610f1f60e084018a610e07565b8381036040850152610f31818a610e07565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b81811015610f8457835183529284019291840191600101610f68565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a031215610fac575f80fd5b610fb588610e4e565b9650610fc360208901610e4e565b95506040880135945060608801359350608088013560ff81168114610fe6575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611014575f80fd5b61101d83610e4e565b915061102b60208401610e4e565b90509250929050565b600181811c9082168061104857607f821691505b60208210810361106657634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102fe57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220cdc2566732702bdfff4697695617b2f6b1e00e79e3174e5aaad85856d16daf8764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806370a0823111610093578063a9059cbb11610063578063a9059cbb146101ea578063cade97aa146101fd578063d505accf14610210578063dd62ed3e14610223575f80fd5b806370a082311461018c5780637ecebe00146101b457806384b0196e146101c757806395d89b41146101e2575f80fd5b806323b872dd116100ce57806323b872dd14610147578063313ce5671461015a5780633644e5151461016f57806340c10f1914610177575f80fd5b806306fdde03146100f4578063095ea7b31461011257806318160ddd14610135575b5f80fd5b6100fc61025b565b6040516101099190610e35565b60405180910390f35b610125610120366004610e69565b6102eb565b6040519015158152602001610109565b6002545b604051908152602001610109565b610125610155366004610e91565b610304565b60085460405160ff9091168152602001610109565b610139610327565b61018a610185366004610e69565b610335565b005b61013961019a366004610eca565b6001600160a01b03165f9081526020819052604090205490565b6101396101c2366004610eca565b610343565b6101cf610360565b6040516101099796959493929190610ee3565b6100fc6103be565b6101256101f8366004610e69565b6103cd565b61018a61020b366004610eca565b6103da565b61018a61021e366004610f96565b610404565b610139610231366004611003565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b60606003805461026a90611034565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611034565b80156102e15780601f106102b8576101008083540402835291602001916102e1565b820191905f5260205f20905b8154815290600101906020018083116102c457829003601f168201915b5050505050905090565b5f336102f8818585610571565b60019150505b92915050565b5f33610311858285610583565b61031c858585610618565b506001949350505050565b5f610330610675565b905090565b61033f828261079e565b5050565b6001600160a01b0381165f908152600760205260408120546102fe565b5f6060805f805f60606103716107d2565b6103796107ff565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b60606004805461026a90611034565b5f336102f8818585610618565b610401816103fc836001600160a01b03165f9081526020819052604090205490565b61082c565b50565b83421115610446576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886104918c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f6104eb82610860565b90505f6104fa828787876108a7565b9050896001600160a01b0316816001600160a01b03161461055a576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b16602482015260440161043d565b6105658a8a8a610571565b50505050505050505050565b61057e83838360016108d3565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106125781811015610604576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044810183905260640161043d565b61061284848484035f6108d3565b50505050565b6001600160a01b03831661064157604051634b637e8f60e11b81525f600482015260240161043d565b6001600160a01b03821661066a5760405163ec442f0560e01b81525f600482015260240161043d565b61057e8383836109d7565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156106cd57507f000000000000000000000000000000000000000000000000000000000000000046145b156106f757507f000000000000000000000000000000000000000000000000000000000000000090565b610330604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166107c75760405163ec442f0560e01b81525f600482015260240161043d565b61033f5f83836109d7565b60606103307f00000000000000000000000000000000000000000000000000000000000000006005610b16565b60606103307f00000000000000000000000000000000000000000000000000000000000000006006610b16565b6001600160a01b03821661085557604051634b637e8f60e11b81525f600482015260240161043d565b61033f825f836109d7565b5f6102fe61086c610675565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f805f806108b788888888610bbf565b9250925092506108c78282610c87565b50909695505050505050565b6001600160a01b038416610915576040517fe602df050000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038316610957576040517f94280d620000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561061257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109c991815260200190565b60405180910390a350505050565b6001600160a01b038316610a01578060025f8282546109f6919061106c565b90915550610a8a9050565b6001600160a01b0383165f9081526020819052604090205481811015610a6c576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602481018290526044810183905260640161043d565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610aa657600280548290039055610ac4565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610b0991815260200190565b60405180910390a3505050565b606060ff8314610b3057610b2983610d8a565b90506102fe565b818054610b3c90611034565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6890611034565b8015610bb35780601f10610b8a57610100808354040283529160200191610bb3565b820191905f5260205f20905b815481529060010190602001808311610b9657829003601f168201915b505050505090506102fe565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610bf857505f91506003905082610c7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610c49573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610c7457505f925060019150829050610c7d565b92505f91508190505b9450945094915050565b5f826003811115610c9a57610c9a61108b565b03610ca3575050565b6001826003811115610cb757610cb761108b565b03610cee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610d0257610d0261108b565b03610d3c576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b6003826003811115610d5057610d5061108b565b0361033f576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b60605f610d9683610dc7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f8111156102fe576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e476020830184610e07565b9392505050565b80356001600160a01b0381168114610e64575f80fd5b919050565b5f8060408385031215610e7a575f80fd5b610e8383610e4e565b946020939093013593505050565b5f805f60608486031215610ea3575f80fd5b610eac84610e4e565b9250610eba60208501610e4e565b9150604084013590509250925092565b5f60208284031215610eda575f80fd5b610e4782610e4e565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e06020840152610f1f60e084018a610e07565b8381036040850152610f31818a610e07565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b81811015610f8457835183529284019291840191600101610f68565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a031215610fac575f80fd5b610fb588610e4e565b9650610fc360208901610e4e565b95506040880135945060608801359350608088013560ff81168114610fe6575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611014575f80fd5b61101d83610e4e565b915061102b60208401610e4e565b90509250929050565b600181811c9082168061104857607f821691505b60208210810361106657634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102fe57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220cdc2566732702bdfff4697695617b2f6b1e00e79e3174e5aaad85856d16daf8764736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "45206": [ + { + "length": 32, + "start": 1749 + } + ], + "45208": [ + { + "length": 32, + "start": 1707 + } + ], + "45210": [ + { + "length": 32, + "start": 1665 + } + ], + "45212": [ + { + "length": 32, + "start": 1830 + } + ], + "45214": [ + { + "length": 32, + "start": 1870 + } + ], + "45217": [ + { + "length": 32, + "start": 2009 + } + ], + "45220": [ + { + "length": 32, + "start": 2054 + } + ] + }, + "inputSourceName": "project/test/mocks/MockERC20.sol", + "devdoc": { + "errors": { + "ECDSAInvalidSignature()": [ + { + "details": "The signature derives the `address(0)`." + } + ], + "ECDSAInvalidSignatureLength(uint256)": [ + { + "details": "The signature has an invalid length." + } + ], + "ECDSAInvalidSignatureS(bytes32)": [ + { + "details": "The signature has an S value that is in the upper half order." + } + ], + "ERC20InsufficientAllowance(address,uint256,uint256)": [ + { + "details": "Indicates a failure with the `spender`’s `allowance`. Used in transfers.", + "params": { + "allowance": "Amount of tokens a `spender` is allowed to operate with.", + "needed": "Minimum amount required to perform a transfer.", + "spender": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC20InsufficientBalance(address,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC20InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC20InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC20InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC20InvalidSpender(address)": [ + { + "details": "Indicates a failure with the `spender` to be approved. Used in approvals.", + "params": { + "spender": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC2612ExpiredSignature(uint256)": [ + { + "details": "Permit deadline has expired." + } + ], + "ERC2612InvalidSigner(address,address)": [ + { + "details": "Mismatched signature." + } + ], + "InvalidAccountNonce(address,uint256)": [ + { + "details": "The nonce used for an `account` is not the expected current nonce." + } + ] + }, + "events": { + "Approval(address,address,uint256)": { + "details": "Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance." + }, + "EIP712DomainChanged()": { + "details": "MAY be emitted to signal that the domain could have changed." + }, + "Transfer(address,address,uint256)": { + "details": "Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero." + } + }, + "kind": "dev", + "methods": { + "DOMAIN_SEPARATOR()": { + "details": "Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}." + }, + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "eip712Domain()": { + "details": "returns the fields and values that describe the domain separator used by this contract for EIP-712 signature." + }, + "name()": { + "details": "Returns the name of the token." + }, + "nonces(address)": { + "details": "Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times." + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "861800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "DOMAIN_SEPARATOR()": "infinite", + "allowance(address,address)": "infinite", + "approve(address,uint256)": "24758", + "balanceOf(address)": "2560", + "decimals()": "2333", + "eip712Domain()": "infinite", + "mint(address,uint256)": "infinite", + "name()": "infinite", + "nonces(address)": "2613", + "nuke(address)": "53133", + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": "infinite", + "symbol()": "infinite", + "totalSupply()": "2348", + "transfer(address,uint256)": "51238", + "transferFrom(address,address,uint256)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"allowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSpender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"ERC2612ExpiredSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC2612InvalidSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentNonce\",\"type\":\"uint256\"}],\"name\":\"InvalidAccountNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortString\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"str\",\"type\":\"string\"}],\"name\":\"StringTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EIP712DomainChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eip712Domain\",\"outputs\":[{\"internalType\":\"bytes1\",\"name\":\"fields\",\"type\":\"bytes1\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"verifyingContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"extensions\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nuke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ECDSAInvalidSignature()\":[{\"details\":\"The signature derives the `address(0)`.\"}],\"ECDSAInvalidSignatureLength(uint256)\":[{\"details\":\"The signature has an invalid length.\"}],\"ECDSAInvalidSignatureS(bytes32)\":[{\"details\":\"The signature has an S value that is in the upper half order.\"}],\"ERC20InsufficientAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\",\"params\":{\"allowance\":\"Amount of tokens a `spender` is allowed to operate with.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC20InsufficientBalance(address,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC20InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC20InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidSpender(address)\":[{\"details\":\"Indicates a failure with the `spender` to be approved. Used in approvals.\",\"params\":{\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC2612ExpiredSignature(uint256)\":[{\"details\":\"Permit deadline has expired.\"}],\"ERC2612InvalidSigner(address,address)\":[{\"details\":\"Mismatched signature.\"}],\"InvalidAccountNonce(address,uint256)\":[{\"details\":\"The nonce used for an `account` is not the expected current nonce.\"}]},\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"EIP712DomainChanged()\":{\"details\":\"MAY be emitted to signal that the domain could have changed.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"eip712Domain()\":{\"details\":\"returns the fields and values that describe the domain separator used by this contract for EIP-712 signature.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/test/mocks/MockERC20.sol\":\"MockERC20\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)\\n\\npragma solidity ^0.8.20;\\n\\ninterface IERC5267 {\\n /**\\n * @dev MAY be emitted to signal that the domain could have changed.\\n */\\n event EIP712DomainChanged();\\n\\n /**\\n * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\\n * signature.\\n */\\n function eip712Domain()\\n external\\n view\\n returns (\\n bytes1 fields,\\n string memory name,\\n string memory version,\\n uint256 chainId,\\n address verifyingContract,\\n bytes32 salt,\\n uint256[] memory extensions\\n );\\n}\\n\",\"keccak256\":\"0x92aa1df62dc3d33f1656d63bede0923e0df0b706ad4137c8b10b0a8fe549fd92\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC20Metadata} from \\\"./extensions/IERC20Metadata.sol\\\";\\nimport {Context} from \\\"../../utils/Context.sol\\\";\\nimport {IERC20Errors} from \\\"../../interfaces/draft-IERC6093.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 *\\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 * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\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 ERC-20\\n * applications.\\n */\\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\\n mapping(address account => uint256) private _balances;\\n\\n mapping(address account => mapping(address spender => 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 * Both values are immutable: they can only be set once during 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 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 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 default value returned by this function, unless\\n * it's 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 returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual 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 `value`.\\n */\\n function transfer(address to, uint256 value) public virtual returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, value);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `value` 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 value) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, value);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Skips emitting an {Approval} event indicating an allowance update. This is not\\n * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\\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 `value`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `value`.\\n */\\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, value);\\n _transfer(from, to, value);\\n return true;\\n }\\n\\n /**\\n * @dev Moves a `value` 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 * NOTE: This function is not virtual, {_update} should be overridden instead.\\n */\\n function _transfer(address from, address to, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC20InvalidSender(address(0));\\n }\\n if (to == address(0)) {\\n revert ERC20InvalidReceiver(address(0));\\n }\\n _update(from, to, value);\\n }\\n\\n /**\\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\\n * this function.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _update(address from, address to, uint256 value) internal virtual {\\n if (from == address(0)) {\\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\\n _totalSupply += value;\\n } else {\\n uint256 fromBalance = _balances[from];\\n if (fromBalance < value) {\\n revert ERC20InsufficientBalance(from, fromBalance, value);\\n }\\n unchecked {\\n // Overflow not possible: value <= fromBalance <= totalSupply.\\n _balances[from] = fromBalance - value;\\n }\\n }\\n\\n if (to == address(0)) {\\n unchecked {\\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\\n _totalSupply -= value;\\n }\\n } else {\\n unchecked {\\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\\n _balances[to] += value;\\n }\\n }\\n\\n emit Transfer(from, to, value);\\n }\\n\\n /**\\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\\n * Relies on the `_update` mechanism\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * NOTE: This function is not virtual, {_update} should be overridden instead.\\n */\\n function _mint(address account, uint256 value) internal {\\n if (account == address(0)) {\\n revert ERC20InvalidReceiver(address(0));\\n }\\n _update(address(0), account, value);\\n }\\n\\n /**\\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\\n * Relies on the `_update` mechanism.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * NOTE: This function is not virtual, {_update} should be overridden instead\\n */\\n function _burn(address account, uint256 value) internal {\\n if (account == address(0)) {\\n revert ERC20InvalidSender(address(0));\\n }\\n _update(account, address(0), value);\\n }\\n\\n /**\\n * @dev Sets `value` 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 * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\\n */\\n function _approve(address owner, address spender, uint256 value) internal {\\n _approve(owner, spender, value, true);\\n }\\n\\n /**\\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\\n *\\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\\n * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\\n * `Approval` event during `transferFrom` operations.\\n *\\n * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\\n * true using the following override:\\n *\\n * ```solidity\\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\\n * super._approve(owner, spender, value, true);\\n * }\\n * ```\\n *\\n * Requirements are the same as {_approve}.\\n */\\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\\n if (owner == address(0)) {\\n revert ERC20InvalidApprover(address(0));\\n }\\n if (spender == address(0)) {\\n revert ERC20InvalidSpender(address(0));\\n }\\n _allowances[owner][spender] = value;\\n if (emitEvent) {\\n emit Approval(owner, spender, value);\\n }\\n }\\n\\n /**\\n * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\\n *\\n * Does not update the allowance value in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Does not emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance < type(uint256).max) {\\n if (currentAllowance < value) {\\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\\n }\\n unchecked {\\n _approve(owner, spender, currentAllowance - value, false);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x41f6b3b9e030561e7896dbef372b499cc8d418a80c3884a4d65a68f2fdc7493a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Permit.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20Permit} from \\\"./IERC20Permit.sol\\\";\\nimport {ERC20} from \\\"../ERC20.sol\\\";\\nimport {ECDSA} from \\\"../../../utils/cryptography/ECDSA.sol\\\";\\nimport {EIP712} from \\\"../../../utils/cryptography/EIP712.sol\\\";\\nimport {Nonces} from \\\"../../../utils/Nonces.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC-20 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 */\\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {\\n bytes32 private constant PERMIT_TYPEHASH =\\n keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n /**\\n * @dev Permit deadline has expired.\\n */\\n error ERC2612ExpiredSignature(uint256 deadline);\\n\\n /**\\n * @dev Mismatched signature.\\n */\\n error ERC2612InvalidSigner(address signer, address owner);\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC-20 token name.\\n */\\n constructor(string memory name) EIP712(name, \\\"1\\\") {}\\n\\n /**\\n * @inheritdoc IERC20Permit\\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 ) public virtual {\\n if (block.timestamp > deadline) {\\n revert ERC2612ExpiredSignature(deadline);\\n }\\n\\n bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSA.recover(hash, v, r, s);\\n if (signer != owner) {\\n revert ERC2612InvalidSigner(signer, owner);\\n }\\n\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @inheritdoc IERC20Permit\\n */\\n function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) {\\n return super.nonces(owner);\\n }\\n\\n /**\\n * @inheritdoc IERC20Permit\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n}\\n\",\"keccak256\":\"0xaa7f0646f49ebe2606eeca169f85c56451bbaeeeb06265fa076a03369a25d1d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\\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\",\"keccak256\":\"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC-20 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 *\\n * ==== Security Considerations\\n *\\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\\n * generally recommended is:\\n *\\n * ```solidity\\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\\n * doThing(..., value);\\n * }\\n *\\n * function doThing(..., uint256 value) public {\\n * token.safeTransferFrom(msg.sender, address(this), value);\\n * ...\\n * }\\n * ```\\n *\\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\\n * {SafeERC20-safeTransferFrom}).\\n *\\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\\n * contracts should have entry points that don't rely on permit.\\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 * CAUTION: See Security Considerations above.\\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\",\"keccak256\":\"0x27dbc90e5136ffe46c04f7596fc2dbcc3acebd8d504da3d93fdb8496e6de04f6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Nonces.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides tracking nonces for addresses. Nonces will only increment.\\n */\\nabstract contract Nonces {\\n /**\\n * @dev The nonce used for an `account` is not the expected current nonce.\\n */\\n error InvalidAccountNonce(address account, uint256 currentNonce);\\n\\n mapping(address account => uint256) private _nonces;\\n\\n /**\\n * @dev Returns the next unused nonce for an address.\\n */\\n function nonces(address owner) public view virtual returns (uint256) {\\n return _nonces[owner];\\n }\\n\\n /**\\n * @dev Consumes a nonce.\\n *\\n * Returns the current value and increments nonce.\\n */\\n function _useNonce(address owner) internal virtual returns (uint256) {\\n // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be\\n // decremented or reset. This guarantees that the nonce never overflows.\\n unchecked {\\n // It is important to do x++ and not ++x here.\\n return _nonces[owner]++;\\n }\\n }\\n\\n /**\\n * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.\\n */\\n function _useCheckedNonce(address owner, uint256 nonce) internal virtual {\\n uint256 current = _useNonce(owner);\\n if (nonce != current) {\\n revert InvalidAccountNonce(owner, current);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0082767004fca261c332e9ad100868327a863a88ef724e844857128845ab350f\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\n\\n// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |\\n// | length | 0x BB |\\ntype ShortString is bytes32;\\n\\n/**\\n * @dev This library provides functions to convert short memory strings\\n * into a `ShortString` type that can be used as an immutable variable.\\n *\\n * Strings of arbitrary length can be optimized using this library if\\n * they are short enough (up to 31 bytes) by packing them with their\\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\\n * fallback mechanism can be used for every other case.\\n *\\n * Usage example:\\n *\\n * ```solidity\\n * contract Named {\\n * using ShortStrings for *;\\n *\\n * ShortString private immutable _name;\\n * string private _nameFallback;\\n *\\n * constructor(string memory contractName) {\\n * _name = contractName.toShortStringWithFallback(_nameFallback);\\n * }\\n *\\n * function name() external view returns (string memory) {\\n * return _name.toStringWithFallback(_nameFallback);\\n * }\\n * }\\n * ```\\n */\\nlibrary ShortStrings {\\n // Used as an identifier for strings longer than 31 bytes.\\n bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\\n\\n error StringTooLong(string str);\\n error InvalidShortString();\\n\\n /**\\n * @dev Encode a string of at most 31 chars into a `ShortString`.\\n *\\n * This will trigger a `StringTooLong` error is the input string is too long.\\n */\\n function toShortString(string memory str) internal pure returns (ShortString) {\\n bytes memory bstr = bytes(str);\\n if (bstr.length > 31) {\\n revert StringTooLong(str);\\n }\\n return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\\n }\\n\\n /**\\n * @dev Decode a `ShortString` back to a \\\"normal\\\" string.\\n */\\n function toString(ShortString sstr) internal pure returns (string memory) {\\n uint256 len = byteLength(sstr);\\n // using `new string(len)` would work locally but is not memory safe.\\n string memory str = new string(32);\\n assembly (\\\"memory-safe\\\") {\\n mstore(str, len)\\n mstore(add(str, 0x20), sstr)\\n }\\n return str;\\n }\\n\\n /**\\n * @dev Return the length of a `ShortString`.\\n */\\n function byteLength(ShortString sstr) internal pure returns (uint256) {\\n uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\\n if (result > 31) {\\n revert InvalidShortString();\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\\n */\\n function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\\n if (bytes(value).length < 32) {\\n return toShortString(value);\\n } else {\\n StorageSlot.getStringSlot(store).value = value;\\n return ShortString.wrap(FALLBACK_SENTINEL);\\n }\\n }\\n\\n /**\\n * @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}.\\n */\\n function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\\n return toString(value);\\n } else {\\n return store;\\n }\\n }\\n\\n /**\\n * @dev Return the length of a string that was encoded to `ShortString` or written to storage using\\n * {toShortStringWithFallback}.\\n *\\n * WARNING: This will return the \\\"byte length\\\" of the string. This may not reflect the actual length in terms of\\n * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\\n */\\n function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\\n return byteLength(value);\\n } else {\\n return bytes(store).length;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1fcf8cceb1a67e6c8512267e780933c4a3f63ef44756e6c818fda79be51c8402\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Math} from \\\"./math/Math.sol\\\";\\nimport {SafeCast} from \\\"./math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n using SafeCast for *;\\n\\n bytes16 private constant HEX_DIGITS = \\\"0123456789abcdef\\\";\\n uint8 private constant ADDRESS_LENGTH = 20;\\n uint256 private constant SPECIAL_CHARS_LOOKUP =\\n (1 << 0x08) | // backspace\\n (1 << 0x09) | // tab\\n (1 << 0x0a) | // newline\\n (1 << 0x0c) | // form feed\\n (1 << 0x0d) | // carriage return\\n (1 << 0x22) | // double quote\\n (1 << 0x5c); // backslash\\n\\n /**\\n * @dev The `value` string doesn't fit in the specified `length`.\\n */\\n error StringsInsufficientHexLength(uint256 value, uint256 length);\\n\\n /**\\n * @dev The string being parsed contains characters that are not in scope of the given base.\\n */\\n error StringsInvalidChar();\\n\\n /**\\n * @dev The string being parsed is not a properly formatted address.\\n */\\n error StringsInvalidAddressFormat();\\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 assembly (\\\"memory-safe\\\") {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n assembly (\\\"memory-safe\\\") {\\n mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toStringSigned(int256 value) internal pure returns (string memory) {\\n return string.concat(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value)));\\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 uint256 localValue = value;\\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] = HEX_DIGITS[localValue & 0xf];\\n localValue >>= 4;\\n }\\n if (localValue != 0) {\\n revert StringsInsufficientHexLength(value, length);\\n }\\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\\n * representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\\n * representation, according to EIP-55.\\n */\\n function toChecksumHexString(address addr) internal pure returns (string memory) {\\n bytes memory buffer = bytes(toHexString(addr));\\n\\n // hash the hex part of buffer (skip length + 2 bytes, length 40)\\n uint256 hashValue;\\n assembly (\\\"memory-safe\\\") {\\n hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\\n }\\n\\n for (uint256 i = 41; i > 1; --i) {\\n // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\\n if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\\n // case shift by xoring with 0x20\\n buffer[i] ^= 0x20;\\n }\\n hashValue >>= 4;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input) internal pure returns (uint256) {\\n return parseUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n uint256 result = 0;\\n for (uint256 i = begin; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 9) return (false, 0);\\n result *= 10;\\n result += chr;\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `int256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input) internal pure returns (int256) {\\n return parseInt(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\\n (bool success, int256 value) = tryParseInt(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\\n * the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\\n return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n uint256 private constant ABS_MIN_INT256 = 2 ** 255;\\n\\n /**\\n * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character or if the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, int256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseIntUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseIntUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, int256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // Check presence of a negative sign.\\n bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n bool positiveSign = sign == bytes1(\\\"+\\\");\\n bool negativeSign = sign == bytes1(\\\"-\\\");\\n uint256 offset = (positiveSign || negativeSign).toUint();\\n\\n (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\\n\\n if (absSuccess && absValue < ABS_MIN_INT256) {\\n return (true, negativeSign ? -int256(absValue) : int256(absValue));\\n } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\\n return (true, type(int256).min);\\n } else return (false, 0);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input) internal pure returns (uint256) {\\n return parseHexUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseHexUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\\n * invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseHexUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseHexUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // skip 0x prefix if present\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 offset = hasPrefix.toUint() * 2;\\n\\n uint256 result = 0;\\n for (uint256 i = begin + offset; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 15) return (false, 0);\\n result *= 16;\\n unchecked {\\n // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\\n // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.\\n result += chr;\\n }\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as an `address`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input) internal pure returns (address) {\\n return parseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\\n (bool success, address value) = tryParseAddress(input, begin, end);\\n if (!success) revert StringsInvalidAddressFormat();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\\n * formatted address. See {parseAddress-string} requirements.\\n */\\n function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\\n return tryParseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\\n * formatted address. See {parseAddress-string-uint256-uint256} requirements.\\n */\\n function tryParseAddress(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, address value) {\\n if (end > bytes(input).length || begin > end) return (false, address(0));\\n\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\\n\\n // check that input is the correct length\\n if (end - begin == expectedLength) {\\n // length guarantees that this does not overflow, and value is at most type(uint160).max\\n (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\\n return (s, address(uint160(v)));\\n } else {\\n return (false, address(0));\\n }\\n }\\n\\n function _tryParseChr(bytes1 chr) private pure returns (uint8) {\\n uint8 value = uint8(chr);\\n\\n // Try to parse `chr`:\\n // - Case 1: [0-9]\\n // - Case 2: [a-f]\\n // - Case 3: [A-F]\\n // - otherwise not supported\\n unchecked {\\n if (value > 47 && value < 58) value -= 48;\\n else if (value > 96 && value < 103) value -= 87;\\n else if (value > 64 && value < 71) value -= 55;\\n else return type(uint8).max;\\n }\\n\\n return value;\\n }\\n\\n /**\\n * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.\\n *\\n * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.\\n *\\n * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of\\n * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode\\n * characters that are not in this range, but other tooling may provide different results.\\n */\\n function escapeJSON(string memory input) internal pure returns (string memory) {\\n bytes memory buffer = bytes(input);\\n bytes memory output = new bytes(2 * buffer.length); // worst case scenario\\n uint256 outputLength = 0;\\n\\n for (uint256 i; i < buffer.length; ++i) {\\n bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));\\n if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {\\n output[outputLength++] = \\\"\\\\\\\\\\\";\\n if (char == 0x08) output[outputLength++] = \\\"b\\\";\\n else if (char == 0x09) output[outputLength++] = \\\"t\\\";\\n else if (char == 0x0a) output[outputLength++] = \\\"n\\\";\\n else if (char == 0x0c) output[outputLength++] = \\\"f\\\";\\n else if (char == 0x0d) output[outputLength++] = \\\"r\\\";\\n else if (char == 0x5c) output[outputLength++] = \\\"\\\\\\\\\\\";\\n else if (char == 0x22) {\\n // solhint-disable-next-line quotes\\n output[outputLength++] = '\\\"';\\n }\\n } else {\\n output[outputLength++] = char;\\n }\\n }\\n // write the actual length and deallocate unused memory\\n assembly (\\\"memory-safe\\\") {\\n mstore(output, outputLength)\\n mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))\\n }\\n\\n return string(output);\\n }\\n\\n /**\\n * @dev Reads a bytes32 from a bytes array without bounds checking.\\n *\\n * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\\n * assembly block as such would prevent some optimizations.\\n */\\n function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\\n // This is not memory safe in the general case, but all calls to this private function are within bounds.\\n assembly (\\\"memory-safe\\\") {\\n value := mload(add(buffer, add(0x20, offset)))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x81c274a60a7ae232ae3dc9ff3a4011b4849a853c13b0832cd3351bb1bb2f0dae\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.20;\\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 }\\n\\n /**\\n * @dev The signature derives the `address(0)`.\\n */\\n error ECDSAInvalidSignature();\\n\\n /**\\n * @dev The signature has an invalid length.\\n */\\n error ECDSAInvalidSignatureLength(uint256 length);\\n\\n /**\\n * @dev The signature has an S value that is in the upper half order.\\n */\\n error ECDSAInvalidSignatureS(bytes32 s);\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\\n * return address(0) without also returning an error description. Errors are documented using an enum (error type)\\n * and a bytes32 providing additional information about the error.\\n *\\n * If no error is returned, then the address can be used for verification purposes.\\n *\\n * The `ecrecover` EVM precompile 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 {MessageHashUtils-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 function tryRecover(\\n bytes32 hash,\\n bytes memory signature\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\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 assembly (\\\"memory-safe\\\") {\\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, bytes32(signature.length));\\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 precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\\n _throwError(error, errorArg);\\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[ERC-2098 short signatures]\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n unchecked {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n // We do not check for an overflow here since the shift operation results in 0 or 1.\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\\n _throwError(error, errorArg);\\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 function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\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, s);\\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, bytes32(0));\\n }\\n\\n return (signer, RecoverError.NoError, bytes32(0));\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\\n */\\n function _throwError(RecoverError error, bytes32 errorArg) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert ECDSAInvalidSignature();\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert ECDSAInvalidSignatureLength(uint256(errorArg));\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert ECDSAInvalidSignatureS(errorArg);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x69f54c02b7d81d505910ec198c11ed4c6a728418a868b906b4a0cf29946fda84\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {MessageHashUtils} from \\\"./MessageHashUtils.sol\\\";\\nimport {ShortStrings, ShortString} from \\\"../ShortStrings.sol\\\";\\nimport {IERC5267} from \\\"../../interfaces/IERC5267.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose\\n * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract\\n * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to\\n * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\\n * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the\\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\\n *\\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n */\\nabstract contract EIP712 is IERC5267 {\\n using ShortStrings for *;\\n\\n bytes32 private constant TYPE_HASH =\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _cachedDomainSeparator;\\n uint256 private immutable _cachedChainId;\\n address private immutable _cachedThis;\\n\\n bytes32 private immutable _hashedName;\\n bytes32 private immutable _hashedVersion;\\n\\n ShortString private immutable _name;\\n ShortString private immutable _version;\\n // slither-disable-next-line constable-states\\n string private _nameFallback;\\n // slither-disable-next-line constable-states\\n string private _versionFallback;\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n _name = name.toShortStringWithFallback(_nameFallback);\\n _version = version.toShortStringWithFallback(_versionFallback);\\n _hashedName = keccak256(bytes(name));\\n _hashedVersion = keccak256(bytes(version));\\n\\n _cachedChainId = block.chainid;\\n _cachedDomainSeparator = _buildDomainSeparator();\\n _cachedThis = address(this);\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\\n return _cachedDomainSeparator;\\n } else {\\n return _buildDomainSeparator();\\n }\\n }\\n\\n function _buildDomainSeparator() private view returns (bytes32) {\\n return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n\\n /**\\n * @inheritdoc IERC5267\\n */\\n function eip712Domain()\\n public\\n view\\n virtual\\n returns (\\n bytes1 fields,\\n string memory name,\\n string memory version,\\n uint256 chainId,\\n address verifyingContract,\\n bytes32 salt,\\n uint256[] memory extensions\\n )\\n {\\n return (\\n hex\\\"0f\\\", // 01111\\n _EIP712Name(),\\n _EIP712Version(),\\n block.chainid,\\n address(this),\\n bytes32(0),\\n new uint256[](0)\\n );\\n }\\n\\n /**\\n * @dev The name parameter for the EIP712 domain.\\n *\\n * NOTE: By default this function reads _name which is an immutable value.\\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function _EIP712Name() internal view returns (string memory) {\\n return _name.toStringWithFallback(_nameFallback);\\n }\\n\\n /**\\n * @dev The version parameter for the EIP712 domain.\\n *\\n * NOTE: By default this function reads _version which is an immutable value.\\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function _EIP712Version() internal view returns (string memory) {\\n return _version.toStringWithFallback(_versionFallback);\\n }\\n}\\n\",\"keccak256\":\"0x0c60057e7351874f086db8dc9291b7ada9ad62cb7725befd2991430d04a74572\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Strings} from \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\\n *\\n * The library provides methods for generating a hash of a message that conforms to the\\n * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\\n * specifications.\\n */\\nlibrary MessageHashUtils {\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x45` (`personal_sign` messages).\\n *\\n * The digest is calculated by prefixing a bytes32 `messageHash` with\\n * `\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\"` and hashing the result. It corresponds with the\\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\\n *\\n * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\\n * keccak256, although any bytes32 value can be safely used because the final digest will\\n * be re-hashed.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\") // 32 is the bytes-length of messageHash\\n mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\\n digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\\n }\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x45` (`personal_sign` messages).\\n *\\n * The digest is calculated by prefixing an arbitrary `message` with\\n * `\\\"\\\\x19Ethereum Signed Message:\\\\n\\\" + len(message)` and hashing the result. It corresponds with the\\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\\n return\\n keccak256(bytes.concat(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", bytes(Strings.toString(message.length)), message));\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x00` (data with intended validator).\\n *\\n * The digest is calculated by prefixing an arbitrary `data` with `\\\"\\\\x19\\\\x00\\\"` and the intended\\n * `validator` address. Then hashing the result.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(hex\\\"19_00\\\", validator, data));\\n }\\n\\n /**\\n * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.\\n */\\n function toDataWithIntendedValidatorHash(\\n address validator,\\n bytes32 messageHash\\n ) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, hex\\\"19_00\\\")\\n mstore(0x02, shl(96, validator))\\n mstore(0x16, messageHash)\\n digest := keccak256(0x00, 0x36)\\n }\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).\\n *\\n * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\\n * `\\\\x19\\\\x01` and hashing the result. It corresponds to the hash signed by the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n mstore(ptr, hex\\\"19_01\\\")\\n mstore(add(ptr, 0x02), domainSeparator)\\n mstore(add(ptr, 0x22), structHash)\\n digest := keccak256(ptr, 0x42)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x26670fef37d4adf55570ba78815eec5f31cb017e708f61886add4fc4da665631\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\\n }\\n }\\n\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a > b, a, b);\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a < b, a, b);\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // Formula from the \\\"Bit Twiddling Hacks\\\" by Sean Eron Anderson.\\n // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\\n // taking advantage of the most significant (or \\\"sign\\\" bit) in two's complement representation.\\n // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\\n // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\\n int256 mask = n >> 255;\\n\\n // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\\n return uint256((n + mask) ^ mask);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\"},\"project/test/mocks/MockERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {ERC20Permit} from \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol\\\";\\n\\ncontract MockERC20 is ERC20Permit {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n uint8 private _decimals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor(string memory symbol, uint8 decimals_) ERC20(symbol, symbol) ERC20Permit(symbol) {\\n _decimals = decimals_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function mint(address to, uint256 amount) external {\\n _mint(to, amount);\\n }\\n\\n function nuke(address owner) external {\\n _burn(owner, balanceOf(owner));\\n }\\n\\n function decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\\n\\ncontract MockERC20Blacklist is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n mapping(address account => bool isBlacklisted) public isBlacklisted;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n error Blacklisted(address);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"BLACK\\\", 6) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function setBlacklisted(address account, bool blacklisted) external {\\n isBlacklisted[account] = blacklisted;\\n }\\n\\n function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\\n _checkBlacklist(from);\\n _checkBlacklist(to);\\n return super.transferFrom(from, to, amount);\\n }\\n\\n function _checkBlacklist(address addr) internal view {\\n if (isBlacklisted[addr]) {\\n revert Blacklisted(addr);\\n }\\n }\\n}\\n\\n\\ncontract MockERC20VoidReturn is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"VOID\\\", 11) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\\n super.transferFrom(from, to, amount);\\n assembly {\\n return(0, 0) // return void\\n }\\n }\\n}\\n\\n\\ncontract MockERC20FalseReturn is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"FALSE\\\", 13) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function transferFrom(address, address, uint256) public pure override returns (bool) {\\n return false; // return false instead of revert\\n }\\n}\\n\",\"keccak256\":\"0xf418c9e3b57c817e2ae0085dacf3b79d531ff5e4c5d51634c09d0981d834472b\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 37501, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 37507, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 37509, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 37511, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 37513, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + }, + { + "astId": 45222, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_nameFallback", + "offset": 0, + "slot": "5", + "type": "t_string_storage" + }, + { + "astId": 45224, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_versionFallback", + "offset": 0, + "slot": "6", + "type": "t_string_storage" + }, + { + "astId": 42750, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_nonces", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 74928, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_decimals", + "offset": 0, + "slot": "8", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "argsData": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000045553444300000000000000000000000000000000000000000000000000000000", + "transaction": { + "nonce": "0x2173", + "hash": "0x1257205b5245178e9baaa2c7cda24aa47cbb10f06b3bee76468c9d26ba20e675", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xc9126a6fa5bf57b64e627b5b4aec225e39e89530f5f1fcfddc937544654cb5b4", + "blockNumber": "0xa7c6af", + "transactionIndex": "0xe7" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/PermissionedResolverImpl.json b/contracts/deployments/sepolia-official-v1-20260525-r2/PermissionedResolverImpl.json new file mode 100644 index 000000000..91f2398ba --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/PermissionedResolverImpl.json @@ -0,0 +1,2888 @@ +{ + "address": "0xdce5205a553573ffd47629327dddf36186022ffa", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + } + ], + "name": "InvalidContentType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "name": "InvalidEVMAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "UnsupportedResolverProfile", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + } + ], + "name": "ABIChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "a", + "type": "address" + } + ], + "name": "AddrChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newAddress", + "type": "bytes" + } + ], + "name": "AddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "indexedFromName", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "indexedToName", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "fromName", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "toName", + "type": "bytes" + } + ], + "name": "AliasChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "ContenthashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "indexedData", + "type": "bytes" + } + ], + "name": "DataChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "InterfaceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "NameChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "NamedAddrResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "NamedDataResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "NamedResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "NamedTextResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "name": "PubkeyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "TextChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newVersion", + "type": "uint64" + } + ], + "name": "VersionChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "contentTypes", + "type": "uint256" + } + ], + "name": "ABI", + "outputs": [ + { + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "grant", + "type": "bool" + } + ], + "name": "authorizeAddrRoles", + "outputs": [ + { + "internalType": "bool", + "name": "updated", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "grant", + "type": "bool" + } + ], + "name": "authorizeDataRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "grant", + "type": "bool" + } + ], + "name": "authorizeNameRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "grant", + "type": "bool" + } + ], + "name": "authorizeTextRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "canUpgradeFrom", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "clearRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "contenthash", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "data", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "fromName", + "type": "bytes" + } + ], + "name": "getAlias", + "outputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "hasAddr", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "interfaceImplementer", + "outputs": [ + { + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "calls", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes[]", + "name": "calls", + "type": "bytes[]" + } + ], + "name": "multicallWithNodeCheck", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "pubkey", + "outputs": [ + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "recordVersions", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "fromName", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "fromData", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "setABI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "name": "setAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "addr_", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "fromName", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + } + ], + "name": "setAlias", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "setContenthash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "setData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "setInterface", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "primary", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "name": "setPubkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "setText", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feature", + "type": "bytes4" + } + ], + "name": "supportsFeature", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "text", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "contractName": "PermissionedResolver", + "sourceName": "src/resolver/PermissionedResolver.sol", + "bytecode": "0x60c06040523060a052348015610013575f5ffd5b50604051614d13380380614d13833981016040819052610032916103e4565b6001600160a01b03821660805261006b5f7f0100000000000000000000000000000001000000000000000000000000000000838261007b565b50610074610176565b5050610456565b5f835f0361008a57505f61016e565b61009384610213565b6001600160a01b0383166100ba5760405163761fe2c960e11b815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214610168575f878152602081815260408083206001600160a01b03891684529091529020819055811986166101168882600161025c565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a36001935050505061016e565b5f925050505b949350505050565b5f61017f61038c565b805490915068010000000000000000900460ff16156101b15760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146102105780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561021057604051630153d96960e51b8152600481018290526024015b60405180910390fd5b5f610266836103b6565b905081156102fc575f848152600160205260409020546102ac9082161980195f516020614cf35f395f51905f5291909101165f516020614cd35f395f51905f5216151590565b156102d457604051631f22ca6960e31b81526004810185905260248101849052604401610253565b5f84815260016020526040812080548592906102f1908490610430565b909155506103869050565b5f8481526001602052604090205461033b901982161980195f516020614cf35f395f51905f5291909101165f516020614cd35f395f51905f5216151590565b1561036357604051631f80c19b60e01b81526004810185905260248101849052604401610253565b5f8481526001602052604081208054859290610380908490610443565b90915550505b50505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b5f6103c082610213565b50600181901b17600281901b1790565b6001600160a01b0381168114610210575f5ffd5b5f5f604083850312156103f5575f5ffd5b8251610400816103d0565b6020840151909250610411816103d0565b809150509250929050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156103b0576103b061041c565b818103818111156103b0576103b061041c565b60805160a0516148406104935f395f8181612f8501528181612fae015261314401525f81816104ed0152818161386601526138c701526148405ff3fe608060405260043610610319575f3560e01c8063691f34311161019c578063c8690233116100e7578063dfa70d8b11610092578063ecbfada31161006d578063ecbfada314610a83578063f1cb7e0614610aa2578063f2d1eb2514610ac1578063f41a143d14610ae0575f5ffd5b8063dfa70d8b14610a26578063e32954eb14610a45578063e59d895d14610a64575f5ffd5b8063d3bf89b1116100c2578063d3bf89b11461094b578063d5fa2b00146109b8578063d700ff33146109d7575f5ffd5b8063c8690233146108b9578063cd6dc6871461090d578063ce156e821461092c575f5ffd5b80639061b92311610147578063bbd9abb511610122578063bbd9abb51461085c578063bc1c58d11461087b578063c80ef4e01461089a575f5ffd5b80639061b923146107c9578063ac9650d8146107e8578063ad3cb1cc14610814575f5ffd5b8063781ef8db11610177578063781ef8db146107355780637c3005861461078b5780638b95dd71146107aa575f5ffd5b8063691f3431146106d85780636f3ff726146106f75780637737221314610716575f5ffd5b8063319c22bb116102675780634f1ef28611610212578063587eefd1116101ed578063587eefd11461062f57806359d1d43c1461064e5780635adf47241461067a578063623195b0146106b9575f5ffd5b80634f1ef286146105bf57806352d1902d146105d2578063582de3e7146105e6575f5ffd5b80633634f911116102425780633634f9111461054d5780633b3b57de146105815780634eb9c45e146105a0575f5ffd5b8063319c22bb146104dc57806332f111d71461050f5780633603d7581461052e575f5ffd5b80631c3fc3eb116102c757806329cd62ea116102a257806329cd62ea146104735780632f27fa2414610492578063304e6ade146104bd575f5ffd5b80631c3fc3eb146104065780632203ab5614610427578063291770ae14610454575f5ffd5b806311b8e00a116102f757806311b8e00a14610391578063124a319c146103b05780631a76b72c146103e7575f5ffd5b806301ffc9a71461031d578063072d5d771461035157806310f13a8c14610370575b5f5ffd5b348015610328575f5ffd5b5061033c610337366004613bad565b610b00565b60405190151581526020015b60405180910390f35b34801561035c575f5ffd5b5061033c61036b366004613bda565b610eb7565b34801561037b575f5ffd5b5061038f61038a366004613c46565b610ee2565b005b34801561039c575f5ffd5b5061033c6103ab366004613cbf565b611087565b3480156103bb575f5ffd5b506103cf6103ca366004613cdf565b61109e565b6040516001600160a01b039091168152602001610348565b3480156103f2575f5ffd5b5061033c610401366004613d18565b611113565b348015610411575f5ffd5b506104195f81565b604051908152602001610348565b348015610432575f5ffd5b50610446610441366004613cbf565b611271565b604051610348929190613dd6565b34801561045f575f5ffd5b5061038f61046e366004613dee565b61138d565b34801561047e575f5ffd5b5061038f61048d366004613e5a565b611477565b34801561049d575f5ffd5b506104196104ac366004613e83565b5f9081526001602052604090205490565b3480156104c8575f5ffd5b5061038f6104d7366004613e9a565b611558565b3480156104e7575f5ffd5b506103cf7f000000000000000000000000000000000000000000000000000000000000000081565b34801561051a575f5ffd5b5061033c610529366004613cbf565b611619565b348015610539575f5ffd5b5061038f610548366004613e83565b611668565b348015610558575f5ffd5b5061056c610567366004613cbf565b611755565b60408051928352602083019190915201610348565b34801561058c575f5ffd5b506103cf61059b366004613e83565b611778565b3480156105ab575f5ffd5b5061038f6105ba366004613c46565b611796565b61038f6105cd366004613fa0565b6118fc565b3480156105dd575f5ffd5b5061041961191b565b3480156105f1575f5ffd5b5061033c610600366004613bad565b6001600160e01b0319167f96b62db8000000000000000000000000000000000000000000000000000000001490565b34801561063a575f5ffd5b5061033c610649366004613fed565b611949565b348015610659575f5ffd5b5061066d610668366004613e9a565b611a45565b6040516103489190614058565b348015610685575f5ffd5b50610419610694366004613bda565b5f918252602082815260408084206001600160a01b0393909316845291905290205490565b3480156106c4575f5ffd5b5061038f6106d336600461406a565b611b25565b3480156106e3575f5ffd5b5061066d6106f2366004613e83565b611c43565b348015610702575f5ffd5b5061033c6107113660046140a1565b611d02565b348015610721575f5ffd5b5061038f610730366004613e9a565b611d53565b348015610740575f5ffd5b5061033c61074f366004613bda565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b348015610796575f5ffd5b5061033c6107a53660046140bc565b611e19565b3480156107b5575f5ffd5b5061038f6107c43660046140f2565b611e4d565b3480156107d4575f5ffd5b5061066d6107e3366004613dee565b611fc7565b3480156107f3575f5ffd5b5061080761080236600461417f565b6122c4565b60405161034891906141be565b34801561081f575f5ffd5b5061066d6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b348015610867575f5ffd5b5061033c610876366004613fed565b6123cb565b348015610886575f5ffd5b5061066d610895366004613e83565b6124b7565b3480156108a5575f5ffd5b5061066d6108b4366004614221565b6124f0565b3480156108c4575f5ffd5b5061056c6108d3366004613e83565b5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902060018101546002909101549091565b348015610918575f5ffd5b5061038f610927366004614253565b61253a565b348015610937575f5ffd5b5061033c610946366004613bda565b6126ac565b348015610956575f5ffd5b5061033c6109653660046140bc565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b3480156109c3575f5ffd5b5061038f6109d2366004613bda565b6126c9565b3480156109e2575f5ffd5b50610a0d6109f1366004613e83565b5f908152610103602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610348565b348015610a31575f5ffd5b5061033c610a403660046140bc565b612705565b348015610a50575f5ffd5b50610807610a5f36600461427d565b612739565b348015610a6f575f5ffd5b5061038f610a7e3660046142b8565b612745565b348015610a8e575f5ffd5b5061066d610a9d366004613e9a565b61283b565b348015610aad575f5ffd5b5061066d610abc366004613cbf565b61287c565b348015610acc575f5ffd5b5061033c610adb366004613d18565b612a08565b348015610aeb575f5ffd5b5061033c610afa3660046140a1565b50600190565b5f7f2c7442c9000000000000000000000000000000000000000000000000000000006001600160e01b031983161480610b6257507f9061b923000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610b9657507f582de3e7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610bca57507f4fbf0433000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610bfe57507f2203ab56000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c3257507f3b3b57de000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c6657507ff1cb7e06000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c9a57507fbc1c58d1000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610cce57507fecbfada3000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d0257507f32f111d7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d3657507f124a319c000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d6a57507f691f3431000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d9e57507fc8690233000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610dd257507f59d1d43c000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e0657507fd700ff33000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e3a57507fb0f3d367000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e6e57507ff41a143d000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610ea257507f6f3ff726000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610eb15750610eb182612b13565b92915050565b5f5f83610ecc8282610ec7612b60565b612b6e565b610ed95f86866001612c21565b95945050505050565b84610f2185858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612d3192505050565b60105f610f2c612b60565b9050821580610faa5750610f93610f438585612d3c565b5f908152602081815260408083206001600160a01b03861684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925290912054178316831490565b158015610faa5750610fa8610f435f85612d3c565b155b15610fc357610fc3610fbc855f612d3c565b8383612d5e565b8585610ff78b5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b6005018a8a60405161100a9291906142ea565b9081526020016040518091039020918261102592919061436f565b5087876040516110369291906142ea565b6040518091039020897f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a18a8a8a8a6040516110749493929190614451565b60405180910390a3505050505050505050565b5f5f6110938484611755565b501515949350505050565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083206001600160e01b0319851684526008019091529020546001600160a01b031680610eb1575f6110f784611778565b90506111038184612dff565b1561110c578091505b5092915050565b5f5f61115388888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b90506410000000005f6111668382612d3c565b90505f6111b0846111ab8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612d3192505050565b612d3c565b90508515611248576111c58284610ec7612b60565b5f818152600160205260409020545f036112305788886040516111e99291906142ea565b6040518091039020817fdb7aa4f21d01358b79d5574f3f3f6805f4f97606c53cb70598063387352206ac8d8d8d8d6040516112279493929190614451565b60405180910390a35b61123d8184896001612c21565b945050505050611267565b61125a8284611255612b60565b612e4b565b61123d8184896001612ef8565b9695505050505050565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206001906060905b5f831180156112b25750838311155b156113725782841615611366575f838152600782016020526040902080546112d9906142f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611305906142f9565b80156113505780601f1061132757610100808354040283529160200191611350565b820191905f5260205f20905b81548152906001019060200180831161133357829003601f168201915b505050505091505f825111156113665750611386565b600183901b92506112a3565b505060408051602081019091525f80825291505b9250929050565b63100000006113a45f8261139f612b60565b612d5e565b82826101025f6113e889898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b81526020019081526020015f20918261140292919061436f565b5082826040516114139291906142ea565b6040518091039020858560405161142b9291906142ea565b60405180910390207fa8c2ea0876733fd2146051b3e195e5e1d1f85eff08bf169191dce9569281c529878787876040516114689493929190614451565b60405180910390a35050505050565b825f61100081611485612b60565b90508215806114b3575061149c610f438585612d3c565b1580156114b357506114b1610f435f85612d3c565b155b156114c5576114c5610fbc855f612d3c565b60408051808201825287815260208082018890525f8a8152610104825283812061010383528482205467ffffffffffffffff16825290915291909120600101906002611512929190613b4d565b50604080518781526020810187905288917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a250505050505050565b825f61010081611566612b60565b9050821580611594575061157d610f438585612d3c565b1580156115945750611592610f435f85612d3c565b155b156115a6576115a6610fbc855f612d3c565b85856115da895f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b916115e691908361436f565b50867fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788787604051611547929190614477565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083208484526004019091528120805482919061165d906142f9565b905011905092915050565b805f64010000000081611679612b60565b90508215806116a75750611690610f438585612d3c565b1580156116a757506116a5610f435f85612d3c565b155b156116b9576116b9610fbc855f612d3c565b5f85815261010360205260408120805482906116de9067ffffffffffffffff1661449e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790559050857fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db44482604051611745919067ffffffffffffffff91909116815260200190565b60405180910390a2505050505050565b5f5f61176083612f60565b5f948552600160205260409094205484169492505050565b5f61178482603c61287c565b61178d906144ca565b60601c92915050565b846117d585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612d3192505050565b6410000000005f6117e4612b60565b905082158061181257506117fb610f438585612d3c565b1580156118125750611810610f435f85612d3c565b155b1561182457611824610fbc855f612d3c565b85856118588b5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b6006018a8a60405161186b9291906142ea565b9081526020016040518091039020918261188692919061436f565b5085856040516118979291906142ea565b604051809103902088886040516118af9291906142ea565b60405180910390208a7f3b7ea3580e046bf897ca24f2f45fcf5491dafba8d1b3dd17ca92aa0e82b4dd218b8b6040516118e9929190614477565b60405180910390a4505050505050505050565b611904612f7a565b61190d82613033565b6119178282613051565b5050565b5f611924613139565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f5f61198987878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b905060015f6119988382612d3c565b90505f6119ae846111ab8a5f9081526020902090565b90508515611a2b576119c38284610ec7612b60565b5f818152600160205260409020545f03611a135787817f2fe6caf984256b1a1844b92f52cf88703e829b07ce397a6c7fcf1f779db7a1858c8c604051611a0a929190614477565b60405180910390a35b611a208184896001612c21565b945050505050610ed9565b611a388284611255612b60565b611a208184896001612ef8565b5f8381526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906005018383604051611a869291906142ea565b90815260200160405180910390208054611a9f906142f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611acb906142f9565b8015611b165780601f10611aed57610100808354040283529160200191611b16565b820191905f5260205f20905b815481529060010190602001808311611af957829003601f168201915b505050505090505b9392505050565b835f6201000081611b34612b60565b9050821580611b625750611b4b610f438585612d3c565b158015611b625750611b60610f435f85612d3c565b155b15611b7457611b74610fbc855f612d3c565b611b7d87613182565b611bbb576040517f5742bb26000000000000000000000000000000000000000000000000000000008152600481018890526024015b60405180910390fd5b8585611bef8a5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b5f8a81526007919091016020526040902091611c0c91908361436f565b50604051879089907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3905f90a35050505050505050565b5f8181526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906003018054611c7f906142f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611cab906142f9565b8015611cf65780601f10611ccd57610100808354040283529160200191611cf6565b820191905f5260205f20905b815481529060010190602001808311611cd957829003601f168201915b50505050509050919050565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb560205260408120546f0100000000000000000000000000000090811614610eb1565b825f630100000081611d63612b60565b9050821580611d915750611d7a610f438585612d3c565b158015611d915750611d8f610f435f85612d3c565b155b15611da357611da3610fbc855f612d3c565b8585611dd7895f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b60030191611de691908361436f565b50867fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78787604051611547929190614477565b60405163d1a3b35560e01b815260048101849052602481018390526001600160a01b03821660448201525f90606401611bb2565b5f82815260209020839060015f611e62612b60565b9050821580611e905750611e79610f438585612d3c565b158015611e905750611e8e610f435f85612d3c565b155b15611ea257611ea2610fbc855f612d3c565b845115801590611eb457508451601414155b8015611ec45750611ec4866131a1565b15611efd57846040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611bb29190614058565b5f8781526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083208984526004019091529020611f3d868261451d565b50867f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528787604051611f70929190613dd6565b60405180910390a2603c8603611fbe57867f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2611fab876144ca565b60405160609190911c8152602001611547565b50505050505050565b60605f61200886868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506124f092505050565b90505f612062858561205d85515f146120215785612057565b8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050505b5f612e1a565b6131c6565b90507fac9650d80000000000000000000000000000000000000000000000000000000061208e826145d8565b6001600160e01b03191603612210578051600319810160048301908152915f916120c19190810160200190602401614612565b90505f5b81518110156121e5578181815181106120e0576120e0614710565b602002602001015192505f306001600160a01b0316846040516121039190614724565b5f60405180830381855afa9150503d805f811461213b576040519150601f19603f3d011682016040523d82523d5f602084013e612140565b606091505b5091505080515f036121be57637b1c461b60e01b61215d856145d8565b6040516001600160e01b0319909116602482015260440160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290505b808383815181106121d1576121d1614710565b6020908102919091010152506001016120c5565b50806040516020016121f791906141be565b60405160208183030381529060405293505050506122bc565b5f5f306001600160a01b03168360405161222a9190614724565b5f60405180830381855afa9150503d805f8114612262576040519150601f19603f3d011682016040523d82523d5f602084013e612267565b606091505b50915091508161227957805160208201fd5b80515f036122b15761228b868861473a565b604051637b1c461b60e01b81526001600160e01b03199091166004820152602401611bb2565b93506122bc92505050565b949350505050565b60608167ffffffffffffffff8111156122df576122df613ee2565b60405190808252806020026020018201604052801561231257816020015b60608152602001906001900390816122fd5790505b5090505f5b8281101561110c575f803086868581811061233457612334614710565b9050602002810190612346919061476f565b6040516123549291906142ea565b5f60405180830381855af49150503d805f811461238c576040519150601f19603f3d011682016040523d82523d5f602084013e612391565b606091505b5091509150816123a357805160208201fd5b808484815181106123b6576123b6614710565b60209081029190910101525050600101612317565b5f5f61240b87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b90505f6124188282612d3c565b9050831561249d5761242d8187610ec7612b60565b801580159061244757505f81815260016020526040902054155b1561248757807f737038e72be1d204e2c7336c20bff2169d9dffe11face28c5969af4ecce04f67898960405161247e929190614477565b60405180910390a25b6124948187876001612c21565b92505050610ed9565b6124aa8187611255612b60565b6124948187876001612ef8565b5f8181526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060908054611c7f906142f9565b60605f5b60606124ff846132ab565b80519095509091505f036125135750612534565b80516020820120828103612528575050612534565b84935091506124f49050565b50919050565b5f6125436133fa565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f8115801561256f5750825b90505f8267ffffffffffffffff16600114801561258b5750303b155b905081158015612599575080155b156125d0576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561260457845468ff00000000000000001916680100000000000000001785555b6001600160a01b038716612644576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61264c613422565b6126585f87895f612c21565b508315611fbe57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050505050565b5f5f836126bc8282611255612b60565b610ed95f86866001612ef8565b6040516bffffffffffffffffffffffff19606083901b166020820152611917908390603c90603401604051602081830303815290604052611e4d565b6040516314c09c6360e31b815260048101849052602481018390526001600160a01b03821660448201525f90606401611bb2565b60606122bc83836122c4565b825f6210000081612754612b60565b9050821580612782575061276b610f438585612d3c565b1580156127825750612780610f435f85612d3c565b155b1561279457612794610fbc855f612d3c565b5f8781526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083206001600160e01b03198a168085526008909101835292819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038a16908117909155815190815290518a927f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa928290030190a350505050505050565b5f8381526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906006018383604051611a869291906142ea565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff168452825280832084845260048101909252909120805460609291906128c4906142f9565b80601f01602080910402602001604051908101604052809291908181526020018280546128f0906142f9565b801561293b5780601f106129125761010080835404028352916020019161293b565b820191905f5260205f20905b81548152906001019060200180831161291e57829003601f168201915b5050505050915081515f14801561295f57505f6129578461342a565b63ffffffff16115b1561110c5763800000005f90815260048201602052604090208054612983906142f9565b80601f01602080910402602001604051908101604052809291908181526020018280546129af906142f9565b80156129fa5780601f106129d1576101008083540402835291602001916129fa565b820191905f5260205f20905b8154815290600101906020018083116129dd57829003601f168201915b505050505091505092915050565b5f5f612a4888888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b905060105f612a578382612d3c565b90505f612a9c846111ab8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612d3192505050565b9050851561124857612ab18284610ec7612b60565b5f818152600160205260409020545f03611230578888604051612ad59291906142ea565b6040518091039020817fab228e072dd20e63d6891264ea8f6a2459e6852ab494b707970f978ba630859c8d8d8d8d6040516112279493929190614451565b5f6001600160e01b031982167f8f452d62000000000000000000000000000000000000000000000000000000001480610eb157506301ffc9a760e01b6001600160e01b0319831614610eb1565b5f612b69613454565b905090565b5f612bde84836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b90508019831615612c1b5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401611bb2565b50505050565b5f835f03612c3057505f6122bc565b612c398461345d565b6001600160a01b038316612c79576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214612d27575f878152602081815260408083206001600160a01b0389168452909152902081905581198616612cd5888260016134bd565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3600193505050506122bc565b5f925050506122bc565b805160209091012090565b5f82151580612d4a57508115155b15610eb157505f9182526020526040902090565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5909252909120541782168214612dfa576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401611bb2565b505050565b5f612e0983613659565b8015611b1e5750611b1e838361368b565b5f612e258383613726565b925090508015610eb157611b1e612e3c8484612e1a565b825f9182526020526040902090565b5f612ebb84836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b90508019831615612c1b576040516314c09c6360e31b815260048101859052602481018490526001600160a01b0383166044820152606401611bb2565b5f612f028461345d565b5f858152602081815260408083206001600160a01b038716845290915290205484198116808214612d27575f878152602081815260408083206001600160a01b0389168452909152812082905586831690612cd590899083906134bd565b5f612f6a8261345d565b50600181901b17600281901b1790565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061301357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166130077f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156130315760405163703e46dd60e11b815260040160405180910390fd5b565b6f100000000000000000000000000000006119175f8261139f612b60565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156130ab575060408051601f3d908101601f191682019092526130a8918101906147b2565b60015b6130d357604051634c9c8ce360e01b81526001600160a01b0383166004820152602401611bb2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc811461312f576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401611bb2565b612dfa8383613753565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146130315760405163703e46dd60e11b815260040160405180910390fd5b5f5f82118015610eb15750816131996001826147c9565b161592915050565b5f6380000000821480610eb157505f6131b98361342a565b63ffffffff161192915050565b606083838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525092935061329d92505050565b602481019050600481035160e01c63ac9650d88114613235578183101561322d5750505050565b838252612c1b565b815182019180831015613249575050505050565b825160051b5b8015613295576020840191508084015182018281101561326f575061328c565b805181018087101561327e5750855b613289888284613206565b50505b601f190161324f565b505050505050565b611b1e828251830183613206565b6060805f5b83518110156133f4576101025f6132c78684612e1a565b81526020019081526020015f2080546132df906142f9565b80601f016020809104026020016040519081016040528092919081815260200182805461330b906142f9565b80156133565780601f1061332d57610100808354040283529160200191613356565b820191905f5260205f20905b81548152906001019060200180831161333957829003601f168201915b505050505092505f835111156133e15780156133d957825161337890826147dc565b67ffffffffffffffff81111561339057613390613ee2565b6040519080825280601f01601f1916602001820160405280156133ba576020820181803683370190505b5091508060208501602084015e8251602084018260200184015e6133f4565b8291506133f4565b6133eb84826137a8565b91506132b09050565b50915091565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610eb1565b613031613825565b5f603c820361343b57506001919050565b6380000000918218918210613450575f610eb1565b5090565b5f612b69613863565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156134ba576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401611bb2565b50565b5f6134c783612f60565b90508115613590575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615613568576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401611bb2565b5f84815260016020526040812080548592906135859084906147dc565b90915550612c1b9050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef0116161561362a576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401611bb2565b5f84815260016020526040812080548592906136479084906147c9565b909155505050505050565b5050505050565b5f61366b826301ffc9a760e01b61368b565b8015610eb15750613684826001600160e01b031961368b565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015613710575060208210155b801561371b57505f81115b979650505050505050565b5f5f5f61373385856137a8565b9250905060ff81161561374b57806021858701012092505b509250929050565b61375c82613954565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156137a057612dfa82826139d7565b611917613a40565b5f5f835183106137cd578360405163ba4adc2360e01b8152600401611bb29190614058565b8383815181106137df576137df614710565b016020015160f81c915050818101600101816137ff578351811415613805565b83518110155b15611386578360405163ba4adc2360e01b8152600401611bb29190614058565b61382d613a78565b613031576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661389757503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015613914573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061393891906147ef565b90506001600160a01b03811661394f573391505090565b919050565b806001600160a01b03163b5f0361398957604051634c9c8ce360e01b81526001600160a01b0382166004820152602401611bb2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f5f846001600160a01b0316846040516139f39190614724565b5f60405180830381855af49150503d805f8114613a2b576040519150601f19603f3d011682016040523d82523d5f602084013e613a30565b606091505b5091509150610ed9858383613a96565b3415613031576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613a816133fa565b5468010000000000000000900460ff16919050565b606082613aab57613aa682613b0b565b611b1e565b8151158015613ac257506001600160a01b0384163b155b15613b04576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401611bb2565b5080611b1e565b805115613b1b5780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260028101928215613b7b579160200282015b82811115613b7b578251825591602001919060010190613b60565b506134509291505b80821115613450575f8155600101613b83565b80356001600160e01b03198116811461394f575f5ffd5b5f60208284031215613bbd575f5ffd5b611b1e82613b96565b6001600160a01b03811681146134ba575f5ffd5b5f5f60408385031215613beb575f5ffd5b823591506020830135613bfd81613bc6565b809150509250929050565b5f5f83601f840112613c18575f5ffd5b50813567ffffffffffffffff811115613c2f575f5ffd5b602083019150836020828501011115611386575f5ffd5b5f5f5f5f5f60608688031215613c5a575f5ffd5b85359450602086013567ffffffffffffffff811115613c77575f5ffd5b613c8388828901613c08565b909550935050604086013567ffffffffffffffff811115613ca2575f5ffd5b613cae88828901613c08565b969995985093965092949392505050565b5f5f60408385031215613cd0575f5ffd5b50508035926020909101359150565b5f5f60408385031215613cf0575f5ffd5b82359150613d0060208401613b96565b90509250929050565b8035801515811461394f575f5ffd5b5f5f5f5f5f5f60808789031215613d2d575f5ffd5b863567ffffffffffffffff811115613d43575f5ffd5b613d4f89828a01613c08565b909750955050602087013567ffffffffffffffff811115613d6e575f5ffd5b613d7a89828a01613c08565b9095509350506040870135613d8e81613bc6565b9150613d9c60608801613d09565b90509295509295509295565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f6122bc6040830184613da8565b5f5f5f5f60408587031215613e01575f5ffd5b843567ffffffffffffffff811115613e17575f5ffd5b613e2387828801613c08565b909550935050602085013567ffffffffffffffff811115613e42575f5ffd5b613e4e87828801613c08565b95989497509550505050565b5f5f5f60608486031215613e6c575f5ffd5b505081359360208301359350604090920135919050565b5f60208284031215613e93575f5ffd5b5035919050565b5f5f5f60408486031215613eac575f5ffd5b83359250602084013567ffffffffffffffff811115613ec9575f5ffd5b613ed586828701613c08565b9497909650939450505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613f1f57613f1f613ee2565b604052919050565b5f67ffffffffffffffff821115613f4057613f40613ee2565b50601f01601f191660200190565b5f82601f830112613f5d575f5ffd5b8135613f70613f6b82613f27565b613ef6565b818152846020838601011115613f84575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f60408385031215613fb1575f5ffd5b8235613fbc81613bc6565b9150602083013567ffffffffffffffff811115613fd7575f5ffd5b613fe385828601613f4e565b9150509250929050565b5f5f5f5f5f60808688031215614001575f5ffd5b853567ffffffffffffffff811115614017575f5ffd5b61402388828901613c08565b90965094505060208601359250604086013561403e81613bc6565b915061404c60608701613d09565b90509295509295909350565b602081525f611b1e6020830184613da8565b5f5f5f5f6060858703121561407d575f5ffd5b8435935060208501359250604085013567ffffffffffffffff811115613e42575f5ffd5b5f602082840312156140b1575f5ffd5b8135611b1e81613bc6565b5f5f5f606084860312156140ce575f5ffd5b833592506020840135915060408401356140e781613bc6565b809150509250925092565b5f5f5f60608486031215614104575f5ffd5b8335925060208401359150604084013567ffffffffffffffff811115614128575f5ffd5b61413486828701613f4e565b9150509250925092565b5f5f83601f84011261414e575f5ffd5b50813567ffffffffffffffff811115614165575f5ffd5b6020830191508360208260051b8501011115611386575f5ffd5b5f5f60208385031215614190575f5ffd5b823567ffffffffffffffff8111156141a6575f5ffd5b6141b28582860161413e565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561421557603f19878603018452614200858351613da8565b945060209384019391909101906001016141e4565b50929695505050505050565b5f60208284031215614231575f5ffd5b813567ffffffffffffffff811115614247575f5ffd5b6122bc84828501613f4e565b5f5f60408385031215614264575f5ffd5b823561426f81613bc6565b946020939093013593505050565b5f5f5f6040848603121561428f575f5ffd5b83359250602084013567ffffffffffffffff8111156142ac575f5ffd5b613ed58682870161413e565b5f5f5f606084860312156142ca575f5ffd5b833592506142da60208501613b96565b915060408401356140e781613bc6565b818382375f9101908152919050565b600181811c9082168061430d57607f821691505b60208210810361253457634e487b7160e01b5f52602260045260245ffd5b601f821115612dfa57805f5260205f20601f840160051c810160208510156143505750805b601f840160051c820191505b81811015613652575f815560010161435c565b67ffffffffffffffff83111561438757614387613ee2565b61439b8361439583546142f9565b8361432b565b5f601f8411600181146143cc575f85156143b55750838201355b5f19600387901b1c1916600186901b178355613652565b5f83815260208120601f198716915b828110156143fb57868501358255602094850194600190920191016143db565b5086821015614417575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f614464604083018688614429565b828103602084015261371b818587614429565b602081525f6122bc602083018486614429565b634e487b7160e01b5f52601160045260245ffd5b5f67ffffffffffffffff821667ffffffffffffffff81036144c1576144c161448a565b60010192915050565b805160208201516bffffffffffffffffffffffff19811691906014821015614516576bffffffffffffffffffffffff196bffffffffffffffffffffffff198360140360031b1b82161692505b5050919050565b815167ffffffffffffffff81111561453757614537613ee2565b61454b8161454584546142f9565b8461432b565b6020601f82116001811461457d575f83156145665750848201515b5f19600385901b1c1916600184901b178455613652565b5f84815260208120601f198516915b828110156145ac578785015182556020948501946001909201910161458c565b50848210156145c957868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b805160208201516001600160e01b0319811691906004821015614516576001600160e01b031960049290920360031b82901b161692915050565b5f60208284031215614622575f5ffd5b815167ffffffffffffffff811115614638575f5ffd5b8201601f81018413614648575f5ffd5b805167ffffffffffffffff81111561466257614662613ee2565b8060051b61467260208201613ef6565b9182526020818401810192908101908784111561468d575f5ffd5b6020850192505b8383101561371b57825167ffffffffffffffff8111156146b2575f5ffd5b8501603f810189136146c2575f5ffd5b60208101516146d3613f6b82613f27565b8181526040838301018b10156146e7575f5ffd5b8160408401602083015e5f60208383010152808552505050602082019150602083019250614694565b634e487b7160e01b5f52603260045260245ffd5b5f82518060208501845e5f920191825250919050565b80356001600160e01b0319811690600484101561110c576001600160e01b0319808560040360031b1b82161691505092915050565b5f5f8335601e19843603018112614784575f5ffd5b83018035915067ffffffffffffffff82111561479e575f5ffd5b602001915036819003821315611386575f5ffd5b5f602082840312156147c2575f5ffd5b5051919050565b81810381811115610eb157610eb161448a565b80820180821115610eb157610eb161448a565b5f602082840312156147ff575f5ffd5b8151611b1e81613bc656fea264697066735822122071e1751d4cee131ece0527431341dc717ac0be9da4f353ed3f78f3e6b245c2bf64736f6c634300081b00338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405260043610610319575f3560e01c8063691f34311161019c578063c8690233116100e7578063dfa70d8b11610092578063ecbfada31161006d578063ecbfada314610a83578063f1cb7e0614610aa2578063f2d1eb2514610ac1578063f41a143d14610ae0575f5ffd5b8063dfa70d8b14610a26578063e32954eb14610a45578063e59d895d14610a64575f5ffd5b8063d3bf89b1116100c2578063d3bf89b11461094b578063d5fa2b00146109b8578063d700ff33146109d7575f5ffd5b8063c8690233146108b9578063cd6dc6871461090d578063ce156e821461092c575f5ffd5b80639061b92311610147578063bbd9abb511610122578063bbd9abb51461085c578063bc1c58d11461087b578063c80ef4e01461089a575f5ffd5b80639061b923146107c9578063ac9650d8146107e8578063ad3cb1cc14610814575f5ffd5b8063781ef8db11610177578063781ef8db146107355780637c3005861461078b5780638b95dd71146107aa575f5ffd5b8063691f3431146106d85780636f3ff726146106f75780637737221314610716575f5ffd5b8063319c22bb116102675780634f1ef28611610212578063587eefd1116101ed578063587eefd11461062f57806359d1d43c1461064e5780635adf47241461067a578063623195b0146106b9575f5ffd5b80634f1ef286146105bf57806352d1902d146105d2578063582de3e7146105e6575f5ffd5b80633634f911116102425780633634f9111461054d5780633b3b57de146105815780634eb9c45e146105a0575f5ffd5b8063319c22bb146104dc57806332f111d71461050f5780633603d7581461052e575f5ffd5b80631c3fc3eb116102c757806329cd62ea116102a257806329cd62ea146104735780632f27fa2414610492578063304e6ade146104bd575f5ffd5b80631c3fc3eb146104065780632203ab5614610427578063291770ae14610454575f5ffd5b806311b8e00a116102f757806311b8e00a14610391578063124a319c146103b05780631a76b72c146103e7575f5ffd5b806301ffc9a71461031d578063072d5d771461035157806310f13a8c14610370575b5f5ffd5b348015610328575f5ffd5b5061033c610337366004613bad565b610b00565b60405190151581526020015b60405180910390f35b34801561035c575f5ffd5b5061033c61036b366004613bda565b610eb7565b34801561037b575f5ffd5b5061038f61038a366004613c46565b610ee2565b005b34801561039c575f5ffd5b5061033c6103ab366004613cbf565b611087565b3480156103bb575f5ffd5b506103cf6103ca366004613cdf565b61109e565b6040516001600160a01b039091168152602001610348565b3480156103f2575f5ffd5b5061033c610401366004613d18565b611113565b348015610411575f5ffd5b506104195f81565b604051908152602001610348565b348015610432575f5ffd5b50610446610441366004613cbf565b611271565b604051610348929190613dd6565b34801561045f575f5ffd5b5061038f61046e366004613dee565b61138d565b34801561047e575f5ffd5b5061038f61048d366004613e5a565b611477565b34801561049d575f5ffd5b506104196104ac366004613e83565b5f9081526001602052604090205490565b3480156104c8575f5ffd5b5061038f6104d7366004613e9a565b611558565b3480156104e7575f5ffd5b506103cf7f000000000000000000000000000000000000000000000000000000000000000081565b34801561051a575f5ffd5b5061033c610529366004613cbf565b611619565b348015610539575f5ffd5b5061038f610548366004613e83565b611668565b348015610558575f5ffd5b5061056c610567366004613cbf565b611755565b60408051928352602083019190915201610348565b34801561058c575f5ffd5b506103cf61059b366004613e83565b611778565b3480156105ab575f5ffd5b5061038f6105ba366004613c46565b611796565b61038f6105cd366004613fa0565b6118fc565b3480156105dd575f5ffd5b5061041961191b565b3480156105f1575f5ffd5b5061033c610600366004613bad565b6001600160e01b0319167f96b62db8000000000000000000000000000000000000000000000000000000001490565b34801561063a575f5ffd5b5061033c610649366004613fed565b611949565b348015610659575f5ffd5b5061066d610668366004613e9a565b611a45565b6040516103489190614058565b348015610685575f5ffd5b50610419610694366004613bda565b5f918252602082815260408084206001600160a01b0393909316845291905290205490565b3480156106c4575f5ffd5b5061038f6106d336600461406a565b611b25565b3480156106e3575f5ffd5b5061066d6106f2366004613e83565b611c43565b348015610702575f5ffd5b5061033c6107113660046140a1565b611d02565b348015610721575f5ffd5b5061038f610730366004613e9a565b611d53565b348015610740575f5ffd5b5061033c61074f366004613bda565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b348015610796575f5ffd5b5061033c6107a53660046140bc565b611e19565b3480156107b5575f5ffd5b5061038f6107c43660046140f2565b611e4d565b3480156107d4575f5ffd5b5061066d6107e3366004613dee565b611fc7565b3480156107f3575f5ffd5b5061080761080236600461417f565b6122c4565b60405161034891906141be565b34801561081f575f5ffd5b5061066d6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b348015610867575f5ffd5b5061033c610876366004613fed565b6123cb565b348015610886575f5ffd5b5061066d610895366004613e83565b6124b7565b3480156108a5575f5ffd5b5061066d6108b4366004614221565b6124f0565b3480156108c4575f5ffd5b5061056c6108d3366004613e83565b5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902060018101546002909101549091565b348015610918575f5ffd5b5061038f610927366004614253565b61253a565b348015610937575f5ffd5b5061033c610946366004613bda565b6126ac565b348015610956575f5ffd5b5061033c6109653660046140bc565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b3480156109c3575f5ffd5b5061038f6109d2366004613bda565b6126c9565b3480156109e2575f5ffd5b50610a0d6109f1366004613e83565b5f908152610103602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610348565b348015610a31575f5ffd5b5061033c610a403660046140bc565b612705565b348015610a50575f5ffd5b50610807610a5f36600461427d565b612739565b348015610a6f575f5ffd5b5061038f610a7e3660046142b8565b612745565b348015610a8e575f5ffd5b5061066d610a9d366004613e9a565b61283b565b348015610aad575f5ffd5b5061066d610abc366004613cbf565b61287c565b348015610acc575f5ffd5b5061033c610adb366004613d18565b612a08565b348015610aeb575f5ffd5b5061033c610afa3660046140a1565b50600190565b5f7f2c7442c9000000000000000000000000000000000000000000000000000000006001600160e01b031983161480610b6257507f9061b923000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610b9657507f582de3e7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610bca57507f4fbf0433000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610bfe57507f2203ab56000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c3257507f3b3b57de000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c6657507ff1cb7e06000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c9a57507fbc1c58d1000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610cce57507fecbfada3000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d0257507f32f111d7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d3657507f124a319c000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d6a57507f691f3431000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d9e57507fc8690233000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610dd257507f59d1d43c000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e0657507fd700ff33000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e3a57507fb0f3d367000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e6e57507ff41a143d000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610ea257507f6f3ff726000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610eb15750610eb182612b13565b92915050565b5f5f83610ecc8282610ec7612b60565b612b6e565b610ed95f86866001612c21565b95945050505050565b84610f2185858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612d3192505050565b60105f610f2c612b60565b9050821580610faa5750610f93610f438585612d3c565b5f908152602081815260408083206001600160a01b03861684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925290912054178316831490565b158015610faa5750610fa8610f435f85612d3c565b155b15610fc357610fc3610fbc855f612d3c565b8383612d5e565b8585610ff78b5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b6005018a8a60405161100a9291906142ea565b9081526020016040518091039020918261102592919061436f565b5087876040516110369291906142ea565b6040518091039020897f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a18a8a8a8a6040516110749493929190614451565b60405180910390a3505050505050505050565b5f5f6110938484611755565b501515949350505050565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083206001600160e01b0319851684526008019091529020546001600160a01b031680610eb1575f6110f784611778565b90506111038184612dff565b1561110c578091505b5092915050565b5f5f61115388888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b90506410000000005f6111668382612d3c565b90505f6111b0846111ab8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612d3192505050565b612d3c565b90508515611248576111c58284610ec7612b60565b5f818152600160205260409020545f036112305788886040516111e99291906142ea565b6040518091039020817fdb7aa4f21d01358b79d5574f3f3f6805f4f97606c53cb70598063387352206ac8d8d8d8d6040516112279493929190614451565b60405180910390a35b61123d8184896001612c21565b945050505050611267565b61125a8284611255612b60565b612e4b565b61123d8184896001612ef8565b9695505050505050565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206001906060905b5f831180156112b25750838311155b156113725782841615611366575f838152600782016020526040902080546112d9906142f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611305906142f9565b80156113505780601f1061132757610100808354040283529160200191611350565b820191905f5260205f20905b81548152906001019060200180831161133357829003601f168201915b505050505091505f825111156113665750611386565b600183901b92506112a3565b505060408051602081019091525f80825291505b9250929050565b63100000006113a45f8261139f612b60565b612d5e565b82826101025f6113e889898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b81526020019081526020015f20918261140292919061436f565b5082826040516114139291906142ea565b6040518091039020858560405161142b9291906142ea565b60405180910390207fa8c2ea0876733fd2146051b3e195e5e1d1f85eff08bf169191dce9569281c529878787876040516114689493929190614451565b60405180910390a35050505050565b825f61100081611485612b60565b90508215806114b3575061149c610f438585612d3c565b1580156114b357506114b1610f435f85612d3c565b155b156114c5576114c5610fbc855f612d3c565b60408051808201825287815260208082018890525f8a8152610104825283812061010383528482205467ffffffffffffffff16825290915291909120600101906002611512929190613b4d565b50604080518781526020810187905288917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a250505050505050565b825f61010081611566612b60565b9050821580611594575061157d610f438585612d3c565b1580156115945750611592610f435f85612d3c565b155b156115a6576115a6610fbc855f612d3c565b85856115da895f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b916115e691908361436f565b50867fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788787604051611547929190614477565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083208484526004019091528120805482919061165d906142f9565b905011905092915050565b805f64010000000081611679612b60565b90508215806116a75750611690610f438585612d3c565b1580156116a757506116a5610f435f85612d3c565b155b156116b9576116b9610fbc855f612d3c565b5f85815261010360205260408120805482906116de9067ffffffffffffffff1661449e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790559050857fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db44482604051611745919067ffffffffffffffff91909116815260200190565b60405180910390a2505050505050565b5f5f61176083612f60565b5f948552600160205260409094205484169492505050565b5f61178482603c61287c565b61178d906144ca565b60601c92915050565b846117d585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612d3192505050565b6410000000005f6117e4612b60565b905082158061181257506117fb610f438585612d3c565b1580156118125750611810610f435f85612d3c565b155b1561182457611824610fbc855f612d3c565b85856118588b5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b6006018a8a60405161186b9291906142ea565b9081526020016040518091039020918261188692919061436f565b5085856040516118979291906142ea565b604051809103902088886040516118af9291906142ea565b60405180910390208a7f3b7ea3580e046bf897ca24f2f45fcf5491dafba8d1b3dd17ca92aa0e82b4dd218b8b6040516118e9929190614477565b60405180910390a4505050505050505050565b611904612f7a565b61190d82613033565b6119178282613051565b5050565b5f611924613139565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f5f61198987878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b905060015f6119988382612d3c565b90505f6119ae846111ab8a5f9081526020902090565b90508515611a2b576119c38284610ec7612b60565b5f818152600160205260409020545f03611a135787817f2fe6caf984256b1a1844b92f52cf88703e829b07ce397a6c7fcf1f779db7a1858c8c604051611a0a929190614477565b60405180910390a35b611a208184896001612c21565b945050505050610ed9565b611a388284611255612b60565b611a208184896001612ef8565b5f8381526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906005018383604051611a869291906142ea565b90815260200160405180910390208054611a9f906142f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611acb906142f9565b8015611b165780601f10611aed57610100808354040283529160200191611b16565b820191905f5260205f20905b815481529060010190602001808311611af957829003601f168201915b505050505090505b9392505050565b835f6201000081611b34612b60565b9050821580611b625750611b4b610f438585612d3c565b158015611b625750611b60610f435f85612d3c565b155b15611b7457611b74610fbc855f612d3c565b611b7d87613182565b611bbb576040517f5742bb26000000000000000000000000000000000000000000000000000000008152600481018890526024015b60405180910390fd5b8585611bef8a5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b5f8a81526007919091016020526040902091611c0c91908361436f565b50604051879089907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3905f90a35050505050505050565b5f8181526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906003018054611c7f906142f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611cab906142f9565b8015611cf65780601f10611ccd57610100808354040283529160200191611cf6565b820191905f5260205f20905b815481529060010190602001808311611cd957829003601f168201915b50505050509050919050565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb560205260408120546f0100000000000000000000000000000090811614610eb1565b825f630100000081611d63612b60565b9050821580611d915750611d7a610f438585612d3c565b158015611d915750611d8f610f435f85612d3c565b155b15611da357611da3610fbc855f612d3c565b8585611dd7895f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b60030191611de691908361436f565b50867fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78787604051611547929190614477565b60405163d1a3b35560e01b815260048101849052602481018390526001600160a01b03821660448201525f90606401611bb2565b5f82815260209020839060015f611e62612b60565b9050821580611e905750611e79610f438585612d3c565b158015611e905750611e8e610f435f85612d3c565b155b15611ea257611ea2610fbc855f612d3c565b845115801590611eb457508451601414155b8015611ec45750611ec4866131a1565b15611efd57846040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611bb29190614058565b5f8781526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083208984526004019091529020611f3d868261451d565b50867f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528787604051611f70929190613dd6565b60405180910390a2603c8603611fbe57867f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2611fab876144ca565b60405160609190911c8152602001611547565b50505050505050565b60605f61200886868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506124f092505050565b90505f612062858561205d85515f146120215785612057565b8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050505b5f612e1a565b6131c6565b90507fac9650d80000000000000000000000000000000000000000000000000000000061208e826145d8565b6001600160e01b03191603612210578051600319810160048301908152915f916120c19190810160200190602401614612565b90505f5b81518110156121e5578181815181106120e0576120e0614710565b602002602001015192505f306001600160a01b0316846040516121039190614724565b5f60405180830381855afa9150503d805f811461213b576040519150601f19603f3d011682016040523d82523d5f602084013e612140565b606091505b5091505080515f036121be57637b1c461b60e01b61215d856145d8565b6040516001600160e01b0319909116602482015260440160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290505b808383815181106121d1576121d1614710565b6020908102919091010152506001016120c5565b50806040516020016121f791906141be565b60405160208183030381529060405293505050506122bc565b5f5f306001600160a01b03168360405161222a9190614724565b5f60405180830381855afa9150503d805f8114612262576040519150601f19603f3d011682016040523d82523d5f602084013e612267565b606091505b50915091508161227957805160208201fd5b80515f036122b15761228b868861473a565b604051637b1c461b60e01b81526001600160e01b03199091166004820152602401611bb2565b93506122bc92505050565b949350505050565b60608167ffffffffffffffff8111156122df576122df613ee2565b60405190808252806020026020018201604052801561231257816020015b60608152602001906001900390816122fd5790505b5090505f5b8281101561110c575f803086868581811061233457612334614710565b9050602002810190612346919061476f565b6040516123549291906142ea565b5f60405180830381855af49150503d805f811461238c576040519150601f19603f3d011682016040523d82523d5f602084013e612391565b606091505b5091509150816123a357805160208201fd5b808484815181106123b6576123b6614710565b60209081029190910101525050600101612317565b5f5f61240b87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b90505f6124188282612d3c565b9050831561249d5761242d8187610ec7612b60565b801580159061244757505f81815260016020526040902054155b1561248757807f737038e72be1d204e2c7336c20bff2169d9dffe11face28c5969af4ecce04f67898960405161247e929190614477565b60405180910390a25b6124948187876001612c21565b92505050610ed9565b6124aa8187611255612b60565b6124948187876001612ef8565b5f8181526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060908054611c7f906142f9565b60605f5b60606124ff846132ab565b80519095509091505f036125135750612534565b80516020820120828103612528575050612534565b84935091506124f49050565b50919050565b5f6125436133fa565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f8115801561256f5750825b90505f8267ffffffffffffffff16600114801561258b5750303b155b905081158015612599575080155b156125d0576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561260457845468ff00000000000000001916680100000000000000001785555b6001600160a01b038716612644576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61264c613422565b6126585f87895f612c21565b508315611fbe57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a150505050505050565b5f5f836126bc8282611255612b60565b610ed95f86866001612ef8565b6040516bffffffffffffffffffffffff19606083901b166020820152611917908390603c90603401604051602081830303815290604052611e4d565b6040516314c09c6360e31b815260048101849052602481018390526001600160a01b03821660448201525f90606401611bb2565b60606122bc83836122c4565b825f6210000081612754612b60565b9050821580612782575061276b610f438585612d3c565b1580156127825750612780610f435f85612d3c565b155b1561279457612794610fbc855f612d3c565b5f8781526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083206001600160e01b03198a168085526008909101835292819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038a16908117909155815190815290518a927f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa928290030190a350505050505050565b5f8381526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906006018383604051611a869291906142ea565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff168452825280832084845260048101909252909120805460609291906128c4906142f9565b80601f01602080910402602001604051908101604052809291908181526020018280546128f0906142f9565b801561293b5780601f106129125761010080835404028352916020019161293b565b820191905f5260205f20905b81548152906001019060200180831161291e57829003601f168201915b5050505050915081515f14801561295f57505f6129578461342a565b63ffffffff16115b1561110c5763800000005f90815260048201602052604090208054612983906142f9565b80601f01602080910402602001604051908101604052809291908181526020018280546129af906142f9565b80156129fa5780601f106129d1576101008083540402835291602001916129fa565b820191905f5260205f20905b8154815290600101906020018083116129dd57829003601f168201915b505050505091505092915050565b5f5f612a4888888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612e1a915050565b905060105f612a578382612d3c565b90505f612a9c846111ab8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612d3192505050565b9050851561124857612ab18284610ec7612b60565b5f818152600160205260409020545f03611230578888604051612ad59291906142ea565b6040518091039020817fab228e072dd20e63d6891264ea8f6a2459e6852ab494b707970f978ba630859c8d8d8d8d6040516112279493929190614451565b5f6001600160e01b031982167f8f452d62000000000000000000000000000000000000000000000000000000001480610eb157506301ffc9a760e01b6001600160e01b0319831614610eb1565b5f612b69613454565b905090565b5f612bde84836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b90508019831615612c1b5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401611bb2565b50505050565b5f835f03612c3057505f6122bc565b612c398461345d565b6001600160a01b038316612c79576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214612d27575f878152602081815260408083206001600160a01b0389168452909152902081905581198616612cd5888260016134bd565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3600193505050506122bc565b5f925050506122bc565b805160209091012090565b5f82151580612d4a57508115155b15610eb157505f9182526020526040902090565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5909252909120541782168214612dfa576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401611bb2565b505050565b5f612e0983613659565b8015611b1e5750611b1e838361368b565b5f612e258383613726565b925090508015610eb157611b1e612e3c8484612e1a565b825f9182526020526040902090565b5f612ebb84836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b90508019831615612c1b576040516314c09c6360e31b815260048101859052602481018490526001600160a01b0383166044820152606401611bb2565b5f612f028461345d565b5f858152602081815260408083206001600160a01b038716845290915290205484198116808214612d27575f878152602081815260408083206001600160a01b0389168452909152812082905586831690612cd590899083906134bd565b5f612f6a8261345d565b50600181901b17600281901b1790565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061301357507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166130077f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156130315760405163703e46dd60e11b815260040160405180910390fd5b565b6f100000000000000000000000000000006119175f8261139f612b60565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156130ab575060408051601f3d908101601f191682019092526130a8918101906147b2565b60015b6130d357604051634c9c8ce360e01b81526001600160a01b0383166004820152602401611bb2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc811461312f576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401611bb2565b612dfa8383613753565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146130315760405163703e46dd60e11b815260040160405180910390fd5b5f5f82118015610eb15750816131996001826147c9565b161592915050565b5f6380000000821480610eb157505f6131b98361342a565b63ffffffff161192915050565b606083838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525092935061329d92505050565b602481019050600481035160e01c63ac9650d88114613235578183101561322d5750505050565b838252612c1b565b815182019180831015613249575050505050565b825160051b5b8015613295576020840191508084015182018281101561326f575061328c565b805181018087101561327e5750855b613289888284613206565b50505b601f190161324f565b505050505050565b611b1e828251830183613206565b6060805f5b83518110156133f4576101025f6132c78684612e1a565b81526020019081526020015f2080546132df906142f9565b80601f016020809104026020016040519081016040528092919081815260200182805461330b906142f9565b80156133565780601f1061332d57610100808354040283529160200191613356565b820191905f5260205f20905b81548152906001019060200180831161333957829003601f168201915b505050505092505f835111156133e15780156133d957825161337890826147dc565b67ffffffffffffffff81111561339057613390613ee2565b6040519080825280601f01601f1916602001820160405280156133ba576020820181803683370190505b5091508060208501602084015e8251602084018260200184015e6133f4565b8291506133f4565b6133eb84826137a8565b91506132b09050565b50915091565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610eb1565b613031613825565b5f603c820361343b57506001919050565b6380000000918218918210613450575f610eb1565b5090565b5f612b69613863565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156134ba576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401611bb2565b50565b5f6134c783612f60565b90508115613590575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615613568576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401611bb2565b5f84815260016020526040812080548592906135859084906147dc565b90915550612c1b9050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef0116161561362a576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401611bb2565b5f84815260016020526040812080548592906136479084906147c9565b909155505050505050565b5050505050565b5f61366b826301ffc9a760e01b61368b565b8015610eb15750613684826001600160e01b031961368b565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015613710575060208210155b801561371b57505f81115b979650505050505050565b5f5f5f61373385856137a8565b9250905060ff81161561374b57806021858701012092505b509250929050565b61375c82613954565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156137a057612dfa82826139d7565b611917613a40565b5f5f835183106137cd578360405163ba4adc2360e01b8152600401611bb29190614058565b8383815181106137df576137df614710565b016020015160f81c915050818101600101816137ff578351811415613805565b83518110155b15611386578360405163ba4adc2360e01b8152600401611bb29190614058565b61382d613a78565b613031576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661389757503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015613914573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061393891906147ef565b90506001600160a01b03811661394f573391505090565b919050565b806001600160a01b03163b5f0361398957604051634c9c8ce360e01b81526001600160a01b0382166004820152602401611bb2565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f5f846001600160a01b0316846040516139f39190614724565b5f60405180830381855af49150503d805f8114613a2b576040519150601f19603f3d011682016040523d82523d5f602084013e613a30565b606091505b5091509150610ed9858383613a96565b3415613031576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613a816133fa565b5468010000000000000000900460ff16919050565b606082613aab57613aa682613b0b565b611b1e565b8151158015613ac257506001600160a01b0384163b155b15613b04576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401611bb2565b5080611b1e565b805115613b1b5780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260028101928215613b7b579160200282015b82811115613b7b578251825591602001919060010190613b60565b506134509291505b80821115613450575f8155600101613b83565b80356001600160e01b03198116811461394f575f5ffd5b5f60208284031215613bbd575f5ffd5b611b1e82613b96565b6001600160a01b03811681146134ba575f5ffd5b5f5f60408385031215613beb575f5ffd5b823591506020830135613bfd81613bc6565b809150509250929050565b5f5f83601f840112613c18575f5ffd5b50813567ffffffffffffffff811115613c2f575f5ffd5b602083019150836020828501011115611386575f5ffd5b5f5f5f5f5f60608688031215613c5a575f5ffd5b85359450602086013567ffffffffffffffff811115613c77575f5ffd5b613c8388828901613c08565b909550935050604086013567ffffffffffffffff811115613ca2575f5ffd5b613cae88828901613c08565b969995985093965092949392505050565b5f5f60408385031215613cd0575f5ffd5b50508035926020909101359150565b5f5f60408385031215613cf0575f5ffd5b82359150613d0060208401613b96565b90509250929050565b8035801515811461394f575f5ffd5b5f5f5f5f5f5f60808789031215613d2d575f5ffd5b863567ffffffffffffffff811115613d43575f5ffd5b613d4f89828a01613c08565b909750955050602087013567ffffffffffffffff811115613d6e575f5ffd5b613d7a89828a01613c08565b9095509350506040870135613d8e81613bc6565b9150613d9c60608801613d09565b90509295509295509295565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f6122bc6040830184613da8565b5f5f5f5f60408587031215613e01575f5ffd5b843567ffffffffffffffff811115613e17575f5ffd5b613e2387828801613c08565b909550935050602085013567ffffffffffffffff811115613e42575f5ffd5b613e4e87828801613c08565b95989497509550505050565b5f5f5f60608486031215613e6c575f5ffd5b505081359360208301359350604090920135919050565b5f60208284031215613e93575f5ffd5b5035919050565b5f5f5f60408486031215613eac575f5ffd5b83359250602084013567ffffffffffffffff811115613ec9575f5ffd5b613ed586828701613c08565b9497909650939450505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613f1f57613f1f613ee2565b604052919050565b5f67ffffffffffffffff821115613f4057613f40613ee2565b50601f01601f191660200190565b5f82601f830112613f5d575f5ffd5b8135613f70613f6b82613f27565b613ef6565b818152846020838601011115613f84575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f60408385031215613fb1575f5ffd5b8235613fbc81613bc6565b9150602083013567ffffffffffffffff811115613fd7575f5ffd5b613fe385828601613f4e565b9150509250929050565b5f5f5f5f5f60808688031215614001575f5ffd5b853567ffffffffffffffff811115614017575f5ffd5b61402388828901613c08565b90965094505060208601359250604086013561403e81613bc6565b915061404c60608701613d09565b90509295509295909350565b602081525f611b1e6020830184613da8565b5f5f5f5f6060858703121561407d575f5ffd5b8435935060208501359250604085013567ffffffffffffffff811115613e42575f5ffd5b5f602082840312156140b1575f5ffd5b8135611b1e81613bc6565b5f5f5f606084860312156140ce575f5ffd5b833592506020840135915060408401356140e781613bc6565b809150509250925092565b5f5f5f60608486031215614104575f5ffd5b8335925060208401359150604084013567ffffffffffffffff811115614128575f5ffd5b61413486828701613f4e565b9150509250925092565b5f5f83601f84011261414e575f5ffd5b50813567ffffffffffffffff811115614165575f5ffd5b6020830191508360208260051b8501011115611386575f5ffd5b5f5f60208385031215614190575f5ffd5b823567ffffffffffffffff8111156141a6575f5ffd5b6141b28582860161413e565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561421557603f19878603018452614200858351613da8565b945060209384019391909101906001016141e4565b50929695505050505050565b5f60208284031215614231575f5ffd5b813567ffffffffffffffff811115614247575f5ffd5b6122bc84828501613f4e565b5f5f60408385031215614264575f5ffd5b823561426f81613bc6565b946020939093013593505050565b5f5f5f6040848603121561428f575f5ffd5b83359250602084013567ffffffffffffffff8111156142ac575f5ffd5b613ed58682870161413e565b5f5f5f606084860312156142ca575f5ffd5b833592506142da60208501613b96565b915060408401356140e781613bc6565b818382375f9101908152919050565b600181811c9082168061430d57607f821691505b60208210810361253457634e487b7160e01b5f52602260045260245ffd5b601f821115612dfa57805f5260205f20601f840160051c810160208510156143505750805b601f840160051c820191505b81811015613652575f815560010161435c565b67ffffffffffffffff83111561438757614387613ee2565b61439b8361439583546142f9565b8361432b565b5f601f8411600181146143cc575f85156143b55750838201355b5f19600387901b1c1916600186901b178355613652565b5f83815260208120601f198716915b828110156143fb57868501358255602094850194600190920191016143db565b5086821015614417575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f614464604083018688614429565b828103602084015261371b818587614429565b602081525f6122bc602083018486614429565b634e487b7160e01b5f52601160045260245ffd5b5f67ffffffffffffffff821667ffffffffffffffff81036144c1576144c161448a565b60010192915050565b805160208201516bffffffffffffffffffffffff19811691906014821015614516576bffffffffffffffffffffffff196bffffffffffffffffffffffff198360140360031b1b82161692505b5050919050565b815167ffffffffffffffff81111561453757614537613ee2565b61454b8161454584546142f9565b8461432b565b6020601f82116001811461457d575f83156145665750848201515b5f19600385901b1c1916600184901b178455613652565b5f84815260208120601f198516915b828110156145ac578785015182556020948501946001909201910161458c565b50848210156145c957868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b805160208201516001600160e01b0319811691906004821015614516576001600160e01b031960049290920360031b82901b161692915050565b5f60208284031215614622575f5ffd5b815167ffffffffffffffff811115614638575f5ffd5b8201601f81018413614648575f5ffd5b805167ffffffffffffffff81111561466257614662613ee2565b8060051b61467260208201613ef6565b9182526020818401810192908101908784111561468d575f5ffd5b6020850192505b8383101561371b57825167ffffffffffffffff8111156146b2575f5ffd5b8501603f810189136146c2575f5ffd5b60208101516146d3613f6b82613f27565b8181526040838301018b10156146e7575f5ffd5b8160408401602083015e5f60208383010152808552505050602082019150602083019250614694565b634e487b7160e01b5f52603260045260245ffd5b5f82518060208501845e5f920191825250919050565b80356001600160e01b0319811690600484101561110c576001600160e01b0319808560040360031b1b82161691505092915050565b5f5f8335601e19843603018112614784575f5ffd5b83018035915067ffffffffffffffff82111561479e575f5ffd5b602001915036819003821315611386575f5ffd5b5f602082840312156147c2575f5ffd5b5051919050565b81810381811115610eb157610eb161448a565b80820180821115610eb157610eb161448a565b5f602082840312156147ff575f5ffd5b8151611b1e81613bc656fea264697066735822122071e1751d4cee131ece0527431341dc717ac0be9da4f353ed3f78f3e6b245c2bf64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "28949": [ + { + "length": 32, + "start": 12165 + }, + { + "length": 32, + "start": 12206 + }, + { + "length": 32, + "start": 12612 + } + ], + "60111": [ + { + "length": 32, + "start": 1261 + }, + { + "length": 32, + "start": 14438 + }, + { + "length": 32, + "start": 14535 + } + ] + }, + "inputSourceName": "project/src/resolver/PermissionedResolver.sol", + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "InvalidContentType(uint256)": [ + { + "details": "Error selector: `0x5742bb26`" + } + ], + "InvalidEVMAddress(bytes)": [ + { + "details": "Error selector: `0x8d666f60`" + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ], + "UnsupportedResolverProfile(bytes4)": [ + { + "details": "Error selector: `0x7b1c461b`" + } + ] + }, + "events": { + "AliasChanged(bytes,bytes,bytes,bytes)": { + "params": { + "fromName": "The source DNS-encoded name.", + "indexedFromName": "The source DNS-encoded name. (indexed bytes, hashed)", + "indexedToName": "The destination DNS-encoded name. (indexed bytes, hashed)", + "toName": "The destination DNS-encoded name." + } + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "NamedAddrResource(uint256,bytes,uint256)": { + "params": { + "coinType": "The coin type.", + "name": "The name.", + "resource": "The EAC resource." + } + }, + "NamedDataResource(uint256,bytes,bytes32,string)": { + "params": { + "key": "The key.", + "keyHash": "The hash of the key.", + "name": "The name.", + "resource": "The EAC resource." + } + }, + "NamedResource(uint256,bytes)": { + "params": { + "name": "The name.", + "resource": "The EAC resource." + } + }, + "NamedTextResource(uint256,bytes,bytes32,string)": { + "params": { + "key": "The key.", + "keyHash": "The hash of the key.", + "name": "The name.", + "resource": "The EAC resource." + } + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "ABI(bytes32,uint256)": { + "params": { + "contentTypes": "A bitwise OR of the ABI formats accepted by the caller.", + "node": "The ENS node to query" + }, + "returns": { + "contentType": "The content type of the return value", + "value": "data The ABI data" + } + }, + "addr(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated address." + } + }, + "authorizeAddrRoles(bytes,uint256,address,bool)": { + "params": { + "account": "The account to authorize roles to.", + "coinType": "The coin type to authorize roles for.", + "grant": "If `true`, grants, otherwise, revokes.", + "toName": "The name to authorize roles for." + }, + "returns": { + "updated": "`true` if the roles were updated." + } + }, + "authorizeDataRoles(bytes,string,address,bool)": { + "params": { + "account": "The account to authorize roles to.", + "grant": "If `true`, grants, otherwise, revokes.", + "key": "The data key to authorize roles for.", + "toName": "The name to authorize roles for." + }, + "returns": { + "_0": "`true` if the roles were updated." + } + }, + "authorizeNameRoles(bytes,uint256,address,bool)": { + "params": { + "account": "The account to authorize roles to.", + "grant": "If `true`, grants, otherwise, revokes.", + "roleBitmap": "The roles to authorize.", + "toName": "The name to authorize roles for." + }, + "returns": { + "_0": "success Whether the roles were updated." + } + }, + "authorizeTextRoles(bytes,string,address,bool)": { + "params": { + "account": "The account to authorize roles to.", + "grant": "If `true`, grants, otherwise, revokes.", + "key": "The text key to authorize roles for.", + "toName": "The name to authorize roles for." + }, + "returns": { + "_0": "`true` if the roles were updated." + } + }, + "canUpgradeFrom(address)": { + "details": "Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call.", + "params": { + "": "{previousImplementation} Ignored." + }, + "returns": { + "allowed": "Always `true` for implementations in this resolver family." + } + }, + "clearRecords(bytes32)": { + "params": { + "node": "The node to update." + } + }, + "constructor": { + "params": { + "hcaFactory": "The HCA factory.", + "namer": "The implementation namer." + } + }, + "contenthash(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated contenthash." + } + }, + "data(bytes32,string)": { + "params": { + "key": "The key.", + "node": "The node (namehash) for which data is being fetched." + }, + "returns": { + "_0": "The associated arbitrary `bytes` data." + } + }, + "getAlias(bytes)": { + "params": { + "fromName": "The source DNS-encoded name." + }, + "returns": { + "toName": "The destination DNS-encoded name or empty if not aliased." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "Ignored.", + "resource": "Ignored.", + "roleBitmap": "Ignored." + }, + "returns": { + "_0": "success Ignored, always reverts." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAddr(bytes32,uint256)": { + "params": { + "coinType": "The coin type.", + "node": "The node to query." + }, + "returns": { + "_0": "True if the associated address is not empty." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "initialize(address,uint256)": { + "params": { + "admin": "The resolver owner.", + "roleBitmap": "The roles granted to `admin`." + } + }, + "interfaceImplementer(bytes32,bytes4)": { + "params": { + "interfaceID": "The EIP 165 interface ID to check for.", + "node": "The ENS node to query." + }, + "returns": { + "implementer": "The address that implements this interface, or 0 if the interface is unsupported." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "multicall(bytes[])": { + "details": "Reverts with first error.", + "params": { + "calls": "The calls to make." + }, + "returns": { + "results": "The results of the calls." + } + }, + "multicallWithNodeCheck(bytes32,bytes[])": { + "details": "The node parameter is accepted for interface compatibility but is not used. Permission checking is handled by individual function calls within the multicall.", + "params": { + "": "{node} Ignored, for interface compatibility.", + "calls": "The calls to make." + }, + "returns": { + "_0": "results The results of the calls." + } + }, + "name(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated name." + } + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "pubkey(bytes32)": { + "params": { + "node": "The ENS node to query" + }, + "returns": { + "x": "The X coordinate of the curve point for the public key.", + "y": "The Y coordinate of the curve point for the public key." + } + }, + "recordVersions(bytes32)": { + "params": { + "node": "The node to check." + }, + "returns": { + "_0": "version The current version." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "Ignored.", + "resource": "Ignored.", + "roleBitmap": "Ignored." + }, + "returns": { + "_0": "success Ignored, always reverts." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "setABI(bytes32,uint256,bytes)": { + "params": { + "contentType": "The content type of the ABI.", + "node": "The node to update.", + "value": "The ABI data." + } + }, + "setAddr(bytes32,address)": { + "params": { + "addr_": "The mainnet address.", + "node": "The node to update." + } + }, + "setAddr(bytes32,uint256,bytes)": { + "params": { + "addressBytes": "The encoded address.", + "coinType": "The coin type.", + "node": "The node to update." + } + }, + "setAlias(bytes,bytes)": { + "params": { + "fromName": "The source DNS-encoded name.", + "toName": "The destination DNS-encoded name." + } + }, + "setContenthash(bytes32,bytes)": { + "params": { + "hash": "The contenthash to set.", + "node": "The node to update." + } + }, + "setData(bytes32,string,bytes)": { + "params": { + "key": "The data key.", + "node": "The node to update.", + "value": "The data value." + } + }, + "setInterface(bytes32,bytes4,address)": { + "params": { + "implementer": "The address of the contract that implements this interface for this node.", + "interfaceId": "The EIP-165 interface ID.", + "node": "The node to update." + } + }, + "setName(bytes32,string)": { + "params": { + "node": "The node to update.", + "primary": "The primary name." + } + }, + "setPubkey(bytes32,bytes32,bytes32)": { + "params": { + "node": "The node to update.", + "x": "The x coordinate of the public key.", + "y": "The y coordinate of the public key." + } + }, + "setText(bytes32,string,string)": { + "params": { + "key": "The text key.", + "node": "The node to update.", + "value": "The text value." + } + }, + "supportsFeature(bytes4)": { + "params": { + "featureId": "The feature identifier." + }, + "returns": { + "_0": "`true` if the feature is supported by the contract." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "text(bytes32,string)": { + "params": { + "key": "The text data key to query.", + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated text data." + } + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + } + }, + "stateVariables": { + "_aliases": { + "details": "Aliases for names." + }, + "_records": { + "details": "Records for nodes." + }, + "_versions": { + "details": "Versions for nodes." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "3699200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ABI(bytes32,uint256)": "infinite", + "HCA_FACTORY()": "infinite", + "ROOT_RESOURCE()": "262", + "UPGRADE_INTERFACE_VERSION()": "infinite", + "addr(bytes32)": "infinite", + "addr(bytes32,uint256)": "infinite", + "authorizeAddrRoles(bytes,uint256,address,bool)": "infinite", + "authorizeDataRoles(bytes,string,address,bool)": "infinite", + "authorizeNameRoles(bytes,uint256,address,bool)": "infinite", + "authorizeTextRoles(bytes,string,address,bool)": "infinite", + "canUpgradeFrom(address)": "474", + "clearRecords(bytes32)": "infinite", + "contenthash(bytes32)": "infinite", + "data(bytes32,string)": "infinite", + "getAlias(bytes)": "infinite", + "getAssigneeCount(uint256,uint256)": "2702", + "grantRoles(uint256,uint256,address)": "570", + "grantRootRoles(uint256,address)": "infinite", + "hasAddr(bytes32,uint256)": "5006", + "hasAssignees(uint256,uint256)": "2730", + "hasRoles(uint256,uint256,address)": "4892", + "hasRootRoles(uint256,address)": "2630", + "initialize(address,uint256)": "infinite", + "interfaceImplementer(bytes32,bytes4)": "infinite", + "isContractNamer(address)": "2663", + "multicall(bytes[])": "infinite", + "multicallWithNodeCheck(bytes32,bytes[])": "infinite", + "name(bytes32)": "infinite", + "proxiableUUID()": "infinite", + "pubkey(bytes32)": "6883", + "recordVersions(bytes32)": "2561", + "resolve(bytes,bytes)": "infinite", + "revokeRoles(uint256,uint256,address)": "547", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "2525", + "roles(uint256,address)": "2744", + "setABI(bytes32,uint256,bytes)": "infinite", + "setAddr(bytes32,address)": "infinite", + "setAddr(bytes32,uint256,bytes)": "infinite", + "setAlias(bytes,bytes)": "infinite", + "setContenthash(bytes32,bytes)": "infinite", + "setData(bytes32,string,bytes)": "infinite", + "setInterface(bytes32,bytes4,address)": "infinite", + "setName(bytes32,string)": "infinite", + "setPubkey(bytes32,bytes32,bytes32)": "infinite", + "setText(bytes32,string,string)": "infinite", + "supportsFeature(bytes4)": "485", + "supportsInterface(bytes4)": "infinite", + "text(bytes32,string)": "infinite", + "upgradeToAndCall(address,bytes)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite", + "_contextSuffixLength()": "infinite", + "_isPowerOf2(uint256)": "139", + "_msgData()": "infinite", + "_msgSender()": "infinite", + "_record(bytes32)": "infinite", + "_resolveAlias(bytes memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"InvalidContentType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"selector\",\"type\":\"bytes4\"}],\"name\":\"UnsupportedResolverProfile\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"ABIChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"a\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newAddress\",\"type\":\"bytes\"}],\"name\":\"AddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"indexedFromName\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"indexedToName\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"fromName\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"}],\"name\":\"AliasChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"ContenthashChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"indexedData\",\"type\":\"bytes\"}],\"name\":\"DataChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"name\":\"InterfaceChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"NamedAddrResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"NamedDataResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"NamedResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"NamedTextResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"PubkeyChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newVersion\",\"type\":\"uint64\"}],\"name\":\"VersionChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"contentTypes\",\"type\":\"uint256\"}],\"name\":\"ABI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"grant\",\"type\":\"bool\"}],\"name\":\"authorizeAddrRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"updated\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"grant\",\"type\":\"bool\"}],\"name\":\"authorizeDataRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"grant\",\"type\":\"bool\"}],\"name\":\"authorizeNameRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"grant\",\"type\":\"bool\"}],\"name\":\"authorizeTextRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"canUpgradeFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"clearRecords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"contenthash\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"fromName\",\"type\":\"bytes\"}],\"name\":\"getAlias\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"hasAddr\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"interfaceImplementer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"calls\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"calls\",\"type\":\"bytes[]\"}],\"name\":\"multicallWithNodeCheck\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"recordVersions\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"fromName\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"fromData\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"name\":\"setABI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"fromName\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"}],\"name\":\"setAlias\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"setContenthash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"name\":\"setData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"},{\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"name\":\"setInterface\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"setText\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"feature\",\"type\":\"bytes4\"}],\"name\":\"supportsFeature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidContentType(uint256)\":[{\"details\":\"Error selector: `0x5742bb26`\"}],\"InvalidEVMAddress(bytes)\":[{\"details\":\"Error selector: `0x8d666f60`\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}],\"UnsupportedResolverProfile(bytes4)\":[{\"details\":\"Error selector: `0x7b1c461b`\"}]},\"events\":{\"AliasChanged(bytes,bytes,bytes,bytes)\":{\"params\":{\"fromName\":\"The source DNS-encoded name.\",\"indexedFromName\":\"The source DNS-encoded name. (indexed bytes, hashed)\",\"indexedToName\":\"The destination DNS-encoded name. (indexed bytes, hashed)\",\"toName\":\"The destination DNS-encoded name.\"}},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"NamedAddrResource(uint256,bytes,uint256)\":{\"params\":{\"coinType\":\"The coin type.\",\"name\":\"The name.\",\"resource\":\"The EAC resource.\"}},\"NamedDataResource(uint256,bytes,bytes32,string)\":{\"params\":{\"key\":\"The key.\",\"keyHash\":\"The hash of the key.\",\"name\":\"The name.\",\"resource\":\"The EAC resource.\"}},\"NamedResource(uint256,bytes)\":{\"params\":{\"name\":\"The name.\",\"resource\":\"The EAC resource.\"}},\"NamedTextResource(uint256,bytes,bytes32,string)\":{\"params\":{\"key\":\"The key.\",\"keyHash\":\"The hash of the key.\",\"name\":\"The name.\",\"resource\":\"The EAC resource.\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"ABI(bytes32,uint256)\":{\"params\":{\"contentTypes\":\"A bitwise OR of the ABI formats accepted by the caller.\",\"node\":\"The ENS node to query\"},\"returns\":{\"contentType\":\"The content type of the return value\",\"value\":\"data The ABI data\"}},\"addr(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated address.\"}},\"authorizeAddrRoles(bytes,uint256,address,bool)\":{\"params\":{\"account\":\"The account to authorize roles to.\",\"coinType\":\"The coin type to authorize roles for.\",\"grant\":\"If `true`, grants, otherwise, revokes.\",\"toName\":\"The name to authorize roles for.\"},\"returns\":{\"updated\":\"`true` if the roles were updated.\"}},\"authorizeDataRoles(bytes,string,address,bool)\":{\"params\":{\"account\":\"The account to authorize roles to.\",\"grant\":\"If `true`, grants, otherwise, revokes.\",\"key\":\"The data key to authorize roles for.\",\"toName\":\"The name to authorize roles for.\"},\"returns\":{\"_0\":\"`true` if the roles were updated.\"}},\"authorizeNameRoles(bytes,uint256,address,bool)\":{\"params\":{\"account\":\"The account to authorize roles to.\",\"grant\":\"If `true`, grants, otherwise, revokes.\",\"roleBitmap\":\"The roles to authorize.\",\"toName\":\"The name to authorize roles for.\"},\"returns\":{\"_0\":\"success Whether the roles were updated.\"}},\"authorizeTextRoles(bytes,string,address,bool)\":{\"params\":{\"account\":\"The account to authorize roles to.\",\"grant\":\"If `true`, grants, otherwise, revokes.\",\"key\":\"The text key to authorize roles for.\",\"toName\":\"The name to authorize roles for.\"},\"returns\":{\"_0\":\"`true` if the roles were updated.\"}},\"canUpgradeFrom(address)\":{\"details\":\"Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call.\",\"params\":{\"\":\"{previousImplementation} Ignored.\"},\"returns\":{\"allowed\":\"Always `true` for implementations in this resolver family.\"}},\"clearRecords(bytes32)\":{\"params\":{\"node\":\"The node to update.\"}},\"constructor\":{\"params\":{\"hcaFactory\":\"The HCA factory.\",\"namer\":\"The implementation namer.\"}},\"contenthash(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated contenthash.\"}},\"data(bytes32,string)\":{\"params\":{\"key\":\"The key.\",\"node\":\"The node (namehash) for which data is being fetched.\"},\"returns\":{\"_0\":\"The associated arbitrary `bytes` data.\"}},\"getAlias(bytes)\":{\"params\":{\"fromName\":\"The source DNS-encoded name.\"},\"returns\":{\"toName\":\"The destination DNS-encoded name or empty if not aliased.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"Ignored.\",\"resource\":\"Ignored.\",\"roleBitmap\":\"Ignored.\"},\"returns\":{\"_0\":\"success Ignored, always reverts.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAddr(bytes32,uint256)\":{\"params\":{\"coinType\":\"The coin type.\",\"node\":\"The node to query.\"},\"returns\":{\"_0\":\"True if the associated address is not empty.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"initialize(address,uint256)\":{\"params\":{\"admin\":\"The resolver owner.\",\"roleBitmap\":\"The roles granted to `admin`.\"}},\"interfaceImplementer(bytes32,bytes4)\":{\"params\":{\"interfaceID\":\"The EIP 165 interface ID to check for.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"implementer\":\"The address that implements this interface, or 0 if the interface is unsupported.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"multicall(bytes[])\":{\"details\":\"Reverts with first error.\",\"params\":{\"calls\":\"The calls to make.\"},\"returns\":{\"results\":\"The results of the calls.\"}},\"multicallWithNodeCheck(bytes32,bytes[])\":{\"details\":\"The node parameter is accepted for interface compatibility but is not used. Permission checking is handled by individual function calls within the multicall.\",\"params\":{\"\":\"{node} Ignored, for interface compatibility.\",\"calls\":\"The calls to make.\"},\"returns\":{\"_0\":\"results The results of the calls.\"}},\"name(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated name.\"}},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"pubkey(bytes32)\":{\"params\":{\"node\":\"The ENS node to query\"},\"returns\":{\"x\":\"The X coordinate of the curve point for the public key.\",\"y\":\"The Y coordinate of the curve point for the public key.\"}},\"recordVersions(bytes32)\":{\"params\":{\"node\":\"The node to check.\"},\"returns\":{\"_0\":\"version The current version.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"Ignored.\",\"resource\":\"Ignored.\",\"roleBitmap\":\"Ignored.\"},\"returns\":{\"_0\":\"success Ignored, always reverts.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"setABI(bytes32,uint256,bytes)\":{\"params\":{\"contentType\":\"The content type of the ABI.\",\"node\":\"The node to update.\",\"value\":\"The ABI data.\"}},\"setAddr(bytes32,address)\":{\"params\":{\"addr_\":\"The mainnet address.\",\"node\":\"The node to update.\"}},\"setAddr(bytes32,uint256,bytes)\":{\"params\":{\"addressBytes\":\"The encoded address.\",\"coinType\":\"The coin type.\",\"node\":\"The node to update.\"}},\"setAlias(bytes,bytes)\":{\"params\":{\"fromName\":\"The source DNS-encoded name.\",\"toName\":\"The destination DNS-encoded name.\"}},\"setContenthash(bytes32,bytes)\":{\"params\":{\"hash\":\"The contenthash to set.\",\"node\":\"The node to update.\"}},\"setData(bytes32,string,bytes)\":{\"params\":{\"key\":\"The data key.\",\"node\":\"The node to update.\",\"value\":\"The data value.\"}},\"setInterface(bytes32,bytes4,address)\":{\"params\":{\"implementer\":\"The address of the contract that implements this interface for this node.\",\"interfaceId\":\"The EIP-165 interface ID.\",\"node\":\"The node to update.\"}},\"setName(bytes32,string)\":{\"params\":{\"node\":\"The node to update.\",\"primary\":\"The primary name.\"}},\"setPubkey(bytes32,bytes32,bytes32)\":{\"params\":{\"node\":\"The node to update.\",\"x\":\"The x coordinate of the public key.\",\"y\":\"The y coordinate of the public key.\"}},\"setText(bytes32,string,string)\":{\"params\":{\"key\":\"The text key.\",\"node\":\"The node to update.\",\"value\":\"The text value.\"}},\"supportsFeature(bytes4)\":{\"params\":{\"featureId\":\"The feature identifier.\"},\"returns\":{\"_0\":\"`true` if the feature is supported by the contract.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"text(bytes32,string)\":{\"params\":{\"key\":\"The text data key to query.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated text data.\"}},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"stateVariables\":{\"_aliases\":{\"details\":\"Aliases for names.\"},\"_records\":{\"details\":\"Records for nodes.\"},\"_versions\":{\"details\":\"Versions for nodes.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidContentType(uint256)\":[{\"notice\":\"The coin type is not a power of 2.\"}],\"InvalidEVMAddress(bytes)\":[{\"notice\":\"The address could not be converted to `address`.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"UnsupportedResolverProfile(bytes4)\":[{\"notice\":\"The resolver profile cannot be answered.\"}]},\"events\":{\"AliasChanged(bytes,bytes,bytes,bytes)\":{\"notice\":\"An alias was changed.\"},\"DataChanged(bytes32,string,string,bytes)\":{\"notice\":\"For a specific `node`, the data associated with a `key` has changed.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"NamedAddrResource(uint256,bytes,uint256)\":{\"notice\":\"Associate an EAC resource with a name and specific `addr(coinType)` record.\"},\"NamedDataResource(uint256,bytes,bytes32,string)\":{\"notice\":\"Associate an EAC resource with a name and specific `data(key)` record.\"},\"NamedResource(uint256,bytes)\":{\"notice\":\"Associate an EAC resource with a name.\"},\"NamedTextResource(uint256,bytes,bytes32,string)\":{\"notice\":\"Associate an EAC resource with a name and specific `text(key)` record.\"}},\"kind\":\"user\",\"methods\":{\"ABI(bytes32,uint256)\":{\"notice\":\"Returns the ABI associated with an ENS node. Defined in EIP205.\"},\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"addr(bytes32)\":{\"notice\":\"Returns the address associated with an ENS node.\"},\"authorizeAddrRoles(bytes,uint256,address,bool)\":{\"notice\":\"Authorize `setAddr(coinType)` permission to `account` for `toName`. Use `NameCoder.encode(\\\"\\\")` for any name.\"},\"authorizeDataRoles(bytes,string,address,bool)\":{\"notice\":\"Authorize `setData(key)` permission to `account` for `toName`. Use `NameCoder.encode(\\\"\\\")` for any name.\"},\"authorizeNameRoles(bytes,uint256,address,bool)\":{\"notice\":\"Authorize `roleBitmap` permissions to `account` for `toName`. Use `NameCoder.encode(\\\"\\\")` for any name, which is equivalent to `grantRootRoles()`.\"},\"authorizeTextRoles(bytes,string,address,bool)\":{\"notice\":\"Authorize `setText(key)` permission to `account` for `toName`. Use `NameCoder.encode(\\\"\\\")` for any name.\"},\"canUpgradeFrom(address)\":{\"notice\":\"Declares this implementation as an eligible verifiable proxy upgrade target.\"},\"clearRecords(bytes32)\":{\"notice\":\"Clear all records for `node`.\"},\"contenthash(bytes32)\":{\"notice\":\"Returns the contenthash associated with an ENS node.\"},\"data(bytes32,string)\":{\"notice\":\"For a specific `node`, get the data associated with the key, `key`.\"},\"getAlias(bytes)\":{\"notice\":\"Determine which name is queried when `fromName` is resolved.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAddr(bytes32,uint256)\":{\"notice\":\"Determine if an addresss is stored for the coin type of the associated ENS node.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"initialize(address,uint256)\":{\"notice\":\"Initialize the contract.\"},\"interfaceImplementer(bytes32,bytes4)\":{\"notice\":\"Returns the address of a contract that implements the specified interface for this name. If an implementer has not been set for this interfaceID and name, the resolver will query the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that contract implements EIP165 and returns `true` for the specified interfaceID, its address will be returned.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"multicall(bytes[])\":{\"notice\":\"Perform multiple write operations.\"},\"multicallWithNodeCheck(bytes32,bytes[])\":{\"notice\":\"Same as `multicall()`.\"},\"name(bytes32)\":{\"notice\":\"Returns the name associated with an ENS node, for reverse records. Defined in EIP181.\"},\"pubkey(bytes32)\":{\"notice\":\"Returns the SECP256k1 public key associated with an ENS node. Defined in EIP 619.\"},\"recordVersions(bytes32)\":{\"notice\":\"Get the current version.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"setABI(bytes32,uint256,bytes)\":{\"notice\":\"Set ABI data of the associated ENS node.\"},\"setAddr(bytes32,address)\":{\"notice\":\"Set Ethereum mainnet address of the associated ENS node. `address(0)` is stored as `new bytes(20)`.\"},\"setAddr(bytes32,uint256,bytes)\":{\"notice\":\"Set the address for `coinType` of the associated ENS node. Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes.\"},\"setAlias(bytes,bytes)\":{\"notice\":\"Create an alias from `fromName` to `toName`.\"},\"setContenthash(bytes32,bytes)\":{\"notice\":\"Set the contenthash of the associated ENS node.\"},\"setData(bytes32,string,bytes)\":{\"notice\":\"Set the data for `key` of the associated ENS node.\"},\"setInterface(bytes32,bytes4,address)\":{\"notice\":\"Set an interface of the associated ENS node.\"},\"setName(bytes32,string)\":{\"notice\":\"Set the name of the associated ENS node.\"},\"setPubkey(bytes32,bytes32,bytes32)\":{\"notice\":\"Set the SECP256k1 public key associated with an ENS node.\"},\"setText(bytes32,string,string)\":{\"notice\":\"Set the text for `key` of the associated ENS node.\"},\"supportsFeature(bytes4)\":{\"notice\":\"Check if a feature is supported.\"},\"text(bytes32,string)\":{\"notice\":\"Returns the text data associated with an ENS node and key.\"}},\"notice\":\"A resolver that supports many profiles, multiple names, internal aliasing, and fine-grained permissions. Supported profiles and standards: - ENSIP-1 / EIP-137: addr() - ENSIP-3 / EIP-181: name() - ENSIP-4 / EIP-205: ABI() - EIP-619: pubkey() - ENSIP-5 / EIP-634: text(key) - ENSIP-7 / EIP-1577: contenthash() - ENSIP-8: interfaceImplementer() - ENSIP-9 / EIP-2304: addr(coinType) - ENSIP-19: addr(default) - ENSIP-24: data(key) - IERC7996: supportsFeature() - IVersionableResolver: version() - IHasAddrResolver: hasAddr() Internal Aliasing: * Resolved names find the longest match and rewrite the suffix. * Successful matches recursively check for additional aliasing. * `bytes32 node` in calldata is updated accordingly. * Cycles of length 1 apply once. * Cycles of length 2+ result in OOG. eg. `setAlias(\\\"a.eth\\\", \\\"b.eth\\\")` * `getAlias(\\\"a.eth\\\") => \\\"b.eth\\\"` * `getAlias(\\\"[sub].a.eth\\\") => \\\"[sub].b.eth\\\"` * `getAlias(\\\"[x.y].a.eth\\\") => \\\"[x.y].b.eth\\\"` * `getAlias(\\\"abc.eth\\\") => \\\"\\\"` Fine-grained Permissions: * `setText(key)` can be permissioned with `authorizeTextRoles()` - caller requires `ROLE_SET_TEXT_ADMIN` on `resource(, 0)` - `ROLE_SET_TEXT` is authorized on `resource(, )` * `setData(key)` can be permissioned with `authorizeDataRoles()` - caller requires `ROLE_SET_DATA_ADMIN` on `resource(, 0)` - `ROLE_SET_DATA` is authorized on `resource(, )` * `setAddr(coinType)` can be permissioned with `authorizeAddrRoles()` - caller requires `ROLE_SET_ADDR_ADMIN` on `resource(, 0)` - `ROLE_SET_ADDR` is authorized on `resource(, )` Setters with `node` check (4) EAC resources: Parts Resources +-----------------------------+------------------------------+ | Any (*) | Specific (1) | +--------------+-----------------------------+------------------------------+ | Any (*) | resource(0, 0) | resource(0, ) | Names |--------------+-----------------------------+------------------------------+ | Specific (1) | resource(, 0) | resource(, ) | +--------------+-----------------------------+------------------------------+\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/resolver/PermissionedResolver.sol\":\"PermissionedResolver\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverFeatures.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary ResolverFeatures {\\n /// @notice Implements `resolve(multicall([...]))`.\\n /// @dev Feature: `0x96b62db8`\\n bytes4 constant RESOLVE_MULTICALL =\\n bytes4(keccak256(\\\"eth.ens.resolver.extended.multicall\\\"));\\n\\n /// @notice Returns the same records independent of name or node.\\n /// @dev Feature: `0x86fb8da8`\\n bytes4 constant SINGULAR = bytes4(keccak256(\\\"eth.ens.resolver.singular\\\"));\\n}\\n\",\"keccak256\":\"0x87d131fcbdd7951a17b0a94f7f02470ec3f62c6004cf91c2d2acc54098373be6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IABIResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IABIResolver {\\n event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\\n\\n /// Returns the ABI associated with an ENS node.\\n /// Defined in EIP205.\\n /// @param node The ENS node to query\\n /// @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\\n /// @return contentType The content type of the return value\\n /// @return data The ABI data\\n function ABI(\\n bytes32 node,\\n uint256 contentTypes\\n ) external view returns (uint256, bytes memory);\\n}\\n\",\"keccak256\":\"0x3a7a763d7a4f0d196c4b628545b022b1d1d0e37baf84eaa6eecb1a57a1633cad\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the legacy (ETH-only) addr function.\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /// Returns the address associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated address.\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x91dd0c350698c505d6c7e4c919da9f981d4b8d7ad062e25073fa1f6af7cb79d1\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the new (multicoin) addr function.\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x8da5dd0fc1c5ab4f47e03c23126976a86d4b2dbeac161e70e3af9e2a13330cf0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IContentHashResolver {\\n event ContenthashChanged(bytes32 indexed node, bytes hash);\\n\\n /// Returns the contenthash associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function contenthash(bytes32 node) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0xaa978b1ee4c19e99c8aa409dc553e9b4c1bf9fe3c5bad718cd3589e6c9e6d121\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// @dev Interface selector: `0xecbfada3`\\ninterface IDataResolver {\\n /// @notice For a specific `node`, the data associated with a `key` has changed.\\n event DataChanged(\\n bytes32 indexed node, \\n string indexed indexedKey,\\n string key, \\n bytes indexed indexedData\\n );\\n \\n /// @notice For a specific `node`, get the data associated with the key, `key`.\\n /// @param node The node (namehash) for which data is being fetched.\\n /// @param key The key.\\n /// @return The associated arbitrary `bytes` data.\\n function data(\\n bytes32 node,\\n string calldata key\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x502a38d58d2047db3fa021897eda32bb6f4cde9746606e691e6acf25c396d88e\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IHasAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IHasAddressResolver {\\n /// @notice Determine if an addresss is stored for the coin type of the associated ENS node.\\n /// @param node The node to query.\\n /// @param coinType The coin type.\\n /// @return True if the associated address is not empty.\\n function hasAddr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbe13530b8cc027517c235e422326abd36bb1152dac8546713471be2a7335cf2b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IInterfaceResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IInterfaceResolver {\\n event InterfaceChanged(\\n bytes32 indexed node,\\n bytes4 indexed interfaceID,\\n address implementer\\n );\\n\\n /// Returns the address of a contract that implements the specified interface for this name.\\n /// If an implementer has not been set for this interfaceID and name, the resolver will query\\n /// the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\\n /// contract implements EIP165 and returns `true` for the specified interfaceID, its address\\n /// will be returned.\\n /// @param node The ENS node to query.\\n /// @param interfaceID The EIP 165 interface ID to check for.\\n /// @return The address that implements this interface, or 0 if the interface is unsupported.\\n function interfaceImplementer(\\n bytes32 node,\\n bytes4 interfaceID\\n ) external view returns (address);\\n}\\n\",\"keccak256\":\"0x510176a3fe60471775328756ab025d8bafda7063f52f218728ca559b8f61a357\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x3ab986332e0baad7aeb4b426aace3aa1c235be5efff8db4b6f1ce501bcdd9e68\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IPubkeyResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IPubkeyResolver {\\n event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\\n\\n /// Returns the SECP256k1 public key associated with an ENS node.\\n /// Defined in EIP 619.\\n /// @param node The ENS node to query\\n /// @return x The X coordinate of the curve point for the public key.\\n /// @return y The Y coordinate of the curve point for the public key.\\n function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);\\n}\\n\",\"keccak256\":\"0x1a21561b58ce17db400c015882ff07f12f9bd0df0e7b9305841799aada441820\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ITextResolver {\\n event TextChanged(\\n bytes32 indexed node,\\n string indexed indexedKey,\\n string key,\\n string value\\n );\\n\\n /// Returns the text data associated with an ENS node and key.\\n /// @param node The ENS node to query.\\n /// @param key The text data key to query.\\n /// @return The associated text data.\\n function text(\\n bytes32 node,\\n string calldata key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xe91c15697be2d20417cce3c58d4ecce34796986fdedc97be5b93a823be58e471\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IVersionableResolver {\\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\\n\\n function recordVersions(bytes32 node) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0xd0d09596f20c57bafb2ffa8521a8c57120e9af6c6b194f9c689d4da56f91a57c\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/ENSIP19.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {HexUtils} from \\\"../utils/HexUtils.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\n\\nuint32 constant CHAIN_ID_ETH = 1;\\n\\nuint256 constant COIN_TYPE_ETH = 60;\\nuint256 constant COIN_TYPE_DEFAULT = 1 << 31; // 0x8000_0000\\n\\nstring constant SLUG_ETH = \\\"addr\\\"; // <=> COIN_TYPE_ETH\\nstring constant SLUG_DEFAULT = \\\"default\\\"; // <=> COIN_TYPE_DEFAULT\\nstring constant TLD_REVERSE = \\\"reverse\\\";\\n\\n/// @dev Library for generating reverse names according to ENSIP-19.\\n/// https://docs.ens.domains/ensip/19\\nlibrary ENSIP19 {\\n /// @dev The supplied address was `0x`.\\n /// Error selector: `0x7138356f`\\n error EmptyAddress();\\n\\n /// @dev Extract Chain ID from `coinType`.\\n /// @param coinType The coin type.\\n /// @return The Chain ID or 0 if non-EVM Chain.\\n function chainFromCoinType(\\n uint256 coinType\\n ) internal pure returns (uint32) {\\n if (coinType == COIN_TYPE_ETH) return CHAIN_ID_ETH;\\n coinType ^= COIN_TYPE_DEFAULT;\\n return uint32(coinType < COIN_TYPE_DEFAULT ? coinType : 0);\\n }\\n\\n /// @dev Determine if Coin Type is for an EVM address.\\n /// @param coinType The coin type.\\n /// @return True if coin type represents an EVM address.\\n function isEVMCoinType(uint256 coinType) internal pure returns (bool) {\\n return coinType == COIN_TYPE_DEFAULT || chainFromCoinType(coinType) > 0;\\n }\\n\\n /// @dev Generate Reverse Name from Address + Coin Type.\\n /// Reverts `EmptyAddress` if `addressBytes` is `0x`.\\n /// @param addressBytes The input address.\\n /// @param coinType The coin type.\\n /// @return The ENS reverse name, eg. `1234abcd.addr.reverse`.\\n function reverseName(\\n bytes memory addressBytes,\\n uint256 coinType\\n ) internal pure returns (string memory) {\\n if (addressBytes.length == 0) {\\n revert EmptyAddress();\\n }\\n return\\n string(\\n abi.encodePacked(\\n HexUtils.bytesToHex(addressBytes),\\n bytes1(\\\".\\\"),\\n coinType == COIN_TYPE_ETH\\n ? SLUG_ETH\\n : coinType == COIN_TYPE_DEFAULT\\n ? SLUG_DEFAULT\\n : HexUtils.unpaddedUintToHex(coinType, true),\\n bytes1(\\\".\\\"),\\n TLD_REVERSE\\n )\\n );\\n }\\n\\n /// @dev Parse Reverse Name into Address + Coin Type.\\n /// Matches: `/^[0-9a-fA-F]+\\\\.([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @return addressBytes The address or empty if invalid.\\n /// @return coinType The coin type.\\n function parse(\\n bytes memory name\\n ) internal pure returns (bytes memory addressBytes, uint256 coinType) {\\n (, uint256 offset) = NameCoder.readLabel(name, 0);\\n bool valid;\\n (addressBytes, valid) = HexUtils.hexToBytes(name, 1, offset);\\n if (!valid || addressBytes.length == 0) return (\\\"\\\", 0); // addressBytes not 1+ hex\\n (valid, coinType) = parseNamespace(name, offset);\\n if (!valid) return (\\\"\\\", 0); // invalid namespace\\n }\\n\\n /// @dev Parse Reverse Namespace into Coin Type.\\n /// Matches: `/^([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset to begin parsing.\\n /// @return valid True if a valid reverse namespace.\\n /// @return coinType The coin type.\\n function parseNamespace(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bool valid, uint256 coinType) {\\n (bytes32 labelHash, uint256 offsetTLD) = NameCoder.readLabel(\\n name,\\n offset\\n );\\n if (labelHash == keccak256(bytes(SLUG_ETH))) {\\n coinType = COIN_TYPE_ETH;\\n } else if (labelHash == keccak256(bytes(SLUG_DEFAULT))) {\\n coinType = COIN_TYPE_DEFAULT;\\n } else if (labelHash == bytes32(0)) {\\n return (false, 0); // no slug\\n } else {\\n (bytes32 word, bool validHex) = HexUtils.hexStringToBytes32(\\n name,\\n 1 + offset,\\n offsetTLD\\n );\\n if (!validHex) return (false, 0); // invalid coinType or too long\\n coinType = uint256(word);\\n }\\n (labelHash, offset) = NameCoder.readLabel(name, offsetTLD);\\n if (labelHash != keccak256(bytes(TLD_REVERSE))) return (false, 0); // invalid tld\\n (labelHash, ) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) return (false, 0); // not tld\\n valid = true;\\n }\\n}\\n\",\"keccak256\":\"0xd1af09b014028de4c50489bd58ae424273180bb96d95353d8eefd14845f31824\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/IERC7996.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for expressing contract features not visible from the ABI.\\n/// @dev Interface selector: `0x582de3e7`\\ninterface IERC7996 {\\n /// @notice Check if a feature is supported.\\n /// @param featureId The feature identifier.\\n /// @return `true` if the feature is supported by the contract.\\n function supportsFeature(bytes4 featureId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf499a48e4e879ec7775f375d2cb5af047720ab6ae4b6f89a40a578c4e0f51631\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\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 * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\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 Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\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 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\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 _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\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 // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\\n *\\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\\n */\\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\\n return INITIALIZABLE_STORAGE;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n bytes32 slot = _initializableStorageSlot();\\n assembly {\\n $.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IERC1822Proxiable} from \\\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\\\";\\nimport {Initializable} from \\\"./Initializable.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 */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\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 _checkNotDelegated();\\n _;\\n }\\n\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\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 * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {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 onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: 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\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\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 ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\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 ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.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 the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\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 ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\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 * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, bytes memory returndata) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n _revert(returndata);\\n }\\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 or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) 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 assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IProxyAuthorization {\\n function canUpgradeFrom(address previousImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, _msgSender());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _roles[ROOT_RESOURCE][account] & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return\\n (_roles[ROOT_RESOURCE][account] | _roles[resource][account]) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (_hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (_hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function _hasZeroNybbles(uint256 value) private pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 hasZeroNybbles;\\n unchecked {\\n hasZeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return hasZeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xdf8918a909b0ab3bf17bc3a560fbdff6ca6e9502cbee54eb0923f1fae04d2fb1\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x9f29748b40665df976c08cdaf434b469dc73ef50e938c36be6773dc7b6a6f014\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {ContextUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Same as `HCAContext` but extends `ContextUpgradeable` for use in upgradeable contracts.\\nabstract contract HCAContextUpgradeable is ContextUpgradeable, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override(ContextUpgradeable) returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x15d9d4ec778be9be515c59b6ba99cf483ecf983f5453809df826d1c4a693c1fe\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/resolver/PermissionedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {IMulticallable} from \\\"@ens/contracts/resolvers/IMulticallable.sol\\\";\\nimport {IABIResolver} from \\\"@ens/contracts/resolvers/profiles/IABIResolver.sol\\\";\\nimport {IAddressResolver} from \\\"@ens/contracts/resolvers/profiles/IAddressResolver.sol\\\";\\nimport {IAddrResolver} from \\\"@ens/contracts/resolvers/profiles/IAddrResolver.sol\\\";\\nimport {IContentHashResolver} from \\\"@ens/contracts/resolvers/profiles/IContentHashResolver.sol\\\";\\nimport {IDataResolver} from \\\"@ens/contracts/resolvers/profiles/IDataResolver.sol\\\";\\nimport {IExtendedResolver} from \\\"@ens/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {IHasAddressResolver} from \\\"@ens/contracts/resolvers/profiles/IHasAddressResolver.sol\\\";\\nimport {IInterfaceResolver} from \\\"@ens/contracts/resolvers/profiles/IInterfaceResolver.sol\\\";\\nimport {INameResolver} from \\\"@ens/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport {IPubkeyResolver} from \\\"@ens/contracts/resolvers/profiles/IPubkeyResolver.sol\\\";\\nimport {ITextResolver} from \\\"@ens/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport {IVersionableResolver} from \\\"@ens/contracts/resolvers/profiles/IVersionableResolver.sol\\\";\\nimport {ResolverFeatures} from \\\"@ens/contracts/resolvers/ResolverFeatures.sol\\\";\\nimport {ENSIP19, COIN_TYPE_ETH, COIN_TYPE_DEFAULT} from \\\"@ens/contracts/utils/ENSIP19.sol\\\";\\nimport {IERC7996} from \\\"@ens/contracts/utils/IERC7996.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {IProxyAuthorization} from \\\"@ensdomains/verifiable-factory/IProxyAuthorization.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {ContextUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\\\";\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IEnhancedAccessControl} from \\\"../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\nimport {HCAContextUpgradeable} from \\\"../hca/HCAContextUpgradeable.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IPermissionedResolver} from \\\"./interfaces/IPermissionedResolver.sol\\\";\\nimport {PermissionedResolverLib} from \\\"./libraries/PermissionedResolverLib.sol\\\";\\nimport {ResolverProfileRewriterLib} from \\\"./libraries/ResolverProfileRewriterLib.sol\\\";\\n\\n/// @notice A resolver that supports many profiles, multiple names, internal aliasing, and fine-grained permissions.\\n///\\n/// Supported profiles and standards:\\n///\\n/// - ENSIP-1 / EIP-137: addr()\\n/// - ENSIP-3 / EIP-181: name()\\n/// - ENSIP-4 / EIP-205: ABI()\\n/// - EIP-619: pubkey()\\n/// - ENSIP-5 / EIP-634: text(key)\\n/// - ENSIP-7 / EIP-1577: contenthash()\\n/// - ENSIP-8: interfaceImplementer()\\n/// - ENSIP-9 / EIP-2304: addr(coinType)\\n/// - ENSIP-19: addr(default)\\n/// - ENSIP-24: data(key)\\n/// - IERC7996: supportsFeature()\\n/// - IVersionableResolver: version()\\n/// - IHasAddrResolver: hasAddr()\\n///\\n/// Internal Aliasing:\\n///\\n/// * Resolved names find the longest match and rewrite the suffix.\\n/// * Successful matches recursively check for additional aliasing.\\n/// * `bytes32 node` in calldata is updated accordingly.\\n/// * Cycles of length 1 apply once.\\n/// * Cycles of length 2+ result in OOG.\\n///\\n/// eg. `setAlias(\\\"a.eth\\\", \\\"b.eth\\\")`\\n/// * `getAlias(\\\"a.eth\\\") => \\\"b.eth\\\"`\\n/// * `getAlias(\\\"[sub].a.eth\\\") => \\\"[sub].b.eth\\\"`\\n/// * `getAlias(\\\"[x.y].a.eth\\\") => \\\"[x.y].b.eth\\\"`\\n/// * `getAlias(\\\"abc.eth\\\") => \\\"\\\"`\\n///\\n/// Fine-grained Permissions:\\n///\\n/// * `setText(key)` can be permissioned with `authorizeTextRoles()`\\n/// - caller requires `ROLE_SET_TEXT_ADMIN` on `resource(, 0)`\\n/// - `ROLE_SET_TEXT` is authorized on `resource(, )`\\n/// * `setData(key)` can be permissioned with `authorizeDataRoles()`\\n/// - caller requires `ROLE_SET_DATA_ADMIN` on `resource(, 0)`\\n/// - `ROLE_SET_DATA` is authorized on `resource(, )`\\n/// * `setAddr(coinType)` can be permissioned with `authorizeAddrRoles()`\\n/// - caller requires `ROLE_SET_ADDR_ADMIN` on `resource(, 0)`\\n/// - `ROLE_SET_ADDR` is authorized on `resource(, )`\\n///\\n/// Setters with `node` check (4) EAC resources:\\n/// Parts\\n/// Resources +-----------------------------+------------------------------+\\n/// | Any (*) | Specific (1) |\\n/// +--------------+-----------------------------+------------------------------+\\n/// | Any (*) | resource(0, 0) | resource(0, ) |\\n/// Names |--------------+-----------------------------+------------------------------+\\n/// | Specific (1) | resource(, 0) | resource(, ) |\\n/// +--------------+-----------------------------+------------------------------+\\n///\\ncontract PermissionedResolver is\\n IPermissionedResolver,\\n HCAContextUpgradeable,\\n UUPSUpgradeable,\\n EnhancedAccessControl,\\n IERC7996,\\n IMulticallable,\\n IABIResolver,\\n IAddrResolver,\\n IAddressResolver,\\n IContentHashResolver,\\n IDataResolver,\\n IHasAddressResolver,\\n IInterfaceResolver,\\n INameResolver,\\n IPubkeyResolver,\\n ITextResolver,\\n IVersionableResolver,\\n IProxyAuthorization,\\n IContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n struct Record {\\n bytes contenthash;\\n bytes32[2] pubkey;\\n string name;\\n mapping(uint256 coinType => bytes addressBytes) addresses;\\n mapping(string key => string value) texts;\\n mapping(string key => bytes value) datas;\\n mapping(uint256 contentType => bytes value) abis;\\n mapping(bytes4 interfaceId => address implementer) interfaces;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Aliases for names.\\n mapping(bytes32 node => bytes name) internal _aliases;\\n\\n /// @dev Versions for nodes.\\n mapping(bytes32 node => uint64 version) internal _versions;\\n\\n /// @dev Records for nodes.\\n mapping(bytes32 node => mapping(uint64 version => Record)) internal _records;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate an EAC resource with a name.\\n /// @param resource The EAC resource.\\n /// @param name The name.\\n event NamedResource(uint256 indexed resource, bytes name);\\n\\n /// @notice Associate an EAC resource with a name and specific `text(key)` record.\\n /// @param resource The EAC resource.\\n /// @param name The name.\\n /// @param keyHash The hash of the key.\\n /// @param key The key.\\n event NamedTextResource(\\n uint256 indexed resource,\\n bytes name,\\n bytes32 indexed keyHash,\\n string key\\n );\\n\\n /// @notice Associate an EAC resource with a name and specific `data(key)` record.\\n /// @param resource The EAC resource.\\n /// @param name The name.\\n /// @param keyHash The hash of the key.\\n /// @param key The key.\\n event NamedDataResource(\\n uint256 indexed resource,\\n bytes name,\\n bytes32 indexed keyHash,\\n string key\\n );\\n\\n /// @notice Associate an EAC resource with a name and specific `addr(coinType)` record.\\n /// @param resource The EAC resource.\\n /// @param name The name.\\n /// @param coinType The coin type.\\n event NamedAddrResource(uint256 indexed resource, bytes name, uint256 indexed coinType);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n modifier onlyPartRoles(bytes32 node, bytes32 part, uint256 roleBitmap) {\\n address sender = _msgSender();\\n if (\\n part == bytes32(0) ||\\n (!hasRoles(PermissionedResolverLib.resource(node, part), roleBitmap, sender) &&\\n !hasRoles(PermissionedResolverLib.resource(0, part), roleBitmap, sender))\\n ) {\\n _checkRoles(PermissionedResolverLib.resource(node, 0), roleBitmap, sender); // reverts using \\\"widest\\\" resource\\n }\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory.\\n /// @param namer The implementation namer.\\n constructor(IHCAFactoryBasic hcaFactory, address namer) HCAEquivalence(hcaFactory) {\\n _grantRoles(\\n ROOT_RESOURCE,\\n PermissionedResolverLib.ROLE_CAN_NAME | PermissionedResolverLib.ROLE_CAN_NAME_ADMIN,\\n namer,\\n false\\n );\\n _disableInitializers();\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n type(IPermissionedResolver).interfaceId == interfaceId ||\\n type(IExtendedResolver).interfaceId == interfaceId ||\\n type(IERC7996).interfaceId == interfaceId ||\\n type(IMulticallable).interfaceId == interfaceId ||\\n type(IABIResolver).interfaceId == interfaceId ||\\n type(IAddrResolver).interfaceId == interfaceId ||\\n type(IAddressResolver).interfaceId == interfaceId ||\\n type(IContentHashResolver).interfaceId == interfaceId ||\\n type(IDataResolver).interfaceId == interfaceId ||\\n type(IHasAddressResolver).interfaceId == interfaceId ||\\n type(IInterfaceResolver).interfaceId == interfaceId ||\\n type(INameResolver).interfaceId == interfaceId ||\\n type(IPubkeyResolver).interfaceId == interfaceId ||\\n type(ITextResolver).interfaceId == interfaceId ||\\n type(IVersionableResolver).interfaceId == interfaceId ||\\n type(UUPSUpgradeable).interfaceId == interfaceId ||\\n type(IProxyAuthorization).interfaceId == interfaceId ||\\n type(IContractNamer).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /// @inheritdoc IERC7996\\n function supportsFeature(bytes4 feature) external pure returns (bool) {\\n return ResolverFeatures.RESOLVE_MULTICALL == feature;\\n }\\n\\n /// @inheritdoc IPermissionedResolver\\n function initialize(address admin, uint256 roleBitmap) external initializer {\\n if (admin == address(0)) {\\n revert InvalidOwner();\\n }\\n __UUPSUpgradeable_init();\\n _grantRoles(ROOT_RESOURCE, roleBitmap, admin, false);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Clear all records for `node`.\\n /// @param node The node to update.\\n function clearRecords(bytes32 node)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_CLEAR)\\n {\\n uint64 version = ++_versions[node];\\n emit VersionChanged(node, version);\\n }\\n\\n /// @inheritdoc IPermissionedResolver\\n function setAlias(bytes calldata fromName, bytes calldata toName)\\n external\\n onlyRootRoles(PermissionedResolverLib.ROLE_SET_ALIAS)\\n {\\n _aliases[NameCoder.namehash(fromName, 0)] = toName;\\n emit AliasChanged(fromName, toName, fromName, toName);\\n }\\n\\n /// @notice Authorize `roleBitmap` permissions to `account` for `toName`.\\n /// Use `NameCoder.encode(\\\"\\\")` for any name, which is equivalent to `grantRootRoles()`.\\n /// @param toName The name to authorize roles for.\\n /// @param roleBitmap The roles to authorize.\\n /// @param account The account to authorize roles to.\\n /// @param grant If `true`, grants, otherwise, revokes.\\n /// @return success Whether the roles were updated.\\n function authorizeNameRoles(\\n bytes calldata toName,\\n uint256 roleBitmap,\\n address account,\\n bool grant\\n )\\n external\\n returns (bool)\\n {\\n bytes32 node = NameCoder.namehash(toName, 0);\\n uint256 resource = PermissionedResolverLib.resource(node, 0);\\n if (grant) {\\n _checkCanGrantRoles(resource, roleBitmap, _msgSender());\\n if (resource != ROOT_RESOURCE && roleCount(resource) == 0) {\\n emit NamedResource(resource, toName);\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n } else {\\n _checkCanRevokeRoles(resource, roleBitmap, _msgSender());\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n }\\n\\n /// @notice Authorize `setText(key)` permission to `account` for `toName`.\\n /// Use `NameCoder.encode(\\\"\\\")` for any name.\\n /// @param toName The name to authorize roles for.\\n /// @param key The text key to authorize roles for.\\n /// @param account The account to authorize roles to.\\n /// @param grant If `true`, grants, otherwise, revokes.\\n /// @return `true` if the roles were updated.\\n function authorizeTextRoles(\\n bytes calldata toName,\\n string calldata key,\\n address account,\\n bool grant\\n )\\n external\\n returns (bool)\\n {\\n bytes32 node = NameCoder.namehash(toName, 0);\\n uint256 roleBit = PermissionedResolverLib.ROLE_SET_TEXT;\\n uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0));\\n uint256 partResource =\\n PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(key));\\n if (grant) {\\n _checkCanGrantRoles(nodeResource, roleBit, _msgSender());\\n if (roleCount(partResource) == 0) {\\n emit NamedTextResource(partResource, toName, keccak256(bytes(key)), key);\\n }\\n return _grantRoles(partResource, roleBit, account, true);\\n } else {\\n _checkCanRevokeRoles(nodeResource, roleBit, _msgSender());\\n return _revokeRoles(partResource, roleBit, account, true);\\n }\\n }\\n\\n /// @notice Authorize `setData(key)` permission to `account` for `toName`.\\n /// Use `NameCoder.encode(\\\"\\\")` for any name.\\n /// @param toName The name to authorize roles for.\\n /// @param key The data key to authorize roles for.\\n /// @param account The account to authorize roles to.\\n /// @param grant If `true`, grants, otherwise, revokes.\\n /// @return `true` if the roles were updated.\\n function authorizeDataRoles(\\n bytes calldata toName,\\n string calldata key,\\n address account,\\n bool grant\\n )\\n external\\n returns (bool)\\n {\\n bytes32 node = NameCoder.namehash(toName, 0);\\n uint256 roleBit = PermissionedResolverLib.ROLE_SET_DATA;\\n uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0));\\n uint256 partResource =\\n PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(key));\\n if (grant) {\\n _checkCanGrantRoles(nodeResource, roleBit, _msgSender());\\n if (roleCount(partResource) == 0) {\\n emit NamedDataResource(partResource, toName, keccak256(bytes(key)), key);\\n }\\n return _grantRoles(partResource, roleBit, account, true);\\n } else {\\n _checkCanRevokeRoles(nodeResource, roleBit, _msgSender());\\n return _revokeRoles(partResource, roleBit, account, true);\\n }\\n }\\n\\n /// @notice Authorize `setAddr(coinType)` permission to `account` for `toName`.\\n /// Use `NameCoder.encode(\\\"\\\")` for any name.\\n /// @param toName The name to authorize roles for.\\n /// @param coinType The coin type to authorize roles for.\\n /// @param account The account to authorize roles to.\\n /// @param grant If `true`, grants, otherwise, revokes.\\n /// @return updated `true` if the roles were updated.\\n function authorizeAddrRoles(bytes calldata toName, uint256 coinType, address account, bool grant)\\n external\\n returns (bool updated)\\n {\\n bytes32 node = NameCoder.namehash(toName, 0);\\n uint256 roleBit = PermissionedResolverLib.ROLE_SET_ADDR;\\n uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0));\\n uint256 partResource =\\n PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(coinType));\\n if (grant) {\\n _checkCanGrantRoles(nodeResource, roleBit, _msgSender());\\n if (roleCount(partResource) == 0) {\\n emit NamedAddrResource(partResource, toName, coinType);\\n }\\n return _grantRoles(partResource, roleBit, account, true);\\n } else {\\n _checkCanRevokeRoles(nodeResource, roleBit, _msgSender());\\n return _revokeRoles(partResource, roleBit, account, true);\\n }\\n }\\n\\n /// @notice Set ABI data of the associated ENS node.\\n /// @param node The node to update.\\n /// @param contentType The content type of the ABI.\\n /// @param value The ABI data.\\n function setABI(bytes32 node, uint256 contentType, bytes calldata value)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_ABI)\\n {\\n if (!_isPowerOf2(contentType)) {\\n revert InvalidContentType(contentType);\\n }\\n _record(node).abis[contentType] = value;\\n emit ABIChanged(node, contentType);\\n }\\n\\n /// @notice Set Ethereum mainnet address of the associated ENS node.\\n /// `address(0)` is stored as `new bytes(20)`.\\n /// @param node The node to update.\\n /// @param addr_ The mainnet address.\\n function setAddr(bytes32 node, address addr_) external {\\n setAddr(node, COIN_TYPE_ETH, abi.encodePacked(addr_));\\n }\\n\\n /// @notice Set the contenthash of the associated ENS node.\\n /// @param node The node to update.\\n /// @param hash The contenthash to set.\\n function setContenthash(bytes32 node, bytes calldata hash)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_CONTENTHASH)\\n {\\n _record(node).contenthash = hash;\\n emit ContenthashChanged(node, hash);\\n }\\n\\n /// @notice Set the data for `key` of the associated ENS node.\\n /// @param node The node to update.\\n /// @param key The data key.\\n /// @param value The data value.\\n function setData(bytes32 node, string calldata key, bytes calldata value)\\n external\\n onlyPartRoles(\\n node,\\n PermissionedResolverLib.partHash(key),\\n PermissionedResolverLib.ROLE_SET_DATA\\n )\\n {\\n _record(node).datas[key] = value;\\n emit DataChanged(node, key, key, value);\\n }\\n\\n /// @notice Set an interface of the associated ENS node.\\n /// @param node The node to update.\\n /// @param interfaceId The EIP-165 interface ID.\\n /// @param implementer The address of the contract that implements this interface for this node.\\n function setInterface(bytes32 node, bytes4 interfaceId, address implementer)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_INTERFACE)\\n {\\n _record(node).interfaces[interfaceId] = implementer;\\n emit InterfaceChanged(node, interfaceId, implementer);\\n }\\n\\n /// @notice Set the SECP256k1 public key associated with an ENS node.\\n /// @param node The node to update.\\n /// @param x The x coordinate of the public key.\\n /// @param y The y coordinate of the public key.\\n function setPubkey(bytes32 node, bytes32 x, bytes32 y)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_PUBKEY)\\n {\\n _record(node).pubkey = [x, y];\\n emit PubkeyChanged(node, x, y);\\n }\\n\\n /// @notice Set the name of the associated ENS node.\\n /// @param node The node to update.\\n /// @param primary The primary name.\\n function setName(bytes32 node, string calldata primary)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_NAME)\\n {\\n _record(node).name = primary;\\n emit NameChanged(node, primary);\\n }\\n\\n /// @notice Set the text for `key` of the associated ENS node.\\n /// @param node The node to update.\\n /// @param key The text key.\\n /// @param value The text value.\\n function setText(bytes32 node, string calldata key, string calldata value)\\n external\\n onlyPartRoles(\\n node,\\n PermissionedResolverLib.partHash(key),\\n PermissionedResolverLib.ROLE_SET_TEXT\\n )\\n {\\n _record(node).texts[key] = value;\\n emit TextChanged(node, key, key, value);\\n }\\n\\n /// @notice Same as `multicall()`.\\n /// @dev The node parameter is accepted for interface compatibility but is not used.\\n /// Permission checking is handled by individual function calls within the multicall.\\n /// @param {node} Ignored, for interface compatibility.\\n /// @param calls The calls to make.\\n /// @return results The results of the calls.\\n function multicallWithNodeCheck(\\n bytes32 /* node */,\\n bytes[] calldata calls\\n )\\n external\\n returns (bytes[] memory)\\n {\\n return multicall(calls);\\n }\\n\\n /// @inheritdoc IExtendedResolver\\n function resolve(bytes calldata fromName, bytes calldata fromData)\\n external\\n view\\n returns (bytes memory)\\n {\\n bytes memory toName = getAlias(fromName);\\n bytes memory toData =\\n ResolverProfileRewriterLib.replaceNode(\\n fromData,\\n NameCoder.namehash(toName.length == 0 ? fromName : toName, 0) // always rewrite node\\n );\\n if (bytes4(toData) == IMulticallable.multicall.selector) {\\n // note: cannot staticcall multicall() because it reverts with first error\\n assembly {\\n mstore(add(toData, 4), sub(mload(toData), 4))\\n toData := add(toData, 4) // drop selector\\n }\\n bytes[] memory m = abi.decode(toData, (bytes[]));\\n for (uint256 i; i < m.length; ++i) {\\n toData = m[i];\\n (, bytes memory v) = address(this).staticcall(toData);\\n if (v.length == 0) {\\n v = abi.encodeWithSelector(UnsupportedResolverProfile.selector, bytes4(toData));\\n }\\n m[i] = v;\\n }\\n return abi.encode(m);\\n } else {\\n (bool ok, bytes memory v) = address(this).staticcall(toData);\\n if (!ok) {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n } else if (v.length == 0) {\\n revert UnsupportedResolverProfile(bytes4(fromData));\\n }\\n return v;\\n }\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return hasRootRoles(PermissionedResolverLib.ROLE_CAN_NAME, namer);\\n }\\n\\n /// @notice Get the current version.\\n /// @param node The node to check.\\n /// @return version The current version.\\n function recordVersions(bytes32 node) external view returns (uint64) {\\n return _versions[node];\\n }\\n\\n /// @inheritdoc IABIResolver\\n function ABI(bytes32 node, uint256 contentTypes)\\n external\\n view\\n returns (uint256 contentType, bytes memory value)\\n {\\n Record storage r = _record(node);\\n for (contentType = 1; contentType > 0 && contentType <= contentTypes; contentType <<= 1) {\\n if ((contentType & contentTypes) != 0) {\\n value = r.abis[contentType];\\n if (value.length > 0) {\\n return (contentType, value);\\n }\\n }\\n }\\n return (0, \\\"\\\");\\n }\\n\\n /// @inheritdoc IHasAddressResolver\\n function hasAddr(bytes32 node, uint256 coinType) external view returns (bool) {\\n return _record(node).addresses[coinType].length > 0;\\n }\\n\\n /// @inheritdoc IContentHashResolver\\n function contenthash(bytes32 node) external view returns (bytes memory) {\\n return _record(node).contenthash;\\n }\\n\\n /// @inheritdoc IDataResolver\\n function data(bytes32 node, string calldata key) external view returns (bytes memory) {\\n return _record(node).datas[key];\\n }\\n\\n /// @inheritdoc IInterfaceResolver\\n function interfaceImplementer(bytes32 node, bytes4 interfaceId)\\n external\\n view\\n returns (address implementer)\\n {\\n implementer = _record(node).interfaces[interfaceId];\\n if (implementer == address(0)) {\\n address pointer = addr(node);\\n if (ERC165Checker.supportsInterface(pointer, interfaceId)) {\\n implementer = pointer;\\n }\\n }\\n }\\n\\n /// @inheritdoc INameResolver\\n function name(bytes32 node) external view returns (string memory) {\\n return _record(node).name;\\n }\\n\\n /// @inheritdoc IPubkeyResolver\\n function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y) {\\n Record storage r = _record(node);\\n x = r.pubkey[0];\\n y = r.pubkey[1];\\n }\\n\\n /// @inheritdoc ITextResolver\\n function text(bytes32 node, string calldata key) external view returns (string memory) {\\n return _record(node).texts[key];\\n }\\n\\n /// @notice Declares this implementation as an eligible verifiable proxy upgrade target.\\n /// @dev Upgrade authorization is still enforced by the current implementation during the UUPS\\n /// upgrade call.\\n /// @param {previousImplementation} Ignored.\\n /// @return allowed Always `true` for implementations in this resolver family.\\n function canUpgradeFrom(\\n address /* previousImplementation */\\n )\\n external\\n pure\\n virtual\\n override\\n returns (bool allowed)\\n {\\n return true;\\n }\\n\\n /// @notice Perform multiple write operations.\\n /// @dev Reverts with first error.\\n /// @param calls The calls to make.\\n /// @return results The results of the calls.\\n function multicall(bytes[] calldata calls) public returns (bytes[] memory results) {\\n results = new bytes[](calls.length);\\n for (uint256 i; i < calls.length; ++i) {\\n (bool ok, bytes memory v) = address(this).delegatecall(calls[i]);\\n if (!ok) {\\n assembly {\\n revert(add(v, 32), mload(v)) // propagate the first error\\n }\\n }\\n results[i] = v;\\n }\\n return results;\\n }\\n\\n /// @notice Set the address for `coinType` of the associated ENS node.\\n /// Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes.\\n /// @param node The node to update.\\n /// @param coinType The coin type.\\n /// @param addressBytes The encoded address.\\n function setAddr(bytes32 node, uint256 coinType, bytes memory addressBytes)\\n public\\n onlyPartRoles(\\n node,\\n PermissionedResolverLib.partHash(coinType),\\n PermissionedResolverLib.ROLE_SET_ADDR\\n )\\n {\\n if (\\n addressBytes.length != 0 && addressBytes.length != 20 && ENSIP19.isEVMCoinType(coinType)\\n ) {\\n revert InvalidEVMAddress(addressBytes);\\n }\\n _record(node).addresses[coinType] = addressBytes;\\n emit AddressChanged(node, coinType, addressBytes);\\n if (coinType == COIN_TYPE_ETH) {\\n emit AddrChanged(node, address(bytes20(addressBytes)));\\n }\\n }\\n\\n /// @inheritdoc IAddressResolver\\n function addr(bytes32 node, uint256 coinType) public view returns (bytes memory addressBytes) {\\n Record storage r = _record(node);\\n addressBytes = r.addresses[coinType];\\n if (addressBytes.length == 0 && ENSIP19.chainFromCoinType(coinType) > 0) {\\n addressBytes = r.addresses[COIN_TYPE_DEFAULT];\\n }\\n }\\n\\n /// @inheritdoc IAddrResolver\\n function addr(bytes32 node) public view returns (address payable) {\\n return payable(address(bytes20(addr(node, COIN_TYPE_ETH))));\\n }\\n\\n /// @inheritdoc IPermissionedResolver\\n function getAlias(bytes memory fromName) public view returns (bytes memory toName) {\\n bytes32 prev;\\n for (;;) {\\n bytes memory matchName;\\n (matchName, fromName) = _resolveAlias(fromName);\\n if (fromName.length == 0)\\n break; // no alias\\n bytes32 next = keccak256(matchName);\\n if (next == prev)\\n break; // same alias\\n toName = fromName;\\n prev = next;\\n }\\n }\\n\\n /// @notice Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead.\\n /// @param resource Ignored.\\n /// @param roleBitmap Ignored.\\n /// @param account Ignored.\\n /// @return success Ignored, always reverts.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n pure\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n\\n /// @notice Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead.\\n /// @param resource Ignored.\\n /// @param roleBitmap Ignored.\\n /// @param account Ignored.\\n /// @return success Ignored, always reverts.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n pure\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Allow `ROLE_UPGRADE` to upgrade.\\n function _authorizeUpgrade(address newImplementation)\\n internal\\n override\\n onlyRootRoles(PermissionedResolverLib.ROLE_UPGRADE)\\n {\\n //\\n }\\n\\n /// @dev HCA-compatible `_msgSender()`.\\n function _msgSender()\\n internal\\n view\\n virtual\\n override(HCAContext, HCAContextUpgradeable)\\n returns (address)\\n {\\n return HCAContextUpgradeable._msgSender();\\n }\\n\\n /// @dev Returns the original `msg.data`.\\n /// Needed to resolve Context/ContextUpgradable inheritance.\\n function _msgData()\\n internal\\n view\\n virtual\\n override(Context, ContextUpgradeable)\\n returns (bytes calldata)\\n {\\n return msg.data;\\n }\\n\\n /// @dev Returns 0.\\n /// Needed to resolve Context/ContextUpgradable inheritance.\\n function _contextSuffixLength()\\n internal\\n view\\n virtual\\n override(Context, ContextUpgradeable)\\n returns (uint256)\\n {\\n return 0;\\n }\\n\\n /// @dev Apply one round of aliasing.\\n /// @param fromName The source DNS-encoded name.\\n /// @return matchName The alias that matched.\\n /// @return toName The destination DNS-encoded name or empty if no match.\\n function _resolveAlias(bytes memory fromName)\\n internal\\n view\\n returns (bytes memory matchName, bytes memory toName)\\n {\\n uint256 offset;\\n while (offset < fromName.length) {\\n matchName = _aliases[NameCoder.namehash(fromName, offset)];\\n if (matchName.length > 0) {\\n if (offset > 0) {\\n // rewrite prefix: [x.y].{fromName[offset:]} => [x.y].{matchName}\\n toName = new bytes(offset + matchName.length);\\n assembly {\\n mcopy(add(toName, 32), add(fromName, 32), offset) // copy prefix\\n mcopy(\\n add(toName, add(32, offset)),\\n add(matchName, 32),\\n mload(matchName)\\n ) // copy suffix\\n }\\n } else {\\n toName = matchName;\\n }\\n break;\\n }\\n (, offset) = NameCoder.nextLabel(fromName, offset);\\n }\\n }\\n\\n /// @dev Access record storage pointer.\\n function _record(bytes32 node) internal view returns (Record storage) {\\n return _records[node][_versions[node]];\\n }\\n\\n /// @dev Returns true if `x` has a single bit set.\\n function _isPowerOf2(uint256 x) internal pure returns (bool) {\\n return x > 0 && (x - 1) & x == 0;\\n }\\n}\\n\",\"keccak256\":\"0x2c84aa5c461233bcb421cd577bb99daa0a80b8e03b0931101362dfb4c2ff033a\",\"license\":\"MIT\"},\"project/src/resolver/interfaces/IPermissionedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {IExtendedResolver} from \\\"@ens/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\n\\n/// @dev Interface selector: `0x2c7442c9`\\ninterface IPermissionedResolver is IExtendedResolver, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice An alias was changed.\\n /// @param indexedFromName The source DNS-encoded name. (indexed bytes, hashed)\\n /// @param indexedToName The destination DNS-encoded name. (indexed bytes, hashed)\\n /// @param fromName The source DNS-encoded name.\\n /// @param toName The destination DNS-encoded name.\\n event AliasChanged(\\n bytes indexed indexedFromName,\\n bytes indexed indexedToName,\\n bytes fromName,\\n bytes toName\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The resolver profile cannot be answered.\\n /// @dev Error selector: `0x7b1c461b`\\n error UnsupportedResolverProfile(bytes4 selector);\\n\\n /// @notice The address could not be converted to `address`.\\n /// @dev Error selector: `0x8d666f60`\\n error InvalidEVMAddress(bytes addressBytes);\\n\\n /// @notice The coin type is not a power of 2.\\n /// @dev Error selector: `0x5742bb26`\\n error InvalidContentType(uint256 contentType);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Initialize the contract.\\n /// @param admin The resolver owner.\\n /// @param roleBitmap The roles granted to `admin`.\\n function initialize(address admin, uint256 roleBitmap) external;\\n\\n /// @notice Create an alias from `fromName` to `toName`.\\n /// @param fromName The source DNS-encoded name.\\n /// @param toName The destination DNS-encoded name.\\n function setAlias(bytes calldata fromName, bytes calldata toName) external;\\n\\n /// @notice Determine which name is queried when `fromName` is resolved.\\n /// @param fromName The source DNS-encoded name.\\n /// @return toName The destination DNS-encoded name or empty if not aliased.\\n function getAlias(bytes memory fromName) external view returns (bytes memory toName);\\n}\\n\",\"keccak256\":\"0xe607376967e630e80ffcad4fe0217c6efe531b6f76045aad2739ba4817acf868\",\"license\":\"MIT\"},\"project/src/resolver/libraries/PermissionedResolverLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Roles for PermissionedResolver.\\nlibrary PermissionedResolverLib {\\n /// @dev Nybble 0: authorizes setting address records. Root or name.\\n uint256 internal constant ROLE_SET_ADDR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting ROLE_SET_ADDR.\\n uint256 internal constant ROLE_SET_ADDR_ADMIN = ROLE_SET_ADDR << 128;\\n\\n /// @dev Nybble 1: authorizes setting text records. Root or name.\\n uint256 internal constant ROLE_SET_TEXT = 1 << 4;\\n /// @dev Nybble 33: authorizes setting ROLE_SET_TEXT.\\n uint256 internal constant ROLE_SET_TEXT_ADMIN = ROLE_SET_TEXT << 128;\\n\\n /// @dev Nybble 2: authorizes setting the contenthash record. Root or name.\\n uint256 internal constant ROLE_SET_CONTENTHASH = 1 << 8;\\n /// @dev Nybble 34: authorizes setting ROLE_SET_CONTENTHASH.\\n uint256 internal constant ROLE_SET_CONTENTHASH_ADMIN = ROLE_SET_CONTENTHASH << 128;\\n\\n /// @dev Nybble 3: authorizes setting the public key record. Root or name.\\n uint256 internal constant ROLE_SET_PUBKEY = 1 << 12;\\n /// @dev Nybble 35: authorizes setting ROLE_SET_PUBKEY.\\n uint256 internal constant ROLE_SET_PUBKEY_ADMIN = ROLE_SET_PUBKEY << 128;\\n\\n /// @dev Nybble 4: authorizes setting ABI records. Root or name.\\n uint256 internal constant ROLE_SET_ABI = 1 << 16;\\n /// @dev Nybble 36: authorizes setting ROLE_SET_ABI.\\n uint256 internal constant ROLE_SET_ABI_ADMIN = ROLE_SET_ABI << 128;\\n\\n /// @dev Nybble 5: authorizes setting interface implementer records. Root or name.\\n uint256 internal constant ROLE_SET_INTERFACE = 1 << 20;\\n /// @dev Nybble 37: authorizes setting ROLE_SET_INTERFACE.\\n uint256 internal constant ROLE_SET_INTERFACE_ADMIN = ROLE_SET_INTERFACE << 128;\\n\\n /// @dev Nybble 6: authorizes setting the reverse name record. Root or name.\\n uint256 internal constant ROLE_SET_NAME = 1 << 24;\\n /// @dev Nybble 38: authorizes setting ROLE_SET_NAME.\\n uint256 internal constant ROLE_SET_NAME_ADMIN = ROLE_SET_NAME << 128;\\n\\n /// @dev Nybble 7: authorizes setting alias targets for name rewriting. Root-only.\\n uint256 internal constant ROLE_SET_ALIAS = 1 << 28;\\n /// @dev Nybble 39: authorizes setting ROLE_SET_ALIAS.\\n uint256 internal constant ROLE_SET_ALIAS_ADMIN = ROLE_SET_ALIAS << 128;\\n\\n /// @dev Nybble 8: authorizes clearing (version-bumping) all records for a node. Root or name.\\n uint256 internal constant ROLE_CLEAR = 1 << 32;\\n /// @dev Nybble 40: authorizes setting ROLE_CLEAR.\\n uint256 internal constant ROLE_CLEAR_ADMIN = ROLE_CLEAR << 128;\\n\\n /// @dev Nybble 9: authorizes setting data records. Root or name.\\n uint256 internal constant ROLE_SET_DATA = 1 << 36;\\n /// @dev Nybble 41: authorizes setting ROLE_SET_DATA.\\n uint256 internal constant ROLE_SET_DATA_ADMIN = ROLE_SET_DATA << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting ROLE_UPGRADE.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n\\n /// @dev Computes `keccak256(node, part)` to create a unique EAC resource ID scoped to both\\n /// a name and a record type. Enables fine-grained per-record permissions.\\n /// @param node The ENS namehash of the name.\\n /// @param part The record-type identifier (e.g. from `addrPart` or `textPart`).\\n /// @return ret The computed resource ID.\\n function resource(bytes32 node, bytes32 part) internal pure returns (uint256 ret) {\\n if (node != bytes32(0) || part != bytes32(0)) {\\n assembly {\\n mstore(0, node)\\n mstore(32, part)\\n ret := keccak256(0, 64)\\n }\\n // Equivalent: return uint256(keccak256(abi.encode(node, part)));\\n }\\n }\\n\\n /// @dev Computes a record-type identifier for uint256-keyed records.\\n /// @param x The uint256 value.\\n /// @return part The computed record-type identifier.\\n function partHash(uint256 x) internal pure returns (bytes32 part) {\\n assembly {\\n mstore(0, x)\\n part := keccak256(0, 32)\\n }\\n }\\n\\n /// @dev Computes a record-type identifier for string-keyed records.\\n /// @param x The string value.\\n /// @return part The computed record-type identifier.\\n function partHash(string memory x) internal pure returns (bytes32) {\\n return keccak256(bytes(x));\\n }\\n}\\n\",\"keccak256\":\"0xd0a807cfe94700e67bd26d5975e644f112299d457a102a8d0176af741b7f09f4\",\"license\":\"MIT\"},\"project/src/resolver/libraries/ResolverProfileRewriterLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Rewrites the `bytes32 node` parameter in resolver calldata. Resolver functions follow\\n/// the convention `func(bytes32 node, ...)`, with the node at calldata offset 4. This library\\n/// replaces that node in a memory copy of the calldata, recursively handling `multicall(bytes[])`\\n/// (selector `0xac9650d8`) to rewrite the node in every nested call at arbitrary depth.\\n///\\n/// Used by `PermissionedResolver` when resolving aliased names: after determining the alias target,\\n/// the original calldata must be updated with the new node before forwarding to the actual\\n/// resolver logic.\\n///\\nlibrary ResolverProfileRewriterLib {\\n /// @dev Replace the node in the calldata with a new node.\\n /// Supports `multicall()` to arbitrary depth.\\n /// @param call The calldata for a resolver.\\n /// @param newNode The replacement node.\\n /// @return copy A copy of the calldata with node replaced.\\n function replaceNode(bytes calldata call, bytes32 newNode)\\n internal\\n pure\\n returns (bytes memory copy)\\n {\\n // 0xac9650d8 // selector\\n // 0000000000000000000000000000000000000000000000000000000000000020 // jump\\n // 0000000000000000000000000000000000000000000000000000000000000002 // .length @ jump\\n // 0000000000000000000000000000000000000000000000000000000000000040 // jump[0]\\n // 00000000000000000000000000000000000000000000000000000000000000a0 // jump[1]\\n // 0000000000000000000000000000000000000000000000000000000000000024 // [0].length @ jump[0]\\n // ...\\n // 0000000000000000000000000000000000000000000000000000000000000024 // [1].length @ jump[1]\\n // ...\\n copy = call; // make a copy\\n assembly {\\n function replace(ptr, bound, node) {\\n ptr := add(ptr, 36) // skip length + selector\\n switch shr(224, mload(sub(ptr, 4))) // read selector\\n case 0xac9650d8 {\\n // multicall(bytes[])\\n let lower := ptr\\n ptr := add(ptr, mload(ptr)) // follow jump\\n if lt(ptr, lower) {\\n leave // underflow\\n }\\n let size := shl(5, mload(ptr)) // read word count as size\\n // prettier-ignore\\n for { } size { size := sub(size, 32) } { // backwards\\n lower := add(ptr, 32)\\n let p := add(lower, mload(add(ptr, size))) // local ptr\\n if lt(p, lower) {\\n continue // underflow\\n }\\n let b := add(p, mload(p)) // local bound w/room for 1 word\\n if lt(bound, b) {\\n b := bound // global bound is smaller\\n }\\n replace(p, b, node)\\n }\\n }\\n default {\\n // only bound checks on write\\n if lt(bound, ptr) {\\n leave\\n }\\n mstore(ptr, node) // replace node\\n }\\n }\\n replace(copy, add(copy, mload(copy)), newNode) // bound w/room for 1 word\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdb4abf724531e5ffa50dcb4ed44954beba4dd96949513aa594f0b02bd5d983ea\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 55601, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_roles", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 55606, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_roleCount", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 55611, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 69553, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_aliases", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_bytes32,t_bytes_storage)" + }, + { + "astId": 69558, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_versions", + "offset": 0, + "slot": "259", + "type": "t_mapping(t_bytes32,t_uint64)" + }, + { + "astId": 69566, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_records", + "offset": 0, + "slot": "260", + "type": "t_mapping(t_bytes32,t_mapping(t_uint64,t_struct(Record)69548_storage))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)2_storage": { + "base": "t_bytes32", + "encoding": "inplace", + "label": "bytes32[2]", + "numberOfBytes": "64" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_bytes32,t_mapping(t_uint64,t_struct(Record)69548_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(uint64 => struct PermissionedResolver.Record))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint64,t_struct(Record)69548_storage)" + }, + "t_mapping(t_bytes32,t_uint64)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint64)", + "numberOfBytes": "32", + "value": "t_uint64" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_string_memory_ptr,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_string_memory_ptr,t_string_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_uint256,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint64,t_struct(Record)69548_storage)": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => struct PermissionedResolver.Record)", + "numberOfBytes": "32", + "value": "t_struct(Record)69548_storage" + }, + "t_string_memory_ptr": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Record)69548_storage": { + "encoding": "inplace", + "label": "struct PermissionedResolver.Record", + "members": [ + { + "astId": 69521, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "contenthash", + "offset": 0, + "slot": "0", + "type": "t_bytes_storage" + }, + { + "astId": 69525, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "pubkey", + "offset": 0, + "slot": "1", + "type": "t_array(t_bytes32)2_storage" + }, + { + "astId": 69527, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 69531, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "addresses", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint256,t_bytes_storage)" + }, + { + "astId": 69535, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "texts", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_string_memory_ptr,t_string_storage)" + }, + { + "astId": 69539, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "datas", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_string_memory_ptr,t_bytes_storage)" + }, + { + "astId": 69543, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "abis", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint256,t_bytes_storage)" + }, + { + "astId": 69547, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "interfaces", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_bytes4,t_address)" + } + ], + "numberOfBytes": "288" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "InvalidContentType(uint256)": [ + { + "notice": "The coin type is not a power of 2." + } + ], + "InvalidEVMAddress(bytes)": [ + { + "notice": "The address could not be converted to `address`." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "UnsupportedResolverProfile(bytes4)": [ + { + "notice": "The resolver profile cannot be answered." + } + ] + }, + "events": { + "AliasChanged(bytes,bytes,bytes,bytes)": { + "notice": "An alias was changed." + }, + "DataChanged(bytes32,string,string,bytes)": { + "notice": "For a specific `node`, the data associated with a `key` has changed." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "NamedAddrResource(uint256,bytes,uint256)": { + "notice": "Associate an EAC resource with a name and specific `addr(coinType)` record." + }, + "NamedDataResource(uint256,bytes,bytes32,string)": { + "notice": "Associate an EAC resource with a name and specific `data(key)` record." + }, + "NamedResource(uint256,bytes)": { + "notice": "Associate an EAC resource with a name." + }, + "NamedTextResource(uint256,bytes,bytes32,string)": { + "notice": "Associate an EAC resource with a name and specific `text(key)` record." + } + }, + "kind": "user", + "methods": { + "ABI(bytes32,uint256)": { + "notice": "Returns the ABI associated with an ENS node. Defined in EIP205." + }, + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "addr(bytes32)": { + "notice": "Returns the address associated with an ENS node." + }, + "authorizeAddrRoles(bytes,uint256,address,bool)": { + "notice": "Authorize `setAddr(coinType)` permission to `account` for `toName`. Use `NameCoder.encode(\"\")` for any name." + }, + "authorizeDataRoles(bytes,string,address,bool)": { + "notice": "Authorize `setData(key)` permission to `account` for `toName`. Use `NameCoder.encode(\"\")` for any name." + }, + "authorizeNameRoles(bytes,uint256,address,bool)": { + "notice": "Authorize `roleBitmap` permissions to `account` for `toName`. Use `NameCoder.encode(\"\")` for any name, which is equivalent to `grantRootRoles()`." + }, + "authorizeTextRoles(bytes,string,address,bool)": { + "notice": "Authorize `setText(key)` permission to `account` for `toName`. Use `NameCoder.encode(\"\")` for any name." + }, + "canUpgradeFrom(address)": { + "notice": "Declares this implementation as an eligible verifiable proxy upgrade target." + }, + "clearRecords(bytes32)": { + "notice": "Clear all records for `node`." + }, + "contenthash(bytes32)": { + "notice": "Returns the contenthash associated with an ENS node." + }, + "data(bytes32,string)": { + "notice": "For a specific `node`, get the data associated with the key, `key`." + }, + "getAlias(bytes)": { + "notice": "Determine which name is queried when `fromName` is resolved." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAddr(bytes32,uint256)": { + "notice": "Determine if an addresss is stored for the coin type of the associated ENS node." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "initialize(address,uint256)": { + "notice": "Initialize the contract." + }, + "interfaceImplementer(bytes32,bytes4)": { + "notice": "Returns the address of a contract that implements the specified interface for this name. If an implementer has not been set for this interfaceID and name, the resolver will query the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that contract implements EIP165 and returns `true` for the specified interfaceID, its address will be returned." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "multicall(bytes[])": { + "notice": "Perform multiple write operations." + }, + "multicallWithNodeCheck(bytes32,bytes[])": { + "notice": "Same as `multicall()`." + }, + "name(bytes32)": { + "notice": "Returns the name associated with an ENS node, for reverse records. Defined in EIP181." + }, + "pubkey(bytes32)": { + "notice": "Returns the SECP256k1 public key associated with an ENS node. Defined in EIP 619." + }, + "recordVersions(bytes32)": { + "notice": "Get the current version." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "setABI(bytes32,uint256,bytes)": { + "notice": "Set ABI data of the associated ENS node." + }, + "setAddr(bytes32,address)": { + "notice": "Set Ethereum mainnet address of the associated ENS node. `address(0)` is stored as `new bytes(20)`." + }, + "setAddr(bytes32,uint256,bytes)": { + "notice": "Set the address for `coinType` of the associated ENS node. Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes." + }, + "setAlias(bytes,bytes)": { + "notice": "Create an alias from `fromName` to `toName`." + }, + "setContenthash(bytes32,bytes)": { + "notice": "Set the contenthash of the associated ENS node." + }, + "setData(bytes32,string,bytes)": { + "notice": "Set the data for `key` of the associated ENS node." + }, + "setInterface(bytes32,bytes4,address)": { + "notice": "Set an interface of the associated ENS node." + }, + "setName(bytes32,string)": { + "notice": "Set the name of the associated ENS node." + }, + "setPubkey(bytes32,bytes32,bytes32)": { + "notice": "Set the SECP256k1 public key associated with an ENS node." + }, + "setText(bytes32,string,string)": { + "notice": "Set the text for `key` of the associated ENS node." + }, + "supportsFeature(bytes4)": { + "notice": "Check if a feature is supported." + }, + "text(bytes32,string)": { + "notice": "Returns the text data associated with an ENS node and key." + } + }, + "notice": "A resolver that supports many profiles, multiple names, internal aliasing, and fine-grained permissions. Supported profiles and standards: - ENSIP-1 / EIP-137: addr() - ENSIP-3 / EIP-181: name() - ENSIP-4 / EIP-205: ABI() - EIP-619: pubkey() - ENSIP-5 / EIP-634: text(key) - ENSIP-7 / EIP-1577: contenthash() - ENSIP-8: interfaceImplementer() - ENSIP-9 / EIP-2304: addr(coinType) - ENSIP-19: addr(default) - ENSIP-24: data(key) - IERC7996: supportsFeature() - IVersionableResolver: version() - IHasAddrResolver: hasAddr() Internal Aliasing: * Resolved names find the longest match and rewrite the suffix. * Successful matches recursively check for additional aliasing. * `bytes32 node` in calldata is updated accordingly. * Cycles of length 1 apply once. * Cycles of length 2+ result in OOG. eg. `setAlias(\"a.eth\", \"b.eth\")` * `getAlias(\"a.eth\") => \"b.eth\"` * `getAlias(\"[sub].a.eth\") => \"[sub].b.eth\"` * `getAlias(\"[x.y].a.eth\") => \"[x.y].b.eth\"` * `getAlias(\"abc.eth\") => \"\"` Fine-grained Permissions: * `setText(key)` can be permissioned with `authorizeTextRoles()` - caller requires `ROLE_SET_TEXT_ADMIN` on `resource(, 0)` - `ROLE_SET_TEXT` is authorized on `resource(, )` * `setData(key)` can be permissioned with `authorizeDataRoles()` - caller requires `ROLE_SET_DATA_ADMIN` on `resource(, 0)` - `ROLE_SET_DATA` is authorized on `resource(, )` * `setAddr(coinType)` can be permissioned with `authorizeAddrRoles()` - caller requires `ROLE_SET_ADDR_ADMIN` on `resource(, 0)` - `ROLE_SET_ADDR` is authorized on `resource(, )` Setters with `node` check (4) EAC resources: Parts Resources +-----------------------------+------------------------------+ | Any (*) | Specific (1) | +--------------+-----------------------------+------------------------------+ | Any (*) | resource(0, 0) | resource(0, ) | Names |--------------+-----------------------------+------------------------------+ | Specific (1) | resource(, 0) | resource(, ) | +--------------+-----------------------------+------------------------------+", + "version": 1 + }, + "argsData": "0x000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf943000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80", + "transaction": { + "hash": "0xbdd45a14b50a1738a80d7424fe385bdc8efd1c32fab9c798f1ac2067ceef0da8", + "nonce": "0x1e8f", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x65501b23c4f71d185afc670b3e2e62a2fd38cf4c35be132cd43b77564bdbf219", + "blockNumber": "0xa6a804", + "transactionIndex": "0x42" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/PublicResolverSet.json b/contracts/deployments/sepolia-official-v1-20260525-r2/PublicResolverSet.json new file mode 100644 index 000000000..0b60dc43f --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/PublicResolverSet.json @@ -0,0 +1,956 @@ +{ + "address": "0xfef98bae02b882b00efa02f3d7b379bee6cda86b", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ApprovalChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "includes", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "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" + } + ], + "contractName": "PermissionedAddressSet", + "sourceName": "src/utils/PermissionedAddressSet.sol", + "bytecode": "0x60a060405234801561000f575f5ffd5b506040516112a43803806112a483398101604081905261002e91610305565b6001600160a01b0382166080526100585f7011000000000000000000000000000000118382610060565b50505061037d565b5f835f0361006f57505f610153565b6100788461015b565b6001600160a01b03831661009f5760405163761fe2c960e11b815260040160405180910390fd5b5f858152602081815260408083206001600160a01b038716845290915290205484811780821461014d575f878152602081815260408083206001600160a01b03891684529091529020819055811986166100fb888260016101a7565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050610153565b5f925050505b949350505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156101a457604051630153d96960e51b8152600481018290526024015b60405180910390fd5b50565b5f6101b1836102d7565b90508115610247575f848152600160205260409020546101f79082161980195f5160206112845f395f51905f5291909101165f5160206112645f395f51905f5216151590565b1561021f57604051631f22ca6960e31b8152600481018590526024810184905260440161019b565b5f848152600160205260408120805485929061023c908490610351565b909155506102d19050565b5f84815260016020526040902054610286901982161980195f5160206112845f395f51905f5291909101165f5160206112645f395f51905f5216151590565b156102ae57604051631f80c19b60e01b8152600481018590526024810184905260440161019b565b5f84815260016020526040812080548592906102cb90849061036a565b90915550505b50505050565b5f6102e18261015b565b50600181901b17600281901b1790565b6001600160a01b03811681146101a4575f5ffd5b5f5f60408385031215610316575f5ffd5b8251610321816102f1565b6020840151909250610332816102f1565b809150509250929050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156103645761036461033d565b92915050565b818103818111156103645761036461033d565b608051610ec16103a35f395f81816101b201528181610a120152610a730152610ec15ff3fe608060405234801561000f575f5ffd5b50600436106100fb575f3560e01c80633d140d21116100935780637c300586116100635780637c300586146102f6578063ce156e8214610309578063d3bf89b11461031c578063dfa70d8b1461037d575f5ffd5b80633d140d21146102145780635adf4724146102295780636f3ff7261461025c578063781ef8db146102ac575f5ffd5b80631c3fc3eb116100ce5780631c3fc3eb146101795780632f27fa241461018e578063319c22bb146101ad5780633634f911146101ec575f5ffd5b806301ffc9a7146100ff578063072d5d771461012757806311b8e00a1461013a5780631aedefda1461014d575b5f5ffd5b61011261010d366004610cf5565b610390565b60405190151581526020015b60405180910390f35b610112610135366004610d37565b610407565b610112610148366004610d65565b610432565b61011261015b366004610d85565b6001600160a01b03165f908152610102602052604090205460ff1690565b6101805f81565b60405190815260200161011e565b61018061019c366004610da0565b5f9081526001602052604090205490565b6101d47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161011e565b6101ff6101fa366004610d65565b610449565b6040805192835260208301919091520161011e565b610227610222366004610db7565b61046c565b005b610180610237366004610d37565b5f918252602082815260408084206001600160a01b0393909316845291905290205490565b61011261026a366004610d85565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020526040812054601090811614610401565b6101126102ba366004610d37565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b610112610304366004610de7565b61052b565b610112610317366004610d37565b610570565b61011261032a366004610de7565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b61011261038b366004610de7565b610592565b5f6001600160e01b031982167f1aedefda0000000000000000000000000000000000000000000000000000000014806103f257506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b806104015750610401826105cd565b92915050565b5f5f8361041c8282610417610633565b610641565b6104295f86866001610712565b95945050505050565b5f5f61043e8484610449565b501515949350505050565b5f5f61045483610826565b5f948552600160205260409094205484169492505050565b60016104805f8261047b610633565b610840565b6001600160a01b0383165f908152610102602052604090205482151560ff9091161515036104ac575f5ffd5b6001600160a01b0383165f90815261010260205260409020805460ff19168315151790556104d8610633565b6001600160a01b0316836001600160a01b03167f7da296e993dc16ba7339edda62347c967436bf5bd3c5e3b98a73bfcb27b38f668460405161051e911515815260200190565b60405180910390a3505050565b5f838361053b8282610417610633565b8561055957604051631850848b60e31b815260040160405180910390fd5b6105668686866001610712565b9695505050505050565b5f5f836105858282610580610633565b6108e1565b6104295f868660016109a7565b5f83836105a28282610580610633565b856105c057604051631850848b60e31b815260040160405180910390fd5b61056686868660016109a7565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061040157507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610401565b5f61063c610a0f565b905090565b5f6106b184836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b9050801983161561070c576040517fd1a3b35500000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b03831660448201526064015b60405180910390fd5b50505050565b5f835f0361072157505f61081e565b61072a84610b00565b6001600160a01b03831661076a576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214610818575f878152602081815260408083206001600160a01b03891684529091529020819055811986166107c688826001610b60565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a36001935050505061081e565b5f925050505b949350505050565b5f61083082610b00565b50600181901b17600281901b1790565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb59092529091205417821682146108dc576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610703565b505050565b5f61095184836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b9050801983161561070c576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610703565b5f6109b184610b00565b5f858152602081815260408083206001600160a01b038716845290915290205484198116808214610818575f878152602081815260408083206001600160a01b03891684529091528120829055868316906107c69089908390610b60565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610a4357503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015610ac0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae49190610e1d565b90506001600160a01b038116610afb573391505090565b919050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615610b5d576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610703565b50565b5f610b6a83610826565b90508115610c33575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615610c0b576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610703565b5f8481526001602052604081208054859290610c28908490610e65565b9091555061070c9050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615610ccd576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610703565b5f8481526001602052604081208054859290610cea908490610e78565b909155505050505050565b5f60208284031215610d05575f5ffd5b81356001600160e01b031981168114610d1c575f5ffd5b9392505050565b6001600160a01b0381168114610b5d575f5ffd5b5f5f60408385031215610d48575f5ffd5b823591506020830135610d5a81610d23565b809150509250929050565b5f5f60408385031215610d76575f5ffd5b50508035926020909101359150565b5f60208284031215610d95575f5ffd5b8135610d1c81610d23565b5f60208284031215610db0575f5ffd5b5035919050565b5f5f60408385031215610dc8575f5ffd5b8235610dd381610d23565b915060208301358015158114610d5a575f5ffd5b5f5f5f60608486031215610df9575f5ffd5b83359250602084013591506040840135610e1281610d23565b809150509250925092565b5f60208284031215610e2d575f5ffd5b8151610d1c81610d23565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561040157610401610e38565b8181038181111561040157610401610e3856fea2646970667358221220e5fed629435c9e6acf22a6f2593c2f56450d1b3a2e5eb11f57a142b50fc1c53264736f6c634300081b00338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100fb575f3560e01c80633d140d21116100935780637c300586116100635780637c300586146102f6578063ce156e8214610309578063d3bf89b11461031c578063dfa70d8b1461037d575f5ffd5b80633d140d21146102145780635adf4724146102295780636f3ff7261461025c578063781ef8db146102ac575f5ffd5b80631c3fc3eb116100ce5780631c3fc3eb146101795780632f27fa241461018e578063319c22bb146101ad5780633634f911146101ec575f5ffd5b806301ffc9a7146100ff578063072d5d771461012757806311b8e00a1461013a5780631aedefda1461014d575b5f5ffd5b61011261010d366004610cf5565b610390565b60405190151581526020015b60405180910390f35b610112610135366004610d37565b610407565b610112610148366004610d65565b610432565b61011261015b366004610d85565b6001600160a01b03165f908152610102602052604090205460ff1690565b6101805f81565b60405190815260200161011e565b61018061019c366004610da0565b5f9081526001602052604090205490565b6101d47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161011e565b6101ff6101fa366004610d65565b610449565b6040805192835260208301919091520161011e565b610227610222366004610db7565b61046c565b005b610180610237366004610d37565b5f918252602082815260408084206001600160a01b0393909316845291905290205490565b61011261026a366004610d85565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020526040812054601090811614610401565b6101126102ba366004610d37565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b610112610304366004610de7565b61052b565b610112610317366004610d37565b610570565b61011261032a366004610de7565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b61011261038b366004610de7565b610592565b5f6001600160e01b031982167f1aedefda0000000000000000000000000000000000000000000000000000000014806103f257506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b806104015750610401826105cd565b92915050565b5f5f8361041c8282610417610633565b610641565b6104295f86866001610712565b95945050505050565b5f5f61043e8484610449565b501515949350505050565b5f5f61045483610826565b5f948552600160205260409094205484169492505050565b60016104805f8261047b610633565b610840565b6001600160a01b0383165f908152610102602052604090205482151560ff9091161515036104ac575f5ffd5b6001600160a01b0383165f90815261010260205260409020805460ff19168315151790556104d8610633565b6001600160a01b0316836001600160a01b03167f7da296e993dc16ba7339edda62347c967436bf5bd3c5e3b98a73bfcb27b38f668460405161051e911515815260200190565b60405180910390a3505050565b5f838361053b8282610417610633565b8561055957604051631850848b60e31b815260040160405180910390fd5b6105668686866001610712565b9695505050505050565b5f5f836105858282610580610633565b6108e1565b6104295f868660016109a7565b5f83836105a28282610580610633565b856105c057604051631850848b60e31b815260040160405180910390fd5b61056686868660016109a7565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061040157507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610401565b5f61063c610a0f565b905090565b5f6106b184836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b9050801983161561070c576040517fd1a3b35500000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b03831660448201526064015b60405180910390fd5b50505050565b5f835f0361072157505f61081e565b61072a84610b00565b6001600160a01b03831661076a576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214610818575f878152602081815260408083206001600160a01b03891684529091529020819055811986166107c688826001610b60565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a36001935050505061081e565b5f925050505b949350505050565b5f61083082610b00565b50600181901b17600281901b1790565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb59092529091205417821682146108dc576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610703565b505050565b5f61095184836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b9050801983161561070c576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610703565b5f6109b184610b00565b5f858152602081815260408083206001600160a01b038716845290915290205484198116808214610818575f878152602081815260408083206001600160a01b03891684529091528120829055868316906107c69089908390610b60565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610a4357503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015610ac0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae49190610e1d565b90506001600160a01b038116610afb573391505090565b919050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615610b5d576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610703565b50565b5f610b6a83610826565b90508115610c33575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615610c0b576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610703565b5f8481526001602052604081208054859290610c28908490610e65565b9091555061070c9050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615610ccd576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610703565b5f8481526001602052604081208054859290610cea908490610e78565b909155505050505050565b5f60208284031215610d05575f5ffd5b81356001600160e01b031981168114610d1c575f5ffd5b9392505050565b6001600160a01b0381168114610b5d575f5ffd5b5f5f60408385031215610d48575f5ffd5b823591506020830135610d5a81610d23565b809150509250929050565b5f5f60408385031215610d76575f5ffd5b50508035926020909101359150565b5f60208284031215610d95575f5ffd5b8135610d1c81610d23565b5f60208284031215610db0575f5ffd5b5035919050565b5f5f60408385031215610dc8575f5ffd5b8235610dd381610d23565b915060208301358015158114610d5a575f5ffd5b5f5f5f60608486031215610df9575f5ffd5b83359250602084013591506040840135610e1281610d23565b809150509250925092565b5f60208284031215610e2d575f5ffd5b8151610d1c81610d23565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561040157610401610e38565b8181038181111561040157610401610e3856fea2646970667358221220e5fed629435c9e6acf22a6f2593c2f56450d1b3a2e5eb11f57a142b50fc1c53264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60111": [ + { + "length": 32, + "start": 434 + }, + { + "length": 32, + "start": 2578 + }, + { + "length": 32, + "start": 2675 + } + ] + }, + "inputSourceName": "project/src/utils/PermissionedAddressSet.sol", + "devdoc": { + "errors": { + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ] + }, + "events": { + "ApprovalChanged(address,bool,address)": { + "params": { + "addr": "The address.", + "approved": "If `true`, added, otherwise removed.", + "sender": "The sender of the change." + } + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + } + }, + "kind": "dev", + "methods": { + "approve(address,bool)": { + "params": { + "addr": "The address to approve.", + "approved": "If `true`, added, otherwise removed." + } + }, + "constructor": { + "params": { + "admin": "The initial admin.", + "hcaFactory": "The HCA factory." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "grantRoles(uint256,uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted. Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.", + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "includes(address)": { + "params": { + "addr": "The address to check." + }, + "returns": { + "_0": "`true` if included." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "revokeRoles(uint256,uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked. Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.", + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "stateVariables": { + "_approved": { + "details": "Mapping that determines members of the set." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "755400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "HCA_FACTORY()": "infinite", + "ROOT_RESOURCE()": "216", + "approve(address,bool)": "infinite", + "getAssigneeCount(uint256,uint256)": "2723", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "2729", + "hasRoles(uint256,uint256,address)": "4891", + "hasRootRoles(uint256,address)": "2651", + "includes(address)": "2619", + "isContractNamer(address)": "2627", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "2480", + "roles(uint256,address)": "2678", + "supportsInterface(bytes4)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ApprovalChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"includes\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"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\"}],\"devdoc\":{\"errors\":{\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}]},\"events\":{\"ApprovalChanged(address,bool,address)\":{\"params\":{\"addr\":\"The address.\",\"approved\":\"If `true`, added, otherwise removed.\",\"sender\":\"The sender of the change.\"}},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}}},\"kind\":\"dev\",\"methods\":{\"approve(address,bool)\":{\"params\":{\"addr\":\"The address to approve.\",\"approved\":\"If `true`, added, otherwise removed.\"}},\"constructor\":{\"params\":{\"admin\":\"The initial admin.\",\"hcaFactory\":\"The HCA factory.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"grantRoles(uint256,uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted. Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\",\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"includes(address)\":{\"params\":{\"addr\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if included.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"revokeRoles(uint256,uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked. Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"_approved\":{\"details\":\"Mapping that determines members of the set.\"}},\"version\":1},\"userdoc\":{\"events\":{\"ApprovalChanged(address,bool,address)\":{\"notice\":\"Inclusion of a member of the set has changed.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"}},\"kind\":\"user\",\"methods\":{\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"approve(address,bool)\":{\"notice\":\"Add or remove a member from the set.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"includes(address)\":{\"notice\":\"Check if `addr` is included in the set.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"}},\"notice\":\"An arbitrary set of addresses managed by EAC.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/utils/PermissionedAddressSet.sol\":\"PermissionedAddressSet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, _msgSender());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _roles[ROOT_RESOURCE][account] & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return\\n (_roles[ROOT_RESOURCE][account] | _roles[resource][account]) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (_hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (_hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function _hasZeroNybbles(uint256 value) private pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 hasZeroNybbles;\\n unchecked {\\n hasZeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return hasZeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xdf8918a909b0ab3bf17bc3a560fbdff6ca6e9502cbee54eb0923f1fae04d2fb1\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x9f29748b40665df976c08cdaf434b469dc73ef50e938c36be6773dc7b6a6f014\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/PermissionedAddressSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IAddressSet} from \\\"./interfaces/IAddressSet.sol\\\";\\n\\n/// @dev Nybble 0: authorizes modifying the set. Root only.\\nuint256 constant ROLE_APPROVE = 1 << 0;\\n\\n/// @dev Nybble 32: authorizes setting `ROLE_APPROVE`.\\nuint256 constant ROLE_APPROVE_ADMIN = ROLE_APPROVE << 128;\\n\\n/// @dev Nybble 1: authorizes contract naming. Root only.\\nuint256 constant ROLE_SET_NAME = 1 << 4;\\n\\n/// @dev Nybble 33: authorizes setting `ROLE_SET_NAME`.\\nuint256 constant ROLE_SET_NAME_ADMIN = ROLE_SET_NAME << 128;\\n\\n/// @dev Default root roles assigned at construction.\\nuint256 constant DEFAULT_ROLE_BITMAP =\\n ROLE_APPROVE | ROLE_APPROVE_ADMIN | ROLE_SET_NAME | ROLE_SET_NAME_ADMIN;\\n\\n/// @notice An arbitrary set of addresses managed by EAC.\\ncontract PermissionedAddressSet is EnhancedAccessControl, IAddressSet, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Mapping that determines members of the set.\\n mapping(address addr => bool approved) internal _approved;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Inclusion of a member of the set has changed.\\n /// @param addr The address.\\n /// @param approved If `true`, added, otherwise removed.\\n /// @param sender The sender of the change.\\n event ApprovalChanged(address indexed addr, bool approved, address indexed sender);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory.\\n /// @param admin The initial admin.\\n constructor(IHCAFactoryBasic hcaFactory, address admin) HCAEquivalence(hcaFactory) {\\n _grantRoles(ROOT_RESOURCE, DEFAULT_ROLE_BITMAP, admin, false);\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IAddressSet).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Add or remove a member from the set.\\n /// @param addr The address to approve.\\n /// @param approved If `true`, added, otherwise removed.\\n function approve(address addr, bool approved) external onlyRootRoles(ROLE_APPROVE) {\\n require(_approved[addr] != approved);\\n _approved[addr] = approved;\\n emit ApprovalChanged(addr, approved, _msgSender());\\n }\\n\\n /// @inheritdoc IAddressSet\\n function includes(address addr) external view returns (bool) {\\n return _approved[addr];\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return hasRootRoles(ROLE_SET_NAME, namer);\\n }\\n}\\n\",\"keccak256\":\"0x7caee2bef212dac13595a09685b7389f63d4a693c239fb9c5ed62d284986c190\",\"license\":\"MIT\"},\"project/src/utils/interfaces/IAddressSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x1aedefda`\\ninterface IAddressSet {\\n /// @notice Check if `addr` is included in the set.\\n /// @param addr The address to check.\\n /// @return `true` if included.\\n function includes(address addr) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcb4f9c6364c1cf8a737591088f488ede7a7c6bc9d7d87f2dbdac731b492bd862\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 55601, + "contract": "project/src/utils/PermissionedAddressSet.sol:PermissionedAddressSet", + "label": "_roles", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 55606, + "contract": "project/src/utils/PermissionedAddressSet.sol:PermissionedAddressSet", + "label": "_roleCount", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 55611, + "contract": "project/src/utils/PermissionedAddressSet.sol:PermissionedAddressSet", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 75606, + "contract": "project/src/utils/PermissionedAddressSet.sol:PermissionedAddressSet", + "label": "_approved", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "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_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,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" + } + } + }, + "userdoc": { + "events": { + "ApprovalChanged(address,bool,address)": { + "notice": "Inclusion of a member of the set has changed." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + } + }, + "kind": "user", + "methods": { + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "approve(address,bool)": { + "notice": "Add or remove a member from the set." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "includes(address)": { + "notice": "Check if `addr` is included in the set." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + } + }, + "notice": "An arbitrary set of addresses managed by EAC.", + "version": 1 + }, + "argsData": "0x000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf943000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80", + "transaction": { + "hash": "0xd7a86f910776db5f6b0a9d13aa7ac034ceece49524830f657cb66336e26e3cad", + "nonce": "0x1e97", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x4b344e87c0a0567a8b430e9e8148b38f59439d84482c7f800b00fd9440b4b4d1", + "blockNumber": "0xa6a80c", + "transactionIndex": "0x42" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/PublicResolverV2.json b/contracts/deployments/sepolia-official-v1-20260525-r2/PublicResolverV2.json new file mode 100644 index 000000000..be50d8132 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/PublicResolverV2.json @@ -0,0 +1,2199 @@ +{ + "address": "0x5239a812ec9a62f46dbb5de8f346c8efe7553a9f", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "rootRegistry", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "name": "InvalidEVMAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + } + ], + "name": "ABIChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "a", + "type": "address" + } + ], + "name": "AddrChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newAddress", + "type": "bytes" + } + ], + "name": "AddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "Approved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "ContenthashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "resource", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "record", + "type": "bytes" + } + ], + "name": "DNSRecordChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "resource", + "type": "uint16" + } + ], + "name": "DNSRecordDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "lastzonehash", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "zonehash", + "type": "bytes" + } + ], + "name": "DNSZonehashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "indexedData", + "type": "bytes" + } + ], + "name": "DataChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "InterfaceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "NameChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "name": "PubkeyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "TextChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newVersion", + "type": "uint64" + } + ], + "name": "VersionChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "contentTypes", + "type": "uint256" + } + ], + "name": "ABI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "canModifyName", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "clearRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "contenthash", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "data", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "name", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "resource", + "type": "uint16" + } + ], + "name": "dnsRecord", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "hasAddr", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "name", + "type": "bytes32" + } + ], + "name": "hasDNSRecords", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "interfaceImplementer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + } + ], + "name": "isApprovedFor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "nodehash", + "type": "bytes32" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicallWithNodeCheck", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "pubkey", + "outputs": [ + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "recordVersions", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "setABI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "name": "setAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "setContenthash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "setDNSRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "setData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "setInterface", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "name": "setPubkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "setText", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "setZonehash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "text", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "zonehash", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "PublicResolverV2", + "sourceName": "src/resolver/PublicResolverV2.sol", + "bytecode": "0x610100604052348015610010575f5ffd5b506040516137cb3803806137cb83398101604081905261002f91610068565b6001600160a01b03938416608052831660a05290821660c0521660e0526100c4565b6001600160a01b0381168114610065575f5ffd5b50565b5f5f5f5f6080858703121561007b575f5ffd5b845161008681610051565b602086015190945061009781610051565b60408601519093506100a881610051565b60608601519092506100b981610051565b939692955090935050565b60805160a05160c05160e0516136b161011a5f395f8181610620015261109c01525f8181610321015261101801525f8181610402015261152601525f818161038f015281816126b9015261271a01526136b15ff3fe608060405234801561000f575f5ffd5b506004361061029d575f3560e01c8063691f343111610171578063c8690233116100d2578063e32954eb11610088578063e985e9c51161006e578063e985e9c5146106d0578063ecbfada31461070b578063f1cb7e061461071e575f5ffd5b8063e32954eb146106aa578063e59d895d146106bd575f5ffd5b8063ce3decdc116100b8578063ce3decdc14610642578063d5fa2b0014610655578063d700ff3314610668575f5ffd5b8063c8690233146105c3578063c92cc49a1461061b575f5ffd5b8063a4b91a0111610127578063a9784b3e1161010d578063a9784b3e1461054d578063ac9650d814610590578063bc1c58d1146105b0575f5ffd5b8063a4b91a0114610527578063a8fa56821461053a575f5ffd5b8063773722131161015757806377372213146104ee5780638b95dd7114610501578063a22cb46514610514575f5ffd5b8063691f3431146104c85780636f3ff726146104db575f5ffd5b806332f111d71161021b5780634cbf6ba4116101d157806359d1d43c116101b757806359d1d43c146104825780635c98042b146104a2578063623195b0146104b5575f5ffd5b80634cbf6ba4146104245780634eb9c45e1461046f575f5ffd5b80633b3b57de116102015780633b3b57de146103d757806341415eab146103ea57806348ee1bcc146103fd575f5ffd5b806332f111d7146103b15780633603d758146103c4575f5ffd5b8063192cf07d1161027057806329cd62ea1161025657806329cd62ea14610364578063304e6ade14610377578063319c22bb1461038a575f5ffd5b8063192cf07d1461031c5780632203ab5614610343575f5ffd5b806301ffc9a7146102a15780630af179d7146102c957806310f13a8c146102de578063124a319c146102f1575b5f5ffd5b6102b46102af366004612b45565b610731565b60405190151581526020015b60405180910390f35b6102dc6102d7366004612b9c565b610741565b005b6102dc6102ec366004612be4565b610944565b6103046102ff366004612c5d565b610a0f565b6040516001600160a01b0390911681526020016102c0565b6103047f000000000000000000000000000000000000000000000000000000000000000081565b610356610351366004612c87565b610c85565b6040516102c0929190612cd5565b6102dc610372366004612ced565b610dc1565b6102dc610385366004612b9c565b610e5a565b6103047f000000000000000000000000000000000000000000000000000000000000000081565b6102b46103bf366004612c87565b610ed4565b6102dc6103d2366004612d16565b610f1f565b6103046103e5366004612d16565b610fbf565b6102b46103f8366004612d41565b610fdd565b6103047f000000000000000000000000000000000000000000000000000000000000000081565b6102b4610432366004612c87565b5f828152602081815260408083205467ffffffffffffffff1683526007825280832094835293815283822092825291909152205461ffff16151590565b6102dc61047d366004612be4565b611148565b610495610490366004612b9c565b611299565b6040516102c09190612d6f565b6104956104b0366004612d16565b611377565b6102dc6104c3366004612d81565b611433565b6104956104d6366004612d16565b6114cc565b6102b46104e9366004612dd0565b611505565b6102dc6104fc366004612b9c565b611591565b6102dc61050f366004612e57565b61160b565b6102dc610522366004612ef0565b611748565b6102dc610535366004612f1c565b611846565b610495610548366004612f5b565b61192c565b6102b461055b366004612f8c565b6001600160a01b039283165f908152600d60209081526040808320948352938152838220929094168152925290205460ff1690565b6105a361059e366004613001565b611979565b6040516102c09190613040565b6104956105be366004612d16565b611986565b6106066105d1366004612d16565b5f818152602081815260408083205467ffffffffffffffff168352600a82528083209383529290522080546001909101549091565b604080519283526020830191909152016102c0565b6103047f000000000000000000000000000000000000000000000000000000000000000081565b6102dc610650366004612b9c565b6119bf565b6102dc610663366004612d41565b611afd565b610691610676366004612d16565b5f6020819052908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102c0565b6105a36106b83660046130a3565b611b50565b6102dc6106cb3660046130de565b611b65565b6102b46106de366004613110565b6001600160a01b039182165f908152600c6020908152604080832093909416825291909152205460ff1690565b610495610719366004612b9c565b611c22565b61049561072c366004612c87565b611c61565b5f61073b82611de8565b92915050565b8261074b81611e1c565b610753575f5ffd5b5f84815260208181526040808320548151601f870184900484028101840190925285825283926060928392859267ffffffffffffffff9091169183916107b79183918d908d90819084018382808284375f920191909152509293925050611e299050565b90505b805151602082015110156108de578661ffff165f0361081e57806040015196506107e381611e84565b9450846040516020016107f6919061313c565b60405160208183030381529060405280519060200120925061081781611ea5565b93506108d0565b5f61082882611e84565b9050816040015161ffff168861ffff1614158061084c575061084a8682611ec1565b155b156108ce576108a78c878a8e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505060208801518d915061089e908290613166565b8b51158a611ee5565b8160400151975081602001519650809550858051906020012093506108cb82611ea5565b94505b505b6108d98161214a565b6107ba565b50835115610938576109388a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c925061092f91508290508f613166565b89511588611ee5565b50505050505050505050565b8461094e81611e1c565b610956575f5ffd5b5f868152602081815260408083205467ffffffffffffffff168352600b8252808320898452909152908190209051849184916109959089908990613179565b908152602001604051809103902091826109b0929190613204565b5084846040516109c1929190613179565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a1878787876040516109ff94939291906132e6565b60405180910390a3505050505050565b5f828152602081815260408083205467ffffffffffffffff1683526008825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b03168015610a6257905061073b565b5f610a6c85610fbf565b90506001600160a01b038116610a86575f9250505061073b565b6040516301ffc9a760e01b60248201525f9081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610add919061313c565b5f60405180830381855afa9150503d805f8114610b15576040519150601f19603f3d011682016040523d82523d5f602084013e610b1a565b606091505b5091509150811580610b2d575060208151105b80610b6f575080601f81518110610b4657610b4661330c565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610b80575f94505050505061073b565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610bd6919061313c565b5f60405180830381855afa9150503d805f8114610c0e576040519150601f19603f3d011682016040523d82523d5f602084013e610c13565b606091505b509092509050811580610c27575060208151105b80610c69575080601f81518110610c4057610c4061330c565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610c7a575f94505050505061073b565b509095945050505050565b5f828152602081815260408083205467ffffffffffffffff168352600180835281842086855290925282206060915b5f81118015610cc35750848111155b15610da35780851615801590610cf057505f8181526020839052604081208054610cec90613188565b9050115b15610d9b5780825f8381526020019081526020015f20808054610d1290613188565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3e90613188565b8015610d895780601f10610d6057610100808354040283529160200191610d89565b820191905f5260205f20905b815481529060010190602001808311610d6c57829003601f168201915b50505050509050935093505050610dba565b60011b610cb4565b505f60405180602001604052805f81525092509250505b9250929050565b82610dcb81611e1c565b610dd3575f5ffd5b60408051808201825284815260208082018581525f8881528083528481205467ffffffffffffffff168152600a835284812089825283528490209251835551600190920191909155815185815290810184905285917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a250505050565b82610e6481611e1c565b610e6c575f5ffd5b5f848152602081815260408083205467ffffffffffffffff168352600382528083208784529091529020610ea1838583613204565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788484604051610e4c929190613320565b5f828152602081815260408083205467ffffffffffffffff16835260028252808320858452825280832084845290915281208054829190610f1490613188565b905011905092915050565b80610f2981611e1c565b610f31575f5ffd5b5f828152602081905260408120805467ffffffffffffffff1691610f5483613333565b82546101009290920a67ffffffffffffffff8181021990931691831602179091555f84815260208181526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b5f610fcb82603c611c61565b610fd49061335f565b60601c92915050565b6040517f20c38e2b000000000000000000000000000000000000000000000000000000008152600481018390525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906320c38e2b906024015f60405180830381865afa15801561105c573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261108391908101906133b2565b905080515f03611096575f91505061073b565b5f6110c27f0000000000000000000000000000000000000000000000000000000000000000835f61222f565b9050836001600160a01b0316816001600160a01b0316148061110857506001600160a01b038082165f908152600c602090815260408083209388168352929052205460ff165b8061113f57506001600160a01b038082165f908152600d6020908152604080832089845282528083209388168352929052205460ff165b95945050505050565b8461115281611e1c565b61115a575f5ffd5b5f868152602081815260408083205467ffffffffffffffff16835260048252808320898452909152908190209051849184916111999089908990613179565b908152602001604051809103902091826111b4929190613204565b506112278686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f92019190915250611b4b92505050565b8282604051611237929190613179565b6040518091039020858560405161124f929190613179565b6040518091039020877f3b7ea3580e046bf897ca24f2f45fcf5491dafba8d1b3dd17ca92aa0e82b4dd218888604051611289929190613320565b60405180910390a4505050505050565b5f838152602081815260408083205467ffffffffffffffff168352600b8252808320868452909152908190209051606091906112d89085908590613179565b908152602001604051809103902080546112f190613188565b80601f016020809104026020016040519081016040528092919081815260200182805461131d90613188565b80156113685780601f1061133f57610100808354040283529160200191611368565b820191905f5260205f20905b81548152906001019060200180831161134b57829003601f168201915b505050505090505b9392505050565b5f818152602081815260408083205467ffffffffffffffff1683526005825280832084845290915290208054606091906113b090613188565b80601f01602080910402602001604051908101604052809291908181526020018280546113dc90613188565b80156114275780601f106113fe57610100808354040283529160200191611427565b820191905f5260205f20905b81548152906001019060200180831161140a57829003601f168201915b50505050509050919050565b8361143d81611e1c565b611445575f5ffd5b83611451600182613166565b161561145b575f5ffd5b5f858152602081815260408083205467ffffffffffffffff1683526001825280832088845282528083208784529091529020611498838583613204565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3905f90a35050505050565b5f818152602081815260408083205467ffffffffffffffff1683526009825280832084845290915290208054606091906113b090613188565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561156d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073b9190613427565b8261159b81611e1c565b6115a3575f5ffd5b5f848152602081815260408083205467ffffffffffffffff1683526009825280832087845290915290206115d8838583613204565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051610e4c929190613320565b8261161581611e1c565b61161d575f5ffd5b81511580159061162f57508151601414155b801561163f575061163f836122ed565b1561168157816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016116789190612d6f565b60405180910390fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af75284846040516116b3929190612cd5565b60405180910390a2603c830361170557837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd26116ee8461335f565b60405160609190911c815260200160405180910390a25b5f848152602081815260408083205467ffffffffffffffff16835260028252808320878452825280832086845290915290206117418382613442565b5050505050565b5f611751612312565b9050826001600160a01b0316816001600160a01b0316036117da5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152608401611678565b6001600160a01b038181165f818152600c6020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b5f61184f612312565b9050826001600160a01b0316816001600160a01b0316036118b25760405162461bcd60e51b815260206004820181905260248201527f53657474696e672064656c65676174652073746174757320666f722073656c666044820152606401611678565b6001600160a01b038181165f818152600d60209081526040808320898452825280832094881680845294825291829020805460ff1916871515908117909155915192835290929187917ff0ddb3b04746704017f9aa8bd728fcc2c1d11675041205350018915f5e4750a0910160405180910390a450505050565b5f838152602081815260408083205467ffffffffffffffff168352600682528083208684528252808320858452825280832061ffff8516845290915290208054606091906112f190613188565b60606113705f8484612320565b5f818152602081815260408083205467ffffffffffffffff1683526003825280832084845290915290208054606091906113b090613188565b826119c981611e1c565b6119d1575f5ffd5b5f848152602081815260408083205467ffffffffffffffff168084526005835281842088855290925282208054919291611a0a90613188565b80601f0160208091040260200160405190810160405280929190818152602001828054611a3690613188565b8015611a815780601f10611a5857610100808354040283529160200191611a81565b820191905f5260205f20905b815481529060010190602001808311611a6457829003601f168201915b5050505067ffffffffffffffff84165f9081526005602090815260408083208b84529091529020919250611ab89050858783613204565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f85828787604051611aed939291906134fd565b60405180910390a2505050505050565b81611b0781611e1c565b611b0f575f5ffd5b6040516bffffffffffffffffffffffff19606084901b166020820152611b4b908490603c9060340160405160208183030381529060405261160b565b505050565b6060611b5d848484612320565b949350505050565b82611b6f81611e1c565b611b77575f5ffd5b5f848152602081815260408083205467ffffffffffffffff1683526008825280832087845282528083206001600160e01b031987168085529083529281902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b5f838152602081815260408083205467ffffffffffffffff16835260048252808320868452909152908190209051606091906112d89085908590613179565b5f828152602081815260408083205467ffffffffffffffff1683526002825280832085845282528083208484529182905290912080546060929190611ca590613188565b80601f0160208091040260200160405190810160405280929190818152602001828054611cd190613188565b8015611d1c5780601f10611cf357610100808354040283529160200191611d1c565b820191905f5260205f20905b815481529060010190602001808311611cff57829003601f168201915b5050505050915081515f148015611d4057505f611d38846124df565b63ffffffff16115b15611de15763800000005f9081526020829052604090208054611d6290613188565b80601f0160208091040260200160405190810160405280929190818152602001828054611d8e90613188565b8015611dd95780601f10611db057610100808354040283529160200191611dd9565b820191905f5260205f20905b815481529060010190602001808311611dbc57829003601f168201915b505050505091505b5092915050565b5f6001600160e01b0319821663379ffb9360e11b148061073b57506301ffc9a760e01b6001600160e01b031983161461073b565b5f61073b826103f8612312565b611e716040518060e00160405280606081526020015f81526020015f61ffff1681526020015f61ffff1681526020015f63ffffffff1681526020015f81526020015f81525090565b82815260c0810182905261073b8161214a565b6020810151815160609161073b91611e9c9082612509565b84519190612560565b60a081015160c082015160609161073b91611e9c908290613166565b5f815183511480156113705750508051602091820120825192909101919091201490565b865160208801205f611ef8878787612560565b9050831561201f5767ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611f4290613188565b159050611fa05767ffffffffffffffff83165f9081526007602090815260408083208d845282528083208584529091528120805461ffff1691611f848361352c565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c1684529091528120611fe091612ae0565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a604051612012929190613548565b60405180910390a2610938565b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c1684529091529020805461206190613188565b90505f036120c05767ffffffffffffffff83165f9081526007602090815260408083208d845282528083208584529091528120805461ffff16916120a48361356d565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290206121018282613442565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a8460405161213693929190613584565b60405180910390a250505050505050505050565b60c081015160208201819052815151116121615750565b5f612173825f01518360200151612509565b826020015161218291906135b2565b825190915061219190826125b5565b61ffff1660408301526121a56002826135b2565b82519091506121b490826125b5565b61ffff1660608301526121c86002826135b2565b82519091506121d790826125d6565b63ffffffff1660808301526121ed6004826135b2565b82519091505f906121fe90836125b5565b61ffff16905061220f6002836135b2565b60a08401819052915061222281836135b2565b60c0909301929092525050565b5f5f61223c8585856125f2565b90506001600160a01b038116158015906122625750612262816331ab054760e11b61261e565b156122e5575f6122728585612639565b506040516331ab054760e11b81529091506001600160a01b038316906363560a8e906122a2908490600401612d6f565b602060405180830381865afa1580156122bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122e191906135c5565b9250505b509392505050565b5f638000000082148061073b57505f612305836124df565b63ffffffff161192915050565b5f61231b6126b6565b905090565b60608167ffffffffffffffff81111561233b5761233b612deb565b60405190808252806020026020018201604052801561236e57816020015b60608152602001906001900390816123595790505b5090505f5b828110156122e5578415612437575f8484838181106123945761239461330c565b90506020028101906123a691906135e0565b6123b591602491600491613623565b6123be9161364a565b90508581146124355760405162461bcd60e51b815260206004820152603460248201527f6d756c746963616c6c3a20416c6c207265636f726473206d757374206861766560448201527f2061206d61746368696e67206e616d65686173680000000000000000000000006064820152608401611678565b505b5f803086868581811061244c5761244c61330c565b905060200281019061245e91906135e0565b60405161246c929190613179565b5f60405180830381855af49150503d805f81146124a4576040519150601f19603f3d011682016040523d82523d5f602084013e6124a9565b606091505b5091509150816124b7575f5ffd5b808484815181106124ca576124ca61330c565b60209081029190910101525050600101612373565b5f603c82036124f057506001919050565b6380000000918218918210612505575f61073b565b5090565b5f815b8351811061251c5761251c613667565b5f61252785836127a7565b60ff1690506125378160016135b2565b61254190836135b2565b9150805f036125505750612556565b5061250c565b611b5d8382613166565b60608167ffffffffffffffff81111561257b5761257b612deb565b6040519080825280601f01601f1916602001820160405280156125a5576020820181803683370190505b5090506113708484835f866127d9565b5f6125ca836125c58460026135b2565b61280a565b50016020015160f01c90565b5f6125e6836125c58460046135b2565b50016020015160e01c90565b5f5f5f6125ff8585612856565b90925090508115612615576122e1868683612883565b50509392505050565b5f61262883612962565b801561137057506113708383612994565b60605f5f6126478585612a1a565b925090505f60ff821667ffffffffffffffff81111561266857612668612deb565b6040519080825280601f01601f191660200182016040528015612692576020820181803683370190505b5090506126ab6020820160218888010160ff8516612a97565b959194509092505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166126ea57503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015612767573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061278b91906135c5565b90506001600160a01b0381166127a2573391505090565b919050565b5f6127b7836125c58460016135b2565b8282815181106127c9576127c961330c565b016020015160f81c905092915050565b6127e7856125c583876135b2565b6127f5836125c583856135b2565b61174182602085010185602088010183612a97565b81518111156128525781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152611678918391600401918252602082015260400190565b5050565b5f5f5f6128638585612a1a565b9250905060ff81161561287b57806021858701012092505b509250929050565b5f5f5f6128908585612856565b9092509050816128a4578592505050611370565b5f6128b0878784612883565b90506001600160a01b03811615612958575f6128cc8787612639565b506040517f35af62160000000000000000000000000000000000000000000000000000000081529091506001600160a01b038316906335af621690612915908490600401612d6f565b602060405180830381865afa158015612930573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061295491906135c5565b9450505b5050509392505050565b5f612974826301ffc9a760e01b612994565b801561073b575061298d826001600160e01b0319612994565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015612a04575060208210155b8015612a0f57505f81115b979650505050505050565b5f5f83518310612a3f578360405163ba4adc2360e01b81526004016116789190612d6f565b838381518110612a5157612a5161330c565b016020015160f81c91505081810160010181612a71578351811415612a77565b83518110155b15610dba578360405163ba4adc2360e01b81526004016116789190612d6f565b5b601f811115612ab8578151835260209283019290910190601f1901612a98565b8015611b4b5790518251600160209390930360031b9290921b5f190180199091169116179052565b508054612aec90613188565b5f825580601f10612afb575050565b601f0160209004905f5260205f2090810190612b179190612b1a565b50565b5b80821115612505575f8155600101612b1b565b80356001600160e01b0319811681146127a2575f5ffd5b5f60208284031215612b55575f5ffd5b61137082612b2e565b5f5f83601f840112612b6e575f5ffd5b50813567ffffffffffffffff811115612b85575f5ffd5b602083019150836020828501011115610dba575f5ffd5b5f5f5f60408486031215612bae575f5ffd5b83359250602084013567ffffffffffffffff811115612bcb575f5ffd5b612bd786828701612b5e565b9497909650939450505050565b5f5f5f5f5f60608688031215612bf8575f5ffd5b85359450602086013567ffffffffffffffff811115612c15575f5ffd5b612c2188828901612b5e565b909550935050604086013567ffffffffffffffff811115612c40575f5ffd5b612c4c88828901612b5e565b969995985093965092949392505050565b5f5f60408385031215612c6e575f5ffd5b82359150612c7e60208401612b2e565b90509250929050565b5f5f60408385031215612c98575f5ffd5b50508035926020909101359150565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f611b5d6040830184612ca7565b5f5f5f60608486031215612cff575f5ffd5b505081359360208301359350604090920135919050565b5f60208284031215612d26575f5ffd5b5035919050565b6001600160a01b0381168114612b17575f5ffd5b5f5f60408385031215612d52575f5ffd5b823591506020830135612d6481612d2d565b809150509250929050565b602081525f6113706020830184612ca7565b5f5f5f5f60608587031215612d94575f5ffd5b8435935060208501359250604085013567ffffffffffffffff811115612db8575f5ffd5b612dc487828801612b5e565b95989497509550505050565b5f60208284031215612de0575f5ffd5b813561137081612d2d565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e2857612e28612deb565b604052919050565b5f67ffffffffffffffff821115612e4957612e49612deb565b50601f01601f191660200190565b5f5f5f60608486031215612e69575f5ffd5b8335925060208401359150604084013567ffffffffffffffff811115612e8d575f5ffd5b8401601f81018613612e9d575f5ffd5b8035612eb0612eab82612e30565b612dff565b818152876020838501011115612ec4575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b8015158114612b17575f5ffd5b5f5f60408385031215612f01575f5ffd5b8235612f0c81612d2d565b91506020830135612d6481612ee3565b5f5f5f60608486031215612f2e575f5ffd5b833592506020840135612f4081612d2d565b91506040840135612f5081612ee3565b809150509250925092565b5f5f5f60608486031215612f6d575f5ffd5b8335925060208401359150604084013561ffff81168114612f50575f5ffd5b5f5f5f60608486031215612f9e575f5ffd5b8335612fa981612d2d565b9250602084013591506040840135612f5081612d2d565b5f5f83601f840112612fd0575f5ffd5b50813567ffffffffffffffff811115612fe7575f5ffd5b6020830191508360208260051b8501011115610dba575f5ffd5b5f5f60208385031215613012575f5ffd5b823567ffffffffffffffff811115613028575f5ffd5b61303485828601612fc0565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561309757603f19878603018452613082858351612ca7565b94506020938401939190910190600101613066565b50929695505050505050565b5f5f5f604084860312156130b5575f5ffd5b83359250602084013567ffffffffffffffff8111156130d2575f5ffd5b612bd786828701612fc0565b5f5f5f606084860312156130f0575f5ffd5b8335925061310060208501612b2e565b91506040840135612f5081612d2d565b5f5f60408385031215613121575f5ffd5b823561312c81612d2d565b91506020830135612d6481612d2d565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561073b5761073b613152565b818382375f9101908152919050565b600181811c9082168061319c57607f821691505b6020821081036131ba57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115611b4b57805f5260205f20601f840160051c810160208510156131e55750805b601f840160051c820191505b81811015611741575f81556001016131f1565b67ffffffffffffffff83111561321c5761321c612deb565b6132308361322a8354613188565b836131c0565b5f601f841160018114613261575f851561324a5750838201355b5f19600387901b1c1916600186901b178355611741565b5f83815260208120601f198716915b828110156132905786850135825560209485019460019092019101613270565b50868210156132ac575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f6132f96040830186886132be565b8281036020840152612a0f8185876132be565b634e487b7160e01b5f52603260045260245ffd5b602081525f611b5d6020830184866132be565b5f67ffffffffffffffff821667ffffffffffffffff810361335657613356613152565b60010192915050565b805160208201516bffffffffffffffffffffffff198116919060148210156133ab576bffffffffffffffffffffffff196bffffffffffffffffffffffff198360140360031b1b82161692505b5050919050565b5f602082840312156133c2575f5ffd5b815167ffffffffffffffff8111156133d8575f5ffd5b8201601f810184136133e8575f5ffd5b80516133f6612eab82612e30565b81815285602083850101111561340a575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215613437575f5ffd5b815161137081612ee3565b815167ffffffffffffffff81111561345c5761345c612deb565b6134708161346a8454613188565b846131c0565b6020601f8211600181146134a2575f831561348b5750848201515b5f19600385901b1c1916600184901b178455611741565b5f84815260208120601f198516915b828110156134d157878501518255602094850194600190920191016134b1565b50848210156134ee57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b604081525f61350f6040830186612ca7565b82810360208401526135228185876132be565b9695505050505050565b5f61ffff82168061353f5761353f613152565b5f190192915050565b604081525f61355a6040830185612ca7565b905061ffff831660208301529392505050565b5f61ffff821661ffff810361335657613356613152565b606081525f6135966060830186612ca7565b61ffff8516602084015282810360408401526135228185612ca7565b8082018082111561073b5761073b613152565b5f602082840312156135d5575f5ffd5b815161137081612d2d565b5f5f8335601e198436030181126135f5575f5ffd5b83018035915067ffffffffffffffff82111561360f575f5ffd5b602001915036819003821315610dba575f5ffd5b5f5f85851115613631575f5ffd5b8386111561363d575f5ffd5b5050820193919092039150565b8035602083101561073b575f19602084900360031b1b1692915050565b634e487b7160e01b5f52600160045260245ffdfea264697066735822122029ea813685cfe85d65c9e9882c6336143aded2a491eec0ba5ac4a7160d7e720364736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061029d575f3560e01c8063691f343111610171578063c8690233116100d2578063e32954eb11610088578063e985e9c51161006e578063e985e9c5146106d0578063ecbfada31461070b578063f1cb7e061461071e575f5ffd5b8063e32954eb146106aa578063e59d895d146106bd575f5ffd5b8063ce3decdc116100b8578063ce3decdc14610642578063d5fa2b0014610655578063d700ff3314610668575f5ffd5b8063c8690233146105c3578063c92cc49a1461061b575f5ffd5b8063a4b91a0111610127578063a9784b3e1161010d578063a9784b3e1461054d578063ac9650d814610590578063bc1c58d1146105b0575f5ffd5b8063a4b91a0114610527578063a8fa56821461053a575f5ffd5b8063773722131161015757806377372213146104ee5780638b95dd7114610501578063a22cb46514610514575f5ffd5b8063691f3431146104c85780636f3ff726146104db575f5ffd5b806332f111d71161021b5780634cbf6ba4116101d157806359d1d43c116101b757806359d1d43c146104825780635c98042b146104a2578063623195b0146104b5575f5ffd5b80634cbf6ba4146104245780634eb9c45e1461046f575f5ffd5b80633b3b57de116102015780633b3b57de146103d757806341415eab146103ea57806348ee1bcc146103fd575f5ffd5b806332f111d7146103b15780633603d758146103c4575f5ffd5b8063192cf07d1161027057806329cd62ea1161025657806329cd62ea14610364578063304e6ade14610377578063319c22bb1461038a575f5ffd5b8063192cf07d1461031c5780632203ab5614610343575f5ffd5b806301ffc9a7146102a15780630af179d7146102c957806310f13a8c146102de578063124a319c146102f1575b5f5ffd5b6102b46102af366004612b45565b610731565b60405190151581526020015b60405180910390f35b6102dc6102d7366004612b9c565b610741565b005b6102dc6102ec366004612be4565b610944565b6103046102ff366004612c5d565b610a0f565b6040516001600160a01b0390911681526020016102c0565b6103047f000000000000000000000000000000000000000000000000000000000000000081565b610356610351366004612c87565b610c85565b6040516102c0929190612cd5565b6102dc610372366004612ced565b610dc1565b6102dc610385366004612b9c565b610e5a565b6103047f000000000000000000000000000000000000000000000000000000000000000081565b6102b46103bf366004612c87565b610ed4565b6102dc6103d2366004612d16565b610f1f565b6103046103e5366004612d16565b610fbf565b6102b46103f8366004612d41565b610fdd565b6103047f000000000000000000000000000000000000000000000000000000000000000081565b6102b4610432366004612c87565b5f828152602081815260408083205467ffffffffffffffff1683526007825280832094835293815283822092825291909152205461ffff16151590565b6102dc61047d366004612be4565b611148565b610495610490366004612b9c565b611299565b6040516102c09190612d6f565b6104956104b0366004612d16565b611377565b6102dc6104c3366004612d81565b611433565b6104956104d6366004612d16565b6114cc565b6102b46104e9366004612dd0565b611505565b6102dc6104fc366004612b9c565b611591565b6102dc61050f366004612e57565b61160b565b6102dc610522366004612ef0565b611748565b6102dc610535366004612f1c565b611846565b610495610548366004612f5b565b61192c565b6102b461055b366004612f8c565b6001600160a01b039283165f908152600d60209081526040808320948352938152838220929094168152925290205460ff1690565b6105a361059e366004613001565b611979565b6040516102c09190613040565b6104956105be366004612d16565b611986565b6106066105d1366004612d16565b5f818152602081815260408083205467ffffffffffffffff168352600a82528083209383529290522080546001909101549091565b604080519283526020830191909152016102c0565b6103047f000000000000000000000000000000000000000000000000000000000000000081565b6102dc610650366004612b9c565b6119bf565b6102dc610663366004612d41565b611afd565b610691610676366004612d16565b5f6020819052908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102c0565b6105a36106b83660046130a3565b611b50565b6102dc6106cb3660046130de565b611b65565b6102b46106de366004613110565b6001600160a01b039182165f908152600c6020908152604080832093909416825291909152205460ff1690565b610495610719366004612b9c565b611c22565b61049561072c366004612c87565b611c61565b5f61073b82611de8565b92915050565b8261074b81611e1c565b610753575f5ffd5b5f84815260208181526040808320548151601f870184900484028101840190925285825283926060928392859267ffffffffffffffff9091169183916107b79183918d908d90819084018382808284375f920191909152509293925050611e299050565b90505b805151602082015110156108de578661ffff165f0361081e57806040015196506107e381611e84565b9450846040516020016107f6919061313c565b60405160208183030381529060405280519060200120925061081781611ea5565b93506108d0565b5f61082882611e84565b9050816040015161ffff168861ffff1614158061084c575061084a8682611ec1565b155b156108ce576108a78c878a8e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505060208801518d915061089e908290613166565b8b51158a611ee5565b8160400151975081602001519650809550858051906020012093506108cb82611ea5565b94505b505b6108d98161214a565b6107ba565b50835115610938576109388a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c925061092f91508290508f613166565b89511588611ee5565b50505050505050505050565b8461094e81611e1c565b610956575f5ffd5b5f868152602081815260408083205467ffffffffffffffff168352600b8252808320898452909152908190209051849184916109959089908990613179565b908152602001604051809103902091826109b0929190613204565b5084846040516109c1929190613179565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a1878787876040516109ff94939291906132e6565b60405180910390a3505050505050565b5f828152602081815260408083205467ffffffffffffffff1683526008825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b03168015610a6257905061073b565b5f610a6c85610fbf565b90506001600160a01b038116610a86575f9250505061073b565b6040516301ffc9a760e01b60248201525f9081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610add919061313c565b5f60405180830381855afa9150503d805f8114610b15576040519150601f19603f3d011682016040523d82523d5f602084013e610b1a565b606091505b5091509150811580610b2d575060208151105b80610b6f575080601f81518110610b4657610b4661330c565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610b80575f94505050505061073b565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610bd6919061313c565b5f60405180830381855afa9150503d805f8114610c0e576040519150601f19603f3d011682016040523d82523d5f602084013e610c13565b606091505b509092509050811580610c27575060208151105b80610c69575080601f81518110610c4057610c4061330c565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610c7a575f94505050505061073b565b509095945050505050565b5f828152602081815260408083205467ffffffffffffffff168352600180835281842086855290925282206060915b5f81118015610cc35750848111155b15610da35780851615801590610cf057505f8181526020839052604081208054610cec90613188565b9050115b15610d9b5780825f8381526020019081526020015f20808054610d1290613188565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3e90613188565b8015610d895780601f10610d6057610100808354040283529160200191610d89565b820191905f5260205f20905b815481529060010190602001808311610d6c57829003601f168201915b50505050509050935093505050610dba565b60011b610cb4565b505f60405180602001604052805f81525092509250505b9250929050565b82610dcb81611e1c565b610dd3575f5ffd5b60408051808201825284815260208082018581525f8881528083528481205467ffffffffffffffff168152600a835284812089825283528490209251835551600190920191909155815185815290810184905285917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a250505050565b82610e6481611e1c565b610e6c575f5ffd5b5f848152602081815260408083205467ffffffffffffffff168352600382528083208784529091529020610ea1838583613204565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788484604051610e4c929190613320565b5f828152602081815260408083205467ffffffffffffffff16835260028252808320858452825280832084845290915281208054829190610f1490613188565b905011905092915050565b80610f2981611e1c565b610f31575f5ffd5b5f828152602081905260408120805467ffffffffffffffff1691610f5483613333565b82546101009290920a67ffffffffffffffff8181021990931691831602179091555f84815260208181526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b5f610fcb82603c611c61565b610fd49061335f565b60601c92915050565b6040517f20c38e2b000000000000000000000000000000000000000000000000000000008152600481018390525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906320c38e2b906024015f60405180830381865afa15801561105c573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261108391908101906133b2565b905080515f03611096575f91505061073b565b5f6110c27f0000000000000000000000000000000000000000000000000000000000000000835f61222f565b9050836001600160a01b0316816001600160a01b0316148061110857506001600160a01b038082165f908152600c602090815260408083209388168352929052205460ff165b8061113f57506001600160a01b038082165f908152600d6020908152604080832089845282528083209388168352929052205460ff165b95945050505050565b8461115281611e1c565b61115a575f5ffd5b5f868152602081815260408083205467ffffffffffffffff16835260048252808320898452909152908190209051849184916111999089908990613179565b908152602001604051809103902091826111b4929190613204565b506112278686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f92019190915250611b4b92505050565b8282604051611237929190613179565b6040518091039020858560405161124f929190613179565b6040518091039020877f3b7ea3580e046bf897ca24f2f45fcf5491dafba8d1b3dd17ca92aa0e82b4dd218888604051611289929190613320565b60405180910390a4505050505050565b5f838152602081815260408083205467ffffffffffffffff168352600b8252808320868452909152908190209051606091906112d89085908590613179565b908152602001604051809103902080546112f190613188565b80601f016020809104026020016040519081016040528092919081815260200182805461131d90613188565b80156113685780601f1061133f57610100808354040283529160200191611368565b820191905f5260205f20905b81548152906001019060200180831161134b57829003601f168201915b505050505090505b9392505050565b5f818152602081815260408083205467ffffffffffffffff1683526005825280832084845290915290208054606091906113b090613188565b80601f01602080910402602001604051908101604052809291908181526020018280546113dc90613188565b80156114275780601f106113fe57610100808354040283529160200191611427565b820191905f5260205f20905b81548152906001019060200180831161140a57829003601f168201915b50505050509050919050565b8361143d81611e1c565b611445575f5ffd5b83611451600182613166565b161561145b575f5ffd5b5f858152602081815260408083205467ffffffffffffffff1683526001825280832088845282528083208784529091529020611498838583613204565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3905f90a35050505050565b5f818152602081815260408083205467ffffffffffffffff1683526009825280832084845290915290208054606091906113b090613188565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561156d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061073b9190613427565b8261159b81611e1c565b6115a3575f5ffd5b5f848152602081815260408083205467ffffffffffffffff1683526009825280832087845290915290206115d8838583613204565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051610e4c929190613320565b8261161581611e1c565b61161d575f5ffd5b81511580159061162f57508151601414155b801561163f575061163f836122ed565b1561168157816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016116789190612d6f565b60405180910390fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af75284846040516116b3929190612cd5565b60405180910390a2603c830361170557837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd26116ee8461335f565b60405160609190911c815260200160405180910390a25b5f848152602081815260408083205467ffffffffffffffff16835260028252808320878452825280832086845290915290206117418382613442565b5050505050565b5f611751612312565b9050826001600160a01b0316816001600160a01b0316036117da5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152608401611678565b6001600160a01b038181165f818152600c6020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b5f61184f612312565b9050826001600160a01b0316816001600160a01b0316036118b25760405162461bcd60e51b815260206004820181905260248201527f53657474696e672064656c65676174652073746174757320666f722073656c666044820152606401611678565b6001600160a01b038181165f818152600d60209081526040808320898452825280832094881680845294825291829020805460ff1916871515908117909155915192835290929187917ff0ddb3b04746704017f9aa8bd728fcc2c1d11675041205350018915f5e4750a0910160405180910390a450505050565b5f838152602081815260408083205467ffffffffffffffff168352600682528083208684528252808320858452825280832061ffff8516845290915290208054606091906112f190613188565b60606113705f8484612320565b5f818152602081815260408083205467ffffffffffffffff1683526003825280832084845290915290208054606091906113b090613188565b826119c981611e1c565b6119d1575f5ffd5b5f848152602081815260408083205467ffffffffffffffff168084526005835281842088855290925282208054919291611a0a90613188565b80601f0160208091040260200160405190810160405280929190818152602001828054611a3690613188565b8015611a815780601f10611a5857610100808354040283529160200191611a81565b820191905f5260205f20905b815481529060010190602001808311611a6457829003601f168201915b5050505067ffffffffffffffff84165f9081526005602090815260408083208b84529091529020919250611ab89050858783613204565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f85828787604051611aed939291906134fd565b60405180910390a2505050505050565b81611b0781611e1c565b611b0f575f5ffd5b6040516bffffffffffffffffffffffff19606084901b166020820152611b4b908490603c9060340160405160208183030381529060405261160b565b505050565b6060611b5d848484612320565b949350505050565b82611b6f81611e1c565b611b77575f5ffd5b5f848152602081815260408083205467ffffffffffffffff1683526008825280832087845282528083206001600160e01b031987168085529083529281902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b5f838152602081815260408083205467ffffffffffffffff16835260048252808320868452909152908190209051606091906112d89085908590613179565b5f828152602081815260408083205467ffffffffffffffff1683526002825280832085845282528083208484529182905290912080546060929190611ca590613188565b80601f0160208091040260200160405190810160405280929190818152602001828054611cd190613188565b8015611d1c5780601f10611cf357610100808354040283529160200191611d1c565b820191905f5260205f20905b815481529060010190602001808311611cff57829003601f168201915b5050505050915081515f148015611d4057505f611d38846124df565b63ffffffff16115b15611de15763800000005f9081526020829052604090208054611d6290613188565b80601f0160208091040260200160405190810160405280929190818152602001828054611d8e90613188565b8015611dd95780601f10611db057610100808354040283529160200191611dd9565b820191905f5260205f20905b815481529060010190602001808311611dbc57829003601f168201915b505050505091505b5092915050565b5f6001600160e01b0319821663379ffb9360e11b148061073b57506301ffc9a760e01b6001600160e01b031983161461073b565b5f61073b826103f8612312565b611e716040518060e00160405280606081526020015f81526020015f61ffff1681526020015f61ffff1681526020015f63ffffffff1681526020015f81526020015f81525090565b82815260c0810182905261073b8161214a565b6020810151815160609161073b91611e9c9082612509565b84519190612560565b60a081015160c082015160609161073b91611e9c908290613166565b5f815183511480156113705750508051602091820120825192909101919091201490565b865160208801205f611ef8878787612560565b9050831561201f5767ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611f4290613188565b159050611fa05767ffffffffffffffff83165f9081526007602090815260408083208d845282528083208584529091528120805461ffff1691611f848361352c565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c1684529091528120611fe091612ae0565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a604051612012929190613548565b60405180910390a2610938565b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c1684529091529020805461206190613188565b90505f036120c05767ffffffffffffffff83165f9081526007602090815260408083208d845282528083208584529091528120805461ffff16916120a48361356d565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290206121018282613442565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a8460405161213693929190613584565b60405180910390a250505050505050505050565b60c081015160208201819052815151116121615750565b5f612173825f01518360200151612509565b826020015161218291906135b2565b825190915061219190826125b5565b61ffff1660408301526121a56002826135b2565b82519091506121b490826125b5565b61ffff1660608301526121c86002826135b2565b82519091506121d790826125d6565b63ffffffff1660808301526121ed6004826135b2565b82519091505f906121fe90836125b5565b61ffff16905061220f6002836135b2565b60a08401819052915061222281836135b2565b60c0909301929092525050565b5f5f61223c8585856125f2565b90506001600160a01b038116158015906122625750612262816331ab054760e11b61261e565b156122e5575f6122728585612639565b506040516331ab054760e11b81529091506001600160a01b038316906363560a8e906122a2908490600401612d6f565b602060405180830381865afa1580156122bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122e191906135c5565b9250505b509392505050565b5f638000000082148061073b57505f612305836124df565b63ffffffff161192915050565b5f61231b6126b6565b905090565b60608167ffffffffffffffff81111561233b5761233b612deb565b60405190808252806020026020018201604052801561236e57816020015b60608152602001906001900390816123595790505b5090505f5b828110156122e5578415612437575f8484838181106123945761239461330c565b90506020028101906123a691906135e0565b6123b591602491600491613623565b6123be9161364a565b90508581146124355760405162461bcd60e51b815260206004820152603460248201527f6d756c746963616c6c3a20416c6c207265636f726473206d757374206861766560448201527f2061206d61746368696e67206e616d65686173680000000000000000000000006064820152608401611678565b505b5f803086868581811061244c5761244c61330c565b905060200281019061245e91906135e0565b60405161246c929190613179565b5f60405180830381855af49150503d805f81146124a4576040519150601f19603f3d011682016040523d82523d5f602084013e6124a9565b606091505b5091509150816124b7575f5ffd5b808484815181106124ca576124ca61330c565b60209081029190910101525050600101612373565b5f603c82036124f057506001919050565b6380000000918218918210612505575f61073b565b5090565b5f815b8351811061251c5761251c613667565b5f61252785836127a7565b60ff1690506125378160016135b2565b61254190836135b2565b9150805f036125505750612556565b5061250c565b611b5d8382613166565b60608167ffffffffffffffff81111561257b5761257b612deb565b6040519080825280601f01601f1916602001820160405280156125a5576020820181803683370190505b5090506113708484835f866127d9565b5f6125ca836125c58460026135b2565b61280a565b50016020015160f01c90565b5f6125e6836125c58460046135b2565b50016020015160e01c90565b5f5f5f6125ff8585612856565b90925090508115612615576122e1868683612883565b50509392505050565b5f61262883612962565b801561137057506113708383612994565b60605f5f6126478585612a1a565b925090505f60ff821667ffffffffffffffff81111561266857612668612deb565b6040519080825280601f01601f191660200182016040528015612692576020820181803683370190505b5090506126ab6020820160218888010160ff8516612a97565b959194509092505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166126ea57503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015612767573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061278b91906135c5565b90506001600160a01b0381166127a2573391505090565b919050565b5f6127b7836125c58460016135b2565b8282815181106127c9576127c961330c565b016020015160f81c905092915050565b6127e7856125c583876135b2565b6127f5836125c583856135b2565b61174182602085010185602088010183612a97565b81518111156128525781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152611678918391600401918252602082015260400190565b5050565b5f5f5f6128638585612a1a565b9250905060ff81161561287b57806021858701012092505b509250929050565b5f5f5f6128908585612856565b9092509050816128a4578592505050611370565b5f6128b0878784612883565b90506001600160a01b03811615612958575f6128cc8787612639565b506040517f35af62160000000000000000000000000000000000000000000000000000000081529091506001600160a01b038316906335af621690612915908490600401612d6f565b602060405180830381865afa158015612930573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061295491906135c5565b9450505b5050509392505050565b5f612974826301ffc9a760e01b612994565b801561073b575061298d826001600160e01b0319612994565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015612a04575060208210155b8015612a0f57505f81115b979650505050505050565b5f5f83518310612a3f578360405163ba4adc2360e01b81526004016116789190612d6f565b838381518110612a5157612a5161330c565b016020015160f81c91505081810160010181612a71578351811415612a77565b83518110155b15610dba578360405163ba4adc2360e01b81526004016116789190612d6f565b5b601f811115612ab8578151835260209283019290910190601f1901612a98565b8015611b4b5790518251600160209390930360031b9290921b5f190180199091169116179052565b508054612aec90613188565b5f825580601f10612afb575050565b601f0160209004905f5260205f2090810190612b179190612b1a565b50565b5b80821115612505575f8155600101612b1b565b80356001600160e01b0319811681146127a2575f5ffd5b5f60208284031215612b55575f5ffd5b61137082612b2e565b5f5f83601f840112612b6e575f5ffd5b50813567ffffffffffffffff811115612b85575f5ffd5b602083019150836020828501011115610dba575f5ffd5b5f5f5f60408486031215612bae575f5ffd5b83359250602084013567ffffffffffffffff811115612bcb575f5ffd5b612bd786828701612b5e565b9497909650939450505050565b5f5f5f5f5f60608688031215612bf8575f5ffd5b85359450602086013567ffffffffffffffff811115612c15575f5ffd5b612c2188828901612b5e565b909550935050604086013567ffffffffffffffff811115612c40575f5ffd5b612c4c88828901612b5e565b969995985093965092949392505050565b5f5f60408385031215612c6e575f5ffd5b82359150612c7e60208401612b2e565b90509250929050565b5f5f60408385031215612c98575f5ffd5b50508035926020909101359150565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f611b5d6040830184612ca7565b5f5f5f60608486031215612cff575f5ffd5b505081359360208301359350604090920135919050565b5f60208284031215612d26575f5ffd5b5035919050565b6001600160a01b0381168114612b17575f5ffd5b5f5f60408385031215612d52575f5ffd5b823591506020830135612d6481612d2d565b809150509250929050565b602081525f6113706020830184612ca7565b5f5f5f5f60608587031215612d94575f5ffd5b8435935060208501359250604085013567ffffffffffffffff811115612db8575f5ffd5b612dc487828801612b5e565b95989497509550505050565b5f60208284031215612de0575f5ffd5b813561137081612d2d565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e2857612e28612deb565b604052919050565b5f67ffffffffffffffff821115612e4957612e49612deb565b50601f01601f191660200190565b5f5f5f60608486031215612e69575f5ffd5b8335925060208401359150604084013567ffffffffffffffff811115612e8d575f5ffd5b8401601f81018613612e9d575f5ffd5b8035612eb0612eab82612e30565b612dff565b818152876020838501011115612ec4575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b8015158114612b17575f5ffd5b5f5f60408385031215612f01575f5ffd5b8235612f0c81612d2d565b91506020830135612d6481612ee3565b5f5f5f60608486031215612f2e575f5ffd5b833592506020840135612f4081612d2d565b91506040840135612f5081612ee3565b809150509250925092565b5f5f5f60608486031215612f6d575f5ffd5b8335925060208401359150604084013561ffff81168114612f50575f5ffd5b5f5f5f60608486031215612f9e575f5ffd5b8335612fa981612d2d565b9250602084013591506040840135612f5081612d2d565b5f5f83601f840112612fd0575f5ffd5b50813567ffffffffffffffff811115612fe7575f5ffd5b6020830191508360208260051b8501011115610dba575f5ffd5b5f5f60208385031215613012575f5ffd5b823567ffffffffffffffff811115613028575f5ffd5b61303485828601612fc0565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561309757603f19878603018452613082858351612ca7565b94506020938401939190910190600101613066565b50929695505050505050565b5f5f5f604084860312156130b5575f5ffd5b83359250602084013567ffffffffffffffff8111156130d2575f5ffd5b612bd786828701612fc0565b5f5f5f606084860312156130f0575f5ffd5b8335925061310060208501612b2e565b91506040840135612f5081612d2d565b5f5f60408385031215613121575f5ffd5b823561312c81612d2d565b91506020830135612d6481612d2d565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561073b5761073b613152565b818382375f9101908152919050565b600181811c9082168061319c57607f821691505b6020821081036131ba57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115611b4b57805f5260205f20601f840160051c810160208510156131e55750805b601f840160051c820191505b81811015611741575f81556001016131f1565b67ffffffffffffffff83111561321c5761321c612deb565b6132308361322a8354613188565b836131c0565b5f601f841160018114613261575f851561324a5750838201355b5f19600387901b1c1916600186901b178355611741565b5f83815260208120601f198716915b828110156132905786850135825560209485019460019092019101613270565b50868210156132ac575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f6132f96040830186886132be565b8281036020840152612a0f8185876132be565b634e487b7160e01b5f52603260045260245ffd5b602081525f611b5d6020830184866132be565b5f67ffffffffffffffff821667ffffffffffffffff810361335657613356613152565b60010192915050565b805160208201516bffffffffffffffffffffffff198116919060148210156133ab576bffffffffffffffffffffffff196bffffffffffffffffffffffff198360140360031b1b82161692505b5050919050565b5f602082840312156133c2575f5ffd5b815167ffffffffffffffff8111156133d8575f5ffd5b8201601f810184136133e8575f5ffd5b80516133f6612eab82612e30565b81815285602083850101111561340a575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215613437575f5ffd5b815161137081612ee3565b815167ffffffffffffffff81111561345c5761345c612deb565b6134708161346a8454613188565b846131c0565b6020601f8211600181146134a2575f831561348b5750848201515b5f19600385901b1c1916600184901b178455611741565b5f84815260208120601f198516915b828110156134d157878501518255602094850194600190920191016134b1565b50848210156134ee57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b604081525f61350f6040830186612ca7565b82810360208401526135228185876132be565b9695505050505050565b5f61ffff82168061353f5761353f613152565b5f190192915050565b604081525f61355a6040830185612ca7565b905061ffff831660208301529392505050565b5f61ffff821661ffff810361335657613356613152565b606081525f6135966060830186612ca7565b61ffff8516602084015282810360408401526135228185612ca7565b8082018082111561073b5761073b613152565b5f602082840312156135d5575f5ffd5b815161137081612d2d565b5f5f8335601e198436030181126135f5575f5ffd5b83018035915067ffffffffffffffff82111561360f575f5ffd5b602001915036819003821315610dba575f5ffd5b5f5f85851115613631575f5ffd5b8386111561363d575f5ffd5b5050820193919092039150565b8035602083101561073b575f19602084900360031b1b1692915050565b634e487b7160e01b5f52600160045260245ffdfea264697066735822122029ea813685cfe85d65c9e9882c6336143aded2a491eec0ba5ac4a7160d7e720364736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60111": [ + { + "length": 32, + "start": 911 + }, + { + "length": 32, + "start": 9913 + }, + { + "length": 32, + "start": 10010 + } + ], + "71507": [ + { + "length": 32, + "start": 801 + }, + { + "length": 32, + "start": 4120 + } + ], + "71511": [ + { + "length": 32, + "start": 1568 + }, + { + "length": 32, + "start": 4252 + } + ], + "75212": [ + { + "length": 32, + "start": 1026 + }, + { + "length": 32, + "start": 5414 + } + ] + }, + "inputSourceName": "project/src/resolver/PublicResolverV2.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "InvalidEVMAddress(bytes)": [ + { + "details": "Error selector: `0x8d666f60`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "params": { + "approved": "If `true`, approved, otherwise revoked.", + "operator": "The approved account.", + "owner": "The node owner." + } + }, + "Approved(address,bytes32,address,bool)": { + "params": { + "approved": "If `true`, approved, otherwise revoked.", + "delegate": "The approved account.", + "node": "The namehash.", + "owner": "The node owner." + } + } + }, + "kind": "dev", + "methods": { + "ABI(bytes32,uint256)": { + "params": { + "contentTypes": "A bitwise OR of the ABI formats accepted by the caller.", + "node": "The ENS node to query" + }, + "returns": { + "_0": "contentType The content type of the return value", + "_1": "data The ABI data" + } + }, + "addr(bytes32)": { + "params": { + "node": "The node to query." + }, + "returns": { + "_0": "The associated address." + } + }, + "addr(bytes32,uint256)": { + "params": { + "coinType": "The coin type.", + "node": "The node to query." + }, + "returns": { + "addressBytes": "The assocated address." + } + }, + "approve(bytes32,address,bool)": { + "params": { + "approved": "If `true`, approved, otherwise revoked.", + "delegate": "The account to approve.", + "node": "The namehash to approve." + } + }, + "canModifyName(bytes32,address)": { + "params": { + "node": "The namehash to check.", + "operator": "The account requesting authorization." + }, + "returns": { + "_0": "`true` if `node` is authorized." + } + }, + "clearRecords(bytes32)": { + "params": { + "node": "The node to update." + } + }, + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "hcaFactory": "The HCA factory.", + "nameWrapper": "The ENSv1 `NameWrapper` contract.", + "rootRegistry": "The ENSv2 Root Registry contract." + } + }, + "contenthash(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated contenthash." + } + }, + "data(bytes32,string)": { + "params": { + "key": "The key.", + "node": "The node (namehash) for which data is being fetched." + }, + "returns": { + "_0": "The associated arbitrary `bytes` data." + } + }, + "dnsRecord(bytes32,bytes32,uint16)": { + "params": { + "name": "the keccak-256 hash of the fully-qualified name for which to fetch the record", + "node": "the namehash of the node for which to fetch the record", + "resource": "the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types" + }, + "returns": { + "_0": "the DNS record in wire format if present, otherwise empty" + } + }, + "hasAddr(bytes32,uint256)": { + "params": { + "coinType": "The coin type.", + "node": "The node to query." + }, + "returns": { + "_0": "True if the associated address is not empty." + } + }, + "hasDNSRecords(bytes32,bytes32)": { + "params": { + "name": "the namehash of the node for which to check the records", + "node": "the namehash of the node for which to check the records" + } + }, + "interfaceImplementer(bytes32,bytes4)": { + "params": { + "interfaceID": "The EIP 165 interface ID to check for.", + "node": "The ENS node to query." + }, + "returns": { + "_0": "The address that implements this interface, or 0 if the interface is unsupported." + } + }, + "isApprovedFor(address,bytes32,address)": { + "params": { + "delegate": "The delegated account.", + "node": "The namehash to check.", + "owner": "The owner account." + }, + "returns": { + "_0": "`true` if `operator` is approved." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "operator": "The operator account.", + "owner": "The owner account." + }, + "returns": { + "_0": "`true` if `operator` is approved." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "name(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated name." + } + }, + "pubkey(bytes32)": { + "params": { + "node": "The ENS node to query" + }, + "returns": { + "x": "The X coordinate of the curve point for the public key.", + "y": "The Y coordinate of the curve point for the public key." + } + }, + "setABI(bytes32,uint256,bytes)": { + "params": { + "contentType": "The content type of the ABI", + "data": "The ABI data.", + "node": "The node to update." + } + }, + "setAddr(bytes32,address)": { + "params": { + "_addr": "The address to set.", + "node": "The node to update." + } + }, + "setAddr(bytes32,uint256,bytes)": { + "params": { + "addressBytes": "The address to set.", + "coinType": "The coin type.", + "node": "The node to update." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "If `true`, approved, otherwise revoked.", + "operator": "The account to approve." + } + }, + "setContenthash(bytes32,bytes)": { + "params": { + "hash": "The contenthash to set", + "node": "The node to update." + } + }, + "setDNSRecords(bytes32,bytes)": { + "params": { + "data": "the DNS wire format records to set", + "node": "the namehash of the node for which to set the records" + } + }, + "setData(bytes32,string,bytes)": { + "params": { + "key": "The key to set.", + "node": "The node to update.", + "value": "The arbitrary `bytes` data to set." + } + }, + "setInterface(bytes32,bytes4,address)": { + "params": { + "implementer": "The address of a contract that implements this interface for this node.", + "interfaceID": "The EIP 165 interface ID.", + "node": "The node to update." + } + }, + "setName(bytes32,string)": { + "params": { + "node": "The node to update." + } + }, + "setPubkey(bytes32,bytes32,bytes32)": { + "params": { + "node": "The ENS node to query", + "x": "the X coordinate of the curve point for the public key.", + "y": "the Y coordinate of the curve point for the public key." + } + }, + "setText(bytes32,string,string)": { + "params": { + "key": "The key to set.", + "node": "The node to update.", + "value": "The text data value to set." + } + }, + "setZonehash(bytes32,bytes)": { + "params": { + "hash": "The zonehash to set", + "node": "The node to update." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "text(bytes32,string)": { + "params": { + "key": "The text data key to query.", + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated text data." + } + }, + "zonehash(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated contenthash." + } + } + }, + "stateVariables": { + "_operatorApprovals": { + "details": "A mapping of operators. An address that is authorised for an address may make any changes to the name that the owner could, but may not update the set of authorisations." + }, + "_tokenApprovals": { + "details": "A mapping of delegates. A delegate that is authorised by an owner for a name may make changes to the name's resolver, but may not update the set of token approvals." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "2800200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ABI(bytes32,uint256)": "infinite", + "CONTRACT_NAMER()": "infinite", + "HCA_FACTORY()": "infinite", + "NAME_WRAPPER()": "infinite", + "ROOT_REGISTRY()": "infinite", + "addr(bytes32)": "infinite", + "addr(bytes32,uint256)": "infinite", + "approve(bytes32,address,bool)": "infinite", + "canModifyName(bytes32,address)": "infinite", + "clearRecords(bytes32)": "infinite", + "contenthash(bytes32)": "infinite", + "data(bytes32,string)": "infinite", + "dnsRecord(bytes32,bytes32,uint16)": "infinite", + "hasAddr(bytes32,uint256)": "4984", + "hasDNSRecords(bytes32,bytes32)": "4836", + "interfaceImplementer(bytes32,bytes4)": "infinite", + "isApprovedFor(address,bytes32,address)": "infinite", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "infinite", + "multicall(bytes[])": "infinite", + "multicallWithNodeCheck(bytes32,bytes[])": "infinite", + "name(bytes32)": "infinite", + "pubkey(bytes32)": "6880", + "recordVersions(bytes32)": "2564", + "setABI(bytes32,uint256,bytes)": "infinite", + "setAddr(bytes32,address)": "infinite", + "setAddr(bytes32,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "infinite", + "setContenthash(bytes32,bytes)": "infinite", + "setDNSRecords(bytes32,bytes)": "infinite", + "setData(bytes32,string,bytes)": "infinite", + "setInterface(bytes32,bytes4,address)": "infinite", + "setName(bytes32,string)": "infinite", + "setPubkey(bytes32,bytes32,bytes32)": "infinite", + "setText(bytes32,string,string)": "infinite", + "setZonehash(bytes32,bytes)": "infinite", + "supportsInterface(bytes4)": "infinite", + "text(bytes32,string)": "infinite", + "zonehash(bytes32)": "infinite" + }, + "internal": { + "isAuthorised(bytes32)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"rootRegistry\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"ABIChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"a\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newAddress\",\"type\":\"bytes\"}],\"name\":\"AddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"Approved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"ContenthashChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"resource\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"record\",\"type\":\"bytes\"}],\"name\":\"DNSRecordChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"resource\",\"type\":\"uint16\"}],\"name\":\"DNSRecordDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"lastzonehash\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"zonehash\",\"type\":\"bytes\"}],\"name\":\"DNSZonehashChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"indexedData\",\"type\":\"bytes\"}],\"name\":\"DataChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"name\":\"InterfaceChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"PubkeyChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newVersion\",\"type\":\"uint64\"}],\"name\":\"VersionChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"contentTypes\",\"type\":\"uint256\"}],\"name\":\"ABI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"canModifyName\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"clearRecords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"contenthash\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"name\",\"type\":\"bytes32\"},{\"internalType\":\"uint16\",\"name\":\"resource\",\"type\":\"uint16\"}],\"name\":\"dnsRecord\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"hasAddr\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"name\",\"type\":\"bytes32\"}],\"name\":\"hasDNSRecords\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"interfaceImplementer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"}],\"name\":\"isApprovedFor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodehash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicallWithNodeCheck\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"recordVersions\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"setABI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"setContenthash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"setDNSRecords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"name\":\"setData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"},{\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"name\":\"setInterface\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"newName\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"setText\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"setZonehash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"zonehash\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"InvalidEVMAddress(bytes)\":[{\"details\":\"Error selector: `0x8d666f60`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"params\":{\"approved\":\"If `true`, approved, otherwise revoked.\",\"operator\":\"The approved account.\",\"owner\":\"The node owner.\"}},\"Approved(address,bytes32,address,bool)\":{\"params\":{\"approved\":\"If `true`, approved, otherwise revoked.\",\"delegate\":\"The approved account.\",\"node\":\"The namehash.\",\"owner\":\"The node owner.\"}}},\"kind\":\"dev\",\"methods\":{\"ABI(bytes32,uint256)\":{\"params\":{\"contentTypes\":\"A bitwise OR of the ABI formats accepted by the caller.\",\"node\":\"The ENS node to query\"},\"returns\":{\"_0\":\"contentType The content type of the return value\",\"_1\":\"data The ABI data\"}},\"addr(bytes32)\":{\"params\":{\"node\":\"The node to query.\"},\"returns\":{\"_0\":\"The associated address.\"}},\"addr(bytes32,uint256)\":{\"params\":{\"coinType\":\"The coin type.\",\"node\":\"The node to query.\"},\"returns\":{\"addressBytes\":\"The assocated address.\"}},\"approve(bytes32,address,bool)\":{\"params\":{\"approved\":\"If `true`, approved, otherwise revoked.\",\"delegate\":\"The account to approve.\",\"node\":\"The namehash to approve.\"}},\"canModifyName(bytes32,address)\":{\"params\":{\"node\":\"The namehash to check.\",\"operator\":\"The account requesting authorization.\"},\"returns\":{\"_0\":\"`true` if `node` is authorized.\"}},\"clearRecords(bytes32)\":{\"params\":{\"node\":\"The node to update.\"}},\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"hcaFactory\":\"The HCA factory.\",\"nameWrapper\":\"The ENSv1 `NameWrapper` contract.\",\"rootRegistry\":\"The ENSv2 Root Registry contract.\"}},\"contenthash(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated contenthash.\"}},\"data(bytes32,string)\":{\"params\":{\"key\":\"The key.\",\"node\":\"The node (namehash) for which data is being fetched.\"},\"returns\":{\"_0\":\"The associated arbitrary `bytes` data.\"}},\"dnsRecord(bytes32,bytes32,uint16)\":{\"params\":{\"name\":\"the keccak-256 hash of the fully-qualified name for which to fetch the record\",\"node\":\"the namehash of the node for which to fetch the record\",\"resource\":\"the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\"},\"returns\":{\"_0\":\"the DNS record in wire format if present, otherwise empty\"}},\"hasAddr(bytes32,uint256)\":{\"params\":{\"coinType\":\"The coin type.\",\"node\":\"The node to query.\"},\"returns\":{\"_0\":\"True if the associated address is not empty.\"}},\"hasDNSRecords(bytes32,bytes32)\":{\"params\":{\"name\":\"the namehash of the node for which to check the records\",\"node\":\"the namehash of the node for which to check the records\"}},\"interfaceImplementer(bytes32,bytes4)\":{\"params\":{\"interfaceID\":\"The EIP 165 interface ID to check for.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The address that implements this interface, or 0 if the interface is unsupported.\"}},\"isApprovedFor(address,bytes32,address)\":{\"params\":{\"delegate\":\"The delegated account.\",\"node\":\"The namehash to check.\",\"owner\":\"The owner account.\"},\"returns\":{\"_0\":\"`true` if `operator` is approved.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"operator\":\"The operator account.\",\"owner\":\"The owner account.\"},\"returns\":{\"_0\":\"`true` if `operator` is approved.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"name(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated name.\"}},\"pubkey(bytes32)\":{\"params\":{\"node\":\"The ENS node to query\"},\"returns\":{\"x\":\"The X coordinate of the curve point for the public key.\",\"y\":\"The Y coordinate of the curve point for the public key.\"}},\"setABI(bytes32,uint256,bytes)\":{\"params\":{\"contentType\":\"The content type of the ABI\",\"data\":\"The ABI data.\",\"node\":\"The node to update.\"}},\"setAddr(bytes32,address)\":{\"params\":{\"_addr\":\"The address to set.\",\"node\":\"The node to update.\"}},\"setAddr(bytes32,uint256,bytes)\":{\"params\":{\"addressBytes\":\"The address to set.\",\"coinType\":\"The coin type.\",\"node\":\"The node to update.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"If `true`, approved, otherwise revoked.\",\"operator\":\"The account to approve.\"}},\"setContenthash(bytes32,bytes)\":{\"params\":{\"hash\":\"The contenthash to set\",\"node\":\"The node to update.\"}},\"setDNSRecords(bytes32,bytes)\":{\"params\":{\"data\":\"the DNS wire format records to set\",\"node\":\"the namehash of the node for which to set the records\"}},\"setData(bytes32,string,bytes)\":{\"params\":{\"key\":\"The key to set.\",\"node\":\"The node to update.\",\"value\":\"The arbitrary `bytes` data to set.\"}},\"setInterface(bytes32,bytes4,address)\":{\"params\":{\"implementer\":\"The address of a contract that implements this interface for this node.\",\"interfaceID\":\"The EIP 165 interface ID.\",\"node\":\"The node to update.\"}},\"setName(bytes32,string)\":{\"params\":{\"node\":\"The node to update.\"}},\"setPubkey(bytes32,bytes32,bytes32)\":{\"params\":{\"node\":\"The ENS node to query\",\"x\":\"the X coordinate of the curve point for the public key.\",\"y\":\"the Y coordinate of the curve point for the public key.\"}},\"setText(bytes32,string,string)\":{\"params\":{\"key\":\"The key to set.\",\"node\":\"The node to update.\",\"value\":\"The text data value to set.\"}},\"setZonehash(bytes32,bytes)\":{\"params\":{\"hash\":\"The zonehash to set\",\"node\":\"The node to update.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"text(bytes32,string)\":{\"params\":{\"key\":\"The text data key to query.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated text data.\"}},\"zonehash(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated contenthash.\"}}},\"stateVariables\":{\"_operatorApprovals\":{\"details\":\"A mapping of operators. An address that is authorised for an address may make any changes to the name that the owner could, but may not update the set of authorisations.\"},\"_tokenApprovals\":{\"details\":\"A mapping of delegates. A delegate that is authorised by an owner for a name may make changes to the name's resolver, but may not update the set of token approvals.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidEVMAddress(bytes)\":[{\"notice\":\"The supplied address could not be converted to `address`.\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"notice\":\"An operator is added or removed.\"},\"Approved(address,bytes32,address,bool)\":{\"notice\":\"A delegate is approved or an approval is revoked.\"},\"DataChanged(bytes32,string,string,bytes)\":{\"notice\":\"For a specific `node`, the data associated with a `key` has changed.\"}},\"kind\":\"user\",\"methods\":{\"ABI(bytes32,uint256)\":{\"notice\":\"Returns the ABI associated with an ENS node. Defined in EIP205.\"},\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract.\"},\"ROOT_REGISTRY()\":{\"notice\":\"The ENSv2 Root Registry contract.\"},\"addr(bytes32)\":{\"notice\":\"Get `addr(60)` as `address` of the associated ENS node.\"},\"addr(bytes32,uint256)\":{\"notice\":\"Get the address for coin type of the associated ENS node. If coin type is EVM and empty, defaults to `addr(COIN_TYPE_DEFAULT)`.\"},\"approve(bytes32,address,bool)\":{\"notice\":\"Grant or revoke `delegate` approval on a specific node.\"},\"canModifyName(bytes32,address)\":{\"notice\":\"Determine if `operator` is authorized for `node`.\"},\"clearRecords(bytes32)\":{\"notice\":\"Increments the record version associated with an ENS node. May only be called by the owner of that node in the ENS registry.\"},\"constructor\":{\"notice\":\"Create a WrappedPublicResolver.\"},\"contenthash(bytes32)\":{\"notice\":\"Returns the contenthash associated with an ENS node.\"},\"data(bytes32,string)\":{\"notice\":\"For a specific `node`, get the data associated with the key, `key`.\"},\"dnsRecord(bytes32,bytes32,uint16)\":{\"notice\":\"Obtain a DNS record.\"},\"hasAddr(bytes32,uint256)\":{\"notice\":\"Determine if an addresss is stored for the coin type of the associated ENS node.\"},\"hasDNSRecords(bytes32,bytes32)\":{\"notice\":\"Check if a given node has records.\"},\"interfaceImplementer(bytes32,bytes4)\":{\"notice\":\"Returns the address of a contract that implements the specified interface for this name. If an implementer has not been set for this interfaceID and name, the resolver will query the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that contract implements EIP165 and returns `true` for the specified interfaceID, its address will be returned.\"},\"isApprovedFor(address,bytes32,address)\":{\"notice\":\"Check to see if the delegate has been approved by the owner for the node.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Check if `operator` is approved for all nodes owned by `account`.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"name(bytes32)\":{\"notice\":\"Returns the name associated with an ENS node, for reverse records. Defined in EIP181.\"},\"pubkey(bytes32)\":{\"notice\":\"Returns the SECP256k1 public key associated with an ENS node. Defined in EIP 619.\"},\"setABI(bytes32,uint256,bytes)\":{\"notice\":\"Sets the ABI associated with an ENS node. Nodes may have one ABI of each content type. To remove an ABI, set it to the empty string.\"},\"setAddr(bytes32,address)\":{\"notice\":\"Set `addr(60)` of the associated ENS node. `address(0)` is stored as `new bytes(20)`.\"},\"setAddr(bytes32,uint256,bytes)\":{\"notice\":\"Set the address for coin type of the associated ENS node. Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Grant or revoke `operator` approval.\"},\"setContenthash(bytes32,bytes)\":{\"notice\":\"Sets the contenthash associated with an ENS node. May only be called by the owner of that node in the ENS registry.\"},\"setDNSRecords(bytes32,bytes)\":{\"notice\":\"Set one or more DNS records. Records are supplied in wire-format. Records with the same node/name/resource must be supplied one after the other to ensure the data is updated correctly. For example, if the data was supplied: a.example.com IN A 1.2.3.4 a.example.com IN A 5.6.7.8 www.example.com IN CNAME a.example.com. then this would store the two A records for a.example.com correctly as a single RRSET, however if the data was supplied: a.example.com IN A 1.2.3.4 www.example.com IN CNAME a.example.com. a.example.com IN A 5.6.7.8 then this would store the first A record, the CNAME, then the second A record which would overwrite the first.\"},\"setData(bytes32,string,bytes)\":{\"notice\":\"Sets the data associated with the key, `key` for a specific `node`. May only be called by the owner of that node in the ENS registry.\"},\"setInterface(bytes32,bytes4,address)\":{\"notice\":\"Sets an interface associated with a name. Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support.\"},\"setName(bytes32,string)\":{\"notice\":\"Sets the name associated with an ENS node, for reverse records. May only be called by the owner of that node in the ENS registry.\"},\"setPubkey(bytes32,bytes32,bytes32)\":{\"notice\":\"Sets the SECP256k1 public key associated with an ENS node.\"},\"setText(bytes32,string,string)\":{\"notice\":\"Sets the text data associated with an ENS node and key. May only be called by the owner of that node in the ENS registry.\"},\"setZonehash(bytes32,bytes)\":{\"notice\":\"setZonehash sets the hash for the zone. May only be called by the owner of that node in the ENS registry.\"},\"text(bytes32,string)\":{\"notice\":\"Returns the text data associated with an ENS node and key.\"},\"zonehash(bytes32)\":{\"notice\":\"zonehash obtains the hash for the zone.\"}},\"notice\":\"PublicResolver that respects the ENSv2 registry.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/resolver/PublicResolverV2.sol\":\"PublicResolverV2\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/buffer/contracts/Buffer.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-2-Clause\\npragma solidity ^0.8.4;\\n\\n/**\\n* @dev A library for working with mutable byte buffers in Solidity.\\n*\\n* Byte buffers are mutable and expandable, and provide a variety of primitives\\n* for appending to them. At any time you can fetch a bytes object containing the\\n* current contents of the buffer. The bytes object should not be stored between\\n* operations, as it may change due to resizing of the buffer.\\n*/\\nlibrary Buffer {\\n /**\\n * @dev Represents a mutable buffer. Buffers have a current value (buf) and\\n * a capacity. The capacity may be longer than the current value, in\\n * which case it can be extended without the need to allocate more memory.\\n */\\n struct buffer {\\n bytes buf;\\n uint capacity;\\n }\\n\\n /**\\n * @dev Initializes a buffer with an initial capacity.\\n * @param buf The buffer to initialize.\\n * @param capacity The number of bytes of space to allocate the buffer.\\n * @return The buffer, for chaining.\\n */\\n function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\\n if (capacity % 32 != 0) {\\n capacity += 32 - (capacity % 32);\\n }\\n // Allocate space for the buffer data\\n buf.capacity = capacity;\\n assembly {\\n let ptr := mload(0x40)\\n mstore(buf, ptr)\\n mstore(ptr, 0)\\n let fpm := add(32, add(ptr, capacity))\\n if lt(fpm, ptr) {\\n revert(0, 0)\\n }\\n mstore(0x40, fpm)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Initializes a new buffer from an existing bytes object.\\n * Changes to the buffer may mutate the original value.\\n * @param b The bytes object to initialize the buffer with.\\n * @return A new buffer.\\n */\\n function fromBytes(bytes memory b) internal pure returns(buffer memory) {\\n buffer memory buf;\\n buf.buf = b;\\n buf.capacity = b.length;\\n return buf;\\n }\\n\\n function resize(buffer memory buf, uint capacity) private pure {\\n bytes memory oldbuf = buf.buf;\\n init(buf, capacity);\\n append(buf, oldbuf);\\n }\\n\\n /**\\n * @dev Sets buffer length to 0.\\n * @param buf The buffer to truncate.\\n * @return The original buffer, for chaining..\\n */\\n function truncate(buffer memory buf) internal pure returns (buffer memory) {\\n assembly {\\n let bufptr := mload(buf)\\n mstore(bufptr, 0)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to copy.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {\\n require(len <= data.length);\\n\\n uint off = buf.buf.length;\\n uint newCapacity = off + len;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n uint dest;\\n uint src;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Length of existing buffer data\\n let buflen := mload(bufptr)\\n // Start address = buffer address + offset + sizeof(buffer length)\\n dest := add(add(bufptr, 32), off)\\n // Update buffer length if we're extending it\\n if gt(newCapacity, buflen) {\\n mstore(bufptr, newCapacity)\\n }\\n src := add(data, 32)\\n }\\n\\n // Copy word-length chunks while possible\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n // Copy remaining bytes\\n unchecked {\\n uint mask = (256 ** (32 - len)) - 1;\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\\n return append(buf, data, data.length);\\n }\\n\\n /**\\n * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\\n * capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint offPlusOne = off + 1;\\n if (off >= buf.capacity) {\\n resize(buf, offPlusOne * 2);\\n }\\n\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + off\\n let dest := add(add(bufptr, off), 32)\\n mstore8(dest, data)\\n // Update buffer length if we extended it\\n if gt(offPlusOne, mload(bufptr)) {\\n mstore(bufptr, offPlusOne)\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (left-aligned).\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n unchecked {\\n uint mask = (256 ** len) - 1;\\n // Right-align data\\n data = data >> (8 * (32 - len));\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chhaining.\\n */\\n function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\\n return append(buf, bytes32(data), 20);\\n }\\n\\n /**\\n * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\\n return append(buf, data, 32);\\n }\\n\\n /**\\n * @dev Appends a byte to the end of the buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (right-aligned).\\n * @return The original buffer.\\n */\\n function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n unchecked {\\n uint mask = (256 ** len) - 1;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n }\\n return buf;\\n }\\n}\\n\",\"keccak256\":\"0xd85358722045348893aeedd23539816c9d1b218ab801a3fcd1ec4e38ecc8eb22\",\"license\":\"BSD-2-Clause\"},\"project/lib/ens-contracts/contracts/dnssec-oracle/RRUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../utils/BytesUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/// @dev RRUtils is a library that provides utilities for parsing DNS resource records.\\nlibrary RRUtils {\\n using BytesUtils for *;\\n using Buffer for *;\\n\\n /// @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.\\n /// @param self The byte array to read a name from.\\n /// @param offset The offset to start reading at.\\n /// @return The length of the DNS name at 'offset', in bytes.\\n function nameLength(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 idx = offset;\\n while (true) {\\n assert(idx < self.length);\\n uint256 labelLen = self.readUint8(idx);\\n idx += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n }\\n return idx - offset;\\n }\\n\\n /// @dev Returns a DNS format name at the specified offset of self.\\n /// @param self The byte array to read a name from.\\n /// @param offset The offset to start reading at.\\n /// @return ret The name.\\n function readName(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (bytes memory ret) {\\n uint256 len = nameLength(self, offset);\\n return self.substring(offset, len);\\n }\\n\\n /// @dev Returns the number of labels in the DNS name at 'offset' in 'self'.\\n /// @param self The byte array to read a name from.\\n /// @param offset The offset to start reading at.\\n /// @return The number of labels in the DNS name at 'offset', in bytes.\\n function labelCount(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 count = 0;\\n while (true) {\\n assert(offset < self.length);\\n uint256 labelLen = self.readUint8(offset);\\n offset += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n count += 1;\\n }\\n return count;\\n }\\n\\n uint256 constant RRSIG_TYPE = 0;\\n uint256 constant RRSIG_ALGORITHM = 2;\\n uint256 constant RRSIG_LABELS = 3;\\n uint256 constant RRSIG_TTL = 4;\\n uint256 constant RRSIG_EXPIRATION = 8;\\n uint256 constant RRSIG_INCEPTION = 12;\\n uint256 constant RRSIG_KEY_TAG = 16;\\n uint256 constant RRSIG_SIGNER_NAME = 18;\\n\\n struct SignedSet {\\n uint16 typeCovered;\\n uint8 algorithm;\\n uint8 labels;\\n uint32 ttl;\\n uint32 expiration;\\n uint32 inception;\\n uint16 keytag;\\n bytes signerName;\\n bytes data;\\n bytes name;\\n }\\n\\n function readSignedSet(\\n bytes memory data\\n ) internal pure returns (SignedSet memory self) {\\n self.typeCovered = data.readUint16(RRSIG_TYPE);\\n self.algorithm = data.readUint8(RRSIG_ALGORITHM);\\n self.labels = data.readUint8(RRSIG_LABELS);\\n self.ttl = data.readUint32(RRSIG_TTL);\\n self.expiration = data.readUint32(RRSIG_EXPIRATION);\\n self.inception = data.readUint32(RRSIG_INCEPTION);\\n self.keytag = data.readUint16(RRSIG_KEY_TAG);\\n self.signerName = readName(data, RRSIG_SIGNER_NAME);\\n self.data = data.substring(\\n RRSIG_SIGNER_NAME + self.signerName.length,\\n data.length - RRSIG_SIGNER_NAME - self.signerName.length\\n );\\n }\\n\\n function rrs(\\n SignedSet memory rrset\\n ) internal pure returns (RRIterator memory) {\\n return iterateRRs(rrset.data, 0);\\n }\\n\\n /// @dev An iterator over resource records.\\n struct RRIterator {\\n bytes data;\\n uint256 offset;\\n uint16 dnstype;\\n uint16 class;\\n uint32 ttl;\\n uint256 rdataOffset;\\n uint256 nextOffset;\\n }\\n\\n /// @dev Begins iterating over resource records.\\n /// @param self The byte string to read from.\\n /// @param offset The offset to start reading at.\\n /// @return ret An iterator object.\\n function iterateRRs(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (RRIterator memory ret) {\\n ret.data = self;\\n ret.nextOffset = offset;\\n next(ret);\\n }\\n\\n /// @dev Returns true iff there are more RRs to iterate.\\n /// @param iter The iterator to check.\\n /// @return True iff the iterator has finished.\\n function done(RRIterator memory iter) internal pure returns (bool) {\\n return iter.offset >= iter.data.length;\\n }\\n\\n /// @dev Moves the iterator to the next resource record.\\n /// @param iter The iterator to advance.\\n function next(RRIterator memory iter) internal pure {\\n iter.offset = iter.nextOffset;\\n if (iter.offset >= iter.data.length) {\\n return;\\n }\\n\\n // Skip the name\\n uint256 off = iter.offset + nameLength(iter.data, iter.offset);\\n\\n // Read type, class, and ttl\\n iter.dnstype = iter.data.readUint16(off);\\n off += 2;\\n iter.class = iter.data.readUint16(off);\\n off += 2;\\n iter.ttl = iter.data.readUint32(off);\\n off += 4;\\n\\n // Read the rdata\\n uint256 rdataLength = iter.data.readUint16(off);\\n off += 2;\\n iter.rdataOffset = off;\\n iter.nextOffset = off + rdataLength;\\n }\\n\\n /// @dev Returns the name of the current record.\\n /// @param iter The iterator.\\n /// @return A new bytes object containing the owner name from the RR.\\n function name(RRIterator memory iter) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.offset,\\n nameLength(iter.data, iter.offset)\\n );\\n }\\n\\n /// @dev Returns the rdata portion of the current record.\\n /// @param iter The iterator.\\n /// @return A new bytes object containing the RR's RDATA.\\n function rdata(\\n RRIterator memory iter\\n ) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.rdataOffset,\\n iter.nextOffset - iter.rdataOffset\\n );\\n }\\n\\n uint256 constant DNSKEY_FLAGS = 0;\\n uint256 constant DNSKEY_PROTOCOL = 2;\\n uint256 constant DNSKEY_ALGORITHM = 3;\\n uint256 constant DNSKEY_PUBKEY = 4;\\n\\n struct DNSKEY {\\n uint16 flags;\\n uint8 protocol;\\n uint8 algorithm;\\n bytes publicKey;\\n }\\n\\n function readDNSKEY(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DNSKEY memory self) {\\n self.flags = data.readUint16(offset + DNSKEY_FLAGS);\\n self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);\\n self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);\\n self.publicKey = data.substring(\\n offset + DNSKEY_PUBKEY,\\n length - DNSKEY_PUBKEY\\n );\\n }\\n\\n uint256 constant DS_KEY_TAG = 0;\\n uint256 constant DS_ALGORITHM = 2;\\n uint256 constant DS_DIGEST_TYPE = 3;\\n uint256 constant DS_DIGEST = 4;\\n\\n struct DS {\\n uint16 keytag;\\n uint8 algorithm;\\n uint8 digestType;\\n bytes digest;\\n }\\n\\n function readDS(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DS memory self) {\\n self.keytag = data.readUint16(offset + DS_KEY_TAG);\\n self.algorithm = data.readUint8(offset + DS_ALGORITHM);\\n self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);\\n self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);\\n }\\n\\n function isSubdomainOf(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (bool) {\\n uint256 off = 0;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n while (counts > othercounts) {\\n off = progress(self, off);\\n counts--;\\n }\\n\\n return self.equals(off, other, 0);\\n }\\n\\n function compareNames(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (int256) {\\n if (self.equals(other)) {\\n return 0;\\n }\\n\\n uint256 off;\\n uint256 otheroff;\\n uint256 prevoff;\\n uint256 otherprevoff;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n // Keep removing labels from the front of the name until both names are equal length\\n while (counts > othercounts) {\\n prevoff = off;\\n off = progress(self, off);\\n counts--;\\n }\\n\\n while (othercounts > counts) {\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n othercounts--;\\n }\\n\\n // Compare the last nonequal labels to each other\\n while (counts > 0 && !self.equals(off, other, otheroff)) {\\n prevoff = off;\\n off = progress(self, off);\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n counts -= 1;\\n }\\n\\n if (off == 0) {\\n return -1;\\n }\\n if (otheroff == 0) {\\n return 1;\\n }\\n\\n return\\n self.compare(\\n prevoff + 1,\\n self.readUint8(prevoff),\\n other,\\n otherprevoff + 1,\\n other.readUint8(otherprevoff)\\n );\\n }\\n\\n /// @dev Compares two serial numbers using RFC1982 serial number math.\\n function serialNumberGte(\\n uint32 i1,\\n uint32 i2\\n ) internal pure returns (bool) {\\n unchecked {\\n return int32(i1) - int32(i2) >= 0;\\n }\\n }\\n\\n function progress(\\n bytes memory body,\\n uint256 off\\n ) internal pure returns (uint256) {\\n return off + 1 + body.readUint8(off);\\n }\\n\\n /// @dev Computes the keytag for a chunk of data.\\n /// @param data The data to compute a keytag for.\\n /// @return The computed key tag.\\n function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n /* This function probably deserves some explanation.\\n * The DNSSEC keytag function is a checksum that relies on summing up individual bytes\\n * from the input string, with some mild bitshifting. Here's a Naive solidity implementation:\\n *\\n * function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n * uint ac;\\n * for (uint i = 0; i < data.length; i++) {\\n * ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);\\n * }\\n * return uint16(ac + (ac >> 16));\\n * }\\n *\\n * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;\\n * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's\\n * large words work in our favour.\\n *\\n * The code below works by treating the input as a series of 256 bit words. It first masks out\\n * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.\\n * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're\\n * effectively summing 16 different numbers with each EVM ADD opcode.\\n *\\n * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.\\n * It does this using the same trick - mask out every other value, shift to align them, add them together.\\n * After the first addition on both accumulators, there's enough room to add the two accumulators together,\\n * and the remaining sums can be done just on ac1.\\n */\\n unchecked {\\n require(data.length <= 8192, \\\"Long keys not permitted\\\");\\n uint256 ac1;\\n uint256 ac2;\\n for (uint256 i = 0; i < data.length + 31; i += 32) {\\n uint256 word;\\n assembly {\\n word := mload(add(add(data, 32), i))\\n }\\n if (i + 32 > data.length) {\\n uint256 unused = 256 - (data.length - i) * 8;\\n word = (word >> unused) << unused;\\n }\\n ac1 +=\\n (word &\\n 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>\\n 8;\\n ac2 += (word &\\n 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);\\n }\\n ac1 =\\n (ac1 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac1 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac2 =\\n (ac2 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac2 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac1 = (ac1 << 8) + ac2;\\n ac1 =\\n (ac1 &\\n 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>\\n 32);\\n ac1 =\\n (ac1 &\\n 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>\\n 64);\\n ac1 =\\n (ac1 &\\n 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +\\n (ac1 >> 128);\\n ac1 += (ac1 >> 16) & 0xFFFF;\\n return uint16(ac1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdbab10dde632a1a02ee1c706bd4a31f9fb6195bd15a360528f7f6615e8fc895a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/Multicallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"./IMulticallable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nabstract contract Multicallable is IMulticallable, ERC165 {\\n function _multicall(\\n bytes32 nodehash,\\n bytes[] calldata data\\n ) internal returns (bytes[] memory results) {\\n results = new bytes[](data.length);\\n for (uint256 i = 0; i < data.length; i++) {\\n if (nodehash != bytes32(0)) {\\n bytes32 txNamehash = bytes32(data[i][4:36]);\\n require(\\n txNamehash == nodehash,\\n \\\"multicall: All records must have a matching namehash\\\"\\n );\\n }\\n (bool success, bytes memory result) = address(this).delegatecall(\\n data[i]\\n );\\n require(success);\\n results[i] = result;\\n }\\n return results;\\n }\\n\\n // This function provides an extra security check when called\\n // from privileged contracts (such as EthRegistrarController)\\n // that can set records on behalf of the node owners\\n function multicallWithNodeCheck(\\n bytes32 nodehash,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results) {\\n return _multicall(nodehash, data);\\n }\\n\\n function multicall(\\n bytes[] calldata data\\n ) public override returns (bytes[] memory results) {\\n return _multicall(bytes32(0), data);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IMulticallable).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x2bf0cc11477d25abf9b3c85826bfe979911d1b48ea747f65a7fc4fd882bc9e9a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverBase.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"./profiles/IVersionableResolver.sol\\\";\\n\\nabstract contract ResolverBase is ERC165, IVersionableResolver {\\n mapping(bytes32 => uint64) public recordVersions;\\n\\n function isAuthorised(bytes32 node) internal view virtual returns (bool);\\n\\n modifier authorised(bytes32 node) {\\n require(isAuthorised(node));\\n _;\\n }\\n\\n /// Increments the record version associated with an ENS node.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n function clearRecords(bytes32 node) public virtual authorised(node) {\\n recordVersions[node]++;\\n emit VersionChanged(node, recordVersions[node]);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IVersionableResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0xb063f86c1e75508779fd23762f20ebfbb2f3ef6d84328038e3de01cf59d18e4b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ABIResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"./IABIResolver.sol\\\";\\nimport \\\"../ResolverBase.sol\\\";\\n\\nabstract contract ABIResolver is IABIResolver, ResolverBase {\\n mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_abis;\\n\\n /// Sets the ABI associated with an ENS node.\\n /// Nodes may have one ABI of each content type. To remove an ABI, set it to\\n /// the empty string.\\n /// @param node The node to update.\\n /// @param contentType The content type of the ABI\\n /// @param data The ABI data.\\n function setABI(\\n bytes32 node,\\n uint256 contentType,\\n bytes calldata data\\n ) external virtual authorised(node) {\\n // Content types must be powers of 2\\n require(((contentType - 1) & contentType) == 0);\\n\\n versionable_abis[recordVersions[node]][node][contentType] = data;\\n emit ABIChanged(node, contentType);\\n }\\n\\n /// Returns the ABI associated with an ENS node.\\n /// Defined in EIP205.\\n /// @param node The ENS node to query\\n /// @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\\n /// @return contentType The content type of the return value\\n /// @return data The ABI data\\n function ABI(\\n bytes32 node,\\n uint256 contentTypes\\n ) external view virtual override returns (uint256, bytes memory) {\\n mapping(uint256 => bytes) storage abiset = versionable_abis[\\n recordVersions[node]\\n ][node];\\n\\n for (\\n uint256 contentType = 1;\\n contentType > 0 && contentType <= contentTypes;\\n contentType <<= 1\\n ) {\\n if (\\n (contentType & contentTypes) != 0 &&\\n abiset[contentType].length > 0\\n ) {\\n return (contentType, abiset[contentType]);\\n }\\n }\\n\\n return (0, bytes(\\\"\\\"));\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IABIResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0xf938b15d989964645a1aba2c151663fd63d2942c8daf46470ac7b15fe3d41641\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/AddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport {ResolverBase, IERC165} from \\\"../ResolverBase.sol\\\";\\nimport {IAddrResolver} from \\\"./IAddrResolver.sol\\\";\\nimport {IAddressResolver} from \\\"./IAddressResolver.sol\\\";\\nimport {IHasAddressResolver} from \\\"./IHasAddressResolver.sol\\\";\\nimport {ENSIP19, COIN_TYPE_ETH, COIN_TYPE_DEFAULT} from \\\"../../utils/ENSIP19.sol\\\";\\n\\nabstract contract AddrResolver is\\n IAddrResolver,\\n IAddressResolver,\\n IHasAddressResolver,\\n ResolverBase\\n{\\n mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_addresses;\\n\\n /// @notice The supplied address could not be converted to `address`.\\n /// @dev Error selector: `0x8d666f60`\\n error InvalidEVMAddress(bytes addressBytes);\\n\\n /// @notice Set `addr(60)` of the associated ENS node.\\n /// `address(0)` is stored as `new bytes(20)`.\\n /// @param node The node to update.\\n /// @param _addr The address to set.\\n function setAddr(\\n bytes32 node,\\n address _addr\\n ) external virtual authorised(node) {\\n setAddr(node, COIN_TYPE_ETH, abi.encodePacked(_addr));\\n }\\n\\n /// @notice Get `addr(60)` as `address` of the associated ENS node.\\n /// @param node The node to query.\\n /// @return The associated address.\\n function addr(\\n bytes32 node\\n ) public view virtual override returns (address payable) {\\n return payable(address(bytes20(addr(node, COIN_TYPE_ETH))));\\n }\\n\\n /// @notice Set the address for coin type of the associated ENS node.\\n /// Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes.\\n /// @param node The node to update.\\n /// @param coinType The coin type.\\n /// @param addressBytes The address to set.\\n function setAddr(\\n bytes32 node,\\n uint256 coinType,\\n bytes memory addressBytes\\n ) public virtual authorised(node) {\\n if (\\n addressBytes.length != 0 &&\\n addressBytes.length != 20 &&\\n ENSIP19.isEVMCoinType(coinType)\\n ) {\\n revert InvalidEVMAddress(addressBytes);\\n }\\n emit AddressChanged(node, coinType, addressBytes);\\n if (coinType == COIN_TYPE_ETH) {\\n emit AddrChanged(node, address(bytes20(addressBytes)));\\n }\\n versionable_addresses[recordVersions[node]][node][\\n coinType\\n ] = addressBytes;\\n }\\n\\n /// @notice Get the address for coin type of the associated ENS node.\\n /// If coin type is EVM and empty, defaults to `addr(COIN_TYPE_DEFAULT)`.\\n /// @param node The node to query.\\n /// @param coinType The coin type.\\n /// @return addressBytes The assocated address.\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) public view virtual override returns (bytes memory addressBytes) {\\n mapping(uint256 => bytes) storage addrs = versionable_addresses[\\n recordVersions[node]\\n ][node];\\n addressBytes = addrs[coinType];\\n if (\\n addressBytes.length == 0 && ENSIP19.chainFromCoinType(coinType) > 0\\n ) {\\n addressBytes = addrs[COIN_TYPE_DEFAULT];\\n }\\n }\\n\\n /// @inheritdoc IHasAddressResolver\\n function hasAddr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bool) {\\n return\\n versionable_addresses[recordVersions[node]][node][coinType].length >\\n 0;\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public view virtual override returns (bool) {\\n return\\n type(IAddrResolver).interfaceId == interfaceId ||\\n type(IAddressResolver).interfaceId == interfaceId ||\\n type(IHasAddressResolver).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0x2d214ea1213dbd8cc02d32355edf044a6551296df56e8a4931d3447092e8abcc\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ContentHashResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./IContentHashResolver.sol\\\";\\n\\nabstract contract ContentHashResolver is IContentHashResolver, ResolverBase {\\n mapping(uint64 => mapping(bytes32 => bytes)) versionable_hashes;\\n\\n /// Sets the contenthash associated with an ENS node.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n /// @param hash The contenthash to set\\n function setContenthash(\\n bytes32 node,\\n bytes calldata hash\\n ) external virtual authorised(node) {\\n versionable_hashes[recordVersions[node]][node] = hash;\\n emit ContenthashChanged(node, hash);\\n }\\n\\n /// Returns the contenthash associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function contenthash(\\n bytes32 node\\n ) external view virtual override returns (bytes memory) {\\n return versionable_hashes[recordVersions[node]][node];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IContentHashResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x8eddfb712744906b41ad3458171438605982cdcd0c570d91fed49eca56bf7def\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/DNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"../../dnssec-oracle/RRUtils.sol\\\";\\nimport \\\"./IDNSRecordResolver.sol\\\";\\nimport \\\"./IDNSZoneResolver.sol\\\";\\n\\nabstract contract DNSResolver is\\n IDNSRecordResolver,\\n IDNSZoneResolver,\\n ResolverBase\\n{\\n using RRUtils for *;\\n using BytesUtils for bytes;\\n\\n // Zone hashes for the domains.\\n // A zone hash is an EIP-1577 content hash in binary format that should point to a\\n // resource containing a single zonefile.\\n // node => contenthash\\n mapping(uint64 => mapping(bytes32 => bytes)) private versionable_zonehashes;\\n\\n // The records themselves. Stored as binary RRSETs\\n // node => version => name => resource => data\\n mapping(uint64 => mapping(bytes32 => mapping(bytes32 => mapping(uint16 => bytes))))\\n private versionable_records;\\n\\n // Count of number of entries for a given name. Required for DNS resolvers\\n // when resolving wildcards.\\n // node => version => name => number of records\\n mapping(uint64 => mapping(bytes32 => mapping(bytes32 => uint16)))\\n private versionable_nameEntriesCount;\\n\\n /// Set one or more DNS records. Records are supplied in wire-format.\\n /// Records with the same node/name/resource must be supplied one after the\\n /// other to ensure the data is updated correctly. For example, if the data\\n /// was supplied:\\n /// a.example.com IN A 1.2.3.4\\n /// a.example.com IN A 5.6.7.8\\n /// www.example.com IN CNAME a.example.com.\\n /// then this would store the two A records for a.example.com correctly as a\\n /// single RRSET, however if the data was supplied:\\n /// a.example.com IN A 1.2.3.4\\n /// www.example.com IN CNAME a.example.com.\\n /// a.example.com IN A 5.6.7.8\\n /// then this would store the first A record, the CNAME, then the second A\\n /// record which would overwrite the first.\\n ///\\n /// @param node the namehash of the node for which to set the records\\n /// @param data the DNS wire format records to set\\n function setDNSRecords(\\n bytes32 node,\\n bytes calldata data\\n ) external virtual authorised(node) {\\n uint16 resource = 0;\\n uint256 offset = 0;\\n bytes memory name;\\n bytes memory value;\\n bytes32 nameHash;\\n uint64 version = recordVersions[node];\\n // Iterate over the data to add the resource records\\n for (\\n RRUtils.RRIterator memory iter = data.iterateRRs(0);\\n !iter.done();\\n iter.next()\\n ) {\\n if (resource == 0) {\\n resource = iter.dnstype;\\n name = iter.name();\\n nameHash = keccak256(abi.encodePacked(name));\\n value = bytes(iter.rdata());\\n } else {\\n bytes memory newName = iter.name();\\n if (resource != iter.dnstype || !name.equals(newName)) {\\n setDNSRRSet(\\n node,\\n name,\\n resource,\\n data,\\n offset,\\n iter.offset - offset,\\n value.length == 0,\\n version\\n );\\n resource = iter.dnstype;\\n offset = iter.offset;\\n name = newName;\\n nameHash = keccak256(name);\\n value = bytes(iter.rdata());\\n }\\n }\\n }\\n if (name.length > 0) {\\n setDNSRRSet(\\n node,\\n name,\\n resource,\\n data,\\n offset,\\n data.length - offset,\\n value.length == 0,\\n version\\n );\\n }\\n }\\n\\n /// Obtain a DNS record.\\n /// @param node the namehash of the node for which to fetch the record\\n /// @param name the keccak-256 hash of the fully-qualified name for which to fetch the record\\n /// @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\\n /// @return the DNS record in wire format if present, otherwise empty\\n function dnsRecord(\\n bytes32 node,\\n bytes32 name,\\n uint16 resource\\n ) public view virtual override returns (bytes memory) {\\n return versionable_records[recordVersions[node]][node][name][resource];\\n }\\n\\n /// Check if a given node has records.\\n /// @param node the namehash of the node for which to check the records\\n /// @param name the namehash of the node for which to check the records\\n function hasDNSRecords(\\n bytes32 node,\\n bytes32 name\\n ) public view virtual returns (bool) {\\n return (versionable_nameEntriesCount[recordVersions[node]][node][\\n name\\n ] != 0);\\n }\\n\\n /// setZonehash sets the hash for the zone.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n /// @param hash The zonehash to set\\n function setZonehash(\\n bytes32 node,\\n bytes calldata hash\\n ) external virtual authorised(node) {\\n uint64 currentRecordVersion = recordVersions[node];\\n bytes memory oldhash = versionable_zonehashes[currentRecordVersion][\\n node\\n ];\\n versionable_zonehashes[currentRecordVersion][node] = hash;\\n emit DNSZonehashChanged(node, oldhash, hash);\\n }\\n\\n /// zonehash obtains the hash for the zone.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function zonehash(\\n bytes32 node\\n ) external view virtual override returns (bytes memory) {\\n return versionable_zonehashes[recordVersions[node]][node];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IDNSRecordResolver).interfaceId ||\\n interfaceID == type(IDNSZoneResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n\\n function setDNSRRSet(\\n bytes32 node,\\n bytes memory name,\\n uint16 resource,\\n bytes memory data,\\n uint256 offset,\\n uint256 size,\\n bool deleteRecord,\\n uint64 version\\n ) private {\\n bytes32 nameHash = keccak256(name);\\n bytes memory rrData = data.substring(offset, size);\\n if (deleteRecord) {\\n if (\\n versionable_records[version][node][nameHash][resource].length !=\\n 0\\n ) {\\n versionable_nameEntriesCount[version][node][nameHash]--;\\n }\\n delete (versionable_records[version][node][nameHash][resource]);\\n emit DNSRecordDeleted(node, name, resource);\\n } else {\\n if (\\n versionable_records[version][node][nameHash][resource].length ==\\n 0\\n ) {\\n versionable_nameEntriesCount[version][node][nameHash]++;\\n }\\n versionable_records[version][node][nameHash][resource] = rrData;\\n emit DNSRecordChanged(node, name, resource, rrData);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3f5344239a3461c06389c952ae8e6feb29f0fd72dea1baaf31be81ba8b6a194a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/DataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./IDataResolver.sol\\\";\\n\\nabstract contract DataResolver is\\n IDataResolver,\\n ResolverBase\\n{\\n mapping(uint64 => mapping(bytes32 node => mapping(string key => bytes data)))\\n private versionable_dataStore;\\n\\n /// @notice Sets the data associated with the key, `key` for a specific `node`.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n /// @param key The key to set.\\n /// @param value The arbitrary `bytes` data to set.\\n function setData(\\n bytes32 node,\\n string calldata key,\\n bytes calldata value\\n ) external virtual authorised(node) {\\n versionable_dataStore[recordVersions[node]][node][key] = value;\\n _afterSetData(node, key, value);\\n emit DataChanged(node, key, key, value);\\n }\\n\\n /// @dev Hook called after data is set. Override to add custom behavior.\\n function _afterSetData(\\n bytes32 node,\\n string memory key,\\n bytes memory value\\n ) internal virtual {}\\n\\n /// @notice For a specific `node`, get the data associated with the key, `key`.\\n /// @param node The node (namehash) for which data is being fetched.\\n /// @param key The key.\\n /// @return The associated arbitrary `bytes` data.\\n function data(\\n bytes32 node,\\n string calldata key\\n ) external view returns (bytes memory) {\\n return versionable_dataStore[recordVersions[node]][node][key];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IDataResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x0ce3e6b2244a9d074371ecb43ba9eaca8a1b3410c73c50d852b4e3696de1cd7d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IABIResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IABIResolver {\\n event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\\n\\n /// Returns the ABI associated with an ENS node.\\n /// Defined in EIP205.\\n /// @param node The ENS node to query\\n /// @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\\n /// @return contentType The content type of the return value\\n /// @return data The ABI data\\n function ABI(\\n bytes32 node,\\n uint256 contentTypes\\n ) external view returns (uint256, bytes memory);\\n}\\n\",\"keccak256\":\"0x3a7a763d7a4f0d196c4b628545b022b1d1d0e37baf84eaa6eecb1a57a1633cad\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the legacy (ETH-only) addr function.\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /// Returns the address associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated address.\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x91dd0c350698c505d6c7e4c919da9f981d4b8d7ad062e25073fa1f6af7cb79d1\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the new (multicoin) addr function.\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x8da5dd0fc1c5ab4f47e03c23126976a86d4b2dbeac161e70e3af9e2a13330cf0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IContentHashResolver {\\n event ContenthashChanged(bytes32 indexed node, bytes hash);\\n\\n /// Returns the contenthash associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function contenthash(bytes32 node) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0xaa978b1ee4c19e99c8aa409dc553e9b4c1bf9fe3c5bad718cd3589e6c9e6d121\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDNSRecordResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IDNSRecordResolver {\\n // DNSRecordChanged is emitted whenever a given node/name/resource's RRSET is updated.\\n event DNSRecordChanged(\\n bytes32 indexed node,\\n bytes name,\\n uint16 resource,\\n bytes record\\n );\\n // DNSRecordDeleted is emitted whenever a given node/name/resource's RRSET is deleted.\\n event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);\\n\\n /// Obtain a DNS record.\\n /// @param node the namehash of the node for which to fetch the record\\n /// @param name the keccak-256 hash of the fully-qualified name for which to fetch the record\\n /// @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\\n /// @return the DNS record in wire format if present, otherwise empty\\n function dnsRecord(\\n bytes32 node,\\n bytes32 name,\\n uint16 resource\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x434bf76bba71eed3e0f22b3a5b9f8aaed0ddd8b79f6a1e7c7447785be5924d3b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDNSZoneResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IDNSZoneResolver {\\n // DNSZonehashChanged is emitted whenever a given node's zone hash is updated.\\n event DNSZonehashChanged(\\n bytes32 indexed node,\\n bytes lastzonehash,\\n bytes zonehash\\n );\\n\\n /// zonehash obtains the hash for the zone.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function zonehash(bytes32 node) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x3a028c0b13721c7627c55bbf5a7d0762d5b1db1045fdc0f8e417011876bd2d29\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// @dev Interface selector: `0xecbfada3`\\ninterface IDataResolver {\\n /// @notice For a specific `node`, the data associated with a `key` has changed.\\n event DataChanged(\\n bytes32 indexed node, \\n string indexed indexedKey,\\n string key, \\n bytes indexed indexedData\\n );\\n \\n /// @notice For a specific `node`, get the data associated with the key, `key`.\\n /// @param node The node (namehash) for which data is being fetched.\\n /// @param key The key.\\n /// @return The associated arbitrary `bytes` data.\\n function data(\\n bytes32 node,\\n string calldata key\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x502a38d58d2047db3fa021897eda32bb6f4cde9746606e691e6acf25c396d88e\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IHasAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IHasAddressResolver {\\n /// @notice Determine if an addresss is stored for the coin type of the associated ENS node.\\n /// @param node The node to query.\\n /// @param coinType The coin type.\\n /// @return True if the associated address is not empty.\\n function hasAddr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbe13530b8cc027517c235e422326abd36bb1152dac8546713471be2a7335cf2b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IInterfaceResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IInterfaceResolver {\\n event InterfaceChanged(\\n bytes32 indexed node,\\n bytes4 indexed interfaceID,\\n address implementer\\n );\\n\\n /// Returns the address of a contract that implements the specified interface for this name.\\n /// If an implementer has not been set for this interfaceID and name, the resolver will query\\n /// the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\\n /// contract implements EIP165 and returns `true` for the specified interfaceID, its address\\n /// will be returned.\\n /// @param node The ENS node to query.\\n /// @param interfaceID The EIP 165 interface ID to check for.\\n /// @return The address that implements this interface, or 0 if the interface is unsupported.\\n function interfaceImplementer(\\n bytes32 node,\\n bytes4 interfaceID\\n ) external view returns (address);\\n}\\n\",\"keccak256\":\"0x510176a3fe60471775328756ab025d8bafda7063f52f218728ca559b8f61a357\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x3ab986332e0baad7aeb4b426aace3aa1c235be5efff8db4b6f1ce501bcdd9e68\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IPubkeyResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IPubkeyResolver {\\n event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\\n\\n /// Returns the SECP256k1 public key associated with an ENS node.\\n /// Defined in EIP 619.\\n /// @param node The ENS node to query\\n /// @return x The X coordinate of the curve point for the public key.\\n /// @return y The Y coordinate of the curve point for the public key.\\n function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);\\n}\\n\",\"keccak256\":\"0x1a21561b58ce17db400c015882ff07f12f9bd0df0e7b9305841799aada441820\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ITextResolver {\\n event TextChanged(\\n bytes32 indexed node,\\n string indexed indexedKey,\\n string key,\\n string value\\n );\\n\\n /// Returns the text data associated with an ENS node and key.\\n /// @param node The ENS node to query.\\n /// @param key The text data key to query.\\n /// @return The associated text data.\\n function text(\\n bytes32 node,\\n string calldata key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xe91c15697be2d20417cce3c58d4ecce34796986fdedc97be5b93a823be58e471\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IVersionableResolver {\\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\\n\\n function recordVersions(bytes32 node) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0xd0d09596f20c57bafb2ffa8521a8c57120e9af6c6b194f9c689d4da56f91a57c\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/InterfaceResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./AddrResolver.sol\\\";\\nimport \\\"./IInterfaceResolver.sol\\\";\\n\\nabstract contract InterfaceResolver is IInterfaceResolver, AddrResolver {\\n mapping(uint64 => mapping(bytes32 => mapping(bytes4 => address))) versionable_interfaces;\\n\\n /// Sets an interface associated with a name.\\n /// Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support.\\n /// @param node The node to update.\\n /// @param interfaceID The EIP 165 interface ID.\\n /// @param implementer The address of a contract that implements this interface for this node.\\n function setInterface(\\n bytes32 node,\\n bytes4 interfaceID,\\n address implementer\\n ) external virtual authorised(node) {\\n versionable_interfaces[recordVersions[node]][node][\\n interfaceID\\n ] = implementer;\\n emit InterfaceChanged(node, interfaceID, implementer);\\n }\\n\\n /// Returns the address of a contract that implements the specified interface for this name.\\n /// If an implementer has not been set for this interfaceID and name, the resolver will query\\n /// the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\\n /// contract implements EIP165 and returns `true` for the specified interfaceID, its address\\n /// will be returned.\\n /// @param node The ENS node to query.\\n /// @param interfaceID The EIP 165 interface ID to check for.\\n /// @return The address that implements this interface, or 0 if the interface is unsupported.\\n function interfaceImplementer(\\n bytes32 node,\\n bytes4 interfaceID\\n ) external view virtual override returns (address) {\\n address implementer = versionable_interfaces[recordVersions[node]][\\n node\\n ][interfaceID];\\n if (implementer != address(0)) {\\n return implementer;\\n }\\n\\n address a = addr(node);\\n if (a == address(0)) {\\n return address(0);\\n }\\n\\n (bool success, bytes memory returnData) = a.staticcall(\\n abi.encodeWithSignature(\\n \\\"supportsInterface(bytes4)\\\",\\n type(IERC165).interfaceId\\n )\\n );\\n if (!success || returnData.length < 32 || returnData[31] == 0) {\\n // EIP 165 not supported by target\\n return address(0);\\n }\\n\\n (success, returnData) = a.staticcall(\\n abi.encodeWithSignature(\\\"supportsInterface(bytes4)\\\", interfaceID)\\n );\\n if (!success || returnData.length < 32 || returnData[31] == 0) {\\n // Specified interface not supported by target\\n return address(0);\\n }\\n\\n return a;\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IInterfaceResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x029b7f2fa0e763b914e2769c05b8b230aea7991f3947e5324499454e98310300\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/NameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./INameResolver.sol\\\";\\n\\nabstract contract NameResolver is INameResolver, ResolverBase {\\n mapping(uint64 => mapping(bytes32 => string)) versionable_names;\\n\\n /// Sets the name associated with an ENS node, for reverse records.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n function setName(\\n bytes32 node,\\n string calldata newName\\n ) external virtual authorised(node) {\\n versionable_names[recordVersions[node]][node] = newName;\\n emit NameChanged(node, newName);\\n }\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(\\n bytes32 node\\n ) external view virtual override returns (string memory) {\\n return versionable_names[recordVersions[node]][node];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(INameResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x2bee21414404629419db708bd8b8e284e702a175c17451c4b8f0f06ce5c7a250\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/PubkeyResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./IPubkeyResolver.sol\\\";\\n\\nabstract contract PubkeyResolver is IPubkeyResolver, ResolverBase {\\n struct PublicKey {\\n bytes32 x;\\n bytes32 y;\\n }\\n\\n mapping(uint64 => mapping(bytes32 => PublicKey)) versionable_pubkeys;\\n\\n /// Sets the SECP256k1 public key associated with an ENS node.\\n /// @param node The ENS node to query\\n /// @param x the X coordinate of the curve point for the public key.\\n /// @param y the Y coordinate of the curve point for the public key.\\n function setPubkey(\\n bytes32 node,\\n bytes32 x,\\n bytes32 y\\n ) external virtual authorised(node) {\\n versionable_pubkeys[recordVersions[node]][node] = PublicKey(x, y);\\n emit PubkeyChanged(node, x, y);\\n }\\n\\n /// Returns the SECP256k1 public key associated with an ENS node.\\n /// Defined in EIP 619.\\n /// @param node The ENS node to query\\n /// @return x The X coordinate of the curve point for the public key.\\n /// @return y The Y coordinate of the curve point for the public key.\\n function pubkey(\\n bytes32 node\\n ) external view virtual override returns (bytes32 x, bytes32 y) {\\n uint64 currentRecordVersion = recordVersions[node];\\n return (\\n versionable_pubkeys[currentRecordVersion][node].x,\\n versionable_pubkeys[currentRecordVersion][node].y\\n );\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IPubkeyResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x697b350cd142af9ed401e1e73f395f039bb12cdb503bc6c3488482788d69587b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/TextResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./ITextResolver.sol\\\";\\n\\nabstract contract TextResolver is ITextResolver, ResolverBase {\\n mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts;\\n\\n /// Sets the text data associated with an ENS node and key.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n /// @param key The key to set.\\n /// @param value The text data value to set.\\n function setText(\\n bytes32 node,\\n string calldata key,\\n string calldata value\\n ) external virtual authorised(node) {\\n versionable_texts[recordVersions[node]][node][key] = value;\\n emit TextChanged(node, key, key, value);\\n }\\n\\n /// Returns the text data associated with an ENS node and key.\\n /// @param node The ENS node to query.\\n /// @param key The text data key to query.\\n /// @return The associated text data.\\n function text(\\n bytes32 node,\\n string calldata key\\n ) external view virtual override returns (string memory) {\\n return versionable_texts[recordVersions[node]][node][key];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(ITextResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x82a914dfe1b30634e729c03450e4c9ef4afd53919993231a92fb9cca2f8b3a83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/ENSIP19.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {HexUtils} from \\\"../utils/HexUtils.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\n\\nuint32 constant CHAIN_ID_ETH = 1;\\n\\nuint256 constant COIN_TYPE_ETH = 60;\\nuint256 constant COIN_TYPE_DEFAULT = 1 << 31; // 0x8000_0000\\n\\nstring constant SLUG_ETH = \\\"addr\\\"; // <=> COIN_TYPE_ETH\\nstring constant SLUG_DEFAULT = \\\"default\\\"; // <=> COIN_TYPE_DEFAULT\\nstring constant TLD_REVERSE = \\\"reverse\\\";\\n\\n/// @dev Library for generating reverse names according to ENSIP-19.\\n/// https://docs.ens.domains/ensip/19\\nlibrary ENSIP19 {\\n /// @dev The supplied address was `0x`.\\n /// Error selector: `0x7138356f`\\n error EmptyAddress();\\n\\n /// @dev Extract Chain ID from `coinType`.\\n /// @param coinType The coin type.\\n /// @return The Chain ID or 0 if non-EVM Chain.\\n function chainFromCoinType(\\n uint256 coinType\\n ) internal pure returns (uint32) {\\n if (coinType == COIN_TYPE_ETH) return CHAIN_ID_ETH;\\n coinType ^= COIN_TYPE_DEFAULT;\\n return uint32(coinType < COIN_TYPE_DEFAULT ? coinType : 0);\\n }\\n\\n /// @dev Determine if Coin Type is for an EVM address.\\n /// @param coinType The coin type.\\n /// @return True if coin type represents an EVM address.\\n function isEVMCoinType(uint256 coinType) internal pure returns (bool) {\\n return coinType == COIN_TYPE_DEFAULT || chainFromCoinType(coinType) > 0;\\n }\\n\\n /// @dev Generate Reverse Name from Address + Coin Type.\\n /// Reverts `EmptyAddress` if `addressBytes` is `0x`.\\n /// @param addressBytes The input address.\\n /// @param coinType The coin type.\\n /// @return The ENS reverse name, eg. `1234abcd.addr.reverse`.\\n function reverseName(\\n bytes memory addressBytes,\\n uint256 coinType\\n ) internal pure returns (string memory) {\\n if (addressBytes.length == 0) {\\n revert EmptyAddress();\\n }\\n return\\n string(\\n abi.encodePacked(\\n HexUtils.bytesToHex(addressBytes),\\n bytes1(\\\".\\\"),\\n coinType == COIN_TYPE_ETH\\n ? SLUG_ETH\\n : coinType == COIN_TYPE_DEFAULT\\n ? SLUG_DEFAULT\\n : HexUtils.unpaddedUintToHex(coinType, true),\\n bytes1(\\\".\\\"),\\n TLD_REVERSE\\n )\\n );\\n }\\n\\n /// @dev Parse Reverse Name into Address + Coin Type.\\n /// Matches: `/^[0-9a-fA-F]+\\\\.([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @return addressBytes The address or empty if invalid.\\n /// @return coinType The coin type.\\n function parse(\\n bytes memory name\\n ) internal pure returns (bytes memory addressBytes, uint256 coinType) {\\n (, uint256 offset) = NameCoder.readLabel(name, 0);\\n bool valid;\\n (addressBytes, valid) = HexUtils.hexToBytes(name, 1, offset);\\n if (!valid || addressBytes.length == 0) return (\\\"\\\", 0); // addressBytes not 1+ hex\\n (valid, coinType) = parseNamespace(name, offset);\\n if (!valid) return (\\\"\\\", 0); // invalid namespace\\n }\\n\\n /// @dev Parse Reverse Namespace into Coin Type.\\n /// Matches: `/^([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset to begin parsing.\\n /// @return valid True if a valid reverse namespace.\\n /// @return coinType The coin type.\\n function parseNamespace(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bool valid, uint256 coinType) {\\n (bytes32 labelHash, uint256 offsetTLD) = NameCoder.readLabel(\\n name,\\n offset\\n );\\n if (labelHash == keccak256(bytes(SLUG_ETH))) {\\n coinType = COIN_TYPE_ETH;\\n } else if (labelHash == keccak256(bytes(SLUG_DEFAULT))) {\\n coinType = COIN_TYPE_DEFAULT;\\n } else if (labelHash == bytes32(0)) {\\n return (false, 0); // no slug\\n } else {\\n (bytes32 word, bool validHex) = HexUtils.hexStringToBytes32(\\n name,\\n 1 + offset,\\n offsetTLD\\n );\\n if (!validHex) return (false, 0); // invalid coinType or too long\\n coinType = uint256(word);\\n }\\n (labelHash, offset) = NameCoder.readLabel(name, offsetTLD);\\n if (labelHash != keccak256(bytes(TLD_REVERSE))) return (false, 0); // invalid tld\\n (labelHash, ) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) return (false, 0); // not tld\\n valid = true;\\n }\\n}\\n\",\"keccak256\":\"0xd1af09b014028de4c50489bd58ae424273180bb96d95353d8eefd14845f31824\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/resolver/PublicResolverV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {Multicallable} from \\\"@ens/contracts/resolvers/Multicallable.sol\\\";\\nimport {ABIResolver} from \\\"@ens/contracts/resolvers/profiles/ABIResolver.sol\\\";\\nimport {AddrResolver} from \\\"@ens/contracts/resolvers/profiles/AddrResolver.sol\\\";\\nimport {ContentHashResolver} from \\\"@ens/contracts/resolvers/profiles/ContentHashResolver.sol\\\";\\nimport {DataResolver} from \\\"@ens/contracts/resolvers/profiles/DataResolver.sol\\\";\\nimport {DNSResolver} from \\\"@ens/contracts/resolvers/profiles/DNSResolver.sol\\\";\\nimport {InterfaceResolver} from \\\"@ens/contracts/resolvers/profiles/InterfaceResolver.sol\\\";\\nimport {NameResolver} from \\\"@ens/contracts/resolvers/profiles/NameResolver.sol\\\";\\nimport {PubkeyResolver} from \\\"@ens/contracts/resolvers/profiles/PubkeyResolver.sol\\\";\\nimport {TextResolver} from \\\"@ens/contracts/resolvers/profiles/TextResolver.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {LibRegistry} from \\\"../universalResolver/libraries/LibRegistry.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\n/// @notice PublicResolver that respects the ENSv2 registry.\\ncontract PublicResolverV2 is\\n Multicallable,\\n ABIResolver,\\n AddrResolver,\\n ContentHashResolver,\\n DataResolver,\\n DNSResolver,\\n InterfaceResolver,\\n NameResolver,\\n PubkeyResolver,\\n TextResolver,\\n HCAContext,\\n DelegatedContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice The ENSv2 Root Registry contract.\\n IPermissionedRegistry public immutable ROOT_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev A mapping of operators. An address that is authorised for an address\\n /// may make any changes to the name that the owner could, but may not update\\n /// the set of authorisations.\\n mapping(address owner => mapping(address operator => bool approved)) internal _operatorApprovals;\\n\\n /// @dev A mapping of delegates. A delegate that is authorised by an owner\\n /// for a name may make changes to the name's resolver, but may not update\\n /// the set of token approvals.\\n mapping(address owner => mapping(bytes32 node => mapping(address delegate => bool approved))) internal _tokenApprovals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice An operator is added or removed.\\n /// @param owner The node owner.\\n /// @param operator The approved account.\\n /// @param approved If `true`, approved, otherwise revoked.\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /// @notice A delegate is approved or an approval is revoked.\\n /// @param owner The node owner.\\n /// @param node The namehash.\\n /// @param delegate The approved account.\\n /// @param approved If `true`, approved, otherwise revoked.\\n event Approved(\\n address owner,\\n bytes32 indexed node,\\n address indexed delegate,\\n bool indexed approved\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Create a WrappedPublicResolver.\\n /// @param hcaFactory The HCA factory.\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param rootRegistry The ENSv2 Root Registry contract.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n IHCAFactoryBasic hcaFactory,\\n INameWrapper nameWrapper,\\n IPermissionedRegistry rootRegistry,\\n IContractNamer contractNamer\\n )\\n HCAEquivalence(hcaFactory)\\n DelegatedContractNamer(contractNamer)\\n {\\n NAME_WRAPPER = nameWrapper;\\n ROOT_REGISTRY = rootRegistry;\\n }\\n\\n /// @inheritdoc AddrResolver\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n override(\\n Multicallable,\\n ABIResolver,\\n AddrResolver,\\n ContentHashResolver,\\n DataResolver,\\n DNSResolver,\\n InterfaceResolver,\\n NameResolver,\\n PubkeyResolver,\\n TextResolver,\\n DelegatedContractNamer\\n )\\n returns (bool)\\n {\\n return super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grant or revoke `operator` approval.\\n /// @param operator The account to approve.\\n /// @param approved If `true`, approved, otherwise revoked.\\n function setApprovalForAll(address operator, bool approved) external {\\n address sender = _msgSender();\\n require(sender != operator, \\\"ERC1155: setting approval status for self\\\");\\n _operatorApprovals[sender][operator] = approved;\\n emit ApprovalForAll(sender, operator, approved);\\n }\\n\\n /// @notice Grant or revoke `delegate` approval on a specific node.\\n /// @param node The namehash to approve.\\n /// @param delegate The account to approve.\\n /// @param approved If `true`, approved, otherwise revoked.\\n function approve(bytes32 node, address delegate, bool approved) external {\\n address sender = _msgSender();\\n require(sender != delegate, \\\"Setting delegate status for self\\\");\\n _tokenApprovals[sender][node][delegate] = approved;\\n emit Approved(sender, node, delegate, approved);\\n }\\n\\n /// @notice Check if `operator` is approved for all nodes owned by `account`.\\n /// @param owner The owner account.\\n /// @param operator The operator account.\\n /// @return `true` if `operator` is approved.\\n function isApprovedForAll(address owner, address operator) public view returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /// @notice Check to see if the delegate has been approved by the owner for the node.\\n /// @param owner The owner account.\\n /// @param node The namehash to check.\\n /// @param delegate The delegated account.\\n /// @return `true` if `operator` is approved.\\n function isApprovedFor(address owner, bytes32 node, address delegate)\\n public\\n view\\n returns (bool)\\n {\\n return _tokenApprovals[owner][node][delegate];\\n }\\n\\n /// @notice Determine if `operator` is authorized for `node`.\\n /// @param node The namehash to check.\\n /// @param operator The account requesting authorization.\\n /// @return `true` if `node` is authorized.\\n function canModifyName(bytes32 node, address operator) public view returns (bool) {\\n bytes memory name = NAME_WRAPPER.names(node);\\n if (name.length == 0) {\\n return false;\\n }\\n address owner = LibRegistry.findOwner(ROOT_REGISTRY, name, 0);\\n return\\n owner == operator ||\\n isApprovedForAll(owner, operator) ||\\n isApprovedFor(owner, node, operator);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n // solhint-disable private-vars-leading-underscore\\n /// @dev Determine if the caller is authorized for `node`.\\n function isAuthorised(bytes32 node) internal view override returns (bool) {\\n return canModifyName(node, _msgSender());\\n }\\n}\\n\",\"keccak256\":\"0x3a1ebb7d7aaf7058130f769ae2eb801759eb458f9fceeeb64deb90c3b9c7d4dd\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/universalResolver/libraries/LibRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"../../registry/interfaces/IOwnedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Recursive traversal helpers for the namechain registry tree \\u2014 resolver lookup, registry\\n/// discovery, canonical name construction, and ancestry enumeration.\\nlibrary LibRegistry {\\n /// @dev Find the resolver address for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return exactRegistry The exact registry or null if not exact.\\n /// @return resolver The resolver or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n // supply if end of name\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return (rootRegistry, address(0), bytes32(0), offset);\\n }\\n // lookup parent name\\n (exactRegistry, resolver, node, resolverOffset) = findResolver(rootRegistry, name, next);\\n // if there was a parent registry...\\n if (address(exactRegistry) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n // remember the resolver (if it exists)\\n address res = exactRegistry.getResolver(label);\\n if (res != address(0)) {\\n resolver = res;\\n resolverOffset = offset;\\n }\\n exactRegistry = exactRegistry.getSubregistry(label);\\n }\\n node = NameCoder.namehash(node, labelHash); // update namehash\\n }\\n\\n /// @dev Find the owner for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return owner The owner address or null if unowned or not found.\\n function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (address owner)\\n {\\n IRegistry registry = findParentRegistry(rootRegistry, name, offset);\\n if (\\n address(registry) != address(0) &&\\n ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId)\\n ) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n owner = IOwnedRegistry(address(registry)).findOwner(label);\\n }\\n }\\n\\n /// @dev Construct the canonical name for `registry`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param registry The registry to name.\\n /// @return name The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry rootRegistry, IRegistry registry)\\n internal\\n view\\n returns (bytes memory name)\\n {\\n if (address(registry) == address(0)) {\\n return \\\"\\\";\\n }\\n for (;;) {\\n if (address(registry) == address(rootRegistry)) {\\n return abi.encodePacked(name, uint8(0)); // add terminator\\n }\\n (IRegistry parent, string memory label) = registry.getParent();\\n if (address(parent) == address(0)) {\\n return \\\"\\\"; // no canonical parent\\n }\\n IRegistry child = parent.getSubregistry(label);\\n if (address(child) != address(registry)) {\\n return \\\"\\\"; // wrong canonical child\\n }\\n name = abi.encodePacked(name, NameCoder.assertLabelSize(label), label); // reverts if invalid label\\n registry = parent;\\n }\\n }\\n\\n /// @dev Find the registry for `name` and return it iff it is canonical for that name.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name)\\n internal\\n view\\n returns (IRegistry)\\n {\\n IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0);\\n return\\n address(registry) != address(0) &&\\n keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) ==\\n keccak256(name)\\n ? registry\\n : IRegistry(address(0));\\n }\\n\\n /// @dev Find the exact registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return exactRegistry The exact registry or null if not found.\\n function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return rootRegistry;\\n }\\n IRegistry parent = findExactRegistry(rootRegistry, name, next);\\n if (address(parent) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n exactRegistry = parent.getSubregistry(label);\\n }\\n }\\n\\n /// @dev Find the parent registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return parentRegistry The parent registry or null if not found.\\n function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry parentRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n parentRegistry = findExactRegistry(rootRegistry, name, next);\\n }\\n }\\n\\n /// @dev Find all registries in the ancestry of `name`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return registries Array of registries in label-order.\\n function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry[] memory registries)\\n {\\n registries = new IRegistry[](1 + NameCoder.countLabels(name, offset));\\n registries[registries.length - 1] = rootRegistry;\\n _findRegistries(name, offset, registries, 0);\\n }\\n\\n /// @dev Recursive function for building ancestry.\\n function _findRegistries(\\n bytes memory name,\\n uint256 offset,\\n IRegistry[] memory registries,\\n uint256 index\\n )\\n private\\n view\\n returns (IRegistry registry)\\n {\\n (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset);\\n if (bytes(label).length == 0) {\\n return registries[registries.length - 1];\\n }\\n registry = _findRegistries(name, nextOffset, registries, index + 1);\\n if (address(registry) != address(0)) {\\n registry = registry.getSubregistry(label);\\n registries[index] = registry;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0b5f34bcc76ee3e49d300444fbcbe1ed152faee49a91c87eaea5f6d61ce6fb0b\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 11710, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "recordVersions", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_bytes32,t_uint64)" + }, + { + "astId": 11825, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_abis", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage)))" + }, + { + "astId": 11992, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_addresses", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage)))" + }, + { + "astId": 12234, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_hashes", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_bytes_storage))" + }, + { + "astId": 12793, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_dataStore", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_bytes_storage)))" + }, + { + "astId": 12324, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_zonehashes", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_bytes_storage))" + }, + { + "astId": 12334, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_records", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage))))" + }, + { + "astId": 12342, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_nameEntriesCount", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes32,t_uint16)))" + }, + { + "astId": 14030, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_interfaces", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes4,t_address)))" + }, + { + "astId": 14222, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_names", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_string_storage))" + }, + { + "astId": 14309, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_pubkeys", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_struct(PublicKey)14302_storage))" + }, + { + "astId": 14520, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_texts", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage)))" + }, + { + "astId": 71518, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "_operatorApprovals", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 71527, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "_tokenApprovals", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_mapping(t_address,t_bool)))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_mapping(t_bytes32,t_mapping(t_address,t_bool)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(bytes32 => mapping(address => bool)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))" + }, + "t_mapping(t_bytes32,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_bytes32,t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage)))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(bytes32 => mapping(uint16 => bytes)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage))" + }, + "t_mapping(t_bytes32,t_mapping(t_bytes32,t_uint16))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(bytes32 => uint16))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_uint16)" + }, + "t_mapping(t_bytes32,t_mapping(t_bytes4,t_address))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(bytes4 => address))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes4,t_address)" + }, + "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_bytes_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(string => bytes))", + "numberOfBytes": "32", + "value": "t_mapping(t_string_memory_ptr,t_bytes_storage)" + }, + "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(string => string))", + "numberOfBytes": "32", + "value": "t_mapping(t_string_memory_ptr,t_string_storage)" + }, + "t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(uint16 => bytes))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint16,t_bytes_storage)" + }, + "t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(uint256 => bytes))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_bytes_storage)" + }, + "t_mapping(t_bytes32,t_string_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_bytes32,t_struct(PublicKey)14302_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct PubkeyResolver.PublicKey)", + "numberOfBytes": "32", + "value": "t_struct(PublicKey)14302_storage" + }, + "t_mapping(t_bytes32,t_uint16)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint16)", + "numberOfBytes": "32", + "value": "t_uint16" + }, + "t_mapping(t_bytes32,t_uint64)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint64)", + "numberOfBytes": "32", + "value": "t_uint64" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_string_memory_ptr,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_string_memory_ptr,t_string_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_uint16,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_uint16", + "label": "mapping(uint16 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_uint256,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_bytes_storage))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => bytes))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_bytes_storage)" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage))))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(bytes32 => mapping(uint16 => bytes))))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage)))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes32,t_uint16)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(bytes32 => uint16)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_bytes32,t_uint16))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes4,t_address)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(bytes4 => address)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_bytes4,t_address))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_bytes_storage)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(string => bytes)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_bytes_storage))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(string => string)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_string_storage))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => string))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_string_storage)" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_struct(PublicKey)14302_storage))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => struct PubkeyResolver.PublicKey))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_struct(PublicKey)14302_storage)" + }, + "t_string_memory_ptr": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(PublicKey)14302_storage": { + "encoding": "inplace", + "label": "struct PubkeyResolver.PublicKey", + "members": [ + { + "astId": 14299, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_bytes32" + }, + { + "astId": 14301, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "y", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "encoding": "inplace", + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "InvalidEVMAddress(bytes)": [ + { + "notice": "The supplied address could not be converted to `address`." + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "notice": "An operator is added or removed." + }, + "Approved(address,bytes32,address,bool)": { + "notice": "A delegate is approved or an approval is revoked." + }, + "DataChanged(bytes32,string,string,bytes)": { + "notice": "For a specific `node`, the data associated with a `key` has changed." + } + }, + "kind": "user", + "methods": { + "ABI(bytes32,uint256)": { + "notice": "Returns the ABI associated with an ENS node. Defined in EIP205." + }, + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract." + }, + "ROOT_REGISTRY()": { + "notice": "The ENSv2 Root Registry contract." + }, + "addr(bytes32)": { + "notice": "Get `addr(60)` as `address` of the associated ENS node." + }, + "addr(bytes32,uint256)": { + "notice": "Get the address for coin type of the associated ENS node. If coin type is EVM and empty, defaults to `addr(COIN_TYPE_DEFAULT)`." + }, + "approve(bytes32,address,bool)": { + "notice": "Grant or revoke `delegate` approval on a specific node." + }, + "canModifyName(bytes32,address)": { + "notice": "Determine if `operator` is authorized for `node`." + }, + "clearRecords(bytes32)": { + "notice": "Increments the record version associated with an ENS node. May only be called by the owner of that node in the ENS registry." + }, + "constructor": { + "notice": "Create a WrappedPublicResolver." + }, + "contenthash(bytes32)": { + "notice": "Returns the contenthash associated with an ENS node." + }, + "data(bytes32,string)": { + "notice": "For a specific `node`, get the data associated with the key, `key`." + }, + "dnsRecord(bytes32,bytes32,uint16)": { + "notice": "Obtain a DNS record." + }, + "hasAddr(bytes32,uint256)": { + "notice": "Determine if an addresss is stored for the coin type of the associated ENS node." + }, + "hasDNSRecords(bytes32,bytes32)": { + "notice": "Check if a given node has records." + }, + "interfaceImplementer(bytes32,bytes4)": { + "notice": "Returns the address of a contract that implements the specified interface for this name. If an implementer has not been set for this interfaceID and name, the resolver will query the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that contract implements EIP165 and returns `true` for the specified interfaceID, its address will be returned." + }, + "isApprovedFor(address,bytes32,address)": { + "notice": "Check to see if the delegate has been approved by the owner for the node." + }, + "isApprovedForAll(address,address)": { + "notice": "Check if `operator` is approved for all nodes owned by `account`." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "name(bytes32)": { + "notice": "Returns the name associated with an ENS node, for reverse records. Defined in EIP181." + }, + "pubkey(bytes32)": { + "notice": "Returns the SECP256k1 public key associated with an ENS node. Defined in EIP 619." + }, + "setABI(bytes32,uint256,bytes)": { + "notice": "Sets the ABI associated with an ENS node. Nodes may have one ABI of each content type. To remove an ABI, set it to the empty string." + }, + "setAddr(bytes32,address)": { + "notice": "Set `addr(60)` of the associated ENS node. `address(0)` is stored as `new bytes(20)`." + }, + "setAddr(bytes32,uint256,bytes)": { + "notice": "Set the address for coin type of the associated ENS node. Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes." + }, + "setApprovalForAll(address,bool)": { + "notice": "Grant or revoke `operator` approval." + }, + "setContenthash(bytes32,bytes)": { + "notice": "Sets the contenthash associated with an ENS node. May only be called by the owner of that node in the ENS registry." + }, + "setDNSRecords(bytes32,bytes)": { + "notice": "Set one or more DNS records. Records are supplied in wire-format. Records with the same node/name/resource must be supplied one after the other to ensure the data is updated correctly. For example, if the data was supplied: a.example.com IN A 1.2.3.4 a.example.com IN A 5.6.7.8 www.example.com IN CNAME a.example.com. then this would store the two A records for a.example.com correctly as a single RRSET, however if the data was supplied: a.example.com IN A 1.2.3.4 www.example.com IN CNAME a.example.com. a.example.com IN A 5.6.7.8 then this would store the first A record, the CNAME, then the second A record which would overwrite the first." + }, + "setData(bytes32,string,bytes)": { + "notice": "Sets the data associated with the key, `key` for a specific `node`. May only be called by the owner of that node in the ENS registry." + }, + "setInterface(bytes32,bytes4,address)": { + "notice": "Sets an interface associated with a name. Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support." + }, + "setName(bytes32,string)": { + "notice": "Sets the name associated with an ENS node, for reverse records. May only be called by the owner of that node in the ENS registry." + }, + "setPubkey(bytes32,bytes32,bytes32)": { + "notice": "Sets the SECP256k1 public key associated with an ENS node." + }, + "setText(bytes32,string,string)": { + "notice": "Sets the text data associated with an ENS node and key. May only be called by the owner of that node in the ENS registry." + }, + "setZonehash(bytes32,bytes)": { + "notice": "setZonehash sets the hash for the zone. May only be called by the owner of that node in the ENS registry." + }, + "text(bytes32,string)": { + "notice": "Returns the text data associated with an ENS node and key." + }, + "zonehash(bytes32)": { + "notice": "zonehash obtains the hash for the zone." + } + }, + "notice": "PublicResolver that respects the ENSv2 registry.", + "version": 1 + }, + "argsData": "0x000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf9430000000000000000000000000635513f179d50a207757e05759cbd106d7dfce8000000000000000000000000c960f7217d3643b525ef36bec8adf86953cd9ab8000000000000000000000000fc8bf9234969d6b85729b756fa9e14bb84a06754", + "transaction": { + "hash": "0xfe28ab45b6cc541b553678bdb8d9f0351962f09ed2e0e48a8860021df738827c", + "nonce": "0x1e99", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x68c47bf90574ef778ee4cfef11c903ec6572230ca72c9547b3aad1d21bda8285", + "blockNumber": "0xa6a80e", + "transactionIndex": "0x3a" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/RootRegistry.json b/contracts/deployments/sepolia-official-v1-20260525-r2/RootRegistry.json new file mode 100644 index 000000000..32683c8cb --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/RootRegistry.json @@ -0,0 +1,2800 @@ +{ + "address": "0xc960f7217d3643b525ef36bec8adf86953cd9ab8", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "contract ILabelStore", + "name": "labelStore", + "type": "address" + }, + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "oldExpiry", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "CannotReduceExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "CannotSetPastExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "LabelExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "TransferDisallowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExpiryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ParentUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RegistryCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ResolverUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SubregistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTokenId", + "type": "uint256" + } + ], + "name": "TokenRegenerated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "TokenResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "renderer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "URIUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LABEL_STORE", + "outputs": [ + { + "internalType": "contract ILabelStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParent", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getResource", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "internalType": "address", + "name": "latestOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "internalType": "struct IPermissionedRegistry.State", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getStatus", + "outputs": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getSubregistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "latestOwnerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setParent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "setSubregistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + }, + { + "internalType": "contract IRegistryURIRenderer", + "name": "renderer", + "type": "address" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "PermissionedRegistry", + "sourceName": "src/registry/PermissionedRegistry.sol", + "bytecode": "0x60c060405234801561000f575f5ffd5b50604051614be8380380614be883398101604081905261002e91610cb8565b6001600160a01b0384166080526040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16001600160a01b03831660a05261007c5f828482610086565b5050505050610f15565b5f835f0361009557505f610190565b61009e84610198565b6001600160a01b0383166100c55760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461018a575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616610125888260016101e4565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561017e5761017e888785858b610314565b60019350505050610190565b5f925050505b949350505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156101e157604051630153d96960e51b8152600481018290526024015b60405180910390fd5b50565b5f6101ee83610324565b90508115610284575f848152600360205260409020546102349082161980195f516020614bc85f395f51905f5291909101165f516020614ba85f395f51905f5216151590565b1561025c57604051631f22ca6960e31b815260048101859052602481018490526044016101d8565b5f8481526003602052604081208054859290610279908490610d1c565b9091555061030e9050565b5f848152600360205260409020546102c3901982161980195f516020614bc85f395f51905f5291909101165f516020614ba85f395f51905f5216151590565b156102eb57604051631f80c19b60e01b815260048101859052602481018490526044016101d8565b5f8481526003602052604081208054859290610308908490610d2f565b90915550505b50505050565b61031d8561033e565b5050505050565b5f61032e82610198565b50600181901b17600281901b1790565b80156101e15763ffffffff811681185f9081526101086020526040812090610366838361042a565b5f818152602081905260409020549091506001600160a01b031661038c8183600161044d565b825483906004906103aa90640100000000900463ffffffff16610d42565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6103d9838561042a60201b60201c565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a361031d8282600160405180602001604052805f8152506104b460201b60201c565b80545f9063ffffffff808516851864010000000090920416185b90505b92915050565b6001600160a01b03831661047557604051626a0d4560e21b81525f60048201526024016101d8565b604080516001808252602082018590528183019081526060820184905260a082019092525f6080820181815291929161031d9187918590859083610529565b6001600160a01b0384166104dd57604051632bfa23e760e11b81525f60048201526024016101d8565b604080516001808252602082018690528183019081526060820185905260808201909252906105105f8784848784610529565b505050505050565b63ffffffff82811690921891161890565b6105358686868661058c565b6001600160a01b03851615610510575f61054d610667565b9050811561056857610563818888888888610675565b610583565b60208581015190850151610580838a8a85858a610796565b50505b50505050505050565b6105988484848461087d565b6001600160a01b038316158015906105b857506001600160a01b03841615155b1561030e575f5b825181101561031d575f8382815181106105db576105db610d66565b602002602001015190506105fa816001609c1b88610a8660201b60201c565b610629576040516372c7b6ad60e11b8152600481018290526001600160a01b03871660248201526044016101d8565b5f83838151811061063c5761063c610d66565b6020026020010151111561065e5761065e61065682610ae5565b87875f610b0c565b506001016105bf565b5f610670610b4d565b905090565b6001600160a01b0384163b156105105760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906106b99089908990889088908890600401610de2565b6020604051808303815f875af19250505080156106f3575060408051601f3d908101601f191682019092526106f091810190610e3f565b60015b61075a573d808015610720576040519150601f19603f3d011682016040523d82523d5f602084013e610725565b606091505b5080515f0361075257604051632bfa23e760e11b81526001600160a01b03861660048201526024016101d8565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461058357604051632bfa23e760e11b81526001600160a01b03861660048201526024016101d8565b6001600160a01b0384163b156105105760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906107da9089908990889088908890600401610e6d565b6020604051808303815f875af1925050508015610814575060408051601f3d908101601f1916820190925261081191810190610e3f565b60015b610841573d808015610720576040519150601f19603f3d011682016040523d82523d5f602084013e610725565b6001600160e01b0319811663f23a6e6160e01b1461058357604051632bfa23e760e11b81526001600160a01b03861660048201526024016101d8565b80518251146108ac5781518151604051635b05999160e01b8152600481019290925260248201526044016101d8565b5f6108b5610667565b90505f5b83518110156109a857602081810285810182015190850190910151801561099e575f828152602081905260409020546001600160a01b039081169089168114610934576040516303dee4c560e01b81526001600160a01b038a1660048201525f602482015260448101839052606481018490526084016101d8565b6001821115610976576040516303dee4c560e01b81526001600160a01b038a1660048201526001602482015260448101839052606481018490526084016101d8565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0389161790555b50506001016108b9565b508251600103610a285760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051610a19929190918252602082015260400190565b60405180910390a4505061031d565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051610a77929190610eb1565b60405180910390a45050505050565b5f610190610a9385610ae5565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f61044782610b078163ffffffff8116185f9081526101086020526040902090565b610bea565b5f8481526002602090815260408083206001600160a01b0387168452909152902054801561031d57610b4085828685610c38565b5061051085828585610086565b6080515f906001600160a01b0316610b6457503390565b60805160405163110ac5cb60e21b81523360048201525f916001600160a01b03169063442b172c90602401602060405180830381865afa158015610baa573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bce9190610ede565b90506001600160a01b038116610be5573391505090565b919050565b5f82610bf7575081610447565b60018201546104449084906001600160401b0316421015610c2557835463ffffffff82811690921891161890565b83546105189063ffffffff166001610ef9565b5f610c4284610198565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461018a575f8781526002602090815260408083206001600160a01b038916845290915281208290558683169061012590899083906101e4565b6001600160a01b03811681146101e1575f5ffd5b5f5f5f5f60808587031215610ccb575f5ffd5b8451610cd681610ca4565b6020860151909450610ce781610ca4565b6040860151909350610cf881610ca4565b6060959095015193969295505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561044757610447610d08565b8181038181111561044757610447610d08565b5f63ffffffff821663ffffffff8103610d5d57610d5d610d08565b60010192915050565b634e487b7160e01b5f52603260045260245ffd5b5f8151808452602084019350602083015f5b82811015610daa578151865260209586019590910190600101610d8c565b5093949350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0386811682528516602082015260a0604082018190525f90610e0d90830186610d7a565b8281036060840152610e1f8186610d7a565b90508281036080840152610e338185610db4565b98975050505050505050565b5f60208284031215610e4f575f5ffd5b81516001600160e01b031981168114610e66575f5ffd5b9392505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f90610ea690830184610db4565b979650505050505050565b604081525f610ec36040830185610d7a565b8281036020840152610ed58185610d7a565b95945050505050565b5f60208284031215610eee575f5ffd5b8151610e6681610ca4565b63ffffffff818116838216019081111561044757610447610d08565b60805160a051613c5d610f4b5f395f81816106250152611bb501525f81816104070152818161245701526124b80152613c5d5ff3fe608060405234801561000f575f5ffd5b50600436106102cc575f3560e01c80635c622a0e1161017c5780639dbba19d116100dd578063ce156e8211610093578063e4ae7d771161006e578063e4ae7d77146106cc578063e985e9c5146106df578063f242432a1461071a575f5ffd5b8063ce156e8214610693578063d3bf89b1146106a6578063dfa70d8b146106b9575f5ffd5b8063a22cb465116100c3578063a22cb4651461065a578063bc7b6d621461066d578063bd242bcb14610680575f5ffd5b80639dbba19d14610620578063a02b161e14610647575f5ffd5b8063781ef8db1161013257806380f760211161011857806380f76021146105e457806385f3e643146105fa57806391b3c0371461060d575f5ffd5b8063781ef8db146105875780637c300586146105d1575f5ffd5b806363560a8e1161016257806363560a8e1461054e5780636f3ff726146105615780636f537c7214610574575f5ffd5b80635c622a0e1461051b5780636352211e1461053b575f5ffd5b80632f27fa241161023157806344c9af28116101e75780635357263f116101c25780635357263f146104e25780635569f33d146104f55780635adf472414610508575f5ffd5b806344c9af281461048f57806348688f95146104af5780634e1273f4146104c2575f5ffd5b8063341ec55911610217578063341ec5591461044157806335af6216146104545780633634f91114610467575f5ffd5b80632f27fa24146103ef578063319c22bb14610402575f5ffd5b806313c72608116102865780631c3fc3eb1161026c5780631c3fc3eb146103c05780631e8fca2d146103c75780632eb2c2d6146103da575f5ffd5b806313c726081461035f57806314ff5ea3146103ad575f5ffd5b8063072d5d77116102b6578063072d5d77146103195780630e89341c1461032c57806311b8e00a1461034c575f5ffd5b8062fdd58e146102d057806301ffc9a7146102f6575b5f5ffd5b6102e36102de366004612fe9565b61072d565b6040519081526020015b60405180910390f35b610309610304366004613028565b610764565b60405190151581526020016102ed565b610309610327366004613043565b6108d9565b61033f61033a366004613071565b610904565b6040516102ed91906130b6565b61030961035a3660046130c8565b610a34565b61039461036d366004613071565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016102ed565b6102e36103bb366004613071565b610a4e565b6102e35f81565b6102e36103d5366004613071565b610a75565b6103ed6103e8366004613230565b610a9c565b005b6102e36103fd366004613071565b610b39565b6104297f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102ed565b6103ed61044f366004613043565b610b57565b610429610462366004613321565b610bf5565b61047a6104753660046130c8565b610c90565b604080519283526020830191909152016102ed565b6104a261049d366004613071565b610cb0565b6040516102ed9190613394565b6103ed6104bd3660046133e7565b610d82565b6104d56104d036600461343a565b610e24565b6040516102ed9190613539565b6103ed6104f036600461354b565b610eef565b6103ed6105033660046135a5565b610f8d565b6102e3610516366004613043565b61112a565b61052e610529366004613071565b61115c565b6040516102ed91906135cf565b610429610549366004613071565b6111b2565b61042961055c366004613321565b611217565b61030961056f3660046135dd565b611225565b610394610582366004613321565b611276565b610309610595366004613043565b6001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b6103096105df3660046135f8565b6112b8565b6105ec6112cc565b6040516102ed929190613623565b6102e3610608366004613644565b611377565b6102e361061b366004613321565b611393565b6104297f000000000000000000000000000000000000000000000000000000000000000081565b6103ed610655366004613071565b6113d5565b6103ed6106683660046136cd565b6114e2565b6103ed61067b366004613043565b6114f8565b61042961068e366004613071565b61159b565b6103096106a1366004613043565b6115b7565b6103096106b43660046135f8565b6115d9565b6103096106c73660046135f8565b611638565b6104296106da366004613321565b61164c565b6103096106ed3660046136fd565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6103ed610728366004613729565b6116c7565b5f826001600160a01b0316610741836111b2565b6001600160a01b031614610755575f610758565b60015b60ff1690505b92915050565b5f6001600160e01b031982167fafff3a630000000000000000000000000000000000000000000000000000000014806107c657506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b806107fa57506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b8061082e57506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b8061086257506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b8061089657506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b806108ca57506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061075e575061075e82611757565b5f5f836108ee82826108e9611794565b6117a2565b6108fb5f868660016117f0565b95945050505050565b610107546060906001600160a01b03166109a757610106805461092690613781565b80601f016020809104026020016040519081016040528092919081815260200182805461095290613781565b801561099d5780601f106109745761010080835404028352916020019161099d565b820191905f5260205f20905b81548152906001019060200180831161098057829003601f168201915b505050505061075e565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610a0d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261075e91908101906137b9565b5f610a47610a4184610a75565b83611919565b9392505050565b5f61075e82610a708463ffffffff8116185f9081526101086020526040902090565b611930565b5f61075e82610a978463ffffffff8116185f9081526101086020526040902090565b61194e565b5f610aa5611794565b9050806001600160a01b0316866001600160a01b031614158015610aee57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b15610b245760405163711bec9160e11b81526001600160a01b038083166004830152871660248201526044015b60405180910390fd5b610b3186868686866119a8565b505050505050565b5f61075e610b4683610a75565b5f9081526003602052604090205490565b5f5f610b668462100000611a0f565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038716021781559092509050610baf611794565b6001600160a01b0316836001600160a01b0316837fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a450505050565b5f5f610c51610c3885858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610c865780546801000000000000000090046001600160a01b0316610c88565b5f5b949350505050565b5f5f610ca4610c9e85610a75565b84611a85565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610d0e8584611930565b606085018190529050610d21858461194e565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610d4f8382611aa8565b85906002811115610d6257610d62613360565b90816002811115610d7557610d75613360565b8152505050505050919050565b641000000000610d9a5f82610d95611794565b611adf565b610106610da8848683613872565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416179055610dda611794565b6001600160a01b03167fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd5858585604051610e169392919061392c565b60405180910390a250505050565b60608151835114610e555781518351604051635b05999160e01b815260048101929092526024820152604401610b1b565b5f835167ffffffffffffffff811115610e7057610e706130e8565b604051908082528060200260200182016040528015610e99578160200160208202803683370190505b5090505f5b8451811015610ee757602080820286010151610ec29060208084028701015161072d565b828281518110610ed457610ed461396c565b6020908102919091010152600101610e9e565b509392505050565b610100610eff5f82610d95611794565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105610f358382613980565b50610f3e611794565b6001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff484604051610f8091906130b6565b60405180910390a3505050565b63ffffffff821682185f9081526101086020526040812090610faf8483611930565b90505f610fba611794565b600184015490915067ffffffffffffffff164281116110515767ffffffffffffffff8116158061102b575061102962010000836001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b155b1561104c5760405163311388dd60e21b815260048101849052602401610b1b565b611068565b61106861105e878661194e565b6201000084611adf565b8067ffffffffffffffff168567ffffffffffffffff1610156110ca576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015286166024820152604401610b1b565b60018401805467ffffffffffffffff191667ffffffffffffffff87169081179091556040516001600160a01b038416919085907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a4505050505050565b5f610a4761113784610a75565b5f9081526002602090815260408083206001600160a01b038716845290915290205490565b63ffffffff811681185f908152610108602052604081206001810154610a479067ffffffffffffffff166111ad6111938685611930565b5f908152602081905260409020546001600160a01b031690565b611aa8565b63ffffffff811681185f908152610108602052604081206111d38382611930565b831415806111ef5750600181015467ffffffffffffffff164210155b61120f575f838152602081905260409020546001600160a01b0316610a47565b5f9392505050565b5f610a476105498484611393565b6001600160a01b0381165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b60205260408120546f010000000000000000000000000000009081161461075e565b5f610a4761036d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b5f610c886112c585610a75565b8484611b3e565b6101045461010580545f926060926001600160a01b039091169181906112f190613781565b80601f016020809104026020016040519081016040528092919081815260200182805461131d90613781565b80156113685780601f1061133f57610100808354040283529160200191611368565b820191905f5260205f20905b81548152906001019060200180831161134b57829003601f168201915b50505050509050915091509091565b5f6113888787878787876001611b83565b979650505050505050565b5f610a476103bb84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b5f5f6113e383611000611a0f565b915091506113ef611794565b6001600160a01b0316827f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea860405160405180910390a35f828152602081905260409020546001600160a01b031680156114bf5761144e818460016120e4565b815482905f906114639063ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166114a090613a4f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b6114f46114ed611794565b838361214b565b5050565b5f5f611508846301000000611a0f565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038816021790559092509050611555611794565b6001600160a01b0316836001600160a01b0316837f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a450505050565b5f818152602081905260408120546001600160a01b031661075e565b5f5f836115cc82826115c7611794565b6121f1565b6108fb5f86866001612252565b5f610c886115e685610a75565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f610c8861164585610a75565b84846122be565b5f5f61168f610c3885858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b600181015490915067ffffffffffffffff16421015610c865760018101546801000000000000000090046001600160a01b0316610c88565b5f6116d0611794565b9050806001600160a01b0316866001600160a01b03161415801561171957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561174a5760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610b1b565b610b3186868686866122f9565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061075e575061075e82612386565b5f61179d612454565b905090565b5f6117ad8483612545565b905080198316156117ea5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610b1b565b50505050565b5f835f036117ff57505f610c88565b6118088461260b565b6001600160a01b038316611848576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461190d575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166118a88882600161266b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561190157611901888785858b612800565b60019350505050610c88565b505f9695505050505050565b5f5f6119258484610c90565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610a47565b5f8261195b57508161075e565b6001820154610a4790849067ffffffffffffffff1642101561198457835463ffffffff16611997565b83546119979063ffffffff166001613a73565b63ffffffff82811690921891161890565b6001600160a01b0384166119d157604051632bfa23e760e11b81525f6004820152602401610b1b565b6001600160a01b0385166119f957604051626a0d4560e21b81525f6004820152602401610b1b565b611a0885858585856001612809565b5050505050565b63ffffffff821682185f90815261010860205260408120611a308482611930565b600182015490925067ffffffffffffffff164210611a645760405163311388dd60e21b815260048101839052602401610b1b565b610ca9611a71858361194e565b84610d95611794565b805160209091012090565b5f5f611a908361286b565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff83164210611ac157505f61075e565b6001600160a01b038216611ad75750600161075e565b50600261075e565b611aea8383836115d9565b611b39576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610b1b565b505050565b5f8383611b4e82826108e9611794565b85611b6c57604051631850848b60e31b815260040160405180910390fd5b611b7986868660016117f0565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990611bea908b906004016130b6565b5f604051808303815f87803b158015611c01575f5ffd5b505af1158015611c13573d5f5f3e3d5ffd5b5050895160208b012091505f9050611c3e8263ffffffff8116185f9081526101086020526040902090565b9050611c4a8282611930565b5f818152602081905260408120549194506001600160a01b0390911690611c6f611794565b600184015490915067ffffffffffffffff164210611cea578515611c9957611c995f600183611adf565b6001600160a01b038b16158015611caf57508715155b15611ce55760405163d1a3b35560e01b81525f6004820152602481018990526001600160a01b0382166044820152606401610b1b565b611daf565b6001600160a01b03821615611d2d578b6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610b1b91906130b6565b6001600160a01b038b16611d6f578b6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610b1b91906130b6565b8515611d8157611d815f601083611adf565b8667ffffffffffffffff165f03611da457600183015467ffffffffffffffff1696505b640100000000881797505b6001600160a01b038b1615611dd15767ffffffffffffffff8716421015611dde565b67ffffffffffffffff8716155b15611e21576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff88166004820152602401610b1b565b6001600160a01b03821615611eb957611e3c828660016120e4565b825483905f90611e519063ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550825f01600481819054906101000a900463ffffffff16611e8e90613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550611eb68584611930565b94505b60018301805484546001600160a01b03808e16680100000000000000009081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921787558c81169091026001600160e01b031990921667ffffffffffffffff8b1617919091179091558b16611f7a57806001600160a01b0316845f1b867f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88f8b604051611f6d929190613a8f565b60405180910390a4612033565b806001600160a01b0316845f1b867f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8f8f8c604051611fbb93929190613aba565b60405180910390a4611fde8b86600160405180602001604052805f815250612885565b5f611fe9868561194e565b905080611ff857611ff8613af5565b604051819087907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a3612030818a8e5f6117f0565b50505b6001600160a01b038a161561208457806001600160a01b03168a6001600160a01b0316867fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a45b6001600160a01b038916156120d557806001600160a01b0316896001600160a01b0316867f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a45b50505050979650505050505050565b6001600160a01b03831661210c57604051626a0d4560e21b81525f6004820152602401610b1b565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291611a089187918590859083612809565b6001600160a01b03821661218d576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610b1b565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610f80565b5f6121fc84836128e1565b905080198316156117ea576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610b1b565b5f61225c8461260b565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461190d575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906118a8908990839061266b565b5f83836122ce82826115c7611794565b856122ec57604051631850848b60e31b815260040160405180910390fd5b611b798686866001612252565b6001600160a01b03841661232257604051632bfa23e760e11b81525f6004820152602401610b1b565b6001600160a01b03851661234a57604051626a0d4560e21b81525f6004820152602401610b1b565b6040805160018082526020820186905281830190815260608201859052608082019092529061237d87878484875f612809565b50505050505050565b5f6001600160e01b031982167fd9b67a260000000000000000000000000000000000000000000000000000000014806123e857506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b8061241c57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061075e57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461075e565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661248857503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015612505573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125299190613b09565b90506001600160a01b038116612540573391505090565b919050565b5f5f6125b784846001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b9050836125c557905061075e565b5f6125ea61054986610a708163ffffffff8116185f9081526101086020526040902090565b6001600160a01b031603612601575f91505061075e565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612668576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610b1b565b50565b5f6126758361286b565b9050811561273e575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612716576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610b1b565b5f8481526003602052604081208054859290612733908490613b24565b909155506117ea9050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156127d8576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610b1b565b5f84815260036020526040812080548592906127f5908490613b37565b909155505050505050565b611a0885612998565b61281586868686612a78565b6001600160a01b03851615610b31575f61282d611794565b9050811561284857612843818888888888612b76565b61237d565b60208581015190850151612860838a8a85858a612c97565b505050505050505050565b5f6128758261260b565b50600181901b17600281901b1790565b6001600160a01b0384166128ae57604051632bfa23e760e11b81525f6004820152602401610b1b565b60408051600180825260208201869052818301908152606082018590526080820190925290610b315f8784848784612809565b5f821580159061291c57505f61291161054985610a708163ffffffff8116185f9081526101086020526040902090565b6001600160a01b0316145b1561292857505f61075e565b610a4783836001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b80156126685763ffffffff811681185f90815261010860205260408120906129c08383611930565b5f818152602081905260409020549091506001600160a01b03166129e6818360016120e4565b82548390600490612a0490640100000000900463ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f612a2d8385611930565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3611a088282600160405180602001604052805f815250612885565b612a8484848484612d7e565b6001600160a01b03831615801590612aa457506001600160a01b03841615155b156117ea575f5b8251811015611a08575f838281518110612ac757612ac761396c565b60200260200101519050612af081731000000000000000000000000000000000000000886115d9565b612b38576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610b1b565b5f838381518110612b4b57612b4b61396c565b60200260200101511115612b6d57612b6d612b6582610a75565b87875f612f94565b50600101612aab565b6001600160a01b0384163b15610b315760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612bba9089908990889088908890600401613b4a565b6020604051808303815f875af1925050508015612bf4575060408051601f3d908101601f19168201909252612bf191810190613bac565b60015b612c5b573d808015612c21576040519150601f19603f3d011682016040523d82523d5f602084013e612c26565b606091505b5080515f03612c5357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461237d57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b6001600160a01b0384163b15610b315760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612cdb9089908990889088908890600401613bc7565b6020604051808303815f875af1925050508015612d15575060408051601f3d908101601f19168201909252612d1291810190613bac565b60015b612d42573d808015612c21576040519150601f19603f3d011682016040523d82523d5f602084013e612c26565b6001600160e01b0319811663f23a6e6160e01b1461237d57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b8051825114612dad5781518151604051635b05999160e01b815260048101929092526024820152604401610b1b565b5f612db6611794565b90505f5b8351811015612eb6576020818102858101820151908501909101518015612eac575f828152602081905260409020546001600160a01b039081169089168114612e35576040516303dee4c560e01b81526001600160a01b038a1660048201525f60248201526044810183905260648101849052608401610b1b565b6001821115612e77576040516303dee4c560e01b81526001600160a01b038a166004820152600160248201526044810183905260648101849052608401610b1b565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389161790555b5050600101612dba565b508251600103612f365760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051612f27929190918252602082015260400190565b60405180910390a45050611a08565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051612f85929190613c03565b60405180910390a45050505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015611a0857612fc885828685612252565b50610b31858285856117f0565b6001600160a01b0381168114612668575f5ffd5b5f5f60408385031215612ffa575f5ffd5b823561300581612fd5565b946020939093013593505050565b6001600160e01b031981168114612668575f5ffd5b5f60208284031215613038575f5ffd5b8135610a4781613013565b5f5f60408385031215613054575f5ffd5b82359150602083013561306681612fd5565b809150509250929050565b5f60208284031215613081575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610a476020830184613088565b5f5f604083850312156130d9575f5ffd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613125576131256130e8565b604052919050565b5f67ffffffffffffffff821115613146576131466130e8565b5060051b60200190565b5f82601f83011261315f575f5ffd5b813561317261316d8261312d565b6130fc565b8082825260208201915060208360051b860101925085831115613193575f5ffd5b602085015b838110156131b0578035835260209283019201613198565b5095945050505050565b5f67ffffffffffffffff8211156131d3576131d36130e8565b50601f01601f191660200190565b5f82601f8301126131f0575f5ffd5b8135602083015f61320361316d846131ba565b9050828152858383011115613216575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f5f5f60a08688031215613244575f5ffd5b853561324f81612fd5565b9450602086013561325f81612fd5565b9350604086013567ffffffffffffffff81111561327a575f5ffd5b61328688828901613150565b935050606086013567ffffffffffffffff8111156132a2575f5ffd5b6132ae88828901613150565b925050608086013567ffffffffffffffff8111156132ca575f5ffd5b6132d6888289016131e1565b9150509295509295909350565b5f5f83601f8401126132f3575f5ffd5b50813567ffffffffffffffff81111561330a575f5ffd5b602083019150836020828501011115610ca9575f5ffd5b5f5f60208385031215613332575f5ffd5b823567ffffffffffffffff811115613348575f5ffd5b613354858286016132e3565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b6003811061339057634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506133a6828451613374565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f5f5f604084860312156133f9575f5ffd5b833567ffffffffffffffff81111561340f575f5ffd5b61341b868287016132e3565b909450925050602084013561342f81612fd5565b809150509250925092565b5f5f6040838503121561344b575f5ffd5b823567ffffffffffffffff811115613461575f5ffd5b8301601f81018513613471575f5ffd5b803561347f61316d8261312d565b8082825260208201915060208360051b8501019250878311156134a0575f5ffd5b6020840193505b828410156134cb5783356134ba81612fd5565b8252602093840193909101906134a7565b9450505050602083013567ffffffffffffffff8111156134e9575f5ffd5b6134f585828601613150565b9150509250929050565b5f8151808452602084019350602083015f5b8281101561352f578151865260209586019590910190600101613511565b5093949350505050565b602081525f610a4760208301846134ff565b5f5f6040838503121561355c575f5ffd5b823561356781612fd5565b9150602083013567ffffffffffffffff811115613582575f5ffd5b6134f5858286016131e1565b803567ffffffffffffffff81168114612540575f5ffd5b5f5f604083850312156135b6575f5ffd5b823591506135c66020840161358e565b90509250929050565b6020810161075e8284613374565b5f602082840312156135ed575f5ffd5b8135610a4781612fd5565b5f5f5f6060848603121561360a575f5ffd5b8335925060208401359150604084013561342f81612fd5565b6001600160a01b0383168152604060208201525f610c886040830184613088565b5f5f5f5f5f5f60c08789031215613659575f5ffd5b863567ffffffffffffffff81111561366f575f5ffd5b61367b89828a016131e1565b965050602087013561368c81612fd5565b9450604087013561369c81612fd5565b935060608701356136ac81612fd5565b9250608087013591506136c160a0880161358e565b90509295509295509295565b5f5f604083850312156136de575f5ffd5b82356136e981612fd5565b915060208301358015158114613066575f5ffd5b5f5f6040838503121561370e575f5ffd5b823561371981612fd5565b9150602083013561306681612fd5565b5f5f5f5f5f60a0868803121561373d575f5ffd5b853561374881612fd5565b9450602086013561375881612fd5565b93506040860135925060608601359150608086013567ffffffffffffffff8111156132ca575f5ffd5b600181811c9082168061379557607f821691505b6020821081036137b357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f602082840312156137c9575f5ffd5b815167ffffffffffffffff8111156137df575f5ffd5b8201601f810184136137ef575f5ffd5b80516137fd61316d826131ba565b818152856020838501011115613811575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b601f821115611b3957805f5260205f20601f840160051c810160208510156138535750805b601f840160051c820191505b81811015611a08575f815560010161385f565b67ffffffffffffffff83111561388a5761388a6130e8565b61389e836138988354613781565b8361382e565b5f601f8411600181146138cf575f85156138b85750838201355b5f19600387901b1c1916600186901b178355611a08565b5f83815260208120601f198716915b828110156138fe57868501358255602094850194600190920191016138de565b508682101561391a575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff81111561399a5761399a6130e8565b6139ae816139a88454613781565b8461382e565b6020601f8211600181146139e0575f83156139c95750848201515b5f19600385901b1c1916600184901b178455611a08565b5f84815260208120601f198516915b82811015613a0f57878501518255602094850194600190920191016139ef565b5084821015613a2c57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff821663ffffffff8103613a6a57613a6a613a3b565b60010192915050565b63ffffffff818116838216019081111561075e5761075e613a3b565b604081525f613aa16040830185613088565b905067ffffffffffffffff831660208301529392505050565b606081525f613acc6060830186613088565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613b19575f5ffd5b8151610a4781612fd5565b8082018082111561075e5761075e613a3b565b8181038181111561075e5761075e613a3b565b6001600160a01b03861681526001600160a01b038516602082015260a060408201525f613b7a60a08301866134ff565b8281036060840152613b8c81866134ff565b90508281036080840152613ba08185613088565b98975050505050505050565b5f60208284031215613bbc575f5ffd5b8151610a4781613013565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a060808201525f61138860a0830184613088565b604081525f613c1560408301856134ff565b82810360208401526108fb81856134ff56fea26469706673582212203914af91977250fe376ae8bb05590e09aa035e67aac01531e596e3fa8023817f64736f6c634300081b00338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106102cc575f3560e01c80635c622a0e1161017c5780639dbba19d116100dd578063ce156e8211610093578063e4ae7d771161006e578063e4ae7d77146106cc578063e985e9c5146106df578063f242432a1461071a575f5ffd5b8063ce156e8214610693578063d3bf89b1146106a6578063dfa70d8b146106b9575f5ffd5b8063a22cb465116100c3578063a22cb4651461065a578063bc7b6d621461066d578063bd242bcb14610680575f5ffd5b80639dbba19d14610620578063a02b161e14610647575f5ffd5b8063781ef8db1161013257806380f760211161011857806380f76021146105e457806385f3e643146105fa57806391b3c0371461060d575f5ffd5b8063781ef8db146105875780637c300586146105d1575f5ffd5b806363560a8e1161016257806363560a8e1461054e5780636f3ff726146105615780636f537c7214610574575f5ffd5b80635c622a0e1461051b5780636352211e1461053b575f5ffd5b80632f27fa241161023157806344c9af28116101e75780635357263f116101c25780635357263f146104e25780635569f33d146104f55780635adf472414610508575f5ffd5b806344c9af281461048f57806348688f95146104af5780634e1273f4146104c2575f5ffd5b8063341ec55911610217578063341ec5591461044157806335af6216146104545780633634f91114610467575f5ffd5b80632f27fa24146103ef578063319c22bb14610402575f5ffd5b806313c72608116102865780631c3fc3eb1161026c5780631c3fc3eb146103c05780631e8fca2d146103c75780632eb2c2d6146103da575f5ffd5b806313c726081461035f57806314ff5ea3146103ad575f5ffd5b8063072d5d77116102b6578063072d5d77146103195780630e89341c1461032c57806311b8e00a1461034c575f5ffd5b8062fdd58e146102d057806301ffc9a7146102f6575b5f5ffd5b6102e36102de366004612fe9565b61072d565b6040519081526020015b60405180910390f35b610309610304366004613028565b610764565b60405190151581526020016102ed565b610309610327366004613043565b6108d9565b61033f61033a366004613071565b610904565b6040516102ed91906130b6565b61030961035a3660046130c8565b610a34565b61039461036d366004613071565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016102ed565b6102e36103bb366004613071565b610a4e565b6102e35f81565b6102e36103d5366004613071565b610a75565b6103ed6103e8366004613230565b610a9c565b005b6102e36103fd366004613071565b610b39565b6104297f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102ed565b6103ed61044f366004613043565b610b57565b610429610462366004613321565b610bf5565b61047a6104753660046130c8565b610c90565b604080519283526020830191909152016102ed565b6104a261049d366004613071565b610cb0565b6040516102ed9190613394565b6103ed6104bd3660046133e7565b610d82565b6104d56104d036600461343a565b610e24565b6040516102ed9190613539565b6103ed6104f036600461354b565b610eef565b6103ed6105033660046135a5565b610f8d565b6102e3610516366004613043565b61112a565b61052e610529366004613071565b61115c565b6040516102ed91906135cf565b610429610549366004613071565b6111b2565b61042961055c366004613321565b611217565b61030961056f3660046135dd565b611225565b610394610582366004613321565b611276565b610309610595366004613043565b6001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b6103096105df3660046135f8565b6112b8565b6105ec6112cc565b6040516102ed929190613623565b6102e3610608366004613644565b611377565b6102e361061b366004613321565b611393565b6104297f000000000000000000000000000000000000000000000000000000000000000081565b6103ed610655366004613071565b6113d5565b6103ed6106683660046136cd565b6114e2565b6103ed61067b366004613043565b6114f8565b61042961068e366004613071565b61159b565b6103096106a1366004613043565b6115b7565b6103096106b43660046135f8565b6115d9565b6103096106c73660046135f8565b611638565b6104296106da366004613321565b61164c565b6103096106ed3660046136fd565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6103ed610728366004613729565b6116c7565b5f826001600160a01b0316610741836111b2565b6001600160a01b031614610755575f610758565b60015b60ff1690505b92915050565b5f6001600160e01b031982167fafff3a630000000000000000000000000000000000000000000000000000000014806107c657506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b806107fa57506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b8061082e57506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b8061086257506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b8061089657506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b806108ca57506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061075e575061075e82611757565b5f5f836108ee82826108e9611794565b6117a2565b6108fb5f868660016117f0565b95945050505050565b610107546060906001600160a01b03166109a757610106805461092690613781565b80601f016020809104026020016040519081016040528092919081815260200182805461095290613781565b801561099d5780601f106109745761010080835404028352916020019161099d565b820191905f5260205f20905b81548152906001019060200180831161098057829003601f168201915b505050505061075e565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610a0d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261075e91908101906137b9565b5f610a47610a4184610a75565b83611919565b9392505050565b5f61075e82610a708463ffffffff8116185f9081526101086020526040902090565b611930565b5f61075e82610a978463ffffffff8116185f9081526101086020526040902090565b61194e565b5f610aa5611794565b9050806001600160a01b0316866001600160a01b031614158015610aee57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b15610b245760405163711bec9160e11b81526001600160a01b038083166004830152871660248201526044015b60405180910390fd5b610b3186868686866119a8565b505050505050565b5f61075e610b4683610a75565b5f9081526003602052604090205490565b5f5f610b668462100000611a0f565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038716021781559092509050610baf611794565b6001600160a01b0316836001600160a01b0316837fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a450505050565b5f5f610c51610c3885858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610c865780546801000000000000000090046001600160a01b0316610c88565b5f5b949350505050565b5f5f610ca4610c9e85610a75565b84611a85565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610d0e8584611930565b606085018190529050610d21858461194e565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610d4f8382611aa8565b85906002811115610d6257610d62613360565b90816002811115610d7557610d75613360565b8152505050505050919050565b641000000000610d9a5f82610d95611794565b611adf565b610106610da8848683613872565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416179055610dda611794565b6001600160a01b03167fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd5858585604051610e169392919061392c565b60405180910390a250505050565b60608151835114610e555781518351604051635b05999160e01b815260048101929092526024820152604401610b1b565b5f835167ffffffffffffffff811115610e7057610e706130e8565b604051908082528060200260200182016040528015610e99578160200160208202803683370190505b5090505f5b8451811015610ee757602080820286010151610ec29060208084028701015161072d565b828281518110610ed457610ed461396c565b6020908102919091010152600101610e9e565b509392505050565b610100610eff5f82610d95611794565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105610f358382613980565b50610f3e611794565b6001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff484604051610f8091906130b6565b60405180910390a3505050565b63ffffffff821682185f9081526101086020526040812090610faf8483611930565b90505f610fba611794565b600184015490915067ffffffffffffffff164281116110515767ffffffffffffffff8116158061102b575061102962010000836001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b155b1561104c5760405163311388dd60e21b815260048101849052602401610b1b565b611068565b61106861105e878661194e565b6201000084611adf565b8067ffffffffffffffff168567ffffffffffffffff1610156110ca576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015286166024820152604401610b1b565b60018401805467ffffffffffffffff191667ffffffffffffffff87169081179091556040516001600160a01b038416919085907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a4505050505050565b5f610a4761113784610a75565b5f9081526002602090815260408083206001600160a01b038716845290915290205490565b63ffffffff811681185f908152610108602052604081206001810154610a479067ffffffffffffffff166111ad6111938685611930565b5f908152602081905260409020546001600160a01b031690565b611aa8565b63ffffffff811681185f908152610108602052604081206111d38382611930565b831415806111ef5750600181015467ffffffffffffffff164210155b61120f575f838152602081905260409020546001600160a01b0316610a47565b5f9392505050565b5f610a476105498484611393565b6001600160a01b0381165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b60205260408120546f010000000000000000000000000000009081161461075e565b5f610a4761036d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b5f610c886112c585610a75565b8484611b3e565b6101045461010580545f926060926001600160a01b039091169181906112f190613781565b80601f016020809104026020016040519081016040528092919081815260200182805461131d90613781565b80156113685780601f1061133f57610100808354040283529160200191611368565b820191905f5260205f20905b81548152906001019060200180831161134b57829003601f168201915b50505050509050915091509091565b5f6113888787878787876001611b83565b979650505050505050565b5f610a476103bb84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b5f5f6113e383611000611a0f565b915091506113ef611794565b6001600160a01b0316827f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea860405160405180910390a35f828152602081905260409020546001600160a01b031680156114bf5761144e818460016120e4565b815482905f906114639063ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166114a090613a4f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b6114f46114ed611794565b838361214b565b5050565b5f5f611508846301000000611a0f565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038816021790559092509050611555611794565b6001600160a01b0316836001600160a01b0316837f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a450505050565b5f818152602081905260408120546001600160a01b031661075e565b5f5f836115cc82826115c7611794565b6121f1565b6108fb5f86866001612252565b5f610c886115e685610a75565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f610c8861164585610a75565b84846122be565b5f5f61168f610c3885858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611a7a92505050565b600181015490915067ffffffffffffffff16421015610c865760018101546801000000000000000090046001600160a01b0316610c88565b5f6116d0611794565b9050806001600160a01b0316866001600160a01b03161415801561171957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b1561174a5760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610b1b565b610b3186868686866122f9565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061075e575061075e82612386565b5f61179d612454565b905090565b5f6117ad8483612545565b905080198316156117ea5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610b1b565b50505050565b5f835f036117ff57505f610c88565b6118088461260b565b6001600160a01b038316611848576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461190d575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166118a88882600161266b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561190157611901888785858b612800565b60019350505050610c88565b505f9695505050505050565b5f5f6119258484610c90565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610a47565b5f8261195b57508161075e565b6001820154610a4790849067ffffffffffffffff1642101561198457835463ffffffff16611997565b83546119979063ffffffff166001613a73565b63ffffffff82811690921891161890565b6001600160a01b0384166119d157604051632bfa23e760e11b81525f6004820152602401610b1b565b6001600160a01b0385166119f957604051626a0d4560e21b81525f6004820152602401610b1b565b611a0885858585856001612809565b5050505050565b63ffffffff821682185f90815261010860205260408120611a308482611930565b600182015490925067ffffffffffffffff164210611a645760405163311388dd60e21b815260048101839052602401610b1b565b610ca9611a71858361194e565b84610d95611794565b805160209091012090565b5f5f611a908361286b565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff83164210611ac157505f61075e565b6001600160a01b038216611ad75750600161075e565b50600261075e565b611aea8383836115d9565b611b39576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610b1b565b505050565b5f8383611b4e82826108e9611794565b85611b6c57604051631850848b60e31b815260040160405180910390fd5b611b7986868660016117f0565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990611bea908b906004016130b6565b5f604051808303815f87803b158015611c01575f5ffd5b505af1158015611c13573d5f5f3e3d5ffd5b5050895160208b012091505f9050611c3e8263ffffffff8116185f9081526101086020526040902090565b9050611c4a8282611930565b5f818152602081905260408120549194506001600160a01b0390911690611c6f611794565b600184015490915067ffffffffffffffff164210611cea578515611c9957611c995f600183611adf565b6001600160a01b038b16158015611caf57508715155b15611ce55760405163d1a3b35560e01b81525f6004820152602481018990526001600160a01b0382166044820152606401610b1b565b611daf565b6001600160a01b03821615611d2d578b6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610b1b91906130b6565b6001600160a01b038b16611d6f578b6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610b1b91906130b6565b8515611d8157611d815f601083611adf565b8667ffffffffffffffff165f03611da457600183015467ffffffffffffffff1696505b640100000000881797505b6001600160a01b038b1615611dd15767ffffffffffffffff8716421015611dde565b67ffffffffffffffff8716155b15611e21576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff88166004820152602401610b1b565b6001600160a01b03821615611eb957611e3c828660016120e4565b825483905f90611e519063ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550825f01600481819054906101000a900463ffffffff16611e8e90613a4f565b91906101000a81548163ffffffff021916908363ffffffff160217905550611eb68584611930565b94505b60018301805484546001600160a01b03808e16680100000000000000009081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921787558c81169091026001600160e01b031990921667ffffffffffffffff8b1617919091179091558b16611f7a57806001600160a01b0316845f1b867f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88f8b604051611f6d929190613a8f565b60405180910390a4612033565b806001600160a01b0316845f1b867f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8f8f8c604051611fbb93929190613aba565b60405180910390a4611fde8b86600160405180602001604052805f815250612885565b5f611fe9868561194e565b905080611ff857611ff8613af5565b604051819087907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a3612030818a8e5f6117f0565b50505b6001600160a01b038a161561208457806001600160a01b03168a6001600160a01b0316867fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a45b6001600160a01b038916156120d557806001600160a01b0316896001600160a01b0316867f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a45b50505050979650505050505050565b6001600160a01b03831661210c57604051626a0d4560e21b81525f6004820152602401610b1b565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291611a089187918590859083612809565b6001600160a01b03821661218d576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610b1b565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610f80565b5f6121fc84836128e1565b905080198316156117ea576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610b1b565b5f61225c8461260b565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461190d575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906118a8908990839061266b565b5f83836122ce82826115c7611794565b856122ec57604051631850848b60e31b815260040160405180910390fd5b611b798686866001612252565b6001600160a01b03841661232257604051632bfa23e760e11b81525f6004820152602401610b1b565b6001600160a01b03851661234a57604051626a0d4560e21b81525f6004820152602401610b1b565b6040805160018082526020820186905281830190815260608201859052608082019092529061237d87878484875f612809565b50505050505050565b5f6001600160e01b031982167fd9b67a260000000000000000000000000000000000000000000000000000000014806123e857506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b8061241c57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061075e57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461075e565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661248857503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015612505573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125299190613b09565b90506001600160a01b038116612540573391505090565b919050565b5f5f6125b784846001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b9050836125c557905061075e565b5f6125ea61054986610a708163ffffffff8116185f9081526101086020526040902090565b6001600160a01b031603612601575f91505061075e565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612668576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610b1b565b50565b5f6126758361286b565b9050811561273e575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612716576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610b1b565b5f8481526003602052604081208054859290612733908490613b24565b909155506117ea9050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156127d8576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610b1b565b5f84815260036020526040812080548592906127f5908490613b37565b909155505050505050565b611a0885612998565b61281586868686612a78565b6001600160a01b03851615610b31575f61282d611794565b9050811561284857612843818888888888612b76565b61237d565b60208581015190850151612860838a8a85858a612c97565b505050505050505050565b5f6128758261260b565b50600181901b17600281901b1790565b6001600160a01b0384166128ae57604051632bfa23e760e11b81525f6004820152602401610b1b565b60408051600180825260208201869052818301908152606082018590526080820190925290610b315f8784848784612809565b5f821580159061291c57505f61291161054985610a708163ffffffff8116185f9081526101086020526040902090565b6001600160a01b0316145b1561292857505f61075e565b610a4783836001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b80156126685763ffffffff811681185f90815261010860205260408120906129c08383611930565b5f818152602081905260409020549091506001600160a01b03166129e6818360016120e4565b82548390600490612a0490640100000000900463ffffffff16613a4f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f612a2d8385611930565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3611a088282600160405180602001604052805f815250612885565b612a8484848484612d7e565b6001600160a01b03831615801590612aa457506001600160a01b03841615155b156117ea575f5b8251811015611a08575f838281518110612ac757612ac761396c565b60200260200101519050612af081731000000000000000000000000000000000000000886115d9565b612b38576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610b1b565b5f838381518110612b4b57612b4b61396c565b60200260200101511115612b6d57612b6d612b6582610a75565b87875f612f94565b50600101612aab565b6001600160a01b0384163b15610b315760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612bba9089908990889088908890600401613b4a565b6020604051808303815f875af1925050508015612bf4575060408051601f3d908101601f19168201909252612bf191810190613bac565b60015b612c5b573d808015612c21576040519150601f19603f3d011682016040523d82523d5f602084013e612c26565b606091505b5080515f03612c5357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461237d57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b6001600160a01b0384163b15610b315760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612cdb9089908990889088908890600401613bc7565b6020604051808303815f875af1925050508015612d15575060408051601f3d908101601f19168201909252612d1291810190613bac565b60015b612d42573d808015612c21576040519150601f19603f3d011682016040523d82523d5f602084013e612c26565b6001600160e01b0319811663f23a6e6160e01b1461237d57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610b1b565b8051825114612dad5781518151604051635b05999160e01b815260048101929092526024820152604401610b1b565b5f612db6611794565b90505f5b8351811015612eb6576020818102858101820151908501909101518015612eac575f828152602081905260409020546001600160a01b039081169089168114612e35576040516303dee4c560e01b81526001600160a01b038a1660048201525f60248201526044810183905260648101849052608401610b1b565b6001821115612e77576040516303dee4c560e01b81526001600160a01b038a166004820152600160248201526044810183905260648101849052608401610b1b565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389161790555b5050600101612dba565b508251600103612f365760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051612f27929190918252602082015260400190565b60405180910390a45050611a08565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051612f85929190613c03565b60405180910390a45050505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015611a0857612fc885828685612252565b50610b31858285856117f0565b6001600160a01b0381168114612668575f5ffd5b5f5f60408385031215612ffa575f5ffd5b823561300581612fd5565b946020939093013593505050565b6001600160e01b031981168114612668575f5ffd5b5f60208284031215613038575f5ffd5b8135610a4781613013565b5f5f60408385031215613054575f5ffd5b82359150602083013561306681612fd5565b809150509250929050565b5f60208284031215613081575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610a476020830184613088565b5f5f604083850312156130d9575f5ffd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613125576131256130e8565b604052919050565b5f67ffffffffffffffff821115613146576131466130e8565b5060051b60200190565b5f82601f83011261315f575f5ffd5b813561317261316d8261312d565b6130fc565b8082825260208201915060208360051b860101925085831115613193575f5ffd5b602085015b838110156131b0578035835260209283019201613198565b5095945050505050565b5f67ffffffffffffffff8211156131d3576131d36130e8565b50601f01601f191660200190565b5f82601f8301126131f0575f5ffd5b8135602083015f61320361316d846131ba565b9050828152858383011115613216575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f5f5f60a08688031215613244575f5ffd5b853561324f81612fd5565b9450602086013561325f81612fd5565b9350604086013567ffffffffffffffff81111561327a575f5ffd5b61328688828901613150565b935050606086013567ffffffffffffffff8111156132a2575f5ffd5b6132ae88828901613150565b925050608086013567ffffffffffffffff8111156132ca575f5ffd5b6132d6888289016131e1565b9150509295509295909350565b5f5f83601f8401126132f3575f5ffd5b50813567ffffffffffffffff81111561330a575f5ffd5b602083019150836020828501011115610ca9575f5ffd5b5f5f60208385031215613332575f5ffd5b823567ffffffffffffffff811115613348575f5ffd5b613354858286016132e3565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b6003811061339057634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506133a6828451613374565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f5f5f604084860312156133f9575f5ffd5b833567ffffffffffffffff81111561340f575f5ffd5b61341b868287016132e3565b909450925050602084013561342f81612fd5565b809150509250925092565b5f5f6040838503121561344b575f5ffd5b823567ffffffffffffffff811115613461575f5ffd5b8301601f81018513613471575f5ffd5b803561347f61316d8261312d565b8082825260208201915060208360051b8501019250878311156134a0575f5ffd5b6020840193505b828410156134cb5783356134ba81612fd5565b8252602093840193909101906134a7565b9450505050602083013567ffffffffffffffff8111156134e9575f5ffd5b6134f585828601613150565b9150509250929050565b5f8151808452602084019350602083015f5b8281101561352f578151865260209586019590910190600101613511565b5093949350505050565b602081525f610a4760208301846134ff565b5f5f6040838503121561355c575f5ffd5b823561356781612fd5565b9150602083013567ffffffffffffffff811115613582575f5ffd5b6134f5858286016131e1565b803567ffffffffffffffff81168114612540575f5ffd5b5f5f604083850312156135b6575f5ffd5b823591506135c66020840161358e565b90509250929050565b6020810161075e8284613374565b5f602082840312156135ed575f5ffd5b8135610a4781612fd5565b5f5f5f6060848603121561360a575f5ffd5b8335925060208401359150604084013561342f81612fd5565b6001600160a01b0383168152604060208201525f610c886040830184613088565b5f5f5f5f5f5f60c08789031215613659575f5ffd5b863567ffffffffffffffff81111561366f575f5ffd5b61367b89828a016131e1565b965050602087013561368c81612fd5565b9450604087013561369c81612fd5565b935060608701356136ac81612fd5565b9250608087013591506136c160a0880161358e565b90509295509295509295565b5f5f604083850312156136de575f5ffd5b82356136e981612fd5565b915060208301358015158114613066575f5ffd5b5f5f6040838503121561370e575f5ffd5b823561371981612fd5565b9150602083013561306681612fd5565b5f5f5f5f5f60a0868803121561373d575f5ffd5b853561374881612fd5565b9450602086013561375881612fd5565b93506040860135925060608601359150608086013567ffffffffffffffff8111156132ca575f5ffd5b600181811c9082168061379557607f821691505b6020821081036137b357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f602082840312156137c9575f5ffd5b815167ffffffffffffffff8111156137df575f5ffd5b8201601f810184136137ef575f5ffd5b80516137fd61316d826131ba565b818152856020838501011115613811575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b601f821115611b3957805f5260205f20601f840160051c810160208510156138535750805b601f840160051c820191505b81811015611a08575f815560010161385f565b67ffffffffffffffff83111561388a5761388a6130e8565b61389e836138988354613781565b8361382e565b5f601f8411600181146138cf575f85156138b85750838201355b5f19600387901b1c1916600186901b178355611a08565b5f83815260208120601f198716915b828110156138fe57868501358255602094850194600190920191016138de565b508682101561391a575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff81111561399a5761399a6130e8565b6139ae816139a88454613781565b8461382e565b6020601f8211600181146139e0575f83156139c95750848201515b5f19600385901b1c1916600184901b178455611a08565b5f84815260208120601f198516915b82811015613a0f57878501518255602094850194600190920191016139ef565b5084821015613a2c57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff821663ffffffff8103613a6a57613a6a613a3b565b60010192915050565b63ffffffff818116838216019081111561075e5761075e613a3b565b604081525f613aa16040830185613088565b905067ffffffffffffffff831660208301529392505050565b606081525f613acc6060830186613088565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613b19575f5ffd5b8151610a4781612fd5565b8082018082111561075e5761075e613a3b565b8181038181111561075e5761075e613a3b565b6001600160a01b03861681526001600160a01b038516602082015260a060408201525f613b7a60a08301866134ff565b8281036060840152613b8c81866134ff565b90508281036080840152613ba08185613088565b98975050505050505050565b5f60208284031215613bbc575f5ffd5b8151610a4781613013565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a060808201525f61138860a0830184613088565b604081525f613c1560408301856134ff565b82810360208401526108fb81856134ff56fea26469706673582212203914af91977250fe376ae8bb05590e09aa035e67aac01531e596e3fa8023817f64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60111": [ + { + "length": 32, + "start": 1031 + }, + { + "length": 32, + "start": 9303 + }, + { + "length": 32, + "start": 9400 + } + ], + "66658": [ + { + "length": 32, + "start": 1573 + }, + { + "length": 32, + "start": 7093 + } + ] + }, + "inputSourceName": "project/src/registry/PermissionedRegistry.sol", + "devdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "details": "Error selector: `0x68c1425a`" + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "details": "Error selector: `0xf1d446c3`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1155InsufficientBalance(address,uint256,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred.", + "tokenId": "Identifier number of a token." + } + } + ], + "ERC1155InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "ERC1155InvalidOperator(address)": [ + { + "details": "Indicates a failure with the `operator` to be approved. Used in approvals.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC1155InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC1155InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC1155MissingApprovalForAll(address,address)": [ + { + "details": "Indicates a failure with the `operator`’s approval. Used in transfers.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner.", + "owner": "Address of the current owner of a token." + } + } + ], + "LabelAlreadyRegistered(string)": [ + { + "details": "Error selector: `0xdef545a4`" + } + ], + "LabelAlreadyReserved(string)": [ + { + "details": "Error selector: `0xf60759e0`" + } + ], + "LabelExpired(uint256)": [ + { + "details": "Error selector: `0xc44e2374`" + } + ], + "TransferDisallowed(uint256,address)": [ + { + "details": "Error selector: `0xe58f6d5a`" + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "ExpiryUpdated(uint256,uint64,address)": { + "params": { + "newExpiry": "The new expiry of the label.", + "sender": "The sender of the call to update the expiry.", + "tokenId": "The token ID of the label." + } + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label registered.", + "labelHash": "The label hash registered.", + "owner": "The owner of the label.", + "sender": "The sender of the call to register.", + "tokenId": "The token ID registered." + } + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label reserved.", + "labelHash": "The label hash reserved.", + "sender": "The sender of the call to reserve.", + "tokenId": "The token ID reserved." + } + }, + "LabelUnregistered(uint256,address)": { + "params": { + "sender": "The sender of the call to unregister.", + "tokenId": "The token ID unregistered." + } + }, + "ParentUpdated(address,string,address)": { + "params": { + "label": "The new label.", + "parent": "The new parent.", + "sender": "The sender of the call to update the parent." + } + }, + "ResolverUpdated(uint256,address,address)": { + "params": { + "resolver": "The new resolver.", + "sender": "The sender of the call to update the resolver.", + "tokenId": "The token ID of the label." + } + }, + "SubregistryUpdated(uint256,address,address)": { + "params": { + "sender": "The sender of the call to update the subregistry.", + "subregistry": "The new subregistry.", + "tokenId": "The token ID of the label." + } + }, + "TokenRegenerated(uint256,uint256)": { + "params": { + "newTokenId": "The new token ID.", + "oldTokenId": "The old token ID." + } + }, + "TokenResource(uint256,uint256)": { + "params": { + "resource": "The EAC resource.", + "tokenId": "The token ID." + } + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + }, + "URIUpdated(string,address,address)": { + "params": { + "renderer": "The new render address.", + "sender": "The sender of the call to update the URI.", + "uri": "The new URI." + } + } + }, + "kind": "dev", + "methods": { + "balanceOf(address,uint256)": { + "params": { + "account": "The account to get the balance for.", + "id": "The token ID." + }, + "returns": { + "_0": "balance The balance of the token for the account. This will only ever be 1 or 0." + } + }, + "balanceOfBatch(address[],uint256[])": { + "details": "`accounts` and `ids` must have the same length.", + "params": { + "accounts": "The accounts to get the balances for.", + "ids": "The token IDs." + }, + "returns": { + "_0": "batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0." + } + }, + "constructor": { + "params": { + "hcaFactory": "The HCA factory to use.", + "labelStore": "The shared label database.", + "roleBitmap": "The role bitmap granted to `rootAccount`.", + "rootAccount": "Account granted root roles." + } + }, + "findExpiry(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The expiry of the label." + } + }, + "findOwner(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The owner of the label." + } + }, + "findTokenId(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The token ID of the label." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getExpiry(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The expiry of the label, in seconds." + } + }, + "getParent()": { + "returns": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "getResolver(string)": { + "params": { + "label": "The label to fetch a resolver for." + }, + "returns": { + "_0": "resolver The address of a resolver responsible for this label, or `address(0)` if none exists." + } + }, + "getResource(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The resource." + } + }, + "getState(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "state": "The state of the label." + } + }, + "getStatus(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The status of the label." + } + }, + "getSubregistry(string)": { + "params": { + "label": "The label to resolve." + }, + "returns": { + "_0": "The address of the registry for this label, or `address(0)` if none exists." + } + }, + "getTokenId(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token ID." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "account": "The account to get the approval for.", + "operator": "The operator to get the approval for." + }, + "returns": { + "_0": "approved The approval status." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "latestOwnerOf(uint256)": { + "params": { + "tokenId": "The token ID to query." + }, + "returns": { + "_0": "The latest owner address." + } + }, + "ownerOf(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The owner of the token." + } + }, + "register(string,address,address,address,uint256,uint64)": { + "params": { + "expiry": "The expiry of the label, in seconds.", + "label": "The label to register.", + "owner": "The address of the owner of the label.", + "registry": "The registry to set as the label.", + "resolver": "The resolver to set for the label.", + "roleBitmap": "The role bitmap to set for the label." + }, + "returns": { + "_0": "The token ID." + } + }, + "renew(uint256,uint64)": { + "details": "If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.", + "params": { + "anyId": "The labelhash, token ID, or resource.", + "newExpiry": "The new expiry, in seconds." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the tokens from.", + "ids": "The token IDs.", + "to": "The address to transfer the tokens to.", + "values": "The amounts of tokens to transfer." + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the token from.", + "id": "The token ID.", + "to": "The address to transfer the token to.", + "value": "The amount of tokens to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "The approval status.", + "operator": "The operator to set the approval for." + } + }, + "setParent(address,string)": { + "details": "Should emit `ParentUpdated`.", + "params": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "setResolver(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "resolver": "The new resolver." + } + }, + "setSubregistry(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "registry": "The new registry." + } + }, + "setURI(string,address)": { + "params": { + "renderer": "The new renderer address.", + "uri_": "The new URI." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "unregister(uint256)": { + "details": "Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.", + "params": { + "anyId": "The labelhash, token ID, or resource." + } + }, + "uri(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The URI for the token." + } + } + }, + "stateVariables": { + "__gap": { + "details": "Storage gap for future changes." + }, + "_childLabel": { + "details": "The child label of this registry." + }, + "_entries": { + "details": "The entries of this registry." + }, + "_parentRegistry": { + "details": "The parent registry of this registry." + }, + "_uri": { + "details": "The metadata URI." + }, + "_uriRenderer": { + "details": "The metadata renderer." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "3090600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "HCA_FACTORY()": "infinite", + "LABEL_STORE()": "infinite", + "ROOT_RESOURCE()": "250", + "balanceOf(address,uint256)": "infinite", + "balanceOfBatch(address[],uint256[])": "infinite", + "findExpiry(string)": "infinite", + "findOwner(string)": "infinite", + "findTokenId(string)": "infinite", + "getAssigneeCount(uint256,uint256)": "7307", + "getExpiry(uint256)": "2537", + "getParent()": "infinite", + "getResolver(string)": "infinite", + "getResource(uint256)": "4834", + "getState(uint256)": "infinite", + "getStatus(uint256)": "infinite", + "getSubregistry(string)": "infinite", + "getTokenId(uint256)": "2663", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "infinite", + "hasRoles(uint256,uint256,address)": "9465", + "hasRootRoles(uint256,address)": "2641", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "2673", + "latestOwnerOf(uint256)": "2619", + "ownerOf(uint256)": "infinite", + "register(string,address,address,address,uint256,uint64)": "infinite", + "renew(uint256,uint64)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "infinite", + "roles(uint256,address)": "infinite", + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": "infinite", + "safeTransferFrom(address,address,uint256,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "infinite", + "setParent(address,string)": "infinite", + "setResolver(uint256,address)": "infinite", + "setSubregistry(uint256,address)": "infinite", + "setURI(string,address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "unregister(uint256)": "infinite", + "uri(uint256)": "infinite" + }, + "internal": { + "_checkExpiryAndTokenRoles(uint256,uint256)": "infinite", + "_constructResource(uint256,struct PermissionedRegistry.Entry storage pointer)": "4430", + "_constructStatus(uint64,address)": "101", + "_constructTokenId(uint256,struct PermissionedRegistry.Entry storage pointer)": "2179", + "_entry(uint256)": "infinite", + "_getRevokableRoles(uint256,address)": "4553", + "_getSettableRoles(uint256,address)": "infinite", + "_isExpired(uint64)": "infinite", + "_onRolesGranted(uint256,address,uint256,uint256,uint256)": "infinite", + "_onRolesRevoked(uint256,address,uint256,uint256,uint256)": "infinite", + "_regenerate(uint256)": "infinite", + "_register(string memory,address,contract IRegistry,address,uint256,uint64,bool)": "infinite", + "_update(address,address,uint256[] memory,uint256[] memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"contract ILabelStore\",\"name\":\"labelStore\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"oldExpiry\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"CannotReduceExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"CannotSetPastExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyReserved\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"LabelExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"TransferDisallowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ExpiryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelReserved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelUnregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ParentUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RegistryCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ResolverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SubregistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldTokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newTokenId\",\"type\":\"uint256\"}],\"name\":\"TokenRegenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"TokenResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"renderer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"URIUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LABEL_STORE\",\"outputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getParent\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getResource\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"latestOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"internalType\":\"struct IPermissionedRegistry.State\",\"name\":\"state\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getSubregistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"latestOwnerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setParent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"setSubregistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"},{\"internalType\":\"contract IRegistryURIRenderer\",\"name\":\"renderer\",\"type\":\"address\"}],\"name\":\"setURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"details\":\"Error selector: `0x68c1425a`\"}],\"CannotSetPastExpiry(uint64)\":[{\"details\":\"Error selector: `0xf1d446c3`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1155InsufficientBalance(address,uint256,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\",\"tokenId\":\"Identifier number of a token.\"}}],\"ERC1155InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"ERC1155InvalidOperator(address)\":[{\"details\":\"Indicates a failure with the `operator` to be approved. Used in approvals.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC1155InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC1155InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC1155MissingApprovalForAll(address,address)\":[{\"details\":\"Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\",\"owner\":\"Address of the current owner of a token.\"}}],\"LabelAlreadyRegistered(string)\":[{\"details\":\"Error selector: `0xdef545a4`\"}],\"LabelAlreadyReserved(string)\":[{\"details\":\"Error selector: `0xf60759e0`\"}],\"LabelExpired(uint256)\":[{\"details\":\"Error selector: `0xc44e2374`\"}],\"TransferDisallowed(uint256,address)\":[{\"details\":\"Error selector: `0xe58f6d5a`\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"ExpiryUpdated(uint256,uint64,address)\":{\"params\":{\"newExpiry\":\"The new expiry of the label.\",\"sender\":\"The sender of the call to update the expiry.\",\"tokenId\":\"The token ID of the label.\"}},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label registered.\",\"labelHash\":\"The label hash registered.\",\"owner\":\"The owner of the label.\",\"sender\":\"The sender of the call to register.\",\"tokenId\":\"The token ID registered.\"}},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label reserved.\",\"labelHash\":\"The label hash reserved.\",\"sender\":\"The sender of the call to reserve.\",\"tokenId\":\"The token ID reserved.\"}},\"LabelUnregistered(uint256,address)\":{\"params\":{\"sender\":\"The sender of the call to unregister.\",\"tokenId\":\"The token ID unregistered.\"}},\"ParentUpdated(address,string,address)\":{\"params\":{\"label\":\"The new label.\",\"parent\":\"The new parent.\",\"sender\":\"The sender of the call to update the parent.\"}},\"ResolverUpdated(uint256,address,address)\":{\"params\":{\"resolver\":\"The new resolver.\",\"sender\":\"The sender of the call to update the resolver.\",\"tokenId\":\"The token ID of the label.\"}},\"SubregistryUpdated(uint256,address,address)\":{\"params\":{\"sender\":\"The sender of the call to update the subregistry.\",\"subregistry\":\"The new subregistry.\",\"tokenId\":\"The token ID of the label.\"}},\"TokenRegenerated(uint256,uint256)\":{\"params\":{\"newTokenId\":\"The new token ID.\",\"oldTokenId\":\"The old token ID.\"}},\"TokenResource(uint256,uint256)\":{\"params\":{\"resource\":\"The EAC resource.\",\"tokenId\":\"The token ID.\"}},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"},\"URIUpdated(string,address,address)\":{\"params\":{\"renderer\":\"The new render address.\",\"sender\":\"The sender of the call to update the URI.\",\"uri\":\"The new URI.\"}}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"params\":{\"account\":\"The account to get the balance for.\",\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"balance The balance of the token for the account. This will only ever be 1 or 0.\"}},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"`accounts` and `ids` must have the same length.\",\"params\":{\"accounts\":\"The accounts to get the balances for.\",\"ids\":\"The token IDs.\"},\"returns\":{\"_0\":\"batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\"}},\"constructor\":{\"params\":{\"hcaFactory\":\"The HCA factory to use.\",\"labelStore\":\"The shared label database.\",\"roleBitmap\":\"The role bitmap granted to `rootAccount`.\",\"rootAccount\":\"Account granted root roles.\"}},\"findExpiry(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The expiry of the label.\"}},\"findOwner(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The owner of the label.\"}},\"findTokenId(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The token ID of the label.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getExpiry(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The expiry of the label, in seconds.\"}},\"getParent()\":{\"returns\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"getResolver(string)\":{\"params\":{\"label\":\"The label to fetch a resolver for.\"},\"returns\":{\"_0\":\"resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\"}},\"getResource(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The resource.\"}},\"getState(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"state\":\"The state of the label.\"}},\"getStatus(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The status of the label.\"}},\"getSubregistry(string)\":{\"params\":{\"label\":\"The label to resolve.\"},\"returns\":{\"_0\":\"The address of the registry for this label, or `address(0)` if none exists.\"}},\"getTokenId(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"account\":\"The account to get the approval for.\",\"operator\":\"The operator to get the approval for.\"},\"returns\":{\"_0\":\"approved The approval status.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"latestOwnerOf(uint256)\":{\"params\":{\"tokenId\":\"The token ID to query.\"},\"returns\":{\"_0\":\"The latest owner address.\"}},\"ownerOf(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The owner of the token.\"}},\"register(string,address,address,address,uint256,uint64)\":{\"params\":{\"expiry\":\"The expiry of the label, in seconds.\",\"label\":\"The label to register.\",\"owner\":\"The address of the owner of the label.\",\"registry\":\"The registry to set as the label.\",\"resolver\":\"The resolver to set for the label.\",\"roleBitmap\":\"The role bitmap to set for the label.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"renew(uint256,uint64)\":{\"details\":\"If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"newExpiry\":\"The new expiry, in seconds.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the tokens from.\",\"ids\":\"The token IDs.\",\"to\":\"The address to transfer the tokens to.\",\"values\":\"The amounts of tokens to transfer.\"}},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the token from.\",\"id\":\"The token ID.\",\"to\":\"The address to transfer the token to.\",\"value\":\"The amount of tokens to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"The approval status.\",\"operator\":\"The operator to set the approval for.\"}},\"setParent(address,string)\":{\"details\":\"Should emit `ParentUpdated`.\",\"params\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"setResolver(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"resolver\":\"The new resolver.\"}},\"setSubregistry(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"registry\":\"The new registry.\"}},\"setURI(string,address)\":{\"params\":{\"renderer\":\"The new renderer address.\",\"uri_\":\"The new URI.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"unregister(uint256)\":{\"details\":\"Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"}},\"uri(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The URI for the token.\"}}},\"stateVariables\":{\"__gap\":{\"details\":\"Storage gap for future changes.\"},\"_childLabel\":{\"details\":\"The child label of this registry.\"},\"_entries\":{\"details\":\"The entries of this registry.\"},\"_parentRegistry\":{\"details\":\"The parent registry of this registry.\"},\"_uri\":{\"details\":\"The metadata URI.\"},\"_uriRenderer\":{\"details\":\"The metadata renderer.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"notice\":\"Label expiry cannot be reduced.\"}],\"CannotSetPastExpiry(uint64)\":[{\"notice\":\"Label expiry cannot be before now.\"}],\"LabelAlreadyRegistered(string)\":[{\"notice\":\"Label is already registered.\"}],\"LabelAlreadyReserved(string)\":[{\"notice\":\"Label cannot be reserved again.\"}],\"LabelExpired(uint256)\":[{\"notice\":\"Label is expired/unregistered.\"}],\"TransferDisallowed(uint256,address)\":[{\"notice\":\"Transfer is not allowed due to missing transfer admin role.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"ExpiryUpdated(uint256,uint64,address)\":{\"notice\":\"Expiry of label was changed.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"notice\":\"A label was registered.\"},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"notice\":\"A label was reserved.\"},\"LabelUnregistered(uint256,address)\":{\"notice\":\"A label was unregistered.\"},\"ParentUpdated(address,string,address)\":{\"notice\":\"Parent was changed.\"},\"RegistryCreated()\":{\"notice\":\"A registry was created/initialized.\"},\"ResolverUpdated(uint256,address,address)\":{\"notice\":\"Resolver of label was changed.\"},\"SubregistryUpdated(uint256,address,address)\":{\"notice\":\"Subregistry of label was changed.\"},\"TokenRegenerated(uint256,uint256)\":{\"notice\":\"Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance.\"},\"TokenResource(uint256,uint256)\":{\"notice\":\"Associate a token with an EAC resource.\"},\"URIUpdated(string,address,address)\":{\"notice\":\"URI was changed.\"}},\"kind\":\"user\",\"methods\":{\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"LABEL_STORE()\":{\"notice\":\"The shared label database.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"balanceOf(address,uint256)\":{\"notice\":\"Returns the balance of a token for an account.\"},\"balanceOfBatch(address[],uint256[])\":{\"notice\":\"Returns the balances of a batch of tokens for an account.\"},\"findExpiry(string)\":{\"notice\":\"Fetches the label expiry.\"},\"findOwner(string)\":{\"notice\":\"Fetches the label owner.\"},\"findTokenId(string)\":{\"notice\":\"Fetches the token ID for a label.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getExpiry(uint256)\":{\"notice\":\"Get expiry of label.\"},\"getParent()\":{\"notice\":\"Get canonical \\\"location\\\" of this registry.\"},\"getResolver(string)\":{\"notice\":\"Fetches the resolver responsible for the specified label.\"},\"getResource(uint256)\":{\"notice\":\"Get `resource` from `anyId`.\"},\"getState(uint256)\":{\"notice\":\"Get the state of a label.\"},\"getStatus(uint256)\":{\"notice\":\"Get `Status` from `anyId`.\"},\"getSubregistry(string)\":{\"notice\":\"Fetches the registry for a label.\"},\"getTokenId(uint256)\":{\"notice\":\"Get `tokenId` from `anyId`.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Returns the approval for all operator.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"latestOwnerOf(uint256)\":{\"notice\":\"Get the latest owner of a token. If the token was burned, returns null.\"},\"ownerOf(uint256)\":{\"notice\":\"Returns the owner of a token.\"},\"register(string,address,address,address,uint256,uint64)\":{\"notice\":\"Registers a new label.\"},\"renew(uint256,uint64)\":{\"notice\":\"Renew a label.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Transfers multiple tokens from one address to another.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"notice\":\"Transfers a single token from one address to another.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Sets the approval for all operator.\"},\"setParent(address,string)\":{\"notice\":\"Change canonical \\\"location\\\".\"},\"setResolver(uint256,address)\":{\"notice\":\"Change resolver of label.\"},\"setSubregistry(uint256,address)\":{\"notice\":\"Change registry of label.\"},\"setURI(string,address)\":{\"notice\":\"Set the URI for the registry.\"},\"unregister(uint256)\":{\"notice\":\"Delete a label.\"},\"uri(uint256)\":{\"notice\":\"Returns the URI for a token.\"}},\"notice\":\"A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`) to resolve any of these to the canonical storage slot for the name. The registry maintains two independent version counters per name: - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form the EAC resource ID. This means a re-registered name gets a fresh permission scope. - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint) due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring changes to roles create new tokens and prevent frontrunning a transfer with a role revocation. Names are treated as `AVAILABLE` once `block.timestamp >= expiry`. URI renderer address is embedded into URI data as `abi.encodePacked(uint8(1), address)`. State diagram: register() +ROLE_REGISTRAR +------------------->----------------------+ | | | renew() | renew() | +ROLE_RENEW | +ROLE_RENEW | +------+ | +------+ | | | | | | \\u028c \\u028c v v v | AVAILABLE --------> RESERVED -------------> REGISTERED >--+ \\u028c register() v register() v | w/owner=0 | +ROLE_REGISTER_RESERVED | | +ROLE_REGISTRAR | | | | | +--------<---------+------------<------------+ unregister() +ROLE_UNREGISTER\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/PermissionedRegistry.sol\":\"PermissionedRegistry\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155} from \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x35d120c427299af1525aaf07955314d9e36a62f14408eb93dec71a2e001f74d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/utils/ERC1155Utils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\nimport {IERC1155Errors} from \\\"../../../interfaces/draft-IERC6093.sol\\\";\\n\\n/**\\n * @dev Library that provide common ERC-1155 utility functions.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].\\n *\\n * _Available since v5.1._\\n */\\nlibrary ERC1155Utils {\\n /**\\n * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155Received(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver.onERC1155Received.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155BatchReceived(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x22f099c02c252dd1f6ddc464916ce683294a63b23b3c6ee3d290b77398e2474b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)\\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\\n\\npragma solidity ^0.8.20;\\n\\nimport {Comparators} from \\\"./Comparators.sol\\\";\\nimport {SlotDerivation} from \\\"./SlotDerivation.sol\\\";\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\nimport {Math} from \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to array types.\\n */\\nlibrary Arrays {\\n using SlotDerivation for bytes32;\\n using StorageSlot for bytes32;\\n\\n /**\\n * @dev Sort an array of uint256 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n uint256[] memory array,\\n function(uint256, uint256) pure returns (bool) comp\\n ) internal pure returns (uint256[] memory) {\\n _quickSort(_begin(array), _end(array), comp);\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\\n */\\n function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\\n sort(array, Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of address (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n address[] memory array,\\n function(address, address) pure returns (bool) comp\\n ) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of address in increasing order.\\n */\\n function sort(address[] memory array) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n bytes32[] memory array,\\n function(bytes32, bytes32) pure returns (bool) comp\\n ) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\\n */\\n function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\\n * at end (exclusive). Sorting follows the `comp` comparator.\\n *\\n * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\\n *\\n * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\\n * be used only if the limits are within a memory array.\\n */\\n function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\\n unchecked {\\n if (end - begin < 0x40) return;\\n\\n // Use first element as pivot\\n uint256 pivot = _mload(begin);\\n // Position where the pivot should be at the end of the loop\\n uint256 pos = begin;\\n\\n for (uint256 it = begin + 0x20; it < end; it += 0x20) {\\n if (comp(_mload(it), pivot)) {\\n // If the value stored at the iterator's position comes before the pivot, we increment the\\n // position of the pivot and move the value there.\\n pos += 0x20;\\n _swap(pos, it);\\n }\\n }\\n\\n _swap(begin, pos); // Swap pivot into place\\n _quickSort(begin, pos, comp); // Sort the left side of the pivot\\n _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first element of `array`.\\n */\\n function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\\n assembly (\\\"memory-safe\\\") {\\n ptr := add(array, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\\n * that comes just after the last element of the array.\\n */\\n function _end(uint256[] memory array) private pure returns (uint256 ptr) {\\n unchecked {\\n return _begin(array) + array.length * 0x20;\\n }\\n }\\n\\n /**\\n * @dev Load memory word (as a uint256) at location `ptr`.\\n */\\n function _mload(uint256 ptr) private pure returns (uint256 value) {\\n assembly {\\n value := mload(ptr)\\n }\\n }\\n\\n /**\\n * @dev Swaps the elements memory location `ptr1` and `ptr2`.\\n */\\n function _swap(uint256 ptr1, uint256 ptr2) private pure {\\n assembly {\\n let value1 := mload(ptr1)\\n let value2 := mload(ptr2)\\n mstore(ptr1, value2)\\n mstore(ptr2, value1)\\n }\\n }\\n\\n /// @dev Helper: low level cast address memory array to uint256 memory array\\n function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\\n function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast address comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(address, address) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(bytes32, bytes32) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /**\\n * @dev Searches a sorted `array` and returns the first index that contains\\n * a value greater or equal to `element`. If no such index exists (i.e. all\\n * values in the array are strictly less than `element`), the array length is\\n * returned. Time complexity O(log n).\\n *\\n * NOTE: The `array` is expected to be sorted in ascending order, and to\\n * contain no repeated elements.\\n *\\n * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\\n * support for repeated elements in the array. The {lowerBound} function should\\n * be used instead.\\n */\\n function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n low = mid + 1;\\n }\\n }\\n\\n // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\\n if (low > 0 && unsafeAccess(array, low - 1).value == element) {\\n return low - 1;\\n } else {\\n return low;\\n }\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value greater or equal than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\\n */\\n function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value strictly greater than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\\n */\\n function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {lowerBound}, but with an array in memory.\\n */\\n function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {upperBound}, but with an array in memory.\\n */\\n function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getAddressSlot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getBytes32Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getUint256Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(address[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(uint256[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55a4fdb408e3db950b48f4a6131e538980be8c5f48ee59829d92d66477140cd6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides a set of functions to compare values.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Comparators {\\n function lt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a < b;\\n }\\n\\n function gt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a > b;\\n }\\n}\\n\",\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\\n * the solidity language / compiler.\\n *\\n * 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.].\\n *\\n * Example usage:\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using StorageSlot for bytes32;\\n * using SlotDerivation for bytes32;\\n *\\n * // Declare a namespace\\n * string private constant _NAMESPACE = \\\"\\\"; // eg. OpenZeppelin.Slot\\n *\\n * function setValueInNamespace(uint256 key, address newValue) internal {\\n * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\\n * }\\n *\\n * function getValueInNamespace(uint256 key) internal view returns (address) {\\n * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {StorageSlot}.\\n *\\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\\n * upgrade safety will ignore the slots accessed through this library.\\n *\\n * _Available since v5.1._\\n */\\nlibrary SlotDerivation {\\n /**\\n * @dev Derive an ERC-7201 slot from a string (namespace).\\n */\\n function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\\n slot := and(keccak256(0x00, 0x20), not(0xff))\\n }\\n }\\n\\n /**\\n * @dev Add an offset to a slot to get the n-th element of a structure or an array.\\n */\\n function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\\n unchecked {\\n return bytes32(uint256(slot) + pos);\\n }\\n }\\n\\n /**\\n * @dev Derive the location of the first element in an array from the slot where the length is stored.\\n */\\n function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, slot)\\n result := keccak256(0x00, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, and(key, shr(96, not(0))))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, iszero(iszero(key)))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x67672e4ca1dafdcc661d4eba8475cfac631fa0933309258e3af7644b92e1fb26\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, _msgSender());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _roles[ROOT_RESOURCE][account] & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return\\n (_roles[ROOT_RESOURCE][account] | _roles[resource][account]) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (_hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (_hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function _hasZeroNybbles(uint256 value) private pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 hasZeroNybbles;\\n unchecked {\\n hasZeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return hasZeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xdf8918a909b0ab3bf17bc3a560fbdff6ca6e9502cbee54eb0923f1fae04d2fb1\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x9f29748b40665df976c08cdaf434b469dc73ef50e938c36be6773dc7b6a6f014\",\"license\":\"MIT\"},\"project/src/erc1155/ERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {\\n IERC1155MetadataURI\\n} from \\\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\\\";\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport {ERC1155Utils} from \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol\\\";\\nimport {Arrays} from \\\"@openzeppelin/contracts/utils/Arrays.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IERC1155Singleton} from \\\"./interfaces/IERC1155Singleton.sol\\\";\\n\\n/// @notice ERC1155 variant enforcing exactly one owner per token ID.\\n///\\n/// Instead of the standard nested balance mapping (`id \\u2192 address \\u2192 balance`), uses a flat\\n/// `id \\u2192 address` ownership mapping. `balanceOf` returns 1 if the account is the owner,\\n/// 0 otherwise. Transferring value > 1 reverts.\\n///\\n/// Used by `PermissionedRegistry` to represent domain name ownership as non-divisible tokens.\\n/// The registry overrides `ownerOf` to add expiry and version validation on top of raw ownership.\\n///\\n/// Inherits `HCAContext` so that `_msgSender()` resolves HCA proxy accounts to their real\\n/// owners for approval checks and operator tracking.\\n///\\n/// @author OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC1155/ERC1155.sol)\\n/// @dev This contract has been modified from the implementation at the above link.\\nabstract contract ERC1155Singleton is\\n HCAContext,\\n ERC165,\\n IERC1155Singleton,\\n IERC1155Errors,\\n IERC1155MetadataURI\\n{\\n using Arrays for uint256[];\\n\\n using Arrays for address[];\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Maps each token ID to its single owner address.\\n mapping(uint256 id => address account) private _owners;\\n\\n /// @dev Standard ERC1155 operator approval mapping.\\n mapping(address account => mapping(address operator => bool)) private _operatorApprovals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155Singleton).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Sets the approval for all operator.\\n /// @param operator The operator to set the approval for.\\n /// @param approved The approval status.\\n function setApprovalForAll(address operator, bool approved) public virtual {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /// @notice Transfers a single token from one address to another.\\n /// @param from The address to transfer the token from.\\n /// @param to The address to transfer the token to.\\n /// @param id The token ID.\\n /// @param value The amount of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `to` cannot be the zero address.\\n /// @dev If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.\\n /// @dev `from` must have a balance of tokens of type `id` of at least `value` amount.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the\\n /// acceptance magic value.\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data)\\n public\\n virtual\\n {\\n address sender = _msgSender();\\n if (from != sender && !isApprovedForAll(from, sender)) {\\n revert ERC1155MissingApprovalForAll(sender, from);\\n }\\n _safeTransferFrom(from, to, id, value, data);\\n }\\n\\n /// @notice Transfers multiple tokens from one address to another.\\n /// @param from The address to transfer the tokens from.\\n /// @param to The address to transfer the tokens to.\\n /// @param ids The token IDs.\\n /// @param values The amounts of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `ids` and `values` must have the same length.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the\\n /// acceptance magic value.\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n public\\n virtual\\n {\\n address sender = _msgSender();\\n if (from != sender && !isApprovedForAll(from, sender)) {\\n revert ERC1155MissingApprovalForAll(sender, from);\\n }\\n _safeBatchTransferFrom(from, to, ids, values, data);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 id) public view virtual returns (address owner) {\\n return _owners[id];\\n }\\n\\n /// @notice Returns the URI for a token.\\n /// @param id The token ID.\\n /// @return uri The URI for the token.\\n function uri(uint256 id) public view virtual returns (string memory uri);\\n\\n /// @notice Returns the balance of a token for an account.\\n /// @param account The account to get the balance for.\\n /// @param id The token ID.\\n /// @return balance The balance of the token for the account. This will only ever be 1 or 0.\\n function balanceOf(address account, uint256 id) public view virtual returns (uint256) {\\n return ownerOf(id) == account ? 1 : 0;\\n }\\n\\n /// @notice Returns the balances of a batch of tokens for an account.\\n /// @param accounts The accounts to get the balances for.\\n /// @param ids The token IDs.\\n /// @return batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\\n /// @dev `accounts` and `ids` must have the same length.\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n returns (uint256[] memory)\\n {\\n if (accounts.length != ids.length) {\\n revert ERC1155InvalidArrayLength(ids.length, accounts.length);\\n }\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));\\n }\\n\\n return batchBalances;\\n }\\n\\n /// @notice Returns the approval for all operator.\\n /// @param account The account to get the approval for.\\n /// @param operator The operator to get the approval for.\\n /// @return approved The approval status.\\n function isApprovedForAll(address account, address operator) public view virtual returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Apply token updates for each pair in `ids` and `values`.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not the current owner or `value > 1`.\\n /// @dev This function does not perform ERC-1155 receiver acceptance checks.\\n /// @dev Emits `TransferSingle` when one token ID is updated, otherwise emits `TransferBatch`.\\n function _update(address from, address to, uint256[] memory ids, uint256[] memory values)\\n internal\\n virtual\\n {\\n if (ids.length != values.length) {\\n revert ERC1155InvalidArrayLength(ids.length, values.length);\\n }\\n\\n address operator = _msgSender();\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids.unsafeMemoryAccess(i);\\n uint256 value = values.unsafeMemoryAccess(i);\\n\\n if (value > 0) {\\n address owner = _owners[id];\\n if (owner != from) {\\n revert ERC1155InsufficientBalance(from, 0, value, id);\\n } else if (value > 1) {\\n revert ERC1155InsufficientBalance(from, 1, value, id);\\n }\\n _owners[id] = to;\\n }\\n }\\n\\n if (ids.length == 1) {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n emit TransferSingle(operator, from, to, id, value);\\n } else {\\n emit TransferBatch(operator, from, to, ids, values);\\n }\\n }\\n\\n /// @notice Apply token updates and run ERC-1155 receiver acceptance checks.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @param batch `true` if a batch operation.\\n /// @dev Calls `_update` before external receiver callbacks.\\n /// @dev If `to` is a contract, this calls `onERC1155Received` or `onERC1155BatchReceived`.\\n /// @dev Overriding is discouraged because post-callback state writes can introduce reentrancy bugs.\\n function _updateWithAcceptanceCheck(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data,\\n bool batch\\n )\\n internal\\n virtual\\n {\\n _update(from, to, ids, values);\\n if (to != address(0)) {\\n address operator = _msgSender();\\n if (batch) {\\n ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data);\\n } else {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data);\\n }\\n }\\n }\\n\\n /// @notice Safely transfer `value` tokens of token ID `id` from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param id Token ID to transfer.\\n /// @param value Amount to transfer.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, to, ids, values, data, false);\\n }\\n\\n /// @notice Safely transfer multiple token IDs from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param ids Token IDs to transfer.\\n /// @param values Amounts to transfer for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferBatch`.\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n _updateWithAcceptanceCheck(from, to, ids, values, data, true);\\n }\\n\\n /// @notice Mint `value` tokens of token ID `id` to `to`.\\n /// @param to Address receiving the minted token.\\n /// @param id Token ID to mint.\\n /// @param value Amount to mint.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(address(0), to, ids, values, data, false);\\n }\\n\\n /// @notice Burn `value` tokens of token ID `id` from `from`.\\n /// @param from Address to burn from.\\n /// @param id Token ID to burn.\\n /// @param value Amount to burn.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not current owner or `value > 1`.\\n /// @dev Emits `TransferSingle`.\\n function _burn(address from, uint256 id, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, address(0), ids, values, \\\"\\\", false);\\n }\\n\\n /// @notice Set or clear approval for `operator` to manage all tokens owned by `owner`.\\n /// @param owner Token owner granting or revoking approval.\\n /// @param operator Operator receiving approval.\\n /// @param approved Approval status to set.\\n /// @dev Reverts with `ERC1155InvalidOperator` if `operator` is the zero address.\\n /// @dev Emits `ApprovalForAll`.\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n if (operator == address(0)) {\\n revert ERC1155InvalidOperator(address(0));\\n }\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Gas-optimized assembly helper that creates two length-1 memory arrays without Solidity's\\n /// default zero-initialization overhead. Used to adapt single-token operations (`_mint`,\\n /// `_burn`, `_safeTransferFrom`) to the array-based `_update` function.\\n function _asSingletonArrays(uint256 element1, uint256 element2)\\n private\\n pure\\n returns (uint256[] memory array1, uint256[] memory array2)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Load the free memory pointer\\n array1 := mload(0x40)\\n // Set array length to 1\\n mstore(array1, 1)\\n // Store the single element at the next word after the length (where content starts)\\n mstore(add(array1, 0x20), element1)\\n\\n // Repeat for next array locating it right after the first array\\n array2 := add(array1, 0x40)\\n mstore(array2, 1)\\n mstore(add(array2, 0x20), element2)\\n\\n // Update the free memory pointer by pointing after the second array\\n mstore(0x40, add(array2, 0x40))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9af9852c17f9d19765bd2b21fe2076d96845f0c0f7e9b0faa1d905793d3b677d\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/registry/PermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IEnhancedAccessControl} from \\\"../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {ERC1155Singleton} from \\\"../erc1155/ERC1155Singleton.sol\\\";\\nimport {IERC1155Singleton} from \\\"../erc1155/interfaces/IERC1155Singleton.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {ILabelStore} from \\\"../utils/interfaces/ILabelStore.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./interfaces/IOwnedRegistry.sol\\\";\\nimport {IPermissionedRegistry} from \\\"./interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"./interfaces/IRegistry.sol\\\";\\nimport {IRegistryURIRenderer} from \\\"./interfaces/IRegistryURIRenderer.sol\\\";\\nimport {IStandardRegistry} from \\\"./interfaces/IStandardRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./interfaces/ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./interfaces/ITokenizedRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"./libraries/RegistryRolesLib.sol\\\";\\n\\n/// @notice A tokenized (ERC1155) registry with resource-scoped access control for subdomain management.\\n///\\n/// Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource\\n/// interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`)\\n/// to resolve any of these to the canonical storage slot for the name.\\n///\\n/// The registry maintains two independent version counters per name:\\n/// - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form\\n/// the EAC resource ID. This means a re-registered name gets a fresh permission scope.\\n/// - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint)\\n/// due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring\\n/// changes to roles create new tokens and prevent frontrunning a transfer with a role revocation.\\n///\\n/// Names are treated as `AVAILABLE` once `block.timestamp >= expiry`.\\n///\\n/// URI renderer address is embedded into URI data as `abi.encodePacked(uint8(1), address)`.\\n///\\n/// State diagram:\\n///\\n/// register()\\n/// +ROLE_REGISTRAR\\n/// +------------------->----------------------+\\n/// | |\\n/// | renew() | renew()\\n/// | +ROLE_RENEW | +ROLE_RENEW\\n/// | +------+ | +------+\\n/// | | | | | |\\n/// \\u028c \\u028c v v v |\\n/// AVAILABLE --------> RESERVED -------------> REGISTERED >--+\\n/// \\u028c register() v register() v\\n/// | w/owner=0 | +ROLE_REGISTER_RESERVED |\\n/// | +ROLE_REGISTRAR | |\\n/// | | |\\n/// +--------<---------+------------<------------+\\n/// unregister()\\n/// +ROLE_UNREGISTER\\n///\\ncontract PermissionedRegistry is ERC1155Singleton, EnhancedAccessControl, IPermissionedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n struct Entry {\\n /// @dev Incremented on unregister; combined with labelhash to form the EAC resource ID.\\n uint32 eacVersionId;\\n /// @dev Incremented on unregister and on token regeneration; combined with labelhash to form the ERC1155 token ID.\\n uint32 tokenVersionId;\\n /// @dev Child registry for this name.\\n IRegistry subregistry;\\n /// @dev Timestamp at or after which the name is considered expired/available.\\n uint64 expiry;\\n /// @dev Resolver address for this name.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The shared label database.\\n ILabelStore public immutable LABEL_STORE;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The parent registry of this registry.\\n IRegistry internal _parentRegistry;\\n\\n /// @dev The child label of this registry.\\n string internal _childLabel;\\n\\n /// @dev The metadata URI.\\n string internal _uri;\\n\\n /// @dev The metadata renderer.\\n IRegistryURIRenderer internal _uriRenderer;\\n\\n /// @dev The entries of this registry.\\n mapping(uint256 storageId => Entry entry) internal _entries;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory to use.\\n /// @param labelStore The shared label database.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n constructor(\\n IHCAFactoryBasic hcaFactory,\\n ILabelStore labelStore,\\n address rootAccount,\\n uint256 roleBitmap\\n )\\n HCAEquivalence(hcaFactory)\\n {\\n emit RegistryCreated();\\n LABEL_STORE = labelStore;\\n _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false);\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(IERC165, ERC1155Singleton, EnhancedAccessControl)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IPermissionedRegistry).interfaceId ||\\n interfaceId == type(IStandardRegistry).interfaceId ||\\n interfaceId == type(ITokenizedRegistry).interfaceId ||\\n interfaceId == type(ITemporalRegistry).interfaceId ||\\n interfaceId == type(IOwnedRegistry).interfaceId ||\\n interfaceId == type(IRegistry).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IStandardRegistry\\n function setSubregistry(uint256 anyId, IRegistry registry) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_SUBREGISTRY);\\n entry.subregistry = registry;\\n emit SubregistryUpdated(tokenId, registry, _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setResolver(uint256 anyId, address resolver) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_RESOLVER);\\n entry.resolver = resolver;\\n emit ResolverUpdated(tokenId, resolver, _msgSender());\\n }\\n\\n /// @notice Set the URI for the registry.\\n /// @param uri_ The new URI.\\n /// @param renderer The new renderer address.\\n function setURI(string calldata uri_, IRegistryURIRenderer renderer)\\n public\\n virtual\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_URI)\\n {\\n _uri = uri_;\\n _uriRenderer = renderer;\\n emit URIUpdated(uri_, address(renderer), _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setParent(IRegistry parent, string memory label)\\n public\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_PARENT)\\n {\\n _parentRegistry = parent;\\n _childLabel = label;\\n emit ParentUpdated(parent, label, _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n public\\n virtual\\n returns (uint256)\\n {\\n return _register(label, owner, registry, resolver, roleBitmap, expiry, true);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\\n function unregister(uint256 anyId) public {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_UNREGISTER);\\n emit LabelUnregistered(tokenId, _msgSender());\\n address owner = super.ownerOf(tokenId);\\n if (owner != address(0)) {\\n _burn(owner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n }\\n entry.expiry = uint64(block.timestamp);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev If `REGISTERED | RESERVED`, requires `ROLE_RENEW`.\\n /// If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\\n function renew(uint256 anyId, uint64 newExpiry) public override {\\n Entry storage entry = _entry(anyId);\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n address sender = _msgSender();\\n uint64 expiry = entry.expiry;\\n if (_isExpired(expiry)) {\\n if (expiry == 0 || !hasRootRoles(RegistryRolesLib.ROLE_RENEW, sender)) {\\n revert LabelExpired(tokenId); // never registered OR cannot revive\\n }\\n } else {\\n _checkRoles(_constructResource(anyId, entry), RegistryRolesLib.ROLE_RENEW, sender);\\n }\\n if (newExpiry < expiry) {\\n revert CannotReduceExpiry(expiry, newExpiry);\\n }\\n entry.expiry = newExpiry;\\n emit ExpiryUpdated(tokenId, newExpiry, sender);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function grantRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.grantRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function revokeRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.revokeRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IRegistry\\n function getSubregistry(string calldata label) public view virtual returns (IRegistry) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return\\n _isExpired(entry.expiry)\\n ? IRegistry(address(0))\\n : entry.subregistry;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getResolver(string calldata label) public view virtual returns (address) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? address(0) : entry.resolver;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getParent() public view returns (IRegistry parent, string memory label) {\\n return (_parentRegistry, _childLabel);\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) public view returns (bool) {\\n return hasRootRoles(RegistryRolesLib.ROLE_CAN_NAME, namer);\\n }\\n\\n /// @inheritdoc ITemporalRegistry\\n function findExpiry(string calldata label) public view returns (uint64) {\\n return getExpiry(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc IOwnedRegistry\\n function findOwner(string calldata label) public view returns (address) {\\n return ownerOf(findTokenId(label));\\n }\\n\\n /// @inheritdoc ITokenizedRegistry\\n function findTokenId(string calldata label) public view returns (uint256) {\\n return getTokenId(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ERC1155Singleton\\n function uri(uint256 tokenId) public view override returns (string memory) {\\n return\\n address(_uriRenderer) != address(0)\\n ? _uriRenderer.renderURI(this, tokenId)\\n : _uri;\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function getExpiry(uint256 anyId) public view returns (uint64) {\\n return _entry(anyId).expiry;\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getResource(uint256 anyId) public view returns (uint256) {\\n return _constructResource(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getTokenId(uint256 anyId) public view returns (uint256) {\\n return _constructTokenId(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getStatus(uint256 anyId) public view returns (Status) {\\n Entry storage entry = _entry(anyId);\\n return _constructStatus(entry.expiry, super.ownerOf(_constructTokenId(anyId, entry)));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getState(uint256 anyId) public view returns (State memory state) {\\n Entry storage entry = _entry(anyId);\\n uint64 expiry = entry.expiry;\\n state.expiry = expiry;\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n state.tokenId = tokenId;\\n state.resource = _constructResource(anyId, entry);\\n address owner = super.ownerOf(tokenId);\\n state.latestOwner = owner;\\n state.status = _constructStatus(expiry, owner);\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function latestOwnerOf(uint256 tokenId) public view returns (address) {\\n return super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 tokenId)\\n public\\n view\\n override(ERC1155Singleton, IERC1155Singleton)\\n returns (address)\\n {\\n Entry storage entry = _entry(tokenId);\\n return\\n tokenId != _constructTokenId(tokenId, entry) || _isExpired(entry.expiry)\\n ? address(0)\\n : super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 anyId, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roles(getResource(anyId), account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 anyId)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roleCount(getResource(anyId));\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasAssignees(getResource(anyId), roleBitmap);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256 counts, uint256 mask)\\n {\\n return super.getAssigneeCount(getResource(anyId), roleBitmap);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev If `AVAILABLE`, requires `ROLE_REGISTRAR` on root and status becomes `REGISTERED`.\\n /// * If `owner` is null (`roleBitmap` must be 0), status becomes `RESERVED`.\\n /// If `RESERVED`, requires `ROLE_REGISTER_RESERVED` on root and status becomes `REGISTERED`.\\n /// * If `expiry` is 0, uses current expiry.\\n function _register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry,\\n bool checkRoles\\n )\\n internal\\n returns (uint256 tokenId)\\n {\\n LABEL_STORE.setLabel(label);\\n uint256 labelId = LibLabel.id(label);\\n Entry storage entry = _entry(labelId);\\n tokenId = _constructTokenId(labelId, entry);\\n address prevOwner = super.ownerOf(tokenId);\\n address sender = _msgSender(); // the registrar, not the registrant\\n if (_isExpired(entry.expiry)) {\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTRAR, sender);\\n }\\n if (owner == address(0) && roleBitmap != 0) {\\n revert EACCannotGrantRoles(ROOT_RESOURCE, roleBitmap, sender); // strict\\n }\\n } else {\\n if (prevOwner != address(0)) {\\n revert LabelAlreadyRegistered(label); // cannot overwrite REGISTERED\\n } else if (owner == address(0)) {\\n revert LabelAlreadyReserved(label); // cannot overwrite RESERVED\\n }\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTER_RESERVED, sender);\\n }\\n if (expiry == 0) {\\n expiry = entry.expiry; // use RESERVED expiry\\n }\\n roleBitmap |= RegistryRolesLib.ROLE_WAS_RESERVED; // remember\\n }\\n if (owner == address(0) ? expiry == 0 : _isExpired(expiry)) {\\n revert CannotSetPastExpiry(expiry);\\n }\\n if (prevOwner != address(0)) {\\n _burn(prevOwner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n tokenId = _constructTokenId(tokenId, entry);\\n }\\n entry.expiry = expiry;\\n entry.subregistry = registry;\\n entry.resolver = resolver;\\n if (owner == address(0)) {\\n emit LabelReserved(tokenId, bytes32(labelId), label, expiry, sender);\\n } else {\\n emit LabelRegistered(tokenId, bytes32(labelId), label, owner, expiry, sender);\\n _mint(owner, tokenId, 1, \\\"\\\");\\n uint256 resource = _constructResource(tokenId, entry);\\n assert(resource != ROOT_RESOURCE);\\n emit TokenResource(tokenId, resource);\\n _grantRoles(resource, roleBitmap, owner, false);\\n }\\n if (address(registry) != address(0)) {\\n emit SubregistryUpdated(tokenId, registry, sender);\\n }\\n if (address(resolver) != address(0)) {\\n emit ResolverUpdated(tokenId, resolver, sender);\\n }\\n }\\n\\n /// @dev Override `ERC1155Singleton._update()` to transfer the roles to the new owner if the token is transferred.\\n function _update(address from, address to, uint256[] memory tokenIds, uint256[] memory amounts)\\n internal\\n override\\n {\\n super._update(from, to, tokenIds, amounts); // ensures amounts[i] is 0 or 1\\n if (to != address(0) && from != address(0)) {\\n // only transfers (skip mint and burn)\\n for (uint256 i; i < tokenIds.length; ++i) {\\n uint256 tokenId = tokenIds[i];\\n // only check ROLE_CAN_TRANSFER_ADMIN on original owner (from)\\n // ROLE_CAN_TRANSFER_ADMIN is technically a property of the token\\n if (!hasRoles(tokenId, RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, from)) {\\n revert TransferDisallowed(tokenId, from);\\n } else if (amounts[i] > 0) {\\n _transferRoles(getResource(tokenId), from, to, false);\\n }\\n }\\n }\\n }\\n\\n /// @dev Override the base registry _onRolesGranted function to regenerate the token when the roles are granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Override the base registry _onRolesRevoked function to regenerate the token when the roles are revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Bump `tokenVersionId` via burn+mint if token is not expired.\\n function _regenerate(uint256 resource) internal {\\n if (resource != ROOT_RESOURCE) {\\n Entry storage entry = _entry(resource);\\n uint256 tokenId = _constructTokenId(resource, entry);\\n address owner = super.ownerOf(tokenId); // grant/revoke only on registered\\n _burn(owner, tokenId, 1);\\n ++entry.tokenVersionId;\\n uint256 newTokenId = _constructTokenId(tokenId, entry);\\n emit TokenRegenerated(tokenId, newTokenId); // resource is unchanged\\n _mint(owner, newTokenId, 1, \\\"\\\");\\n }\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token non-admin roles can only be granted to registered tokens.\\n ///\\n /// Token admin roles are only assigned during name registration to maintain\\n /// controlled permission management. This ensures that role delegation\\n /// follows the intended security model where admin privileges are granted at\\n /// registration time and cannot be arbitrarily granted afterward.\\n ///\\n /// Root admin roles are unaffected.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles (regular roles only, not admin roles).\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n override\\n returns (uint256)\\n {\\n uint256 roleBitmap = super._getSettableRoles(resource, account);\\n if (resource == ROOT_RESOURCE) {\\n return roleBitmap;\\n } else if (ownerOf(_constructTokenId(resource, _entry(resource))) == address(0)) {\\n return 0; // available or reserved\\n }\\n return roleBitmap >> 128; // remove admin\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token roles can only be revoked from registered tokens.\\n ///\\n /// Root roles are unaffected.\\n ///\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n override\\n returns (uint256)\\n {\\n if (\\n resource != ROOT_RESOURCE &&\\n ownerOf(_constructTokenId(resource, _entry(resource))) == address(0)\\n ) {\\n return 0; // available or reserved\\n }\\n return super._getRevokableRoles(resource, account);\\n }\\n\\n /// @dev Zeroes version bits in `anyId` to return the canonical storage entry for the name.\\n function _entry(uint256 anyId) internal view returns (Entry storage) {\\n return _entries[LibLabel.withVersion(anyId, 0)];\\n }\\n\\n /// @dev Assert token is not expired and caller has necessary roles.\\n function _checkExpiryAndTokenRoles(uint256 anyId, uint256 roleBitmap)\\n internal\\n view\\n returns (uint256 tokenId, Entry storage entry)\\n {\\n entry = _entry(anyId);\\n tokenId = _constructTokenId(anyId, entry);\\n if (_isExpired(entry.expiry)) {\\n revert LabelExpired(tokenId);\\n }\\n _checkRoles(_constructResource(anyId, entry), roleBitmap, _msgSender());\\n }\\n\\n /// @dev Internal logic for expired status.\\n function _isExpired(uint64 expiry) internal view returns (bool) {\\n return block.timestamp >= expiry;\\n }\\n\\n /// @dev Create `resource` from parts.\\n /// Does nothing if `ROOT_RESOURCE`.\\n /// Returns next resource if expired.\\n function _constructResource(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n if (anyId == ROOT_RESOURCE) {\\n return anyId;\\n }\\n return\\n LibLabel.withVersion(\\n anyId,\\n _isExpired(entry.expiry)\\n ? entry.eacVersionId + 1\\n : entry.eacVersionId\\n );\\n }\\n\\n /// @dev Create `tokenId` from parts.\\n function _constructTokenId(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n return LibLabel.withVersion(anyId, entry.tokenVersionId);\\n }\\n\\n /// @dev Create `Status` from parts.\\n function _constructStatus(uint64 expiry, address owner) internal view returns (Status) {\\n if (_isExpired(expiry)) {\\n return Status.AVAILABLE;\\n } else if (owner == address(0)) {\\n return Status.RESERVED;\\n } else {\\n return Status.REGISTERED;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3d065298bcd998d8a638d5e52ff7ed15b8eff4ef43666eb8219a5858ace5a5e7\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryURIRenderer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6c55e19b`\\ninterface IRegistryURIRenderer {\\n /// @notice Generate URI for `tokenId` from `registry`.\\n /// @param registry The registry.\\n /// @param tokenId The token ID in the registry.\\n /// @return The generated URI.\\n function renderURI(IRegistry registry, uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa6ea64ff73d10fa58118ae9c0d0c2caa72f2f3488776227a22bd0cd9cd6586f6\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 7: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x6bd37001025ec90ffe9b852fcfdf68be81a9f70f8777d80136bea1c04da30041\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/interfaces/ILabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @notice Interface for a shared label database.\\n/// @dev Interface selector: `0x0d48fe93`\\ninterface ILabelStore {\\n /// @notice A label was recorded.\\n /// @param labelHash The hash of `label`.\\n /// @param label The recorded label.\\n event Label(bytes32 indexed labelHash, string label);\\n\\n /// @notice Ensure `label` can be inverted from `anyId`.\\n /// @param label The label.\\n function setLabel(string calldata label) external;\\n\\n /// @notice Invert `anyId` to the corresponding label.\\n /// @param anyId The truncated labelhash.\\n /// @return The label or null if unknown.\\n function getLabel(uint256 anyId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 59110, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_owners", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 59117, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 55601, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_roles", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 55606, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_roleCount", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 55611, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "__gap", + "offset": 0, + "slot": "4", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 66662, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_parentRegistry", + "offset": 0, + "slot": "260", + "type": "t_contract(IRegistry)68656" + }, + { + "astId": 66665, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_childLabel", + "offset": 0, + "slot": "261", + "type": "t_string_storage" + }, + { + "astId": 66668, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_uri", + "offset": 0, + "slot": "262", + "type": "t_string_storage" + }, + { + "astId": 66672, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_uriRenderer", + "offset": 0, + "slot": "263", + "type": "t_contract(IRegistryURIRenderer)68771" + }, + { + "astId": 66678, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_entries", + "offset": 0, + "slot": "264", + "type": "t_mapping(t_uint256,t_struct(Entry)66654_storage)" + }, + { + "astId": 66683, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "__gap", + "offset": 0, + "slot": "265", + "type": "t_array(t_uint256)256_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRegistry)68656": { + "encoding": "inplace", + "label": "contract IRegistry", + "numberOfBytes": "20" + }, + "t_contract(IRegistryURIRenderer)68771": { + "encoding": "inplace", + "label": "contract IRegistryURIRenderer", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "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_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_struct(Entry)66654_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct PermissionedRegistry.Entry)", + "numberOfBytes": "32", + "value": "t_struct(Entry)66654_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Entry)66654_storage": { + "encoding": "inplace", + "label": "struct PermissionedRegistry.Entry", + "members": [ + { + "astId": 66640, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "eacVersionId", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 66643, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "tokenVersionId", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 66647, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "subregistry", + "offset": 8, + "slot": "0", + "type": "t_contract(IRegistry)68656" + }, + { + "astId": 66650, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "expiry", + "offset": 0, + "slot": "1", + "type": "t_uint64" + }, + { + "astId": 66653, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "resolver", + "offset": 8, + "slot": "1", + "type": "t_address" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "notice": "Label expiry cannot be reduced." + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "notice": "Label expiry cannot be before now." + } + ], + "LabelAlreadyRegistered(string)": [ + { + "notice": "Label is already registered." + } + ], + "LabelAlreadyReserved(string)": [ + { + "notice": "Label cannot be reserved again." + } + ], + "LabelExpired(uint256)": [ + { + "notice": "Label is expired/unregistered." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "notice": "Transfer is not allowed due to missing transfer admin role." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "ExpiryUpdated(uint256,uint64,address)": { + "notice": "Expiry of label was changed." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "notice": "A label was registered." + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "notice": "A label was reserved." + }, + "LabelUnregistered(uint256,address)": { + "notice": "A label was unregistered." + }, + "ParentUpdated(address,string,address)": { + "notice": "Parent was changed." + }, + "RegistryCreated()": { + "notice": "A registry was created/initialized." + }, + "ResolverUpdated(uint256,address,address)": { + "notice": "Resolver of label was changed." + }, + "SubregistryUpdated(uint256,address,address)": { + "notice": "Subregistry of label was changed." + }, + "TokenRegenerated(uint256,uint256)": { + "notice": "Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance." + }, + "TokenResource(uint256,uint256)": { + "notice": "Associate a token with an EAC resource." + }, + "URIUpdated(string,address,address)": { + "notice": "URI was changed." + } + }, + "kind": "user", + "methods": { + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "LABEL_STORE()": { + "notice": "The shared label database." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "balanceOf(address,uint256)": { + "notice": "Returns the balance of a token for an account." + }, + "balanceOfBatch(address[],uint256[])": { + "notice": "Returns the balances of a batch of tokens for an account." + }, + "findExpiry(string)": { + "notice": "Fetches the label expiry." + }, + "findOwner(string)": { + "notice": "Fetches the label owner." + }, + "findTokenId(string)": { + "notice": "Fetches the token ID for a label." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getExpiry(uint256)": { + "notice": "Get expiry of label." + }, + "getParent()": { + "notice": "Get canonical \"location\" of this registry." + }, + "getResolver(string)": { + "notice": "Fetches the resolver responsible for the specified label." + }, + "getResource(uint256)": { + "notice": "Get `resource` from `anyId`." + }, + "getState(uint256)": { + "notice": "Get the state of a label." + }, + "getStatus(uint256)": { + "notice": "Get `Status` from `anyId`." + }, + "getSubregistry(string)": { + "notice": "Fetches the registry for a label." + }, + "getTokenId(uint256)": { + "notice": "Get `tokenId` from `anyId`." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "isApprovedForAll(address,address)": { + "notice": "Returns the approval for all operator." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "latestOwnerOf(uint256)": { + "notice": "Get the latest owner of a token. If the token was burned, returns null." + }, + "ownerOf(uint256)": { + "notice": "Returns the owner of a token." + }, + "register(string,address,address,address,uint256,uint64)": { + "notice": "Registers a new label." + }, + "renew(uint256,uint64)": { + "notice": "Renew a label." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "notice": "Transfers multiple tokens from one address to another." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "notice": "Transfers a single token from one address to another." + }, + "setApprovalForAll(address,bool)": { + "notice": "Sets the approval for all operator." + }, + "setParent(address,string)": { + "notice": "Change canonical \"location\"." + }, + "setResolver(uint256,address)": { + "notice": "Change resolver of label." + }, + "setSubregistry(uint256,address)": { + "notice": "Change registry of label." + }, + "setURI(string,address)": { + "notice": "Set the URI for the registry." + }, + "unregister(uint256)": { + "notice": "Delete a label." + }, + "uri(uint256)": { + "notice": "Returns the URI for a token." + } + }, + "notice": "A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`) to resolve any of these to the canonical storage slot for the name. The registry maintains two independent version counters per name: - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form the EAC resource ID. This means a re-registered name gets a fresh permission scope. - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint) due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring changes to roles create new tokens and prevent frontrunning a transfer with a role revocation. Names are treated as `AVAILABLE` once `block.timestamp >= expiry`. URI renderer address is embedded into URI data as `abi.encodePacked(uint8(1), address)`. State diagram: register() +ROLE_REGISTRAR +------------------->----------------------+ | | | renew() | renew() | +ROLE_RENEW | +ROLE_RENEW | +------+ | +------+ | | | | | | ʌ ʌ v v v | AVAILABLE --------> RESERVED -------------> REGISTERED >--+ ʌ register() v register() v | w/owner=0 | +ROLE_REGISTER_RESERVED | | +ROLE_REGISTRAR | | | | | +--------<---------+------------<------------+ unregister() +ROLE_UNREGISTER", + "version": 1 + }, + "argsData": "0x000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf94300000000000000000000000023ea712da760c4e09fc9be108f1f1da6d5d6d053000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f800100000000000000000000100001011101000000000000000000001000010111", + "transaction": { + "hash": "0xa7799865af54e9212cbfea3224f18e449822c6d6505091c6d37e64a187f4922d", + "nonce": "0x1e4d", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xf29b77ea9c30e4710e4d001f78ae6e6dd637160d77d1093baf2bbfb3c7ed115f", + "blockNumber": "0xa6a7c0", + "transactionIndex": "0x4e" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/StandardRentPriceOracle.json b/contracts/deployments/sepolia-official-v1-20260525-r2/StandardRentPriceOracle.json new file mode 100644 index 000000000..1247454ba --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/StandardRentPriceOracle.json @@ -0,0 +1,1760 @@ +{ + "address": "0xe19d37839f42f7d2694d8c5712f412c66a218161", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "baseRatePerCp", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + } + ], + "internalType": "struct DiscountPoint[]", + "name": "discountPoints", + "type": "tuple[]" + }, + { + "internalType": "uint128", + "name": "discountDenominator", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "premiumPriceInitial", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "premiumHalvingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "premiumPeriod", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "denom", + "type": "uint128" + } + ], + "internalType": "struct PaymentRatio[]", + "name": "paymentRatios", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBaseRates", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDiscount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRatio", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "NotValid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "PaymentTokenNotSupported", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "numer", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "denom", + "type": "uint128" + } + ], + "name": "PaymentTokenUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DISCOUNT_DENOMINATOR", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIUM_HALVING_PERIOD", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIUM_PERIOD", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIUM_PRICE_INITIAL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIUM_PRICE_OFFSET", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + } + ], + "name": "applyDiscount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "convertUnits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "disablePaymentToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + } + ], + "name": "getBasePrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBaseRates", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDiscountPoints", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + } + ], + "internalType": "struct DiscountPoint[]", + "name": "v", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getPaymentTokenRatio", + "outputs": [ + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "denom", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + } + ], + "name": "getPremiumPriceAfter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "available", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRegisterPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "base", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "premium", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRenewPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "isPaymentToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "isValid", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "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": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "denom", + "type": "uint128" + } + ], + "name": "updatePaymentToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "StandardRentPriceOracle", + "sourceName": "src/registrar/StandardRentPriceOracle.sol", + "bytecode": "0x610140604052348015610010575f5ffd5b506040516130f63803806130f683398101604081905261002f91610c89565b5f608081905261005390710111000000000000000000000000000001118a82610333565b5086515f036100755760405163de27644760e01b815260040160405180910390fd5b8651610089906101029060208a019061098e565b50855180156101d2575f86815b83811015610198575f8a82815181106100b1576100b1610d64565b60200260200101519050836001600160401b0316815f01516001600160401b03161115806100f55750826001600160801b031681602001516001600160801b031610155b15610113576040516304cbf51b60e51b815260040160405180910390fd5b80516020820180516101038054600181810183555f9290925294517f02c297ab74aad0aede3a1895c857b1f2c71e6a203feb727bec95ac752998cb78909501805493516001600160801b031668010000000000000000026001600160c01b03199094166001600160401b03909616959095179290921790935590945090925001610096565b50806001600160801b03165f036101c2576040516304cbf51b60e51b815260040160405180910390fd5b50506001600160801b03861660a0525b60c08590526001600160401b0380851660e08190529084166101008190526101fb91879161042e565b610120525f5b8251811015610324575f83828151811061021d5761021d610d64565b6020026020010151905080602001516001600160801b03165f148061024d575060408101516001600160801b0316155b1561026b5760405163648564d360e01b815260040160405180910390fd5b604080518082018252602080840180516001600160801b0390811684528585018051821684860190815287516001600160a01b039081165f90815261010490965294879020955190518316600160801b0292169190911790935584519051925193519116927f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede492610313929091906001600160801b0392831681529116602082015260400190565b60405180910390a250600101610201565b50505050505050505050610de8565b5f835f0361034257505f610426565b61034b846104d6565b6001600160a01b0383166103725760405163761fe2c960e11b815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214610420575f878152602081815260408083206001600160a01b03891684529091529020819055811986166103ce88826001610522565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050610426565b5f925050505b949350505050565b5f83158061043a575082155b1561044657505f6104cf565b815f036104545750826104cf565b5f83610468670de0b6b3a764000085610d8c565b6104729190610da3565b90505f610487670de0b6b3a764000083610da3565b90505f61049c670de0b6b3a764000083610d8c565b6104a69084610dc2565b90506104c987831c6104c4670de0b6b3a7640000601085901b610da3565b610652565b93505050505b9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561051f57604051630153d96960e51b8152600481018290526024015b60405180910390fd5b50565b5f61052c83610974565b905081156105c2575f848152600160205260409020546105729082161980195f5160206130d65f395f51905f5291909101165f5160206130b65f395f51905f5216151590565b1561059a57604051631f22ca6960e31b81526004810185905260248101849052604401610516565b5f84815260016020526040812080548592906105b7908490610dd5565b9091555061064c9050565b5f84815260016020526040902054610601901982161980195f5160206130d65f395f51905f5291909101165f5160206130b65f395f51905f5216151590565b1561062957604051631f80c19b60e01b81526004810185905260248101849052604401610516565b5f8481526001602052604081208054859290610646908490610dc2565b90915550505b50505050565b5f600182161561068457670de0b6b3a7640000610677670de0ad151d09418085610d8c565b6106819190610da3565b92505b60028216156106b557670de0b6b3a76400006106a8670de0a3769959680085610d8c565b6106b29190610da3565b92505b60048216156106e657670de0b6b3a76400006106d9670de09039a5fa510085610d8c565b6106e39190610da3565b92505b600882161561071757670de0b6b3a764000061070a670de069c00f3e120085610d8c565b6107149190610da3565b92505b601082161561074857670de0b6b3a764000061073b670de01cce21c9440085610d8c565b6107459190610da3565b92505b602082161561077957670de0b6b3a764000061076c670ddf82ef46ce100085610d8c565b6107769190610da3565b92505b60408216156107aa57670de0b6b3a764000061079d670dde4f458f8e8d8085610d8c565b6107a79190610da3565b92505b60808216156107db57670de0b6b3a76400006107ce670ddbe84213d5f08085610d8c565b6107d89190610da3565b92505b61010082161561080d57670de0b6b3a7640000610800670dd71b7aa6df5b8085610d8c565b61080a9190610da3565b92505b61020082161561083f57670de0b6b3a7640000610832670dcd86e7f28cde0085610d8c565b61083c9190610da3565b92505b61040082161561087157670de0b6b3a7640000610864670dba71a3084ad68085610d8c565b61086e9190610da3565b92505b6108008216156108a357670de0b6b3a7640000610896670d94961b13dbde8085610d8c565b6108a09190610da3565b92505b6110008216156108d557670de0b6b3a76400006108c8670d4a171c35c9838085610d8c565b6108d29190610da3565b92505b61200082161561090757670de0b6b3a76400006108fa670cb9da519ccfb70085610d8c565b6109049190610da3565b92505b61400082161561093957670de0b6b3a764000061092c670bab76d59c18d68085610d8c565b6109369190610da3565b92505b61800082161561096b57670de0b6b3a764000061095e6709d025defee4df8085610d8c565b6109689190610da3565b92505b50815b92915050565b5f61097e826104d6565b50600181901b17600281901b1790565b828054828255905f5260205f209081019282156109c7579160200282015b828111156109c75782518255916020019190600101906109ac565b506109d39291506109d7565b5090565b5b808211156109d3575f81556001016109d8565b6001600160a01b038116811461051f575f5ffd5b8051610a0a816109eb565b919050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715610a4557610a45610a0f565b60405290565b604051606081016001600160401b0381118282101715610a4557610a45610a0f565b604051601f8201601f191681016001600160401b0381118282101715610a9557610a95610a0f565b604052919050565b5f6001600160401b03821115610ab557610ab5610a0f565b5060051b60200190565b5f82601f830112610ace575f5ffd5b8151610ae1610adc82610a9d565b610a6d565b8082825260208201915060208360051b860101925085831115610b02575f5ffd5b602085015b83811015610b1f578051835260209283019201610b07565b5095945050505050565b80516001600160401b0381168114610a0a575f5ffd5b80516001600160801b0381168114610a0a575f5ffd5b5f82601f830112610b64575f5ffd5b8151610b72610adc82610a9d565b8082825260208201915060208360061b860101925085831115610b93575f5ffd5b602085015b83811015610b1f5760408188031215610baf575f5ffd5b610bb7610a23565b610bc082610b29565b8152610bce60208301610b3f565b602082015280845250602083019250604081019050610b98565b5f82601f830112610bf7575f5ffd5b8151610c05610adc82610a9d565b80828252602082019150602060608402860101925085831115610c26575f5ffd5b602085015b83811015610b1f5760608188031215610c42575f5ffd5b610c4a610a4b565b8151610c55816109eb565b8152610c6360208301610b3f565b6020820152610c7460408301610b3f565b60408201528352602090920191606001610c2b565b5f5f5f5f5f5f5f5f610100898b031215610ca1575f5ffd5b610caa896109ff565b60208a01519098506001600160401b03811115610cc5575f5ffd5b610cd18b828c01610abf565b60408b015190985090506001600160401b03811115610cee575f5ffd5b610cfa8b828c01610b55565b965050610d0960608a01610b3f565b60808a01519095509350610d1f60a08a01610b29565b9250610d2d60c08a01610b29565b60e08a01519092506001600160401b03811115610d48575f5ffd5b610d548b828c01610be8565b9150509295985092959890939650565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761096e5761096e610d78565b5f82610dbd57634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561096e5761096e610d78565b8082018082111561096e5761096e610d78565b60805160a05160c05160e0516101005161012051612256610e605f395f81816103cb0152610b0c01525f81816104380152610acb01525f81816105d60152610b5101525f81816105af0152610b3001525f818161038c015261081601525f81816102ea015281816116f4015261175501526122565ff3fe608060405234801561000f575f5ffd5b5060043610610201575f3560e01c80636e45511111610123578063ac0d63d0116100b8578063d3bf89b111610088578063dff521a81161006e578063dff521a814610694578063e1de9c83146106a7578063f1dfaefb146106ba575f5ffd5b8063d3bf89b114610620578063dfa70d8b14610681575f5ffd5b8063ac0d63d0146105aa578063b553630e146105d1578063c50f093b146105f8578063ce156e821461060d575f5ffd5b80638b59de43116100f35780638b59de4314610534578063930eaddc146105475780639c7aa7f8146105825780639e6d1a9314610597575f5ffd5b80636e455111146104735780636f3ff72614610486578063781ef8db146104d75780637c30058614610521575f5ffd5b80633634f9111161019957806348b6781f1161016957806348b6781f146103c65780635adf4724146103ed5780636981b5f4146104205780636bab30b714610433575f5ffd5b80633634f9111461033757806339ac7a2a1461035f5780633ad8608314610374578063415175bb14610387575f5ffd5b80632f27fa24116101d45780632f27fa241461026857806330897dba14610287578063319c22bb146102e557806334d8262214610324575f5ffd5b806301ffc9a714610205578063072d5d771461022d57806311b8e00a146102405780631c3fc3eb14610253575b5f5ffd5b610218610213366004611d83565b6106cd565b60405190151581526020015b60405180910390f35b61021861023b366004611dbe565b610744565b61021861024e366004611dec565b61076f565b61025a5f81565b604051908152602001610224565b61025a610276366004611e0c565b5f9081526001602052604090205490565b6102c5610295366004611e23565b6001600160a01b03165f90815261010460205260409020546001600160801b0380821692600160801b9092041690565b604080516001600160801b03938416815292909116602083015201610224565b61030c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610224565b61025a610332366004611e55565b610786565b61034a610345366004611dec565b610851565b60408051928352602083019190915201610224565b610367610874565b6040516102249190611e7f565b61025a610382366004611f25565b6108f5565b6103ae7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160801b039091168152602001610224565b61025a7f000000000000000000000000000000000000000000000000000000000000000081565b61025a6103fb366004611dbe565b5f918252602082815260408084206001600160a01b0393909316845291905290205490565b61025a61042e366004611f9a565b61091c565b61045a7f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610224565b61025a610481366004611fd9565b610962565b610218610494366004611e23565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb560205260408120546101009081161461073e565b6102186104e5366004611dbe565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b61021861052f366004612029565b6109e3565b61025a610542366004611dbe565b610a1e565b610218610555366004611e23565b6001600160a01b03165f9081526101046020526040902054600160801b90046001600160801b0316151590565b610595610590366004611e23565b610a2c565b005b61025a6105a536600461205f565b610ac8565b61025a7f000000000000000000000000000000000000000000000000000000000000000081565b61045a7f000000000000000000000000000000000000000000000000000000000000000081565b610600610b94565b6040516102249190612078565b61021861061b366004611dbe565b610beb565b61021861062e366004612029565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b61021861068f366004612029565b610c0d565b6105956106a23660046120c5565b610c48565b61034a6106b5366004611f25565b610e1c565b6102186106c8366004611f9a565b610e83565b5f6001600160e01b031982167fdb06fc0000000000000000000000000000000000000000000000000000000000148061072f57506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061073e575061073e82610e99565b92915050565b5f5f836107598282610754610eff565b610f0d565b6107665f86866001610fde565b95945050505050565b5f5f61077b8484610851565b501515949350505050565b610103545f9081805b828110156107f6575f61010382815481106107ac576107ac6120fe565b5f918252602090912001805490915067ffffffffffffffff90811690871610156107d657506107f6565b546801000000000000000090046001600160801b0316915060010161078f565b506001600160801b038116156108485761084385826001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160801b03166110f2565b610766565b50929392505050565b5f5f61085c836111a2565b5f948552600160205260409094205484169492505050565b6060610103805480602002602001604051908101604052809291908181526020015f905b828210156108ec575f848152602090819020604080518082019091529084015467ffffffffffffffff811682526801000000000000000090046001600160801b031681830152825260019092019101610898565b50505050905090565b5f6109126109048787866111bc565b61090d84611207565b61129c565b9695505050505050565b5f61095b83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506112ef92505050565b9392505050565b5f82801580610971575060ff81115b1561097f575f91505061095b565b5f61098a868661091c565b6101025490915081111561099e5750610102545b61091267ffffffffffffffff85166101026109ba600185612126565b815481106109ca576109ca6120fe565b905f5260205f2001546109dd9190612139565b85610786565b5f83836109f38282610754610eff565b85610a1157604051631850848b60e31b815260040160405180910390fd5b6109128686866001610fde565b5f61095b8361090d84611207565b6010610a405f82610a3b610eff565b61147c565b6001600160a01b0382165f9081526101046020526040902054600160801b90046001600160801b031615610ac4576001600160a01b0382165f818152610104602090815260408083208390558051838152918201929092527f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff1610610b0a575f61073e565b7f0000000000000000000000000000000000000000000000000000000000000000610b8a7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168567ffffffffffffffff1661151d565b61073e9190612126565b6060610102805480602002602001604051908101604052809291908181526020018280548015610be157602002820191905f5260205f20905b815481526020019060010190808311610bcd575b5050505050905090565b5f5f83610c008282610bfb610eff565b6115c3565b6107665f86866001611689565b5f8383610c1d8282610bfb610eff565b85610c3b57604051631850848b60e31b815260040160405180910390fd5b6109128686866001611689565b6001610c575f82610a3b610eff565b6001600160a01b0384165f90815261010460209081526040918290208251808401909352546001600160801b038082168452600160801b909104811691830191909152831615610dac57836001600160801b03165f03610ce3576040517f648564d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001600160801b0316815f01516001600160801b0316141580610d1d5750826001600160801b031681602001516001600160801b031614155b15610da7576040805180820182526001600160801b0386811680835286821660208085018281526001600160a01b038c165f8181526101048452889020965191518616600160801b029190951617909455845191825292810192909252917f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b610e15565b60208101516001600160801b031615610e15576001600160a01b0385165f818152610104602090815260408083208390558051838152918201929092527f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b5050505050565b5f5f610e298787866111bc565b91505f610e3584611207565b9050610e4086610ac8565b91508115610e6157610e528284612150565b9250610e5e828261129c565b91505b81610e6c848361129c565b610e769190612126565b9250509550959350505050565b5f5f610e9184846001610962565b119392505050565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061073e57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461073e565b5f610f086116f1565b905090565b5f610f7d84836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b90508019831615610fd8576040517fd1a3b35500000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b03831660448201526064015b60405180910390fd5b50505050565b5f835f03610fed57505f6110ea565b610ff6846117dd565b6001600160a01b038316611036576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b03871684529091529020548481178082146110e4575f878152602081815260408083206001600160a01b03891684529091529020819055811986166110928882600161183d565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3600193505050506110ea565b5f925050505b949350505050565b5f5f5f6110ff86866119d2565b91509150815f036111235783818161111957611119612163565b049250505061095b565b81841161113a5761113a60038515026011186119ee565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010185841190960395909502919093039390930492909217029150509392505050565b5f6111ac826117dd565b50600181901b17600281901b1790565b5f6111c8848484610962565b9050805f0361095b5783836040517fdbfa2886000000000000000000000000000000000000000000000000000000008152600401610fcf929190612177565b6040805180820182525f80825260209182018190526001600160a01b038416815261010482528281208351808501909452546001600160801b038082168552600160801b9091041691830182905203611297576040517f02e2ae9e0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610fcf565b919050565b5f81602001516001600160801b0316825f01516001600160801b0316146112e8576112e383835f01516001600160801b031684602001516001600160801b031660016119ff565b61095b565b5090919050565b80515f90819081905b80821015611473575f858381518110611313576113136120fe565b01602001516001600160f81b03191690507f800000000000000000000000000000000000000000000000000000000000000081101561135e57611357600184612150565b9250611460565b7fe0000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561139b57611357600284612150565b7ff0000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156113d857611357600384612150565b7ff8000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561141557611357600484612150565b7ffc000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561145257611357600584612150565b61145d600684612150565b92505b508261146b816121a5565b9350506112f8565b50909392505050565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5909252909120541782168214611518576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610fcf565b505050565b5f831580611529575082155b1561153557505f61095b565b815f0361154357508261095b565b5f83611557670de0b6b3a764000085612139565b61156191906121bd565b90505f611576670de0b6b3a7640000836121bd565b90505f61158b670de0b6b3a764000083612139565b6115959084612126565b90506115b887831c6115b3670de0b6b3a7640000601085901b6121bd565b611a41565b979650505050505050565b5f61163384836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b90508019831615610fd8576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610fcf565b5f611693846117dd565b5f858152602081815260408083206001600160a01b0387168452909152902054841981168082146110e4575f878152602081815260408083206001600160a01b0389168452909152812082905586831690611092908990839061183d565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661172557503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa1580156117a2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c691906121d0565b90506001600160a01b038116611297573391505090565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561183a576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610fcf565b50565b5f611847836111a2565b90508115611910575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156118e8576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610fcf565b5f8481526001602052604081208054859290611905908490612150565b90915550610fd89050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156119aa576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610fcf565b5f84815260016020526040812080548592906119c7908490612126565b909155505050505050565b5f805f1983850993909202808410938190039390930393915050565b634e487b715f52806020526024601cfd5b5f611a2c611a0c83611d57565b8015611a2757505f8480611a2257611a22612163565b868809115b151590565b611a378686866110f2565b6107669190612150565b5f6001821615611a7357670de0b6b3a7640000611a66670de0ad151d09418085612139565b611a7091906121bd565b92505b6002821615611aa457670de0b6b3a7640000611a97670de0a3769959680085612139565b611aa191906121bd565b92505b6004821615611ad557670de0b6b3a7640000611ac8670de09039a5fa510085612139565b611ad291906121bd565b92505b6008821615611b0657670de0b6b3a7640000611af9670de069c00f3e120085612139565b611b0391906121bd565b92505b6010821615611b3757670de0b6b3a7640000611b2a670de01cce21c9440085612139565b611b3491906121bd565b92505b6020821615611b6857670de0b6b3a7640000611b5b670ddf82ef46ce100085612139565b611b6591906121bd565b92505b6040821615611b9957670de0b6b3a7640000611b8c670dde4f458f8e8d8085612139565b611b9691906121bd565b92505b6080821615611bca57670de0b6b3a7640000611bbd670ddbe84213d5f08085612139565b611bc791906121bd565b92505b610100821615611bfc57670de0b6b3a7640000611bef670dd71b7aa6df5b8085612139565b611bf991906121bd565b92505b610200821615611c2e57670de0b6b3a7640000611c21670dcd86e7f28cde0085612139565b611c2b91906121bd565b92505b610400821615611c6057670de0b6b3a7640000611c53670dba71a3084ad68085612139565b611c5d91906121bd565b92505b610800821615611c9257670de0b6b3a7640000611c85670d94961b13dbde8085612139565b611c8f91906121bd565b92505b611000821615611cc457670de0b6b3a7640000611cb7670d4a171c35c9838085612139565b611cc191906121bd565b92505b612000821615611cf657670de0b6b3a7640000611ce9670cb9da519ccfb70085612139565b611cf391906121bd565b92505b614000821615611d2857670de0b6b3a7640000611d1b670bab76d59c18d68085612139565b611d2591906121bd565b92505b6180008216156112e857670de0b6b3a7640000611d4d6709d025defee4df8085612139565b61095b91906121bd565b5f6002826003811115611d6c57611d6c6121eb565b611d7691906121ff565b60ff166001149050919050565b5f60208284031215611d93575f5ffd5b81356001600160e01b03198116811461095b575f5ffd5b6001600160a01b038116811461183a575f5ffd5b5f5f60408385031215611dcf575f5ffd5b823591506020830135611de181611daa565b809150509250929050565b5f5f60408385031215611dfd575f5ffd5b50508035926020909101359150565b5f60208284031215611e1c575f5ffd5b5035919050565b5f60208284031215611e33575f5ffd5b813561095b81611daa565b803567ffffffffffffffff81168114611297575f5ffd5b5f5f60408385031215611e66575f5ffd5b82359150611e7660208401611e3e565b90509250929050565b602080825282518282018190525f918401906040840190835b81811015611ed5578351805167ffffffffffffffff1684526020908101516001600160801b03168185015290930192604090920191600101611e98565b509095945050505050565b5f5f83601f840112611ef0575f5ffd5b50813567ffffffffffffffff811115611f07575f5ffd5b602083019150836020828501011115611f1e575f5ffd5b9250929050565b5f5f5f5f5f60808688031215611f39575f5ffd5b853567ffffffffffffffff811115611f4f575f5ffd5b611f5b88828901611ee0565b9096509450611f6e905060208701611e3e565b9250611f7c60408701611e3e565b91506060860135611f8c81611daa565b809150509295509295909350565b5f5f60208385031215611fab575f5ffd5b823567ffffffffffffffff811115611fc1575f5ffd5b611fcd85828601611ee0565b90969095509350505050565b5f5f5f60408486031215611feb575f5ffd5b833567ffffffffffffffff811115612001575f5ffd5b61200d86828701611ee0565b9094509250612020905060208501611e3e565b90509250925092565b5f5f5f6060848603121561203b575f5ffd5b8335925060208401359150604084013561205481611daa565b809150509250925092565b5f6020828403121561206f575f5ffd5b61095b82611e3e565b602080825282518282018190525f918401906040840190835b81811015611ed5578351835260209384019390920191600101612091565b80356001600160801b0381168114611297575f5ffd5b5f5f5f606084860312156120d7575f5ffd5b83356120e281611daa565b92506120f0602085016120af565b9150612020604085016120af565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8181038181111561073e5761073e612112565b808202811582820484141761073e5761073e612112565b8082018082111561073e5761073e612112565b634e487b7160e01b5f52601260045260245ffd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f600182016121b6576121b6612112565b5060010190565b5f826121cb576121cb612163565b500490565b5f602082840312156121e0575f5ffd5b815161095b81611daa565b634e487b7160e01b5f52602160045260245ffd5b5f60ff83168061221157612211612163565b8060ff8416069150509291505056fea2646970667358221220fc8c2628cdce3e18552406236c68dd77856f787dbe4342cd8f8b2f0b3e517a0564736f6c634300081b00338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610201575f3560e01c80636e45511111610123578063ac0d63d0116100b8578063d3bf89b111610088578063dff521a81161006e578063dff521a814610694578063e1de9c83146106a7578063f1dfaefb146106ba575f5ffd5b8063d3bf89b114610620578063dfa70d8b14610681575f5ffd5b8063ac0d63d0146105aa578063b553630e146105d1578063c50f093b146105f8578063ce156e821461060d575f5ffd5b80638b59de43116100f35780638b59de4314610534578063930eaddc146105475780639c7aa7f8146105825780639e6d1a9314610597575f5ffd5b80636e455111146104735780636f3ff72614610486578063781ef8db146104d75780637c30058614610521575f5ffd5b80633634f9111161019957806348b6781f1161016957806348b6781f146103c65780635adf4724146103ed5780636981b5f4146104205780636bab30b714610433575f5ffd5b80633634f9111461033757806339ac7a2a1461035f5780633ad8608314610374578063415175bb14610387575f5ffd5b80632f27fa24116101d45780632f27fa241461026857806330897dba14610287578063319c22bb146102e557806334d8262214610324575f5ffd5b806301ffc9a714610205578063072d5d771461022d57806311b8e00a146102405780631c3fc3eb14610253575b5f5ffd5b610218610213366004611d83565b6106cd565b60405190151581526020015b60405180910390f35b61021861023b366004611dbe565b610744565b61021861024e366004611dec565b61076f565b61025a5f81565b604051908152602001610224565b61025a610276366004611e0c565b5f9081526001602052604090205490565b6102c5610295366004611e23565b6001600160a01b03165f90815261010460205260409020546001600160801b0380821692600160801b9092041690565b604080516001600160801b03938416815292909116602083015201610224565b61030c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610224565b61025a610332366004611e55565b610786565b61034a610345366004611dec565b610851565b60408051928352602083019190915201610224565b610367610874565b6040516102249190611e7f565b61025a610382366004611f25565b6108f5565b6103ae7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160801b039091168152602001610224565b61025a7f000000000000000000000000000000000000000000000000000000000000000081565b61025a6103fb366004611dbe565b5f918252602082815260408084206001600160a01b0393909316845291905290205490565b61025a61042e366004611f9a565b61091c565b61045a7f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610224565b61025a610481366004611fd9565b610962565b610218610494366004611e23565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb560205260408120546101009081161461073e565b6102186104e5366004611dbe565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b61021861052f366004612029565b6109e3565b61025a610542366004611dbe565b610a1e565b610218610555366004611e23565b6001600160a01b03165f9081526101046020526040902054600160801b90046001600160801b0316151590565b610595610590366004611e23565b610a2c565b005b61025a6105a536600461205f565b610ac8565b61025a7f000000000000000000000000000000000000000000000000000000000000000081565b61045a7f000000000000000000000000000000000000000000000000000000000000000081565b610600610b94565b6040516102249190612078565b61021861061b366004611dbe565b610beb565b61021861062e366004612029565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b61021861068f366004612029565b610c0d565b6105956106a23660046120c5565b610c48565b61034a6106b5366004611f25565b610e1c565b6102186106c8366004611f9a565b610e83565b5f6001600160e01b031982167fdb06fc0000000000000000000000000000000000000000000000000000000000148061072f57506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061073e575061073e82610e99565b92915050565b5f5f836107598282610754610eff565b610f0d565b6107665f86866001610fde565b95945050505050565b5f5f61077b8484610851565b501515949350505050565b610103545f9081805b828110156107f6575f61010382815481106107ac576107ac6120fe565b5f918252602090912001805490915067ffffffffffffffff90811690871610156107d657506107f6565b546801000000000000000090046001600160801b0316915060010161078f565b506001600160801b038116156108485761084385826001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160801b03166110f2565b610766565b50929392505050565b5f5f61085c836111a2565b5f948552600160205260409094205484169492505050565b6060610103805480602002602001604051908101604052809291908181526020015f905b828210156108ec575f848152602090819020604080518082019091529084015467ffffffffffffffff811682526801000000000000000090046001600160801b031681830152825260019092019101610898565b50505050905090565b5f6109126109048787866111bc565b61090d84611207565b61129c565b9695505050505050565b5f61095b83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506112ef92505050565b9392505050565b5f82801580610971575060ff81115b1561097f575f91505061095b565b5f61098a868661091c565b6101025490915081111561099e5750610102545b61091267ffffffffffffffff85166101026109ba600185612126565b815481106109ca576109ca6120fe565b905f5260205f2001546109dd9190612139565b85610786565b5f83836109f38282610754610eff565b85610a1157604051631850848b60e31b815260040160405180910390fd5b6109128686866001610fde565b5f61095b8361090d84611207565b6010610a405f82610a3b610eff565b61147c565b6001600160a01b0382165f9081526101046020526040902054600160801b90046001600160801b031615610ac4576001600160a01b0382165f818152610104602090815260408083208390558051838152918201929092527f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff1610610b0a575f61073e565b7f0000000000000000000000000000000000000000000000000000000000000000610b8a7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168567ffffffffffffffff1661151d565b61073e9190612126565b6060610102805480602002602001604051908101604052809291908181526020018280548015610be157602002820191905f5260205f20905b815481526020019060010190808311610bcd575b5050505050905090565b5f5f83610c008282610bfb610eff565b6115c3565b6107665f86866001611689565b5f8383610c1d8282610bfb610eff565b85610c3b57604051631850848b60e31b815260040160405180910390fd5b6109128686866001611689565b6001610c575f82610a3b610eff565b6001600160a01b0384165f90815261010460209081526040918290208251808401909352546001600160801b038082168452600160801b909104811691830191909152831615610dac57836001600160801b03165f03610ce3576040517f648564d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001600160801b0316815f01516001600160801b0316141580610d1d5750826001600160801b031681602001516001600160801b031614155b15610da7576040805180820182526001600160801b0386811680835286821660208085018281526001600160a01b038c165f8181526101048452889020965191518616600160801b029190951617909455845191825292810192909252917f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b610e15565b60208101516001600160801b031615610e15576001600160a01b0385165f818152610104602090815260408083208390558051838152918201929092527f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b5050505050565b5f5f610e298787866111bc565b91505f610e3584611207565b9050610e4086610ac8565b91508115610e6157610e528284612150565b9250610e5e828261129c565b91505b81610e6c848361129c565b610e769190612126565b9250509550959350505050565b5f5f610e9184846001610962565b119392505050565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061073e57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461073e565b5f610f086116f1565b905090565b5f610f7d84836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b90508019831615610fd8576040517fd1a3b35500000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b03831660448201526064015b60405180910390fd5b50505050565b5f835f03610fed57505f6110ea565b610ff6846117dd565b6001600160a01b038316611036576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b03871684529091529020548481178082146110e4575f878152602081815260408083206001600160a01b03891684529091529020819055811986166110928882600161183d565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3600193505050506110ea565b5f925050505b949350505050565b5f5f5f6110ff86866119d2565b91509150815f036111235783818161111957611119612163565b049250505061095b565b81841161113a5761113a60038515026011186119ee565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010185841190960395909502919093039390930492909217029150509392505050565b5f6111ac826117dd565b50600181901b17600281901b1790565b5f6111c8848484610962565b9050805f0361095b5783836040517fdbfa2886000000000000000000000000000000000000000000000000000000008152600401610fcf929190612177565b6040805180820182525f80825260209182018190526001600160a01b038416815261010482528281208351808501909452546001600160801b038082168552600160801b9091041691830182905203611297576040517f02e2ae9e0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610fcf565b919050565b5f81602001516001600160801b0316825f01516001600160801b0316146112e8576112e383835f01516001600160801b031684602001516001600160801b031660016119ff565b61095b565b5090919050565b80515f90819081905b80821015611473575f858381518110611313576113136120fe565b01602001516001600160f81b03191690507f800000000000000000000000000000000000000000000000000000000000000081101561135e57611357600184612150565b9250611460565b7fe0000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561139b57611357600284612150565b7ff0000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156113d857611357600384612150565b7ff8000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561141557611357600484612150565b7ffc000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561145257611357600584612150565b61145d600684612150565b92505b508261146b816121a5565b9350506112f8565b50909392505050565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5909252909120541782168214611518576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610fcf565b505050565b5f831580611529575082155b1561153557505f61095b565b815f0361154357508261095b565b5f83611557670de0b6b3a764000085612139565b61156191906121bd565b90505f611576670de0b6b3a7640000836121bd565b90505f61158b670de0b6b3a764000083612139565b6115959084612126565b90506115b887831c6115b3670de0b6b3a7640000601085901b6121bd565b611a41565b979650505050505050565b5f61163384836001600160a01b03165f8181527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020908152604080832054948352828252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b90508019831615610fd8576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610fcf565b5f611693846117dd565b5f858152602081815260408083206001600160a01b0387168452909152902054841981168082146110e4575f878152602081815260408083206001600160a01b0389168452909152812082905586831690611092908990839061183d565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661172557503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa1580156117a2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c691906121d0565b90506001600160a01b038116611297573391505090565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561183a576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610fcf565b50565b5f611847836111a2565b90508115611910575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156118e8576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610fcf565b5f8481526001602052604081208054859290611905908490612150565b90915550610fd89050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156119aa576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610fcf565b5f84815260016020526040812080548592906119c7908490612126565b909155505050505050565b5f805f1983850993909202808410938190039390930393915050565b634e487b715f52806020526024601cfd5b5f611a2c611a0c83611d57565b8015611a2757505f8480611a2257611a22612163565b868809115b151590565b611a378686866110f2565b6107669190612150565b5f6001821615611a7357670de0b6b3a7640000611a66670de0ad151d09418085612139565b611a7091906121bd565b92505b6002821615611aa457670de0b6b3a7640000611a97670de0a3769959680085612139565b611aa191906121bd565b92505b6004821615611ad557670de0b6b3a7640000611ac8670de09039a5fa510085612139565b611ad291906121bd565b92505b6008821615611b0657670de0b6b3a7640000611af9670de069c00f3e120085612139565b611b0391906121bd565b92505b6010821615611b3757670de0b6b3a7640000611b2a670de01cce21c9440085612139565b611b3491906121bd565b92505b6020821615611b6857670de0b6b3a7640000611b5b670ddf82ef46ce100085612139565b611b6591906121bd565b92505b6040821615611b9957670de0b6b3a7640000611b8c670dde4f458f8e8d8085612139565b611b9691906121bd565b92505b6080821615611bca57670de0b6b3a7640000611bbd670ddbe84213d5f08085612139565b611bc791906121bd565b92505b610100821615611bfc57670de0b6b3a7640000611bef670dd71b7aa6df5b8085612139565b611bf991906121bd565b92505b610200821615611c2e57670de0b6b3a7640000611c21670dcd86e7f28cde0085612139565b611c2b91906121bd565b92505b610400821615611c6057670de0b6b3a7640000611c53670dba71a3084ad68085612139565b611c5d91906121bd565b92505b610800821615611c9257670de0b6b3a7640000611c85670d94961b13dbde8085612139565b611c8f91906121bd565b92505b611000821615611cc457670de0b6b3a7640000611cb7670d4a171c35c9838085612139565b611cc191906121bd565b92505b612000821615611cf657670de0b6b3a7640000611ce9670cb9da519ccfb70085612139565b611cf391906121bd565b92505b614000821615611d2857670de0b6b3a7640000611d1b670bab76d59c18d68085612139565b611d2591906121bd565b92505b6180008216156112e857670de0b6b3a7640000611d4d6709d025defee4df8085612139565b61095b91906121bd565b5f6002826003811115611d6c57611d6c6121eb565b611d7691906121ff565b60ff166001149050919050565b5f60208284031215611d93575f5ffd5b81356001600160e01b03198116811461095b575f5ffd5b6001600160a01b038116811461183a575f5ffd5b5f5f60408385031215611dcf575f5ffd5b823591506020830135611de181611daa565b809150509250929050565b5f5f60408385031215611dfd575f5ffd5b50508035926020909101359150565b5f60208284031215611e1c575f5ffd5b5035919050565b5f60208284031215611e33575f5ffd5b813561095b81611daa565b803567ffffffffffffffff81168114611297575f5ffd5b5f5f60408385031215611e66575f5ffd5b82359150611e7660208401611e3e565b90509250929050565b602080825282518282018190525f918401906040840190835b81811015611ed5578351805167ffffffffffffffff1684526020908101516001600160801b03168185015290930192604090920191600101611e98565b509095945050505050565b5f5f83601f840112611ef0575f5ffd5b50813567ffffffffffffffff811115611f07575f5ffd5b602083019150836020828501011115611f1e575f5ffd5b9250929050565b5f5f5f5f5f60808688031215611f39575f5ffd5b853567ffffffffffffffff811115611f4f575f5ffd5b611f5b88828901611ee0565b9096509450611f6e905060208701611e3e565b9250611f7c60408701611e3e565b91506060860135611f8c81611daa565b809150509295509295909350565b5f5f60208385031215611fab575f5ffd5b823567ffffffffffffffff811115611fc1575f5ffd5b611fcd85828601611ee0565b90969095509350505050565b5f5f5f60408486031215611feb575f5ffd5b833567ffffffffffffffff811115612001575f5ffd5b61200d86828701611ee0565b9094509250612020905060208501611e3e565b90509250925092565b5f5f5f6060848603121561203b575f5ffd5b8335925060208401359150604084013561205481611daa565b809150509250925092565b5f6020828403121561206f575f5ffd5b61095b82611e3e565b602080825282518282018190525f918401906040840190835b81811015611ed5578351835260209384019390920191600101612091565b80356001600160801b0381168114611297575f5ffd5b5f5f5f606084860312156120d7575f5ffd5b83356120e281611daa565b92506120f0602085016120af565b9150612020604085016120af565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8181038181111561073e5761073e612112565b808202811582820484141761073e5761073e612112565b8082018082111561073e5761073e612112565b634e487b7160e01b5f52601260045260245ffd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f600182016121b6576121b6612112565b5060010190565b5f826121cb576121cb612163565b500490565b5f602082840312156121e0575f5ffd5b815161095b81611daa565b634e487b7160e01b5f52602160045260245ffd5b5f60ff83168061221157612211612163565b8060ff8416069150509291505056fea2646970667358221220fc8c2628cdce3e18552406236c68dd77856f787dbe4342cd8f8b2f0b3e517a0564736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60111": [ + { + "length": 32, + "start": 746 + }, + { + "length": 32, + "start": 5876 + }, + { + "length": 32, + "start": 5973 + } + ], + "64986": [ + { + "length": 32, + "start": 908 + }, + { + "length": 32, + "start": 2070 + } + ], + "64989": [ + { + "length": 32, + "start": 1455 + }, + { + "length": 32, + "start": 2864 + } + ], + "64992": [ + { + "length": 32, + "start": 1494 + }, + { + "length": 32, + "start": 2897 + } + ], + "64995": [ + { + "length": 32, + "start": 1080 + }, + { + "length": 32, + "start": 2763 + } + ], + "64998": [ + { + "length": 32, + "start": 971 + }, + { + "length": 32, + "start": 2828 + } + ] + }, + "inputSourceName": "project/src/registrar/StandardRentPriceOracle.sol", + "devdoc": { + "errors": { + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "InvalidBaseRates()": [ + { + "details": "Error selector: `0xde276447`" + } + ], + "InvalidDiscount()": [ + { + "details": "Error selector: `0x997ea360`" + } + ], + "InvalidRatio()": [ + { + "details": "Error selector: `0x648564d3`" + } + ], + "NotValid(string)": [ + { + "details": "Error selector: `0xdbfa2886`" + } + ], + "PaymentTokenNotSupported(address)": [ + { + "details": "Error selector: `0x02e2ae9e`" + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "PaymentTokenUpdated(address,uint128,uint128)": { + "params": { + "denom": "Exchange rate denominator, relative to base units, or 0 if disabled.", + "numer": "Exchange rate numerator, relative to base units.", + "paymentToken": "The payment token." + } + } + }, + "kind": "dev", + "methods": { + "applyDiscount(uint256,uint64)": { + "params": { + "duration": "The duration, in seconds.", + "value": "An arbitrary value." + }, + "returns": { + "_0": "`value` reduced by discount." + } + }, + "constructor": { + "params": { + "baseRatePerCp": "Base rates, in standard units per second.", + "discountDenominator": "Denominator for discounts.", + "discountPoints": "List of discount points.", + "paymentRatios": "List of payment tokens with exchange rates.", + "premiumHalvingPeriod": "Premium halving period, in seconds.", + "premiumPeriod": "Premium period, in seconds.", + "premiumPriceInitial": "Premium initial price, in standard units.", + "rootAccount": "Account granted root roles." + } + }, + "convertUnits(uint256,address)": { + "params": { + "paymentToken": "The payment token.", + "value": "An arbitrary value, in standard units." + }, + "returns": { + "_0": "The amount of payment token." + } + }, + "disablePaymentToken(address)": { + "params": { + "paymentToken": "The payment token." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getBasePrice(string,uint64)": { + "params": { + "duration": "The duration, in seconds.", + "label": "The name to price." + }, + "returns": { + "_0": "The base price, in standard units, or 0 if not valid." + } + }, + "getLength(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "The number of Unicode codepoints." + } + }, + "getPaymentTokenRatio(address)": { + "params": { + "paymentToken": "The payment token." + }, + "returns": { + "denom": "The denominator of the exchange rate.", + "numer": "The numerator of the exchange rate." + } + }, + "getPremiumPriceAfter(uint64)": { + "details": "Defined over `[0, premiumPeriod)`.", + "params": { + "duration": "The time after expiration, in seconds." + }, + "returns": { + "_0": "The premium price, in standard units." + } + }, + "getRegisterPrice(string,uint64,uint64,address)": { + "params": { + "available": "The duration the name has been available, in seconds.", + "duration": "The duration to register for, in seconds.", + "label": "The name to price.", + "paymentToken": "The payment token." + }, + "returns": { + "base": "The amount of `paymentToken` for the registration.", + "premium": "The amount of `paymentToken` due to premium." + } + }, + "getRenewPrice(string,uint64,uint64,address)": { + "params": { + "duration": "The extension to price, in seconds.", + "expiry": "The current expiry, in seconds.", + "label": "The name to price.", + "paymentToken": "The payment token." + }, + "returns": { + "_0": "The amount of `paymentToken`." + } + }, + "grantRoles(uint256,uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted. Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.", + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "isPaymentToken(address)": { + "params": { + "paymentToken": "The payment token." + }, + "returns": { + "_0": "`true` if `paymentToken` is supported." + } + }, + "isValid(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "`true` if the `label` is valid." + } + }, + "revokeRoles(uint256,uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked. Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.", + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "updatePaymentToken(address,uint128,uint128)": { + "params": { + "denom": "The denominator of the exchange rate, or 0 to disable.", + "numer": "The numerator of the exchange rate.", + "paymentToken": "The payment token." + } + } + }, + "stateVariables": { + "_baseRatePerCp": { + "details": "Per-second base rates indexed by codepoint count; `_baseRatePerCp[i]` prices labels with `i+1` codepoints." + }, + "_discountPoints": { + "details": "Ordered discount points, relative to `DISCOUNT_DENOMINATOR`." + }, + "_paymentRatios": { + "details": "Exchange rates for each accepted payment token, mapping token address to its numerator/denominator ratio." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1758000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "DISCOUNT_DENOMINATOR()": "infinite", + "HCA_FACTORY()": "infinite", + "PREMIUM_HALVING_PERIOD()": "infinite", + "PREMIUM_PERIOD()": "infinite", + "PREMIUM_PRICE_INITIAL()": "infinite", + "PREMIUM_PRICE_OFFSET()": "infinite", + "ROOT_RESOURCE()": "306", + "applyDiscount(uint256,uint64)": "infinite", + "convertUnits(uint256,address)": "infinite", + "disablePaymentToken(address)": "infinite", + "getAssigneeCount(uint256,uint256)": "2680", + "getBasePrice(string,uint64)": "infinite", + "getBaseRates()": "infinite", + "getDiscountPoints()": "infinite", + "getLength(string)": "infinite", + "getPaymentTokenRatio(address)": "2694", + "getPremiumPriceAfter(uint64)": "infinite", + "getRegisterPrice(string,uint64,uint64,address)": "infinite", + "getRenewPrice(string,uint64,uint64,address)": "infinite", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "2752", + "hasRoles(uint256,uint256,address)": "4892", + "hasRootRoles(uint256,address)": "2652", + "isContractNamer(address)": "2628", + "isPaymentToken(address)": "2631", + "isValid(string)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "2481", + "roles(uint256,address)": "2700", + "supportsInterface(bytes4)": "infinite", + "updatePaymentToken(address,uint128,uint128)": "infinite" + }, + "internal": { + "_requireBasePrice(string calldata,uint64)": "infinite", + "_requirePaymentToken(contract IERC20)": "infinite", + "_toAmount(uint256,struct StandardRentPriceOracle.Ratio memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"baseRatePerCp\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"}],\"internalType\":\"struct DiscountPoint[]\",\"name\":\"discountPoints\",\"type\":\"tuple[]\"},{\"internalType\":\"uint128\",\"name\":\"discountDenominator\",\"type\":\"uint128\"},{\"internalType\":\"uint256\",\"name\":\"premiumPriceInitial\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"premiumHalvingPeriod\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumPeriod\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"denom\",\"type\":\"uint128\"}],\"internalType\":\"struct PaymentRatio[]\",\"name\":\"paymentRatios\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBaseRates\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDiscount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRatio\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"NotValid\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"PaymentTokenNotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"denom\",\"type\":\"uint128\"}],\"name\":\"PaymentTokenUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DISCOUNT_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIUM_HALVING_PERIOD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIUM_PERIOD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIUM_PRICE_INITIAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIUM_PRICE_OFFSET\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"}],\"name\":\"applyDiscount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"convertUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"disablePaymentToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"}],\"name\":\"getBasePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBaseRates\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDiscountPoints\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"}],\"internalType\":\"struct DiscountPoint[]\",\"name\":\"v\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getPaymentTokenRatio\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"denom\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"}],\"name\":\"getPremiumPriceAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"available\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRegisterPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"base\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"premium\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRenewPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"isPaymentToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"isValid\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"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\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"denom\",\"type\":\"uint128\"}],\"name\":\"updatePaymentToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"InvalidBaseRates()\":[{\"details\":\"Error selector: `0xde276447`\"}],\"InvalidDiscount()\":[{\"details\":\"Error selector: `0x997ea360`\"}],\"InvalidRatio()\":[{\"details\":\"Error selector: `0x648564d3`\"}],\"NotValid(string)\":[{\"details\":\"Error selector: `0xdbfa2886`\"}],\"PaymentTokenNotSupported(address)\":[{\"details\":\"Error selector: `0x02e2ae9e`\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"PaymentTokenUpdated(address,uint128,uint128)\":{\"params\":{\"denom\":\"Exchange rate denominator, relative to base units, or 0 if disabled.\",\"numer\":\"Exchange rate numerator, relative to base units.\",\"paymentToken\":\"The payment token.\"}}},\"kind\":\"dev\",\"methods\":{\"applyDiscount(uint256,uint64)\":{\"params\":{\"duration\":\"The duration, in seconds.\",\"value\":\"An arbitrary value.\"},\"returns\":{\"_0\":\"`value` reduced by discount.\"}},\"constructor\":{\"params\":{\"baseRatePerCp\":\"Base rates, in standard units per second.\",\"discountDenominator\":\"Denominator for discounts.\",\"discountPoints\":\"List of discount points.\",\"paymentRatios\":\"List of payment tokens with exchange rates.\",\"premiumHalvingPeriod\":\"Premium halving period, in seconds.\",\"premiumPeriod\":\"Premium period, in seconds.\",\"premiumPriceInitial\":\"Premium initial price, in standard units.\",\"rootAccount\":\"Account granted root roles.\"}},\"convertUnits(uint256,address)\":{\"params\":{\"paymentToken\":\"The payment token.\",\"value\":\"An arbitrary value, in standard units.\"},\"returns\":{\"_0\":\"The amount of payment token.\"}},\"disablePaymentToken(address)\":{\"params\":{\"paymentToken\":\"The payment token.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getBasePrice(string,uint64)\":{\"params\":{\"duration\":\"The duration, in seconds.\",\"label\":\"The name to price.\"},\"returns\":{\"_0\":\"The base price, in standard units, or 0 if not valid.\"}},\"getLength(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"The number of Unicode codepoints.\"}},\"getPaymentTokenRatio(address)\":{\"params\":{\"paymentToken\":\"The payment token.\"},\"returns\":{\"denom\":\"The denominator of the exchange rate.\",\"numer\":\"The numerator of the exchange rate.\"}},\"getPremiumPriceAfter(uint64)\":{\"details\":\"Defined over `[0, premiumPeriod)`.\",\"params\":{\"duration\":\"The time after expiration, in seconds.\"},\"returns\":{\"_0\":\"The premium price, in standard units.\"}},\"getRegisterPrice(string,uint64,uint64,address)\":{\"params\":{\"available\":\"The duration the name has been available, in seconds.\",\"duration\":\"The duration to register for, in seconds.\",\"label\":\"The name to price.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"base\":\"The amount of `paymentToken` for the registration.\",\"premium\":\"The amount of `paymentToken` due to premium.\"}},\"getRenewPrice(string,uint64,uint64,address)\":{\"params\":{\"duration\":\"The extension to price, in seconds.\",\"expiry\":\"The current expiry, in seconds.\",\"label\":\"The name to price.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"_0\":\"The amount of `paymentToken`.\"}},\"grantRoles(uint256,uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted. Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\",\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"isPaymentToken(address)\":{\"params\":{\"paymentToken\":\"The payment token.\"},\"returns\":{\"_0\":\"`true` if `paymentToken` is supported.\"}},\"isValid(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"`true` if the `label` is valid.\"}},\"revokeRoles(uint256,uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked. Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updatePaymentToken(address,uint128,uint128)\":{\"params\":{\"denom\":\"The denominator of the exchange rate, or 0 to disable.\",\"numer\":\"The numerator of the exchange rate.\",\"paymentToken\":\"The payment token.\"}}},\"stateVariables\":{\"_baseRatePerCp\":{\"details\":\"Per-second base rates indexed by codepoint count; `_baseRatePerCp[i]` prices labels with `i+1` codepoints.\"},\"_discountPoints\":{\"details\":\"Ordered discount points, relative to `DISCOUNT_DENOMINATOR`.\"},\"_paymentRatios\":{\"details\":\"Exchange rates for each accepted payment token, mapping token address to its numerator/denominator ratio.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBaseRates()\":[{\"notice\":\"Invalid base rates.\"}],\"InvalidDiscount()\":[{\"notice\":\"Invalid discount configuration.\"}],\"InvalidRatio()\":[{\"notice\":\"Invalid payment token exchange rate.\"}],\"NotValid(string)\":[{\"notice\":\"`label` is not valid.\"}],\"PaymentTokenNotSupported(address)\":[{\"notice\":\"`paymentToken` is not supported for payment.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"PaymentTokenUpdated(address,uint128,uint128)\":{\"notice\":\"`paymentToken` has changed.\"}},\"kind\":\"user\",\"methods\":{\"DISCOUNT_DENOMINATOR()\":{\"notice\":\"Denominator for discounts.\"},\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"PREMIUM_HALVING_PERIOD()\":{\"notice\":\"Number of seconds for the premium to halve in value.\"},\"PREMIUM_PERIOD()\":{\"notice\":\"Total duration of the premium window; the premium reaches zero at this offset from expiry.\"},\"PREMIUM_PRICE_INITIAL()\":{\"notice\":\"Starting value of the exponential decay premium for recently expired names, in base pricing units.\"},\"PREMIUM_PRICE_OFFSET()\":{\"notice\":\"Precomputed premium halving at end of period.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"applyDiscount(uint256,uint64)\":{\"notice\":\"Apply discount function to an arbitrary value.\"},\"convertUnits(uint256,address)\":{\"notice\":\"Convert arbitrary standard units to payment token amount.\"},\"disablePaymentToken(address)\":{\"notice\":\"Disable `paymentToken` support.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getBasePrice(string,uint64)\":{\"notice\":\"Get base price to register or renew `label` for `duration` seconds.\"},\"getBaseRates()\":{\"notice\":\"Get all base rates, in standard units per second.\"},\"getDiscountPoints()\":{\"notice\":\"Get all discount durations, in seconds.\"},\"getLength(string)\":{\"notice\":\"Check length of a name.\"},\"getPaymentTokenRatio(address)\":{\"notice\":\"Get numerator/denominator for `paymentToken`.\"},\"getPremiumPriceAfter(uint64)\":{\"notice\":\"Get premium price for a duration after expiry.\"},\"getRegisterPrice(string,uint64,uint64,address)\":{\"notice\":\"Determine registration price for `label`.\"},\"getRenewPrice(string,uint64,uint64,address)\":{\"notice\":\"Determine renewal price for `label`.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"isPaymentToken(address)\":{\"notice\":\"Check if `paymentToken` is supported for payment.\"},\"isValid(string)\":{\"notice\":\"Check if a `label` is valid. Does not check if normalized.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"updatePaymentToken(address,uint128,uint128)\":{\"notice\":\"Update `paymentToken` support and/or exchange rate.\"}},\"notice\":\"Rent pricing oracle with (4) components: 1. Base rates: per-second cost indexed by label codepoint count. Shorter names cost more. Rates are stored in an array where index `i` corresponds to `i+1` codepoints; labels longer than the array use the last entry. 2. Duration discounts: increasing expiry reduce costs. Each dicount point specifies a duration and a numerator. `1 - numerator / DISCOUNT_DENOMINATOR` determines the discount percentage. Rewards longer registrations. 3. Expiry premium: exponential decay from an initial premium with a configurable halving period, reaching zero at the end of the premium period. Only charged to new owners of recently expired names; renewals are exempt. 4. Configurable payment tokens: payment tokens and their exchange rates can be managed with `ROLE_UPDATE_TOKEN`. The exchange rate converts the token to standard units. Since no external oracle is consulted, only stablecoins. Accounts with `ROLE_DISABLE_TOKEN` can only disable payment tokens.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/StandardRentPriceOracle.sol\":\"StandardRentPriceOracle\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nlibrary StringUtils {\\n /// @dev Returns the length of a given string\\n /// @param s The string to measure the length of\\n /// @return The length of the input string\\n function strlen(string memory s) internal pure returns (uint256) {\\n uint256 len;\\n uint256 i = 0;\\n uint256 bytelength = bytes(s).length;\\n for (len = 0; i < bytelength; len++) {\\n bytes1 b = bytes(s)[i];\\n if (b < 0x80) {\\n i += 1;\\n } else if (b < 0xE0) {\\n i += 2;\\n } else if (b < 0xF0) {\\n i += 3;\\n } else if (b < 0xF8) {\\n i += 4;\\n } else if (b < 0xFC) {\\n i += 5;\\n } else {\\n i += 6;\\n }\\n }\\n return len;\\n }\\n\\n /// @dev Escapes special characters in a given string\\n /// @param str The string to escape\\n /// @return The escaped string\\n function escape(string memory str) internal pure returns (string memory) {\\n bytes memory strBytes = bytes(str);\\n uint extraChars = 0;\\n\\n // count extra space needed for escaping\\n for (uint i = 0; i < strBytes.length; i++) {\\n if (_needsEscaping(strBytes[i])) {\\n extraChars++;\\n }\\n }\\n\\n // allocate buffer with the exact size needed\\n bytes memory buffer = new bytes(strBytes.length + extraChars);\\n uint index = 0;\\n\\n // escape characters\\n for (uint i = 0; i < strBytes.length; i++) {\\n if (_needsEscaping(strBytes[i])) {\\n buffer[index++] = \\\"\\\\\\\\\\\";\\n buffer[index++] = _getEscapedChar(strBytes[i]);\\n } else {\\n buffer[index++] = strBytes[i];\\n }\\n }\\n\\n return string(buffer);\\n }\\n\\n // determine if a character needs escaping\\n function _needsEscaping(bytes1 char) private pure returns (bool) {\\n return\\n char == '\\\"' ||\\n char == \\\"/\\\" ||\\n char == \\\"\\\\\\\\\\\" ||\\n char == \\\"\\\\n\\\" ||\\n char == \\\"\\\\r\\\" ||\\n char == \\\"\\\\t\\\";\\n }\\n\\n // get the escaped character\\n function _getEscapedChar(bytes1 char) private pure returns (bytes1) {\\n if (char == \\\"\\\\n\\\") return \\\"n\\\";\\n if (char == \\\"\\\\r\\\") return \\\"r\\\";\\n if (char == \\\"\\\\t\\\") return \\\"t\\\";\\n return char;\\n }\\n}\\n\",\"keccak256\":\"0x0bfe56e70297eb274d45dccd1dab1fe1904f7802fdb27d0b5ff102cec3defb85\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, _msgSender());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _roles[ROOT_RESOURCE][account] & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return\\n (_roles[ROOT_RESOURCE][account] | _roles[resource][account]) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (_hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (_hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function _hasZeroNybbles(uint256 value) private pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 hasZeroNybbles;\\n unchecked {\\n hasZeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return hasZeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xdf8918a909b0ab3bf17bc3a560fbdff6ca6e9502cbee54eb0923f1fae04d2fb1\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x9f29748b40665df976c08cdaf434b469dc73ef50e938c36be6773dc7b6a6f014\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/registrar/StandardRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {StringUtils} from \\\"@ens/contracts/utils/StringUtils.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {Math} from \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\nimport {LibHalving} from \\\"./libraries/LibHalving.sol\\\";\\n\\n/// @dev Nybble 0: authorizes updating tokens. Root only.\\nuint256 constant ROLE_UPDATE_TOKEN = 1 << 0;\\n\\n/// @dev Nybble 32: authorizes setting `ROLE_UPDATE_TOKEN`.\\nuint256 constant ROLE_UPDATE_TOKEN_ADMIN = ROLE_UPDATE_TOKEN << 128;\\n\\n/// @dev Nybble 1: authorizes disabling tokens. Root only.\\nuint256 constant ROLE_DISABLE_TOKEN = 1 << 4;\\n\\n/// @dev Nybble 33: authorizes setting `ROLE_DISABLE_TOKEN`.\\nuint256 constant ROLE_DISABLE_TOKEN_ADMIN = ROLE_DISABLE_TOKEN << 128;\\n\\n/// @dev Nybble 2: authorizes contract naming. Root only.\\nuint256 constant ROLE_SET_NAME = 1 << 8;\\n\\n/// @dev Nybble 34: authorizes setting `ROLE_SET_NAME`.\\nuint256 constant ROLE_SET_NAME_ADMIN = ROLE_SET_NAME << 128;\\n\\n/// @dev Default root roles assigned at construction.\\nuint256 constant DEFAULT_ROLE_BITMAP =\\n ROLE_UPDATE_TOKEN |\\n ROLE_UPDATE_TOKEN_ADMIN |\\n ROLE_DISABLE_TOKEN |\\n ROLE_DISABLE_TOKEN_ADMIN |\\n ROLE_SET_NAME |\\n ROLE_SET_NAME_ADMIN;\\n\\n/// @dev Initialization-time structure for a discount point.\\n/// @param duration Duration threshold, in seconds.\\n/// @param numer Discount numerator, relative to `DISCOUNT_DENOMINATOR`.\\nstruct DiscountPoint {\\n uint64 duration;\\n uint128 numer;\\n}\\n\\n/// @dev Initialization-time structure for a payment token and exchange rate.\\n/// @param paymenToken The payment token.\\n/// @param numer Exchange rate numerator, relative to base units.\\n/// @param denom Exchange rate denominator, relative to base units.\\nstruct PaymentRatio {\\n IERC20 paymentToken;\\n uint128 numer;\\n uint128 denom;\\n}\\n\\n/// @notice Rent pricing oracle with (4) components:\\n///\\n/// 1. Base rates: per-second cost indexed by label codepoint count. Shorter names cost more.\\n/// Rates are stored in an array where index `i` corresponds to `i+1` codepoints; labels\\n/// longer than the array use the last entry.\\n/// 2. Duration discounts: increasing expiry reduce costs. Each dicount point specifies a\\n/// duration and a numerator. `1 - numerator / DISCOUNT_DENOMINATOR` determines the\\n/// discount percentage. Rewards longer registrations.\\n/// 3. Expiry premium: exponential decay from an initial premium with a configurable halving\\n/// period, reaching zero at the end of the premium period. Only charged to new owners of\\n/// recently expired names; renewals are exempt.\\n/// 4. Configurable payment tokens: payment tokens and their exchange rates can be managed\\n/// with `ROLE_UPDATE_TOKEN`. The exchange rate converts the token to standard units.\\n/// Since no external oracle is consulted, only stablecoins.\\n/// Accounts with `ROLE_DISABLE_TOKEN` can only disable payment tokens.\\n///\\ncontract StandardRentPriceOracle is EnhancedAccessControl, IRentPriceOracle, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Internal numerator/denominator pair representing a payment token's exchange rate relative to base pricing units.\\n struct Ratio {\\n uint128 numer;\\n uint128 denom;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Denominator for discounts.\\n uint128 public immutable DISCOUNT_DENOMINATOR;\\n\\n /// @notice Starting value of the exponential decay premium for recently expired names, in base pricing units.\\n uint256 public immutable PREMIUM_PRICE_INITIAL;\\n\\n /// @notice Number of seconds for the premium to halve in value.\\n uint64 public immutable PREMIUM_HALVING_PERIOD;\\n\\n /// @notice Total duration of the premium window; the premium reaches zero at this offset from expiry.\\n uint64 public immutable PREMIUM_PERIOD;\\n\\n /// @notice Precomputed premium halving at end of period.\\n uint256 public immutable PREMIUM_PRICE_OFFSET;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Per-second base rates indexed by codepoint count; `_baseRatePerCp[i]` prices labels with `i+1` codepoints.\\n uint256[] internal _baseRatePerCp;\\n\\n /// @dev Ordered discount points, relative to `DISCOUNT_DENOMINATOR`.\\n DiscountPoint[] internal _discountPoints;\\n\\n /// @dev Exchange rates for each accepted payment token, mapping token address to its numerator/denominator ratio.\\n mapping(IERC20 paymentToken => Ratio ratio) internal _paymentRatios;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `paymentToken` has changed.\\n /// @param paymentToken The payment token.\\n /// @param numer Exchange rate numerator, relative to base units.\\n /// @param denom Exchange rate denominator, relative to base units, or 0 if disabled.\\n event PaymentTokenUpdated(IERC20 indexed paymentToken, uint128 numer, uint128 denom);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Invalid base rates.\\n /// @dev Error selector: `0xde276447`\\n error InvalidBaseRates();\\n\\n /// @notice Invalid payment token exchange rate.\\n /// @dev Error selector: `0x648564d3`\\n error InvalidRatio();\\n\\n /// @notice Invalid discount configuration.\\n /// @dev Error selector: `0x997ea360`\\n error InvalidDiscount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param rootAccount Account granted root roles.\\n /// @param baseRatePerCp Base rates, in standard units per second.\\n /// @param discountPoints List of discount points.\\n /// @param discountDenominator Denominator for discounts.\\n /// @param premiumPriceInitial Premium initial price, in standard units.\\n /// @param premiumHalvingPeriod Premium halving period, in seconds.\\n /// @param premiumPeriod Premium period, in seconds.\\n /// @param paymentRatios List of payment tokens with exchange rates.\\n constructor(\\n address rootAccount,\\n uint256[] memory baseRatePerCp,\\n DiscountPoint[] memory discountPoints,\\n uint128 discountDenominator,\\n uint256 premiumPriceInitial,\\n uint64 premiumHalvingPeriod,\\n uint64 premiumPeriod,\\n PaymentRatio[] memory paymentRatios\\n )\\n HCAEquivalence(IHCAFactoryBasic(address(0)))\\n {\\n _grantRoles(ROOT_RESOURCE, DEFAULT_ROLE_BITMAP, rootAccount, false);\\n\\n if (baseRatePerCp.length == 0) {\\n revert InvalidBaseRates();\\n }\\n _baseRatePerCp = baseRatePerCp;\\n\\n uint256 n = discountPoints.length;\\n if (n > 0) {\\n uint64 duration; // must increase\\n uint128 numer = discountDenominator; // must decrease\\n for (uint256 i; i < n; ++i) {\\n DiscountPoint memory p = discountPoints[i];\\n if (p.duration <= duration || p.numer >= numer) {\\n revert InvalidDiscount(); // not strictly monotonic\\n }\\n duration = p.duration;\\n numer = p.numer;\\n _discountPoints.push(p);\\n }\\n if (numer == 0) {\\n revert InvalidDiscount(); // free\\n }\\n DISCOUNT_DENOMINATOR = discountDenominator;\\n }\\n\\n PREMIUM_PRICE_INITIAL = premiumPriceInitial;\\n PREMIUM_HALVING_PERIOD = premiumHalvingPeriod;\\n PREMIUM_PERIOD = premiumPeriod;\\n PREMIUM_PRICE_OFFSET = LibHalving.halving(\\n premiumPriceInitial,\\n premiumHalvingPeriod,\\n premiumPeriod\\n );\\n\\n for (uint256 i; i < paymentRatios.length; ++i) {\\n PaymentRatio memory pr = paymentRatios[i];\\n if (pr.numer == 0 || pr.denom == 0) {\\n revert InvalidRatio();\\n }\\n _paymentRatios[pr.paymentToken] = Ratio(pr.numer, pr.denom);\\n emit PaymentTokenUpdated(pr.paymentToken, pr.numer, pr.denom);\\n }\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return\\n interfaceId == type(IRentPriceOracle).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Update `paymentToken` support and/or exchange rate.\\n /// @param paymentToken The payment token.\\n /// @param numer The numerator of the exchange rate.\\n /// @param denom The denominator of the exchange rate, or 0 to disable.\\n function updatePaymentToken(IERC20 paymentToken, uint128 numer, uint128 denom)\\n external\\n onlyRootRoles(ROLE_UPDATE_TOKEN)\\n {\\n Ratio memory ratio = _paymentRatios[paymentToken];\\n if (denom > 0) {\\n if (numer == 0) {\\n revert InvalidRatio();\\n }\\n if (ratio.numer != numer || ratio.denom != denom) {\\n _paymentRatios[paymentToken] = Ratio(numer, denom);\\n emit PaymentTokenUpdated(paymentToken, numer, denom);\\n }\\n } else if (ratio.denom > 0) {\\n delete _paymentRatios[paymentToken];\\n emit PaymentTokenUpdated(paymentToken, 0, 0);\\n }\\n }\\n\\n /// @notice Disable `paymentToken` support.\\n /// @param paymentToken The payment token.\\n function disablePaymentToken(IERC20 paymentToken) external onlyRootRoles(ROLE_DISABLE_TOKEN) {\\n if (_paymentRatios[paymentToken].denom > 0) {\\n delete _paymentRatios[paymentToken];\\n emit PaymentTokenUpdated(paymentToken, 0, 0);\\n }\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return hasRootRoles(ROLE_SET_NAME, namer);\\n }\\n\\n /// @notice Get all base rates, in standard units per second.\\n function getBaseRates() external view returns (uint256[] memory) {\\n return _baseRatePerCp;\\n }\\n\\n /// @notice Get all discount durations, in seconds.\\n function getDiscountPoints() external view returns (DiscountPoint[] memory v) {\\n return _discountPoints;\\n }\\n\\n /// @notice Check if a `label` is valid. Does not check if normalized.\\n /// @param label The name to check.\\n /// @return `true` if the `label` is valid.\\n function isValid(string calldata label) external view returns (bool) {\\n return getBasePrice(label, 1) > 0;\\n }\\n\\n /// @notice Get numerator/denominator for `paymentToken`.\\n /// @param paymentToken The payment token.\\n /// @return numer The numerator of the exchange rate.\\n /// @return denom The denominator of the exchange rate.\\n function getPaymentTokenRatio(IERC20 paymentToken)\\n external\\n view\\n returns (uint128 numer, uint128 denom)\\n {\\n Ratio storage ratio = _paymentRatios[paymentToken];\\n return (ratio.numer, ratio.denom);\\n }\\n\\n /// @notice Check if `paymentToken` is supported for payment.\\n /// @param paymentToken The payment token.\\n /// @return `true` if `paymentToken` is supported.\\n function isPaymentToken(IERC20 paymentToken) external view returns (bool) {\\n return _paymentRatios[paymentToken].denom > 0;\\n }\\n\\n /// @inheritdoc IRentPriceOracle\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium)\\n {\\n base = _requireBasePrice(label, duration);\\n Ratio memory ratio = _requirePaymentToken(paymentToken);\\n premium = getPremiumPriceAfter(available);\\n if (premium > 0) {\\n base += premium; // total\\n premium = _toAmount(premium, ratio);\\n }\\n base = _toAmount(base, ratio) - premium; // ensure: f(a+b) - f(a) == f(b)\\n }\\n\\n /// @inheritdoc IRentPriceOracle\\n function getRenewPrice(\\n string calldata label,\\n uint64 /*expiry*/,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256)\\n {\\n return _toAmount(_requireBasePrice(label, duration), _requirePaymentToken(paymentToken));\\n }\\n\\n /// @notice Convert arbitrary standard units to payment token amount.\\n /// @param value An arbitrary value, in standard units.\\n /// @param paymentToken The payment token.\\n /// @return The amount of payment token.\\n function convertUnits(uint256 value, IERC20 paymentToken) external view returns (uint256) {\\n return _toAmount(value, _requirePaymentToken(paymentToken));\\n }\\n\\n /// @notice Apply discount function to an arbitrary value.\\n /// @param value An arbitrary value.\\n /// @param duration The duration, in seconds.\\n /// @return `value` reduced by discount.\\n function applyDiscount(uint256 value, uint64 duration) public view returns (uint256) {\\n uint256 n = _discountPoints.length;\\n uint128 numer;\\n for (uint256 i; i < n; ++i) {\\n DiscountPoint storage p = _discountPoints[i];\\n if (duration < p.duration)\\n break;\\n numer = p.numer;\\n }\\n return\\n numer == 0\\n ? value\\n : Math.mulDiv(value, numer, DISCOUNT_DENOMINATOR);\\n }\\n\\n /// @notice Get base price to register or renew `label` for `duration` seconds.\\n /// @param label The name to price.\\n /// @param duration The duration, in seconds.\\n /// @return The base price, in standard units, or 0 if not valid.\\n function getBasePrice(string calldata label, uint64 duration) public view returns (uint256) {\\n uint256 n = bytes(label).length;\\n if (n == 0 || n > 255)\\n return 0; // too long or too short\\n uint256 i = getLength(label);\\n if (i > _baseRatePerCp.length) {\\n i = _baseRatePerCp.length;\\n }\\n return applyDiscount(_baseRatePerCp[i - 1] * duration, duration);\\n }\\n\\n /// @notice Get premium price for a duration after expiry.\\n /// @dev Defined over `[0, premiumPeriod)`.\\n /// @param duration The time after expiration, in seconds.\\n /// @return The premium price, in standard units.\\n function getPremiumPriceAfter(uint64 duration) public view returns (uint256) {\\n return\\n duration < PREMIUM_PERIOD\\n ? LibHalving.halving(PREMIUM_PRICE_INITIAL, PREMIUM_HALVING_PERIOD, duration) -\\n PREMIUM_PRICE_OFFSET\\n : 0;\\n }\\n\\n /// @notice Check length of a name.\\n /// @param label The name to check.\\n /// @return The number of Unicode codepoints.\\n function getLength(string calldata label) public pure returns (uint256) {\\n return StringUtils.strlen(label);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Compute `rate * duration` and apply discount.\\n function _requireBasePrice(string calldata label, uint64 duration)\\n internal\\n view\\n returns (uint256 rate)\\n {\\n rate = getBasePrice(label, duration);\\n if (rate == 0) {\\n revert NotValid(label);\\n }\\n }\\n\\n /// @dev Ensure `paymentToken` is supported.\\n function _requirePaymentToken(IERC20 paymentToken) internal view returns (Ratio memory ratio) {\\n ratio = _paymentRatios[paymentToken];\\n if (ratio.denom == 0) {\\n revert PaymentTokenNotSupported(paymentToken);\\n }\\n }\\n\\n /// @dev Convert standard units to token amount.\\n function _toAmount(uint256 value, Ratio memory ratio) internal pure returns (uint256) {\\n return\\n ratio.numer == ratio.denom\\n ? value\\n : Math.mulDiv(value, ratio.numer, ratio.denom, Math.Rounding.Ceil);\\n }\\n}\\n\",\"keccak256\":\"0x2f61ddc629c9c6f304b43ae6774b6590e9ab30f2f6a826ef6ea43f1d2d50e710\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registrar/libraries/LibHalving.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Computes exponential decay `initial / 2^(elapsed / half)` using fixed-point arithmetic\\n/// with 18-decimal precision. The elapsed/half ratio is decomposed into integer and fractional\\n/// parts: the integer part is applied via right-shift, the fractional part via multiplication\\n/// with precomputed constants.\\nlibrary LibHalving {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Fixed-point scale factor (10^18).\\n uint256 private constant PRECISION = 1e18;\\n\\n // solgrid-disable docs/natspec\\n\\n /// @dev Precomputed values of `0.5^(2^k / 65536) * 10^18` for the corresponding power-of-two\\n /// bit position. Together they compose any fractional power of 0.5 in 16-bit resolution\\n /// via binary decomposition.\\n uint256 private constant BIT1 = 999989423469314432; // 0.5 ^ 1/65536 * (10 ** 18)\\n uint256 private constant BIT2 = 999978847050491904; // 0.5 ^ 2/65536 * (10 ** 18)\\n uint256 private constant BIT3 = 999957694548431104;\\n uint256 private constant BIT4 = 999915390886613504;\\n uint256 private constant BIT5 = 999830788931929088;\\n uint256 private constant BIT6 = 999661606496243712;\\n uint256 private constant BIT7 = 999323327502650752;\\n uint256 private constant BIT8 = 998647112890970240;\\n uint256 private constant BIT9 = 997296056085470080;\\n uint256 private constant BIT10 = 994599423483633152;\\n uint256 private constant BIT11 = 989228013193975424;\\n uint256 private constant BIT12 = 978572062087700096;\\n uint256 private constant BIT13 = 957603280698573696;\\n uint256 private constant BIT14 = 917004043204671232;\\n uint256 private constant BIT15 = 840896415253714560;\\n uint256 private constant BIT16 = 707106781186547584;\\n\\n // solgrid-enable docs/natspec\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Library Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Compute `initial / 2 ** (elapsed / half)`.\\n /// @param initial The initial value.\\n /// @param half The halving period.\\n /// @param elapsed The elapsed duration.\\n function halving(uint256 initial, uint256 half, uint256 elapsed)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (initial == 0 || half == 0)\\n return 0;\\n if (elapsed == 0)\\n return initial;\\n uint256 x = (elapsed * PRECISION) / half;\\n uint256 i = x / PRECISION;\\n uint256 f = x - i * PRECISION;\\n return _addFraction(initial >> i, (f << 16) / PRECISION);\\n }\\n\\n /// @dev Applies the fractional part of the exponent by multiplying `x` with each precomputed\\n /// constant whose corresponding bit is set in the 16-bit fraction, implementing\\n /// `x * 0.5^(fraction / 65536)`.\\n function _addFraction(uint256 x, uint256 fraction) private pure returns (uint256) {\\n if (fraction & (1 << 0) != 0) {\\n x = (x * BIT1) / PRECISION;\\n }\\n if (fraction & (1 << 1) != 0) {\\n x = (x * BIT2) / PRECISION;\\n }\\n if (fraction & (1 << 2) != 0) {\\n x = (x * BIT3) / PRECISION;\\n }\\n if (fraction & (1 << 3) != 0) {\\n x = (x * BIT4) / PRECISION;\\n }\\n if (fraction & (1 << 4) != 0) {\\n x = (x * BIT5) / PRECISION;\\n }\\n if (fraction & (1 << 5) != 0) {\\n x = (x * BIT6) / PRECISION;\\n }\\n if (fraction & (1 << 6) != 0) {\\n x = (x * BIT7) / PRECISION;\\n }\\n if (fraction & (1 << 7) != 0) {\\n x = (x * BIT8) / PRECISION;\\n }\\n if (fraction & (1 << 8) != 0) {\\n x = (x * BIT9) / PRECISION;\\n }\\n if (fraction & (1 << 9) != 0) {\\n x = (x * BIT10) / PRECISION;\\n }\\n if (fraction & (1 << 10) != 0) {\\n x = (x * BIT11) / PRECISION;\\n }\\n if (fraction & (1 << 11) != 0) {\\n x = (x * BIT12) / PRECISION;\\n }\\n if (fraction & (1 << 12) != 0) {\\n x = (x * BIT13) / PRECISION;\\n }\\n if (fraction & (1 << 13) != 0) {\\n x = (x * BIT14) / PRECISION;\\n }\\n if (fraction & (1 << 14) != 0) {\\n x = (x * BIT15) / PRECISION;\\n }\\n if (fraction & (1 << 15) != 0) {\\n x = (x * BIT16) / PRECISION;\\n }\\n return x;\\n }\\n}\\n\",\"keccak256\":\"0xee476242b69612db26589dfa47817c4381e7dd5a3713a961a2bf2ac656aff67d\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 55601, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_roles", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 55606, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_roleCount", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 55611, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 65002, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_baseRatePerCp", + "offset": 0, + "slot": "258", + "type": "t_array(t_uint256)dyn_storage" + }, + { + "astId": 65007, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_discountPoints", + "offset": 0, + "slot": "259", + "type": "t_array(t_struct(DiscountPoint)64961_storage)dyn_storage" + }, + { + "astId": 65014, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_paymentRatios", + "offset": 0, + "slot": "260", + "type": "t_mapping(t_contract(IERC20)38071,t_struct(Ratio)64983_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(DiscountPoint)64961_storage)dyn_storage": { + "base": "t_struct(DiscountPoint)64961_storage", + "encoding": "dynamic_array", + "label": "struct DiscountPoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_array(t_uint256)dyn_storage": { + "base": "t_uint256", + "encoding": "dynamic_array", + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_contract(IERC20)38071": { + "encoding": "inplace", + "label": "contract IERC20", + "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_contract(IERC20)38071,t_struct(Ratio)64983_storage)": { + "encoding": "mapping", + "key": "t_contract(IERC20)38071", + "label": "mapping(contract IERC20 => struct StandardRentPriceOracle.Ratio)", + "numberOfBytes": "32", + "value": "t_struct(Ratio)64983_storage" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(DiscountPoint)64961_storage": { + "encoding": "inplace", + "label": "struct DiscountPoint", + "members": [ + { + "astId": 64958, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "duration", + "offset": 0, + "slot": "0", + "type": "t_uint64" + }, + { + "astId": 64960, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "numer", + "offset": 8, + "slot": "0", + "type": "t_uint128" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Ratio)64983_storage": { + "encoding": "inplace", + "label": "struct StandardRentPriceOracle.Ratio", + "members": [ + { + "astId": 64980, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "numer", + "offset": 0, + "slot": "0", + "type": "t_uint128" + }, + { + "astId": 64982, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "denom", + "offset": 16, + "slot": "0", + "type": "t_uint128" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "InvalidBaseRates()": [ + { + "notice": "Invalid base rates." + } + ], + "InvalidDiscount()": [ + { + "notice": "Invalid discount configuration." + } + ], + "InvalidRatio()": [ + { + "notice": "Invalid payment token exchange rate." + } + ], + "NotValid(string)": [ + { + "notice": "`label` is not valid." + } + ], + "PaymentTokenNotSupported(address)": [ + { + "notice": "`paymentToken` is not supported for payment." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "PaymentTokenUpdated(address,uint128,uint128)": { + "notice": "`paymentToken` has changed." + } + }, + "kind": "user", + "methods": { + "DISCOUNT_DENOMINATOR()": { + "notice": "Denominator for discounts." + }, + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "PREMIUM_HALVING_PERIOD()": { + "notice": "Number of seconds for the premium to halve in value." + }, + "PREMIUM_PERIOD()": { + "notice": "Total duration of the premium window; the premium reaches zero at this offset from expiry." + }, + "PREMIUM_PRICE_INITIAL()": { + "notice": "Starting value of the exponential decay premium for recently expired names, in base pricing units." + }, + "PREMIUM_PRICE_OFFSET()": { + "notice": "Precomputed premium halving at end of period." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "applyDiscount(uint256,uint64)": { + "notice": "Apply discount function to an arbitrary value." + }, + "convertUnits(uint256,address)": { + "notice": "Convert arbitrary standard units to payment token amount." + }, + "disablePaymentToken(address)": { + "notice": "Disable `paymentToken` support." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getBasePrice(string,uint64)": { + "notice": "Get base price to register or renew `label` for `duration` seconds." + }, + "getBaseRates()": { + "notice": "Get all base rates, in standard units per second." + }, + "getDiscountPoints()": { + "notice": "Get all discount durations, in seconds." + }, + "getLength(string)": { + "notice": "Check length of a name." + }, + "getPaymentTokenRatio(address)": { + "notice": "Get numerator/denominator for `paymentToken`." + }, + "getPremiumPriceAfter(uint64)": { + "notice": "Get premium price for a duration after expiry." + }, + "getRegisterPrice(string,uint64,uint64,address)": { + "notice": "Determine registration price for `label`." + }, + "getRenewPrice(string,uint64,uint64,address)": { + "notice": "Determine renewal price for `label`." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "isPaymentToken(address)": { + "notice": "Check if `paymentToken` is supported for payment." + }, + "isValid(string)": { + "notice": "Check if a `label` is valid. Does not check if normalized." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "updatePaymentToken(address,uint128,uint128)": { + "notice": "Update `paymentToken` support and/or exchange rate." + } + }, + "notice": "Rent pricing oracle with (4) components: 1. Base rates: per-second cost indexed by label codepoint count. Shorter names cost more. Rates are stored in an array where index `i` corresponds to `i+1` codepoints; labels longer than the array use the last entry. 2. Duration discounts: increasing expiry reduce costs. Each dicount point specifies a duration and a numerator. `1 - numerator / DISCOUNT_DENOMINATOR` determines the discount percentage. Rewards longer registrations. 3. Expiry premium: exponential decay from an initial premium with a configurable halving period, reaching zero at the end of the premium period. Only charged to new owners of recently expired names; renewals are exempt. 4. Configurable payment tokens: payment tokens and their exchange rates can be managed with `ROLE_UPDATE_TOKEN`. The exchange rate converts the token to standard units. Since no external oracle is consulted, only stablecoins. Accounts with `ROLE_DISABLE_TOKEN` can only disable payment tokens.", + "version": 1 + }, + "argsData": "0x000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000004b3b4ca85a86c47a098a2240000000000000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000000000000000000000000000000000000001518000000000000000000000000000000000000000000000000000000000001baf8000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000135743900000000000000000000000000000000000000000000000000000000004d5d0f000000000000000000000000000000000000000000000000000000000003de4100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000003c30fc00000000000000000000000000000000041d3e3134f35ebeac858ddf8000000000000000000000000000000000000000000000000000000000000000005a497a00000000000000000000000000000000033b8c4b3be3ca713e68ef78c00000000000000000000000000000000000000000000000000000000000000000b492f40000000000000000000000000000000002a515b1eb2ebce84a55db3440000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000003dfc8b53dafa5ebbb071a8b97678ab534ed838d9000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000e915cebbc1570a74177b6c589fed1e8f5311755900000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240", + "transaction": { + "hash": "0x7d0f70cd7676460a4cd277433b03b8a4252801981d79a5838304f8d109228403", + "nonce": "0x1e90", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x4480964b0f1d6508f71e522aec9c60c28c986cac1c584f88bc29b0eca54c895b", + "blockNumber": "0xa6a805", + "transactionIndex": "0x49" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/TestnetV1PremigrationRegistrar.json b/contracts/deployments/sepolia-official-v1-20260525-r2/TestnetV1PremigrationRegistrar.json new file mode 100644 index 000000000..0d788879a --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/TestnetV1PremigrationRegistrar.json @@ -0,0 +1,709 @@ +{ + "address": "0xdf60c561ca35ad3c89d24bba854654b1c3477078", + "abi": [ + { + "inputs": [ + { + "internalType": "contract BaseRegistrarImplementation", + "name": "base_", + "type": "address" + }, + { + "internalType": "contract ENS", + "name": "ensRegistry_", + "type": "address" + }, + { + "internalType": "contract IReverseRegistrar", + "name": "reverseRegistrar_", + "type": "address" + }, + { + "internalType": "contract IDefaultReverseRegistrar", + "name": "defaultReverseRegistrar_", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry_", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "premigrationRegistry_", + "type": "address" + }, + { + "internalType": "address", + "name": "premigrationResolver_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "DurationTooShort", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + } + ], + "name": "ExpiryTooLarge", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "NameNotAvailable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RefundFailed", + "type": "error" + }, + { + "inputs": [], + "name": "ResolverRequiredForReverseRecord", + "type": "error" + }, + { + "inputs": [], + "name": "ResolverRequiredWhenDataSupplied", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelhash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "baseCost", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "premium", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "expires", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "NameRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelhash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "cost", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "expires", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "NameRenewed", + "type": "event" + }, + { + "inputs": [], + "name": "BASE", + "outputs": [ + { + "internalType": "contract BaseRegistrarImplementation", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_REVERSE_REGISTRAR", + "outputs": [ + { + "internalType": "contract IDefaultReverseRegistrar", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ENS_REGISTRY", + "outputs": [ + { + "internalType": "contract ENS", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_NODE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_REGISTRATION_DURATION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIGRATION_REGISTRY", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIGRATION_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REVERSE_RECORD_DEFAULT_BIT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REVERSE_RECORD_ETHEREUM_BIT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REVERSE_REGISTRAR", + "outputs": [ + { + "internalType": "contract IReverseRegistrar", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "secret", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + }, + { + "internalType": "uint8", + "name": "reverseRecord", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "internalType": "struct IETHRegistrarController.Registration", + "name": "registration", + "type": "tuple" + } + ], + "name": "register", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "contractName": "TestnetV1PremigrationRegistrar", + "sourceName": "src/testnet/TestnetV1PremigrationRegistrar.sol", + "bytecode": "0x610160604052348015610010575f5ffd5b5060405161193138038061193183398101604081905261002f9161007c565b6001600160a01b0396871660805294861660a05292851660c05290841660e0528316610100528216610120521661014052610113565b6001600160a01b0381168114610079575f5ffd5b50565b5f5f5f5f5f5f5f60e0888a031215610092575f5ffd5b875161009d81610065565b60208901519097506100ae81610065565b60408901519096506100bf81610065565b60608901519095506100d081610065565b60808901519094506100e181610065565b60a08901519093506100f281610065565b60c089015190925061010381610065565b8091505092959891949750929550565b60805160a05160c05160e05161010051610120516101405161177a6101b75f395f81816101280152610d9c01525f818160d80152610d7a01525f818161018101528181610c3301528181610d470152610e9101525f81816101e70152610b7c01525f818161023e0152610a9701525f81816101b4015261080f01525f81816102a40152818161059a0152818161063e0152818161074b0152610990015261177a5ff3fe6080604052600436106100c3575f3560e01c80638a95b09f11610071578063ec342ad01161004c578063ec342ad014610293578063ef9c8805146102c6578063f7e686cc146102db575f5ffd5b80638a95b09f14610209578063952899fc1461022d578063cc473be314610260575f5ffd5b806347500708116100a1578063475007081461017057806385e96917146101a35780638633886d146101d6575f5ffd5b80630a3f3ed9146100c75780632696964914610117578063370d4ad11461014a575b5f5ffd5b3480156100d2575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610122575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b348015610155575f5ffd5b5061015e600281565b60405160ff909116815260200161010e565b34801561017b575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101ae575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101e1575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b348015610214575f5ffd5b5061021f6224ea0081565b60405190815260200161010e565b348015610238575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b34801561026b575f5ffd5b5061021f7f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae81565b34801561029e575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6102d96102d4366004611123565b6102ef565b005b3480156102e6575f5ffd5b5061015e600181565b5f6102fa8280611162565b6040516103089291906111ac565b604051809103902090506224ea008260400135101561035e57604080517f9a71997b0000000000000000000000000000000000000000000000000000000081529083013560048201526024015b60405180910390fd5b61037161036b8380611162565b83610521565b6103b35761037f8280611162565b6040517f477707e80000000000000000000000000000000000000000000000000000000081526004016103559291906111e3565b5f6103c160a08401846111f6565b90501180156103e757505f6103dc60a0840160808501611250565b6001600160a01b0316145b1561041e576040517fd3f605c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61042e60e0830160c0840161126b565b60ff161580159061045657505f61044b60a0840160808501611250565b6001600160a01b0316145b1561048d576040517f7d4a034a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6104988383610613565b90506104ad6104a78480611162565b83610beb565b6104bd6040840160208501611250565b6001600160a01b0316827fc2240194853531f1ae318dcef227de79c6ad0fd9d1b0e4fe08568415be2e08a56104f28680611162565b5f5f878a60e0013560405161050c9695949392919061128b565b60405180910390a361051c610ef8565b505050565b5f600361056285858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f8b92505050565b1015801561060b57506040517f96e494e8000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906396e494e890602401602060405180830381865afa1580156105e7573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061060b91906112c3565b949350505050565b5f818161062660a0860160808701611250565b6001600160a01b03160361070c576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663fca247ac826106746040880160208901611250565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526001600160a01b03909116602483015287013560448201526064016020604051808303815f875af11580156106e0573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061070491906112e2565b915050610be5565b604080517ffca247ac000000000000000000000000000000000000000000000000000000008152600481018390523060248201529085013560448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fca247ac906064016020604051808303815f875af1158015610799573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107bd91906112e2565b604080517f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae60208201529081018590529092505f906060016040516020818303038152906040528051906020012090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cf408823828760200160208101906108509190611250565b61086060a08a0160808b01611250565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526001600160a01b0391821660248401521660448201525f60648201526084015f604051808303815f87803b1580156108ca575f5ffd5b505af11580156108dc573d5f5f3e3d5ffd5b505f92506108f091505060a08701876111f6565b905011156109865761090860a0860160808701611250565b6001600160a01b031663e32954eb8261092460a08901896111f6565b6040518463ffffffff1660e01b8152600401610942939291906112f9565b5f604051808303815f875af115801561095d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610984919081019061140e565b505b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd306109c66040890160208a01611250565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018590526064015f604051808303815f87803b158015610a2a575f5ffd5b505af1158015610a3c573d5f5f3e3d5ffd5b505f9250610a4e915087905080611162565b604051602001610a5f929190611536565b60408051601f1981840301815291905290506001610a8360e0880160c0890161126b565b1660ff165f14610b30576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016637a806d6b3380610ace60a08b0160808c01611250565b856040518563ffffffff1660e01b8152600401610aee9493929190611596565b6020604051808303815f875af1158015610b0a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b2e91906112e2565b505b6002610b4260e0880160c0890161126b565b1660ff165f14610be1576040517fc91199410000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c911994190610bb390339085906004016115df565b5f604051808303815f87803b158015610bca575f5ffd5b505af1158015610bdc573d5f5f3e3d5ffd5b505050505b5050505b92915050565b67ffffffffffffffff811115610c30576040517f544476c300000000000000000000000000000000000000000000000000000000815260048101829052602401610355565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610c9e86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061111892505050565b6040518263ffffffff1660e01b8152600401610cbc91815260200190565b60a060405180830381865afa158015610cd7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfb9190611600565b9050815f82516002811115610d1257610d12611679565b03610e0e576040517f85f3e6430000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385f3e64390610dc890889088905f907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009083908a9060040161168d565b6020604051808303815f875af1158015610de4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e0891906112e2565b50610ef1565b600182516002811115610e2357610e23611679565b148015610e475750816020015167ffffffffffffffff168167ffffffffffffffff16115b15610ef15760608201516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff821660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b158015610eda575f5ffd5b505af1158015610eec573d5f5f3e3d5ffd5b505050505b5050505050565b345f03610f0157565b6040515f90339034908381818185875af1925050503d805f8114610f40576040519150601f19603f3d011682016040523d82523d5f602084013e610f45565b606091505b5050905080610f88576040517faf73b0b2000000000000000000000000000000000000000000000000000000008152336004820152346024820152604401610355565b50565b80515f90819081905b8082101561110f575f858381518110610faf57610faf6116f1565b01602001516001600160f81b03191690507f8000000000000000000000000000000000000000000000000000000000000000811015610ffa57610ff3600184611719565b92506110fc565b7fe0000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561103757610ff3600284611719565b7ff0000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561107457610ff3600384611719565b7ff8000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156110b157610ff3600484611719565b7ffc000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156110ee57610ff3600584611719565b6110f9600684611719565b92505b50826111078161172c565b935050610f94565b50909392505050565b805160209091012090565b5f60208284031215611133575f5ffd5b813567ffffffffffffffff811115611149575f5ffd5b8201610100818503121561115b575f5ffd5b9392505050565b5f5f8335601e19843603018112611177575f5ffd5b83018035915067ffffffffffffffff821115611191575f5ffd5b6020019150368190038213156111a5575f5ffd5b9250929050565b818382375f9101908152919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f61060b6020830184866111bb565b5f5f8335601e1984360301811261120b575f5ffd5b83018035915067ffffffffffffffff821115611225575f5ffd5b6020019150600581901b36038213156111a5575f5ffd5b6001600160a01b0381168114610f88575f5ffd5b5f60208284031215611260575f5ffd5b813561115b8161123c565b5f6020828403121561127b575f5ffd5b813560ff8116811461115b575f5ffd5b60a081525f61129e60a08301888a6111bb565b9050856020830152846040830152836060830152826080830152979650505050505050565b5f602082840312156112d3575f5ffd5b8151801515811461115b575f5ffd5b5f602082840312156112f2575f5ffd5b5051919050565b83815260406020820181905281018290525f6060600584901b830181019083018583601e1936839003015b8782101561139257868503605f190184528235818112611342575f5ffd5b890160208101903567ffffffffffffffff81111561135e575f5ffd5b80360382131561136c575f5ffd5b6113778782846111bb565b96505050602083019250602084019350600182019150611324565b509298975050505050505050565b634e487b7160e01b5f52604160045260245ffd5b60405160a0810167ffffffffffffffff811182821017156113d7576113d76113a0565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611406576114066113a0565b604052919050565b5f6020828403121561141e575f5ffd5b815167ffffffffffffffff811115611434575f5ffd5b8201601f81018413611444575f5ffd5b805167ffffffffffffffff81111561145e5761145e6113a0565b8060051b61146e602082016113dd565b91825260208184018101929081019087841115611489575f5ffd5b6020850192505b8383101561152b57825167ffffffffffffffff8111156114ae575f5ffd5b8501603f810189136114be575f5ffd5b602081015167ffffffffffffffff8111156114db576114db6113a0565b6114ee601f8201601f19166020016113dd565b8181526040838301018b1015611502575f5ffd5b8160408401602083015e5f60208383010152808552505050602082019150602083019250611490565b979650505050505050565b818382377f2e657468000000000000000000000000000000000000000000000000000000009101908152600401919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03851681526001600160a01b03841660208201526001600160a01b0383166040820152608060608201525f6115d56080830184611568565b9695505050505050565b6001600160a01b0383168152604060208201525f61060b6040830184611568565b5f60a0828403128015611611575f5ffd5b5061161a6113b4565b825160038110611628575f5ffd5b8152602083015167ffffffffffffffff81168114611644575f5ffd5b602082015260408301516116578161123c565b6040820152606083810151908201526080928301519281019290925250919050565b634e487b7160e01b5f52602160045260245ffd5b60c081525f6116a060c08301898b6111bb565b90506001600160a01b03871660208301526001600160a01b03861660408301526001600160a01b038516606083015283608083015267ffffffffffffffff831660a083015298975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610be557610be5611705565b5f6001820161173d5761173d611705565b506001019056fea264697066735822122075affff2dcbb04f0a251bb7b19b9961e5e1c772f5663631c65f3c702365188aa64736f6c634300081b0033", + "deployedBytecode": "0x6080604052600436106100c3575f3560e01c80638a95b09f11610071578063ec342ad01161004c578063ec342ad014610293578063ef9c8805146102c6578063f7e686cc146102db575f5ffd5b80638a95b09f14610209578063952899fc1461022d578063cc473be314610260575f5ffd5b806347500708116100a1578063475007081461017057806385e96917146101a35780638633886d146101d6575f5ffd5b80630a3f3ed9146100c75780632696964914610117578063370d4ad11461014a575b5f5ffd5b3480156100d2575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610122575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b348015610155575f5ffd5b5061015e600281565b60405160ff909116815260200161010e565b34801561017b575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101ae575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b3480156101e1575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b348015610214575f5ffd5b5061021f6224ea0081565b60405190815260200161010e565b348015610238575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b34801561026b575f5ffd5b5061021f7f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae81565b34801561029e575f5ffd5b506100fa7f000000000000000000000000000000000000000000000000000000000000000081565b6102d96102d4366004611123565b6102ef565b005b3480156102e6575f5ffd5b5061015e600181565b5f6102fa8280611162565b6040516103089291906111ac565b604051809103902090506224ea008260400135101561035e57604080517f9a71997b0000000000000000000000000000000000000000000000000000000081529083013560048201526024015b60405180910390fd5b61037161036b8380611162565b83610521565b6103b35761037f8280611162565b6040517f477707e80000000000000000000000000000000000000000000000000000000081526004016103559291906111e3565b5f6103c160a08401846111f6565b90501180156103e757505f6103dc60a0840160808501611250565b6001600160a01b0316145b1561041e576040517fd3f605c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61042e60e0830160c0840161126b565b60ff161580159061045657505f61044b60a0840160808501611250565b6001600160a01b0316145b1561048d576040517f7d4a034a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6104988383610613565b90506104ad6104a78480611162565b83610beb565b6104bd6040840160208501611250565b6001600160a01b0316827fc2240194853531f1ae318dcef227de79c6ad0fd9d1b0e4fe08568415be2e08a56104f28680611162565b5f5f878a60e0013560405161050c9695949392919061128b565b60405180910390a361051c610ef8565b505050565b5f600361056285858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610f8b92505050565b1015801561060b57506040517f96e494e8000000000000000000000000000000000000000000000000000000008152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906396e494e890602401602060405180830381865afa1580156105e7573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061060b91906112c3565b949350505050565b5f818161062660a0860160808701611250565b6001600160a01b03160361070c576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663fca247ac826106746040880160208901611250565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526001600160a01b03909116602483015287013560448201526064016020604051808303815f875af11580156106e0573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061070491906112e2565b915050610be5565b604080517ffca247ac000000000000000000000000000000000000000000000000000000008152600481018390523060248201529085013560448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063fca247ac906064016020604051808303815f875af1158015610799573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107bd91906112e2565b604080517f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae60208201529081018590529092505f906060016040516020818303038152906040528051906020012090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663cf408823828760200160208101906108509190611250565b61086060a08a0160808b01611250565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526001600160a01b0391821660248401521660448201525f60648201526084015f604051808303815f87803b1580156108ca575f5ffd5b505af11580156108dc573d5f5f3e3d5ffd5b505f92506108f091505060a08701876111f6565b905011156109865761090860a0860160808701611250565b6001600160a01b031663e32954eb8261092460a08901896111f6565b6040518463ffffffff1660e01b8152600401610942939291906112f9565b5f604051808303815f875af115801561095d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610984919081019061140e565b505b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd306109c66040890160208a01611250565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604481018590526064015f604051808303815f87803b158015610a2a575f5ffd5b505af1158015610a3c573d5f5f3e3d5ffd5b505f9250610a4e915087905080611162565b604051602001610a5f929190611536565b60408051601f1981840301815291905290506001610a8360e0880160c0890161126b565b1660ff165f14610b30576001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016637a806d6b3380610ace60a08b0160808c01611250565b856040518563ffffffff1660e01b8152600401610aee9493929190611596565b6020604051808303815f875af1158015610b0a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b2e91906112e2565b505b6002610b4260e0880160c0890161126b565b1660ff165f14610be1576040517fc91199410000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c911994190610bb390339085906004016115df565b5f604051808303815f87803b158015610bca575f5ffd5b505af1158015610bdc573d5f5f3e3d5ffd5b505050505b5050505b92915050565b67ffffffffffffffff811115610c30576040517f544476c300000000000000000000000000000000000000000000000000000000815260048101829052602401610355565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610c9e86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061111892505050565b6040518263ffffffff1660e01b8152600401610cbc91815260200190565b60a060405180830381865afa158015610cd7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfb9190611600565b9050815f82516002811115610d1257610d12611679565b03610e0e576040517f85f3e6430000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385f3e64390610dc890889088905f907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009083908a9060040161168d565b6020604051808303815f875af1158015610de4573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e0891906112e2565b50610ef1565b600182516002811115610e2357610e23611679565b148015610e475750816020015167ffffffffffffffff168167ffffffffffffffff16115b15610ef15760608201516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff821660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b158015610eda575f5ffd5b505af1158015610eec573d5f5f3e3d5ffd5b505050505b5050505050565b345f03610f0157565b6040515f90339034908381818185875af1925050503d805f8114610f40576040519150601f19603f3d011682016040523d82523d5f602084013e610f45565b606091505b5050905080610f88576040517faf73b0b2000000000000000000000000000000000000000000000000000000008152336004820152346024820152604401610355565b50565b80515f90819081905b8082101561110f575f858381518110610faf57610faf6116f1565b01602001516001600160f81b03191690507f8000000000000000000000000000000000000000000000000000000000000000811015610ffa57610ff3600184611719565b92506110fc565b7fe0000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561103757610ff3600284611719565b7ff0000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561107457610ff3600384611719565b7ff8000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156110b157610ff3600484611719565b7ffc000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156110ee57610ff3600584611719565b6110f9600684611719565b92505b50826111078161172c565b935050610f94565b50909392505050565b805160209091012090565b5f60208284031215611133575f5ffd5b813567ffffffffffffffff811115611149575f5ffd5b8201610100818503121561115b575f5ffd5b9392505050565b5f5f8335601e19843603018112611177575f5ffd5b83018035915067ffffffffffffffff821115611191575f5ffd5b6020019150368190038213156111a5575f5ffd5b9250929050565b818382375f9101908152919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f61060b6020830184866111bb565b5f5f8335601e1984360301811261120b575f5ffd5b83018035915067ffffffffffffffff821115611225575f5ffd5b6020019150600581901b36038213156111a5575f5ffd5b6001600160a01b0381168114610f88575f5ffd5b5f60208284031215611260575f5ffd5b813561115b8161123c565b5f6020828403121561127b575f5ffd5b813560ff8116811461115b575f5ffd5b60a081525f61129e60a08301888a6111bb565b9050856020830152846040830152836060830152826080830152979650505050505050565b5f602082840312156112d3575f5ffd5b8151801515811461115b575f5ffd5b5f602082840312156112f2575f5ffd5b5051919050565b83815260406020820181905281018290525f6060600584901b830181019083018583601e1936839003015b8782101561139257868503605f190184528235818112611342575f5ffd5b890160208101903567ffffffffffffffff81111561135e575f5ffd5b80360382131561136c575f5ffd5b6113778782846111bb565b96505050602083019250602084019350600182019150611324565b509298975050505050505050565b634e487b7160e01b5f52604160045260245ffd5b60405160a0810167ffffffffffffffff811182821017156113d7576113d76113a0565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611406576114066113a0565b604052919050565b5f6020828403121561141e575f5ffd5b815167ffffffffffffffff811115611434575f5ffd5b8201601f81018413611444575f5ffd5b805167ffffffffffffffff81111561145e5761145e6113a0565b8060051b61146e602082016113dd565b91825260208184018101929081019087841115611489575f5ffd5b6020850192505b8383101561152b57825167ffffffffffffffff8111156114ae575f5ffd5b8501603f810189136114be575f5ffd5b602081015167ffffffffffffffff8111156114db576114db6113a0565b6114ee601f8201601f19166020016113dd565b8181526040838301018b1015611502575f5ffd5b8160408401602083015e5f60208383010152808552505050602082019150602083019250611490565b979650505050505050565b818382377f2e657468000000000000000000000000000000000000000000000000000000009101908152600401919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03851681526001600160a01b03841660208201526001600160a01b0383166040820152608060608201525f6115d56080830184611568565b9695505050505050565b6001600160a01b0383168152604060208201525f61060b6040830184611568565b5f60a0828403128015611611575f5ffd5b5061161a6113b4565b825160038110611628575f5ffd5b8152602083015167ffffffffffffffff81168114611644575f5ffd5b602082015260408301516116578161123c565b6040820152606083810151908201526080928301519281019290925250919050565b634e487b7160e01b5f52602160045260245ffd5b60c081525f6116a060c08301898b6111bb565b90506001600160a01b03871660208301526001600160a01b03861660408301526001600160a01b038516606083015283608083015267ffffffffffffffff831660a083015298975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610be557610be5611705565b5f6001820161173d5761173d611705565b506001019056fea264697066735822122075affff2dcbb04f0a251bb7b19b9961e5e1c772f5663631c65f3c702365188aa64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "73392": [ + { + "length": 32, + "start": 676 + }, + { + "length": 32, + "start": 1434 + }, + { + "length": 32, + "start": 1598 + }, + { + "length": 32, + "start": 1867 + }, + { + "length": 32, + "start": 2448 + } + ], + "73396": [ + { + "length": 32, + "start": 436 + }, + { + "length": 32, + "start": 2063 + } + ], + "73400": [ + { + "length": 32, + "start": 574 + }, + { + "length": 32, + "start": 2711 + } + ], + "73404": [ + { + "length": 32, + "start": 487 + }, + { + "length": 32, + "start": 2940 + } + ], + "73408": [ + { + "length": 32, + "start": 385 + }, + { + "length": 32, + "start": 3123 + }, + { + "length": 32, + "start": 3399 + }, + { + "length": 32, + "start": 3729 + } + ], + "73412": [ + { + "length": 32, + "start": 216 + }, + { + "length": 32, + "start": 3450 + } + ], + "73415": [ + { + "length": 32, + "start": 296 + }, + { + "length": 32, + "start": 3484 + } + ] + }, + "inputSourceName": "project/src/testnet/TestnetV1PremigrationRegistrar.sol", + "devdoc": { + "errors": { + "DurationTooShort(uint256)": [ + { + "details": "Error selector: `0x9a71997b`", + "params": { + "duration": "The supplied duration." + } + } + ], + "ExpiryTooLarge(uint256)": [ + { + "details": "Error selector: `0x544476c3`", + "params": { + "expiry": "The v1 expiry timestamp." + } + } + ], + "NameNotAvailable(string)": [ + { + "details": "Error selector: `0x477707e8`", + "params": { + "name": "The unavailable label." + } + } + ], + "RefundFailed(address,uint256)": [ + { + "details": "Error selector: `0xaf73b0b2`", + "params": { + "amount": "The amount that failed to refund.", + "recipient": "The refund recipient." + } + } + ], + "ResolverRequiredForReverseRecord()": [ + { + "details": "Error selector: `0x7d4a034a`" + } + ], + "ResolverRequiredWhenDataSupplied()": [ + { + "details": "Error selector: `0xd3f605c4`" + } + ] + }, + "events": { + "NameRegistered(string,bytes32,address,uint256,uint256,uint256,bytes32)": { + "params": { + "baseCost": "The base cost of the name.", + "expires": "The expiry time of the name.", + "label": "The label of the name.", + "labelhash": "The keccak256 hash of the label.", + "owner": "The owner of the name.", + "premium": "The premium cost of the name.", + "referrer": "The referrer of the registration." + } + }, + "NameRenewed(string,bytes32,uint256,uint256,bytes32)": { + "params": { + "cost": "The cost of the name.", + "expires": "The expiry time of the name.", + "label": "The label of the name.", + "labelhash": "The keccak256 hash of the label.", + "referrer": "The referrer of the registration." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "base_": "The ENSv1 base registrar.", + "defaultReverseRegistrar_": "The ENSv1 default reverse registrar.", + "ensRegistry_": "The ENSv1 registry.", + "ethRegistry_": "The ENSv2 `.eth` registry.", + "premigrationRegistry_": "The ENSv2 subregistry to assign to reservations.", + "premigrationResolver_": "The ENSv2 resolver to assign to reservations.", + "reverseRegistrar_": "The ENSv1 Ethereum reverse registrar." + } + }, + "register((string,address,uint256,bytes32,address,bytes[],uint8,bytes32))": { + "params": { + "registration": "The v1 controller registration parameters." + } + } + }, + "title": "TestnetV1PremigrationRegistrar", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1202000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BASE()": "infinite", + "DEFAULT_REVERSE_REGISTRAR()": "infinite", + "ENS_REGISTRY()": "infinite", + "ETH_NODE()": "261", + "ETH_REGISTRY()": "infinite", + "MIN_REGISTRATION_DURATION()": "217", + "PREMIGRATION_REGISTRY()": "infinite", + "PREMIGRATION_RESOLVER()": "infinite", + "REVERSE_RECORD_DEFAULT_BIT()": "271", + "REVERSE_RECORD_ETHEREUM_BIT()": "269", + "REVERSE_REGISTRAR()": "infinite", + "register((string,address,uint256,bytes32,address,bytes[],uint8,bytes32))": "infinite" + }, + "internal": { + "_available(string calldata,bytes32)": "infinite", + "_premigrate(string calldata,uint256)": "infinite", + "_refund()": "infinite", + "_registerV1(struct IETHRegistrarController.Registration calldata,bytes32)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract BaseRegistrarImplementation\",\"name\":\"base_\",\"type\":\"address\"},{\"internalType\":\"contract ENS\",\"name\":\"ensRegistry_\",\"type\":\"address\"},{\"internalType\":\"contract IReverseRegistrar\",\"name\":\"reverseRegistrar_\",\"type\":\"address\"},{\"internalType\":\"contract IDefaultReverseRegistrar\",\"name\":\"defaultReverseRegistrar_\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry_\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"premigrationRegistry_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"premigrationResolver_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"DurationTooShort\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"name\":\"ExpiryTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameNotAvailable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"RefundFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ResolverRequiredForReverseRecord\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ResolverRequiredWhenDataSupplied\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelhash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"baseCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"premium\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expires\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"NameRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelhash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"cost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expires\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"NameRenewed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE\",\"outputs\":[{\"internalType\":\"contract BaseRegistrarImplementation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_REVERSE_REGISTRAR\",\"outputs\":[{\"internalType\":\"contract IDefaultReverseRegistrar\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ENS_REGISTRY\",\"outputs\":[{\"internalType\":\"contract ENS\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_NODE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_REGISTRATION_DURATION\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIGRATION_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIGRATION_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REVERSE_RECORD_DEFAULT_BIT\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REVERSE_RECORD_ETHEREUM_BIT\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REVERSE_REGISTRAR\",\"outputs\":[{\"internalType\":\"contract IReverseRegistrar\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"secret\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"},{\"internalType\":\"uint8\",\"name\":\"reverseRecord\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"internalType\":\"struct IETHRegistrarController.Registration\",\"name\":\"registration\",\"type\":\"tuple\"}],\"name\":\"register\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DurationTooShort(uint256)\":[{\"details\":\"Error selector: `0x9a71997b`\",\"params\":{\"duration\":\"The supplied duration.\"}}],\"ExpiryTooLarge(uint256)\":[{\"details\":\"Error selector: `0x544476c3`\",\"params\":{\"expiry\":\"The v1 expiry timestamp.\"}}],\"NameNotAvailable(string)\":[{\"details\":\"Error selector: `0x477707e8`\",\"params\":{\"name\":\"The unavailable label.\"}}],\"RefundFailed(address,uint256)\":[{\"details\":\"Error selector: `0xaf73b0b2`\",\"params\":{\"amount\":\"The amount that failed to refund.\",\"recipient\":\"The refund recipient.\"}}],\"ResolverRequiredForReverseRecord()\":[{\"details\":\"Error selector: `0x7d4a034a`\"}],\"ResolverRequiredWhenDataSupplied()\":[{\"details\":\"Error selector: `0xd3f605c4`\"}]},\"events\":{\"NameRegistered(string,bytes32,address,uint256,uint256,uint256,bytes32)\":{\"params\":{\"baseCost\":\"The base cost of the name.\",\"expires\":\"The expiry time of the name.\",\"label\":\"The label of the name.\",\"labelhash\":\"The keccak256 hash of the label.\",\"owner\":\"The owner of the name.\",\"premium\":\"The premium cost of the name.\",\"referrer\":\"The referrer of the registration.\"}},\"NameRenewed(string,bytes32,uint256,uint256,bytes32)\":{\"params\":{\"cost\":\"The cost of the name.\",\"expires\":\"The expiry time of the name.\",\"label\":\"The label of the name.\",\"labelhash\":\"The keccak256 hash of the label.\",\"referrer\":\"The referrer of the registration.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"base_\":\"The ENSv1 base registrar.\",\"defaultReverseRegistrar_\":\"The ENSv1 default reverse registrar.\",\"ensRegistry_\":\"The ENSv1 registry.\",\"ethRegistry_\":\"The ENSv2 `.eth` registry.\",\"premigrationRegistry_\":\"The ENSv2 subregistry to assign to reservations.\",\"premigrationResolver_\":\"The ENSv2 resolver to assign to reservations.\",\"reverseRegistrar_\":\"The ENSv1 Ethereum reverse registrar.\"}},\"register((string,address,uint256,bytes32,address,bytes[],uint8,bytes32))\":{\"params\":{\"registration\":\"The v1 controller registration parameters.\"}}},\"title\":\"TestnetV1PremigrationRegistrar\",\"version\":1},\"userdoc\":{\"errors\":{\"DurationTooShort(uint256)\":[{\"notice\":\"Registration duration is below the accepted minimum.\"}],\"ExpiryTooLarge(uint256)\":[{\"notice\":\"The v1 expiry cannot fit in the ENSv2 registry expiry field.\"}],\"NameNotAvailable(string)\":[{\"notice\":\"Name is not available for v1 registration.\"}],\"RefundFailed(address,uint256)\":[{\"notice\":\"Refund of accidentally supplied ETH failed.\"}],\"ResolverRequiredForReverseRecord()\":[{\"notice\":\"A reverse record was requested without a resolver.\"}],\"ResolverRequiredWhenDataSupplied()\":[{\"notice\":\"Resolver calldata was supplied without a resolver.\"}]},\"events\":{\"NameRegistered(string,bytes32,address,uint256,uint256,uint256,bytes32)\":{\"notice\":\"Emitted when a name is registered.\"},\"NameRenewed(string,bytes32,uint256,uint256,bytes32)\":{\"notice\":\"Emitted when a name is renewed.\"}},\"kind\":\"user\",\"methods\":{\"BASE()\":{\"notice\":\"The ENSv1 base registrar used to mint the `.eth` registration.\"},\"DEFAULT_REVERSE_REGISTRAR()\":{\"notice\":\"The ENSv1 default reverse registrar.\"},\"ENS_REGISTRY()\":{\"notice\":\"The ENSv1 registry used when setting resolver records.\"},\"ETH_NODE()\":{\"notice\":\"The ENS namehash for `eth`.\"},\"ETH_REGISTRY()\":{\"notice\":\"The ENSv2 `.eth` registry where names are reserved for premigration.\"},\"MIN_REGISTRATION_DURATION()\":{\"notice\":\"The minimum registration duration accepted by the v1 controller.\"},\"PREMIGRATION_REGISTRY()\":{\"notice\":\"The ENSv2 subregistry assigned to premigrated reservations.\"},\"PREMIGRATION_RESOLVER()\":{\"notice\":\"The ENSv2 resolver assigned to premigrated reservations.\"},\"REVERSE_RECORD_DEFAULT_BIT()\":{\"notice\":\"The bitmask for setting the default reverse record.\"},\"REVERSE_RECORD_ETHEREUM_BIT()\":{\"notice\":\"The bitmask for setting the Ethereum reverse record.\"},\"REVERSE_REGISTRAR()\":{\"notice\":\"The ENSv1 Ethereum reverse registrar.\"},\"constructor\":{\"notice\":\"Initializes the testnet registration controller.\"},\"register((string,address,uint256,bytes32,address,bytes[],uint8,bytes32))\":{\"notice\":\"Registers a `.eth` label in ENSv1 for free and reserves it in ENSv2.\"}},\"notice\":\"Free testnet-only v1 registration controller that immediately reserves names in ENSv2.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/testnet/TestnetV1PremigrationRegistrar.sol\":\"TestnetV1PremigrationRegistrar\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/BaseRegistrarImplementation.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"./IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract BaseRegistrarImplementation is ERC721, IBaseRegistrar, Ownable {\\n // A map of expiry times\\n mapping(uint256 => uint256) expiries;\\n // The ENS registry\\n ENS public ens;\\n // The namehash of the TLD this registrar owns (eg, .eth)\\n bytes32 public baseNode;\\n // A map of addresses that are authorised to register and renew names.\\n mapping(address => bool) public controllers;\\n uint256 public constant GRACE_PERIOD = 90 days;\\n bytes4 private constant INTERFACE_META_ID =\\n bytes4(keccak256(\\\"supportsInterface(bytes4)\\\"));\\n bytes4 private constant ERC721_ID =\\n bytes4(\\n keccak256(\\\"balanceOf(address)\\\") ^\\n keccak256(\\\"ownerOf(uint256)\\\") ^\\n keccak256(\\\"approve(address,uint256)\\\") ^\\n keccak256(\\\"getApproved(uint256)\\\") ^\\n keccak256(\\\"setApprovalForAll(address,bool)\\\") ^\\n keccak256(\\\"isApprovedForAll(address,address)\\\") ^\\n keccak256(\\\"transferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256,bytes)\\\")\\n );\\n bytes4 private constant RECLAIM_ID =\\n bytes4(keccak256(\\\"reclaim(uint256,address)\\\"));\\n\\n /// v2.1.3 version of _isApprovedOrOwner which calls ownerOf(tokenId) and takes grace period into consideration instead of ERC721.ownerOf(tokenId);\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.1.3/contracts/token/ERC721/ERC721.sol#L187\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param spender address of the spender to query\\n /// @param tokenId uint256 ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID,\\n /// is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(\\n address spender,\\n uint256 tokenId\\n ) internal view override returns (bool) {\\n address owner = ownerOf(tokenId);\\n return (spender == owner ||\\n getApproved(tokenId) == spender ||\\n isApprovedForAll(owner, spender));\\n }\\n\\n constructor(ENS _ens, bytes32 _baseNode) ERC721(\\\"\\\", \\\"\\\") {\\n ens = _ens;\\n baseNode = _baseNode;\\n }\\n\\n modifier live() {\\n require(ens.owner(baseNode) == address(this));\\n _;\\n }\\n\\n modifier onlyController() {\\n require(controllers[msg.sender]);\\n _;\\n }\\n\\n /// @dev Gets the owner of the specified token ID. Names become unowned\\n /// when their registration expires.\\n /// @param tokenId uint256 ID of the token to query the owner of\\n /// @return address currently marked as the owner of the given token ID\\n function ownerOf(\\n uint256 tokenId\\n ) public view override(IERC721, ERC721) returns (address) {\\n require(expiries[tokenId] > block.timestamp);\\n return super.ownerOf(tokenId);\\n }\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external override onlyOwner {\\n controllers[controller] = true;\\n emit ControllerAdded(controller);\\n }\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external override onlyOwner {\\n controllers[controller] = false;\\n emit ControllerRemoved(controller);\\n }\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external override onlyOwner {\\n ens.setResolver(baseNode, resolver);\\n }\\n\\n // Returns the expiration timestamp of the specified id.\\n function nameExpires(uint256 id) external view override returns (uint256) {\\n return expiries[id];\\n }\\n\\n // Returns true iff the specified name is available for registration.\\n function available(uint256 id) public view override returns (bool) {\\n // Not available if it's registered here or in its grace period.\\n return expiries[id] + GRACE_PERIOD < block.timestamp;\\n }\\n\\n /// @dev Register a name.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external override returns (uint256) {\\n return _register(id, owner, duration, true);\\n }\\n\\n /// @dev Register a name, without modifying the registry.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function registerOnly(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256) {\\n return _register(id, owner, duration, false);\\n }\\n\\n function _register(\\n uint256 id,\\n address owner,\\n uint256 duration,\\n bool updateRegistry\\n ) internal live onlyController returns (uint256) {\\n require(available(id));\\n require(\\n block.timestamp + duration + GRACE_PERIOD >\\n block.timestamp + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] = block.timestamp + duration;\\n if (_exists(id)) {\\n // Name was previously owned, and expired\\n _burn(id);\\n }\\n _mint(owner, id);\\n if (updateRegistry) {\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n emit NameRegistered(id, owner, block.timestamp + duration);\\n\\n return block.timestamp + duration;\\n }\\n\\n function renew(\\n uint256 id,\\n uint256 duration\\n ) external override live onlyController returns (uint256) {\\n require(expiries[id] + GRACE_PERIOD >= block.timestamp); // Name must be registered here or in grace period\\n require(\\n expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] += duration;\\n emit NameRenewed(id, expiries[id]);\\n return expiries[id];\\n }\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external override live {\\n require(_isApprovedOrOwner(msg.sender, id));\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view override(ERC721, IERC165) returns (bool) {\\n return\\n interfaceID == INTERFACE_META_ID ||\\n interfaceID == ERC721_ID ||\\n interfaceID == RECLAIM_ID;\\n }\\n}\\n\",\"keccak256\":\"0xf7d55afacf1b9b2c54e2ac3603af9a8a1bcafcb9209d246a7854a28a884f1142\"},\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ethregistrar/IETHRegistrarController.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"./IPriceOracle.sol\\\";\\n\\ninterface IETHRegistrarController {\\n struct Registration {\\n string label;\\n address owner;\\n uint256 duration;\\n bytes32 secret;\\n address resolver;\\n bytes[] data;\\n uint8 reverseRecord;\\n bytes32 referrer;\\n }\\n\\n function rentPrice(\\n string memory label,\\n uint256 duration\\n ) external view returns (IPriceOracle.Price memory);\\n\\n function available(string memory label) external returns (bool);\\n\\n function makeCommitment(\\n Registration memory registration\\n ) external pure returns (bytes32 commitment);\\n\\n function commit(bytes32 commitment) external;\\n\\n function register(Registration memory registration) external payable;\\n\\n function renew(\\n string calldata label,\\n uint256 duration,\\n bytes32 referrer\\n ) external payable;\\n}\\n\",\"keccak256\":\"0x7cd3669d0a5e7bcb8dbf82d33344f54c3b9643127a1d7d54cf69ef4e98188d07\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ethregistrar/IPriceOracle.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.17 <0.9.0;\\n\\ninterface IPriceOracle {\\n struct Price {\\n uint256 base;\\n uint256 premium;\\n }\\n\\n /// @dev Returns the price to register or renew a name.\\n /// @param name The name being registered or renewed.\\n /// @param expires When the name presently expires (0 if this is a new registration).\\n /// @param duration How long the name is being registered or extended for, in seconds.\\n /// @return base premium tuple of base price + premium price\\n function price(\\n string calldata name,\\n uint256 expires,\\n uint256 duration\\n ) external view returns (Price calldata);\\n}\\n\",\"keccak256\":\"0x969d967cd3c79a1d9f631a8dbc416ecd3c6d1492cc3f1e8155a34424ca8b06f6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/Resolver.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"./profiles/IABIResolver.sol\\\";\\nimport \\\"./profiles/IAddressResolver.sol\\\";\\nimport \\\"./profiles/IAddrResolver.sol\\\";\\nimport \\\"./profiles/IContentHashResolver.sol\\\";\\nimport \\\"./profiles/IDNSRecordResolver.sol\\\";\\nimport \\\"./profiles/IDNSZoneResolver.sol\\\";\\nimport \\\"./profiles/IInterfaceResolver.sol\\\";\\nimport \\\"./profiles/INameResolver.sol\\\";\\nimport \\\"./profiles/IPubkeyResolver.sol\\\";\\nimport \\\"./profiles/ITextResolver.sol\\\";\\nimport \\\"./profiles/IExtendedResolver.sol\\\";\\n\\n/// A generic resolver interface which includes all the functions including the ones deprecated\\ninterface Resolver is\\n IERC165,\\n IABIResolver,\\n IAddressResolver,\\n IAddrResolver,\\n IContentHashResolver,\\n IDNSRecordResolver,\\n IDNSZoneResolver,\\n IInterfaceResolver,\\n INameResolver,\\n IPubkeyResolver,\\n ITextResolver,\\n IExtendedResolver\\n{\\n /* Deprecated events */\\n event ContentChanged(bytes32 indexed node, bytes32 hash);\\n\\n function setApprovalForAll(address, bool) external;\\n\\n function approve(bytes32 node, address delegate, bool approved) external;\\n\\n function isApprovedForAll(address account, address operator) external;\\n\\n function isApprovedFor(\\n address owner,\\n bytes32 node,\\n address delegate\\n ) external;\\n\\n function setABI(\\n bytes32 node,\\n uint256 contentType,\\n bytes calldata data\\n ) external;\\n\\n function setAddr(bytes32 node, address addr) external;\\n\\n function setAddr(bytes32 node, uint256 coinType, bytes calldata a) external;\\n\\n function setContenthash(bytes32 node, bytes calldata hash) external;\\n\\n function setDnsrr(bytes32 node, bytes calldata data) external;\\n\\n function setName(bytes32 node, string calldata _name) external;\\n\\n function setPubkey(bytes32 node, bytes32 x, bytes32 y) external;\\n\\n function setText(\\n bytes32 node,\\n string calldata key,\\n string calldata value\\n ) external;\\n\\n function setInterface(\\n bytes32 node,\\n bytes4 interfaceID,\\n address implementer\\n ) external;\\n\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32 nodehash,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n /* Deprecated functions */\\n function content(bytes32 node) external view returns (bytes32);\\n\\n function multihash(bytes32 node) external view returns (bytes memory);\\n\\n function setContent(bytes32 node, bytes32 hash) external;\\n\\n function setMultihash(bytes32 node, bytes calldata hash) external;\\n}\\n\",\"keccak256\":\"0xef8edb006018266adfb5ece290cae97945040d67da671a61e4039d334ea7bb9b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IABIResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IABIResolver {\\n event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\\n\\n /// Returns the ABI associated with an ENS node.\\n /// Defined in EIP205.\\n /// @param node The ENS node to query\\n /// @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\\n /// @return contentType The content type of the return value\\n /// @return data The ABI data\\n function ABI(\\n bytes32 node,\\n uint256 contentTypes\\n ) external view returns (uint256, bytes memory);\\n}\\n\",\"keccak256\":\"0x3a7a763d7a4f0d196c4b628545b022b1d1d0e37baf84eaa6eecb1a57a1633cad\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the legacy (ETH-only) addr function.\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /// Returns the address associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated address.\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x91dd0c350698c505d6c7e4c919da9f981d4b8d7ad062e25073fa1f6af7cb79d1\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the new (multicoin) addr function.\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x8da5dd0fc1c5ab4f47e03c23126976a86d4b2dbeac161e70e3af9e2a13330cf0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IContentHashResolver {\\n event ContenthashChanged(bytes32 indexed node, bytes hash);\\n\\n /// Returns the contenthash associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function contenthash(bytes32 node) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0xaa978b1ee4c19e99c8aa409dc553e9b4c1bf9fe3c5bad718cd3589e6c9e6d121\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDNSRecordResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IDNSRecordResolver {\\n // DNSRecordChanged is emitted whenever a given node/name/resource's RRSET is updated.\\n event DNSRecordChanged(\\n bytes32 indexed node,\\n bytes name,\\n uint16 resource,\\n bytes record\\n );\\n // DNSRecordDeleted is emitted whenever a given node/name/resource's RRSET is deleted.\\n event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);\\n\\n /// Obtain a DNS record.\\n /// @param node the namehash of the node for which to fetch the record\\n /// @param name the keccak-256 hash of the fully-qualified name for which to fetch the record\\n /// @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\\n /// @return the DNS record in wire format if present, otherwise empty\\n function dnsRecord(\\n bytes32 node,\\n bytes32 name,\\n uint16 resource\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x434bf76bba71eed3e0f22b3a5b9f8aaed0ddd8b79f6a1e7c7447785be5924d3b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDNSZoneResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IDNSZoneResolver {\\n // DNSZonehashChanged is emitted whenever a given node's zone hash is updated.\\n event DNSZonehashChanged(\\n bytes32 indexed node,\\n bytes lastzonehash,\\n bytes zonehash\\n );\\n\\n /// zonehash obtains the hash for the zone.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function zonehash(bytes32 node) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x3a028c0b13721c7627c55bbf5a7d0762d5b1db1045fdc0f8e417011876bd2d29\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IInterfaceResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IInterfaceResolver {\\n event InterfaceChanged(\\n bytes32 indexed node,\\n bytes4 indexed interfaceID,\\n address implementer\\n );\\n\\n /// Returns the address of a contract that implements the specified interface for this name.\\n /// If an implementer has not been set for this interfaceID and name, the resolver will query\\n /// the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\\n /// contract implements EIP165 and returns `true` for the specified interfaceID, its address\\n /// will be returned.\\n /// @param node The ENS node to query.\\n /// @param interfaceID The EIP 165 interface ID to check for.\\n /// @return The address that implements this interface, or 0 if the interface is unsupported.\\n function interfaceImplementer(\\n bytes32 node,\\n bytes4 interfaceID\\n ) external view returns (address);\\n}\\n\",\"keccak256\":\"0x510176a3fe60471775328756ab025d8bafda7063f52f218728ca559b8f61a357\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x3ab986332e0baad7aeb4b426aace3aa1c235be5efff8db4b6f1ce501bcdd9e68\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IPubkeyResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IPubkeyResolver {\\n event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\\n\\n /// Returns the SECP256k1 public key associated with an ENS node.\\n /// Defined in EIP 619.\\n /// @param node The ENS node to query\\n /// @return x The X coordinate of the curve point for the public key.\\n /// @return y The Y coordinate of the curve point for the public key.\\n function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);\\n}\\n\",\"keccak256\":\"0x1a21561b58ce17db400c015882ff07f12f9bd0df0e7b9305841799aada441820\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ITextResolver {\\n event TextChanged(\\n bytes32 indexed node,\\n string indexed indexedKey,\\n string key,\\n string value\\n );\\n\\n /// Returns the text data associated with an ENS node and key.\\n /// @param node The ENS node to query.\\n /// @param key The text data key to query.\\n /// @return The associated text data.\\n function text(\\n bytes32 node,\\n string calldata key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xe91c15697be2d20417cce3c58d4ecce34796986fdedc97be5b93a823be58e471\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/reverseRegistrar/IDefaultReverseRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Interface for the Default Reverse Registrar.\\ninterface IDefaultReverseRegistrar {\\n /// @notice Sets the `nameForAddr()` record for the calling account.\\n ///\\n /// @param name The name to set.\\n function setName(string memory name) external;\\n\\n /// @notice Sets the `nameForAddr()` record for the addr provided account using a signature.\\n ///\\n /// @param addr The address to set the name for.\\n /// @param name The name to set.\\n /// @param signatureExpiry Date when the signature expires.\\n /// @param signature The signature from the addr.\\n function setNameForAddrWithSignature(\\n address addr,\\n uint256 signatureExpiry,\\n string memory name,\\n bytes memory signature\\n ) external;\\n\\n function setNameForAddr(address addr, string memory name) external;\\n}\\n\",\"keccak256\":\"0x45187ce3d3f5da57eac0453ae7df24295e820da379eeaf21cfc967a21038fe7e\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/reverseRegistrar/IReverseRegistrar.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface IReverseRegistrar {\\n function setDefaultResolver(address resolver) external;\\n\\n function claim(address owner) external returns (bytes32);\\n\\n function claimForAddr(\\n address addr,\\n address owner,\\n address resolver\\n ) external returns (bytes32);\\n\\n function claimWithResolver(\\n address owner,\\n address resolver\\n ) external returns (bytes32);\\n\\n function setName(string memory name) external returns (bytes32);\\n\\n function setNameForAddr(\\n address addr,\\n address owner,\\n address resolver,\\n string memory name\\n ) external returns (bytes32);\\n\\n function node(address addr) external pure returns (bytes32);\\n}\\n\",\"keccak256\":\"0x83adfcf6da72b1bcd1e3ac387afe5fc7fdf7f2ac28b7601544d2ca4b9d45d159\"},\"project/lib/ens-contracts/contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nlibrary StringUtils {\\n /// @dev Returns the length of a given string\\n /// @param s The string to measure the length of\\n /// @return The length of the input string\\n function strlen(string memory s) internal pure returns (uint256) {\\n uint256 len;\\n uint256 i = 0;\\n uint256 bytelength = bytes(s).length;\\n for (len = 0; i < bytelength; len++) {\\n bytes1 b = bytes(s)[i];\\n if (b < 0x80) {\\n i += 1;\\n } else if (b < 0xE0) {\\n i += 2;\\n } else if (b < 0xF0) {\\n i += 3;\\n } else if (b < 0xF8) {\\n i += 4;\\n } else if (b < 0xFC) {\\n i += 5;\\n } else {\\n i += 6;\\n }\\n }\\n return len;\\n }\\n\\n /// @dev Escapes special characters in a given string\\n /// @param str The string to escape\\n /// @return The escaped string\\n function escape(string memory str) internal pure returns (string memory) {\\n bytes memory strBytes = bytes(str);\\n uint extraChars = 0;\\n\\n // count extra space needed for escaping\\n for (uint i = 0; i < strBytes.length; i++) {\\n if (_needsEscaping(strBytes[i])) {\\n extraChars++;\\n }\\n }\\n\\n // allocate buffer with the exact size needed\\n bytes memory buffer = new bytes(strBytes.length + extraChars);\\n uint index = 0;\\n\\n // escape characters\\n for (uint i = 0; i < strBytes.length; i++) {\\n if (_needsEscaping(strBytes[i])) {\\n buffer[index++] = \\\"\\\\\\\\\\\";\\n buffer[index++] = _getEscapedChar(strBytes[i]);\\n } else {\\n buffer[index++] = strBytes[i];\\n }\\n }\\n\\n return string(buffer);\\n }\\n\\n // determine if a character needs escaping\\n function _needsEscaping(bytes1 char) private pure returns (bool) {\\n return\\n char == '\\\"' ||\\n char == \\\"/\\\" ||\\n char == \\\"\\\\\\\\\\\" ||\\n char == \\\"\\\\n\\\" ||\\n char == \\\"\\\\r\\\" ||\\n char == \\\"\\\\t\\\";\\n }\\n\\n // get the escaped character\\n function _getEscapedChar(bytes1 char) private pure returns (bytes1) {\\n if (char == \\\"\\\\n\\\") return \\\"n\\\";\\n if (char == \\\"\\\\r\\\") return \\\"r\\\";\\n if (char == \\\"\\\\t\\\") return \\\"t\\\";\\n return char;\\n }\\n}\\n\",\"keccak256\":\"0x0bfe56e70297eb274d45dccd1dab1fe1904f7802fdb27d0b5ff102cec3defb85\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: address zero is not a valid owner\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _ownerOf(tokenId);\\n require(owner != address(0), \\\"ERC721: invalid token ID\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n _requireMinted(tokenId);\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not token owner or approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n _requireMinted(tokenId);\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n _safeTransfer(from, to, tokenId, data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\\n */\\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\\n return _owners[tokenId];\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _ownerOf(tokenId) != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId, 1);\\n\\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n unchecked {\\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\\n // Given that tokens are minted one by one, it is impossible in practice that\\n // this ever happens. Might change if we allow batch minting.\\n // The ERC fails to describe this case.\\n _balances[to] += 1;\\n }\\n\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n * This is an internal function that does not check if the sender is authorized to operate on the token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\\n\\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\\n owner = ERC721.ownerOf(tokenId);\\n\\n // Clear approvals\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // Cannot overflow, as that would require more tokens to be burned/transferred\\n // out than the owner initially received through minting and transferring in.\\n _balances[owner] -= 1;\\n }\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId, 1);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId, 1);\\n\\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n\\n // Clear approvals from the previous owner\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\\n // `from`'s balance is the number of token held, which is at least one before the current\\n // transfer.\\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\\n // all 2**256 token ids to be minted, which in practice is impossible.\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n }\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits an {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Reverts if the `tokenId` has not been minted yet.\\n */\\n function _requireMinted(uint256 tokenId) internal view virtual {\\n require(_exists(tokenId), \\\"ERC721: invalid token ID\\\");\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n /// @solidity memory-safe-assembly\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\\n * - When `from` is zero, the tokens will be minted for `to`.\\n * - When `to` is zero, ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\\n * - When `from` is zero, the tokens were minted for `to`.\\n * - When `to` is zero, ``from``'s tokens were burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Unsafe write access to the balances, used by extensions that \\\"mint\\\" tokens using an {ownerOf} override.\\n *\\n * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\\n * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\\n * that `ownerOf(tokenId)` is `a`.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __unsafe_increaseBalance(address account, uint256 amount) internal {\\n _balances[account] += amount;\\n }\\n}\\n\",\"keccak256\":\"0x2c309e7df9e05e6ce15bedfe74f3c61b467fc37e0fae9eab496acf5ea0bbd7ff\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\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://consensys.net/diligence/blog/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.8.0/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(address target, bytes memory data, uint256 value) 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\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.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 `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\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 /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(uint256 x, uint256 y, uint256 denominator) 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 // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\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(uint256 x, uint256 y, uint256 denominator, Rounding rounding) 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 256, 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 << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/testnet/TestnetV1PremigrationRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.17;\\n\\nimport {\\n BaseRegistrarImplementation\\n} from \\\"@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol\\\";\\nimport {IETHRegistrarController} from \\\"@ens/contracts/ethregistrar/IETHRegistrarController.sol\\\";\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {Resolver} from \\\"@ens/contracts/resolvers/Resolver.sol\\\";\\nimport {\\n IDefaultReverseRegistrar\\n} from \\\"@ens/contracts/reverseRegistrar/IDefaultReverseRegistrar.sol\\\";\\nimport {IReverseRegistrar} from \\\"@ens/contracts/reverseRegistrar/IReverseRegistrar.sol\\\";\\nimport {StringUtils} from \\\"@ens/contracts/utils/StringUtils.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\n/// @title TestnetV1PremigrationRegistrar\\n/// @notice Free testnet-only v1 registration controller that immediately reserves names in ENSv2.\\ncontract TestnetV1PremigrationRegistrar {\\n using StringUtils for *;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The bitmask for setting the Ethereum reverse record.\\n uint8 public constant REVERSE_RECORD_ETHEREUM_BIT = 1;\\n\\n /// @notice The bitmask for setting the default reverse record.\\n uint8 public constant REVERSE_RECORD_DEFAULT_BIT = 2;\\n\\n /// @notice The minimum registration duration accepted by the v1 controller.\\n uint256 public constant MIN_REGISTRATION_DURATION = 28 days;\\n\\n /// @notice The ENS namehash for `eth`.\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @notice The ENSv1 base registrar used to mint the `.eth` registration.\\n BaseRegistrarImplementation public immutable BASE;\\n\\n /// @notice The ENSv1 registry used when setting resolver records.\\n ENS public immutable ENS_REGISTRY;\\n\\n /// @notice The ENSv1 Ethereum reverse registrar.\\n IReverseRegistrar public immutable REVERSE_REGISTRAR;\\n\\n /// @notice The ENSv1 default reverse registrar.\\n IDefaultReverseRegistrar public immutable DEFAULT_REVERSE_REGISTRAR;\\n\\n /// @notice The ENSv2 `.eth` registry where names are reserved for premigration.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice The ENSv2 subregistry assigned to premigrated reservations.\\n IRegistry public immutable PREMIGRATION_REGISTRY;\\n\\n /// @notice The ENSv2 resolver assigned to premigrated reservations.\\n address public immutable PREMIGRATION_RESOLVER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when a name is registered.\\n /// @param label The label of the name.\\n /// @param labelhash The keccak256 hash of the label.\\n /// @param owner The owner of the name.\\n /// @param baseCost The base cost of the name.\\n /// @param premium The premium cost of the name.\\n /// @param expires The expiry time of the name.\\n /// @param referrer The referrer of the registration.\\n event NameRegistered(\\n string label,\\n bytes32 indexed labelhash,\\n address indexed owner,\\n uint256 baseCost,\\n uint256 premium,\\n uint256 expires,\\n bytes32 referrer\\n );\\n\\n /// @notice Emitted when a name is renewed.\\n /// @param label The label of the name.\\n /// @param labelhash The keccak256 hash of the label.\\n /// @param cost The cost of the name.\\n /// @param expires The expiry time of the name.\\n /// @param referrer The referrer of the registration.\\n event NameRenewed(\\n string label,\\n bytes32 indexed labelhash,\\n uint256 cost,\\n uint256 expires,\\n bytes32 referrer\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name is not available for v1 registration.\\n /// @dev Error selector: `0x477707e8`\\n /// @param name The unavailable label.\\n error NameNotAvailable(string name);\\n\\n /// @notice Registration duration is below the accepted minimum.\\n /// @dev Error selector: `0x9a71997b`\\n /// @param duration The supplied duration.\\n error DurationTooShort(uint256 duration);\\n\\n /// @notice Resolver calldata was supplied without a resolver.\\n /// @dev Error selector: `0xd3f605c4`\\n error ResolverRequiredWhenDataSupplied();\\n\\n /// @notice A reverse record was requested without a resolver.\\n /// @dev Error selector: `0x7d4a034a`\\n error ResolverRequiredForReverseRecord();\\n\\n /// @notice The v1 expiry cannot fit in the ENSv2 registry expiry field.\\n /// @dev Error selector: `0x544476c3`\\n /// @param expiry The v1 expiry timestamp.\\n error ExpiryTooLarge(uint256 expiry);\\n\\n /// @notice Refund of accidentally supplied ETH failed.\\n /// @dev Error selector: `0xaf73b0b2`\\n /// @param recipient The refund recipient.\\n /// @param amount The amount that failed to refund.\\n error RefundFailed(address recipient, uint256 amount);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Initializes the testnet registration controller.\\n /// @param base_ The ENSv1 base registrar.\\n /// @param ensRegistry_ The ENSv1 registry.\\n /// @param reverseRegistrar_ The ENSv1 Ethereum reverse registrar.\\n /// @param defaultReverseRegistrar_ The ENSv1 default reverse registrar.\\n /// @param ethRegistry_ The ENSv2 `.eth` registry.\\n /// @param premigrationRegistry_ The ENSv2 subregistry to assign to reservations.\\n /// @param premigrationResolver_ The ENSv2 resolver to assign to reservations.\\n constructor(\\n BaseRegistrarImplementation base_,\\n ENS ensRegistry_,\\n IReverseRegistrar reverseRegistrar_,\\n IDefaultReverseRegistrar defaultReverseRegistrar_,\\n IPermissionedRegistry ethRegistry_,\\n IRegistry premigrationRegistry_,\\n address premigrationResolver_\\n ) {\\n BASE = base_;\\n ENS_REGISTRY = ensRegistry_;\\n REVERSE_REGISTRAR = reverseRegistrar_;\\n DEFAULT_REVERSE_REGISTRAR = defaultReverseRegistrar_;\\n ETH_REGISTRY = ethRegistry_;\\n PREMIGRATION_REGISTRY = premigrationRegistry_;\\n PREMIGRATION_RESOLVER = premigrationResolver_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a `.eth` label in ENSv1 for free and reserves it in ENSv2.\\n /// @param registration The v1 controller registration parameters.\\n function register(IETHRegistrarController.Registration calldata registration) external payable {\\n bytes32 labelhash = keccak256(bytes(registration.label));\\n\\n if (registration.duration < MIN_REGISTRATION_DURATION) {\\n revert DurationTooShort(registration.duration);\\n }\\n if (!_available(registration.label, labelhash)) {\\n revert NameNotAvailable(registration.label);\\n }\\n if (registration.data.length > 0 && registration.resolver == address(0)) {\\n revert ResolverRequiredWhenDataSupplied();\\n }\\n if (registration.reverseRecord != 0 && registration.resolver == address(0)) {\\n revert ResolverRequiredForReverseRecord();\\n }\\n\\n uint256 expires = _registerV1(registration, labelhash);\\n _premigrate(registration.label, expires);\\n\\n emit NameRegistered(\\n registration.label,\\n labelhash,\\n registration.owner,\\n 0,\\n 0,\\n expires,\\n registration.referrer\\n );\\n\\n _refund();\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Registers the name in ENSv1 and applies optional resolver and reverse records.\\n function _registerV1(\\n IETHRegistrarController.Registration calldata registration,\\n bytes32 labelhash\\n ) internal returns (uint256 expires) {\\n uint256 tokenId = uint256(labelhash);\\n if (registration.resolver == address(0)) {\\n return BASE.register(tokenId, registration.owner, registration.duration);\\n }\\n\\n expires = BASE.register(tokenId, address(this), registration.duration);\\n bytes32 namehash = keccak256(abi.encodePacked(ETH_NODE, labelhash));\\n ENS_REGISTRY.setRecord(namehash, registration.owner, registration.resolver, 0);\\n\\n if (registration.data.length > 0) {\\n Resolver(registration.resolver).multicallWithNodeCheck(namehash, registration.data);\\n }\\n\\n BASE.transferFrom(address(this), registration.owner, tokenId);\\n\\n string memory name = string.concat(registration.label, \\\".eth\\\");\\n if (registration.reverseRecord & REVERSE_RECORD_ETHEREUM_BIT != 0) {\\n REVERSE_REGISTRAR.setNameForAddr(msg.sender, msg.sender, registration.resolver, name);\\n }\\n if (registration.reverseRecord & REVERSE_RECORD_DEFAULT_BIT != 0) {\\n DEFAULT_REVERSE_REGISTRAR.setNameForAddr(msg.sender, name);\\n }\\n }\\n\\n /// @dev Reserves or extends the matching ENSv2 reservation.\\n function _premigrate(string calldata label, uint256 expires) internal {\\n if (expires > type(uint64).max) {\\n revert ExpiryTooLarge(expires);\\n }\\n\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n uint64 expiry = uint64(expires);\\n\\n if (state.status == IPermissionedRegistry.Status.AVAILABLE) {\\n ETH_REGISTRY.register(\\n label,\\n address(0),\\n PREMIGRATION_REGISTRY,\\n PREMIGRATION_RESOLVER,\\n 0,\\n expiry\\n );\\n } else if (state.status == IPermissionedRegistry.Status.RESERVED && expiry > state.expiry) {\\n ETH_REGISTRY.renew(state.tokenId, expiry);\\n }\\n }\\n\\n /// @dev Refunds ETH because this testnet controller is free.\\n function _refund() internal {\\n if (msg.value == 0) return;\\n\\n (bool ok, ) = payable(msg.sender).call{value: msg.value}(\\\"\\\");\\n if (!ok) {\\n revert RefundFailed(msg.sender, msg.value);\\n }\\n }\\n\\n /// @dev Returns true when the label is valid and available in ENSv1.\\n function _available(string calldata label, bytes32 labelhash) internal view returns (bool) {\\n return label.strlen() >= 3 && BASE.available(uint256(labelhash));\\n }\\n}\\n\",\"keccak256\":\"0x34a39ca296666f7bd2dffe45cf4c0348b2bb0a016ce6caff0ac0274b5de5adf5\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "DurationTooShort(uint256)": [ + { + "notice": "Registration duration is below the accepted minimum." + } + ], + "ExpiryTooLarge(uint256)": [ + { + "notice": "The v1 expiry cannot fit in the ENSv2 registry expiry field." + } + ], + "NameNotAvailable(string)": [ + { + "notice": "Name is not available for v1 registration." + } + ], + "RefundFailed(address,uint256)": [ + { + "notice": "Refund of accidentally supplied ETH failed." + } + ], + "ResolverRequiredForReverseRecord()": [ + { + "notice": "A reverse record was requested without a resolver." + } + ], + "ResolverRequiredWhenDataSupplied()": [ + { + "notice": "Resolver calldata was supplied without a resolver." + } + ] + }, + "events": { + "NameRegistered(string,bytes32,address,uint256,uint256,uint256,bytes32)": { + "notice": "Emitted when a name is registered." + }, + "NameRenewed(string,bytes32,uint256,uint256,bytes32)": { + "notice": "Emitted when a name is renewed." + } + }, + "kind": "user", + "methods": { + "BASE()": { + "notice": "The ENSv1 base registrar used to mint the `.eth` registration." + }, + "DEFAULT_REVERSE_REGISTRAR()": { + "notice": "The ENSv1 default reverse registrar." + }, + "ENS_REGISTRY()": { + "notice": "The ENSv1 registry used when setting resolver records." + }, + "ETH_NODE()": { + "notice": "The ENS namehash for `eth`." + }, + "ETH_REGISTRY()": { + "notice": "The ENSv2 `.eth` registry where names are reserved for premigration." + }, + "MIN_REGISTRATION_DURATION()": { + "notice": "The minimum registration duration accepted by the v1 controller." + }, + "PREMIGRATION_REGISTRY()": { + "notice": "The ENSv2 subregistry assigned to premigrated reservations." + }, + "PREMIGRATION_RESOLVER()": { + "notice": "The ENSv2 resolver assigned to premigrated reservations." + }, + "REVERSE_RECORD_DEFAULT_BIT()": { + "notice": "The bitmask for setting the default reverse record." + }, + "REVERSE_RECORD_ETHEREUM_BIT()": { + "notice": "The bitmask for setting the Ethereum reverse record." + }, + "REVERSE_REGISTRAR()": { + "notice": "The ENSv1 Ethereum reverse registrar." + }, + "constructor": { + "notice": "Initializes the testnet registration controller." + }, + "register((string,address,uint256,bytes32,address,bytes[],uint8,bytes32))": { + "notice": "Registers a `.eth` label in ENSv1 for free and reserves it in ENSv2." + } + }, + "notice": "Free testnet-only v1 registration controller that immediately reserves names in ENSv2.", + "version": 1 + }, + "argsData": "0x00000000000000000000000057f1887a8bf19b14fc0df6fd9b2acc9af147ea8500000000000000000000000000000000000c2e074ec69a0dfb2997ba6c7d2e1e000000000000000000000000a0a1abcdae1a2a4a2ef8e9113ff0e02dd81dc0c60000000000000000000000004f382928805ba0e23b30cfb75fc9e848e82dfd47000000000000000000000000dedb92913a25abe1f7bcdd85d8a344a43b398b670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000422484c2d51f92830bfb563fa5e172aa2d8b884b", + "transaction": { + "hash": "0x65300d62a6d11f73de407953a004e3a91b8f130b6608bc031b3f10cb6b49785a", + "nonce": "0x1ea0", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0xd557d8adb853e66a42886a68a6f2aa769558489df02d0b6ce43d8303c263f0b1", + "blockNumber": "0xa6a815", + "transactionIndex": "0x4b" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/UniversalResolverV2.json b/contracts/deployments/sepolia-official-v1-20260525-r2/UniversalResolverV2.json new file mode 100644 index 000000000..c0b02f25d --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/UniversalResolverV2.json @@ -0,0 +1,1406 @@ +{ + "address": "0x2f8a180604c42457cb56c7c4f708748ff1f91df1", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "rootRegistry", + "type": "address" + }, + { + "internalType": "contract IGatewayProvider", + "name": "batchGatewayProvider", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "ens", + "type": "string" + } + ], + "name": "DNSEncodingFailed", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "status", + "type": "uint16" + }, + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "HttpError", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBatchGatewayResponse", + "type": "error" + }, + { + "inputs": [], + "name": "LabelIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelIsTooLong", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "errorData", + "type": "bytes" + } + ], + "name": "ResolverError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "ResolverNotContract", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "ResolverNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "primary", + "type": "string" + }, + { + "internalType": "bytes", + "name": "primaryAddress", + "type": "bytes" + } + ], + "name": "ReverseAddressMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "UnsupportedResolverProfile", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchGatewayProvider", + "outputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "name": "ccipBatch", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipBatchCallback", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipReadCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "findCanonicalName", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findCanonicalRegistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findExactRegistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findParentRegistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findRegistries", + "outputs": [ + { + "internalType": "contract IRegistry[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findResolver", + "outputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "requireResolver", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bool", + "name": "extended", + "type": "bool" + } + ], + "internalType": "struct AbstractUniversalResolver.ResolverInfo", + "name": "info", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveBatchCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveDirectCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "resolveDirectCallbackError", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "name": "resolveWithGateways", + "outputs": [ + { + "internalType": "bytes", + "name": "result", + "type": "bytes" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "name": "resolveWithResolver", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "lookupAddress", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "reverse", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "reverseAddressCallback", + "outputs": [ + { + "internalType": "string", + "name": "primary", + "type": "string" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "address", + "name": "reverseResolver", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "reverseNameCallback", + "outputs": [ + { + "internalType": "string", + "name": "primary", + "type": "string" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "lookupAddress", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "name": "reverseWithGateways", + "outputs": [ + { + "internalType": "string", + "name": "primary", + "type": "string" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "address", + "name": "reverseResolver", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "UniversalResolverV2", + "sourceName": "src/universalResolver/UniversalResolverV2.sol", + "bytecode": "0x610100604052348015610010575f5ffd5b5060405161499038038061499083398101604081905261002f91610068565b61c3506080526001600160a01b0391821660a052811660c0521660e0526100b2565b6001600160a01b0381168114610065575f5ffd5b50565b5f5f5f6060848603121561007a575f5ffd5b835161008581610051565b602085015190935061009681610051565b60408501519092506100a781610051565b809150509250925092565b60805160a05160c05160e05161486561012b5f395f818161042e0152818161053201528181610b5901528181610d2501528181610ffa01528181611034015281816114d501526115bb01525f81816102480152610ae701525f81816101e101528181610a370152610b8a01525f61227f01526148655ff3fe608060405234801561000f575f5ffd5b50600436106101b0575f3560e01c806394fbfa87116100f3578063b536af7611610093578063c92cc49a1161006e578063c92cc49a14610429578063e4f8ce0514610450578063ef46c0b814610463578063f272e2af14610476575f5ffd5b8063b536af76146103e3578063b7d6ca64146103f6578063c285238a14610409575f5ffd5b8063a1472844116100ce578063a147284414610372578063a1cbcbaf14610385578063b363cc73146103bd578063b4a85801146103d0575f5ffd5b806394fbfa871461032c57806397ad3b3b1461033f5780639f28e99d14610352575f5ffd5b80634a3e39941161015e5780635d78a217116101395780635d78a217146102d25780636f3ff726146102e557806383a64339146102f85780639061b9231461030b575f5ffd5b80634a3e39941461027d57806355391bb81461029d578063575de750146102b0575f5ffd5b80634878c6dd1161018e5780634878c6dd1461023057806348ee1bcc14610243578063491fc4f91461026a575f5ffd5b806301ffc9a7146101b457806302cf2578146101dc5780633c6cbda81461021b575b5f5ffd5b6101c76101c2366004613355565b610496565b60405190151581526020015b60405180910390f35b6102037f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101d3565b61022e6102293660046133ad565b6104e8565b005b61020361023e366004613417565b61052c565b6102037f000000000000000000000000000000000000000000000000000000000000000081565b61022e6102783660046133ad565b610593565b61029061028b36600461363d565b610703565b6040516101d39190613712565b61022e6102ab366004613724565b610847565b6102c36102be3660046133ad565b6108ca565b6040516101d39392919061378b565b6102c36102e03660046137bd565b610a2b565b6101c76102f3366004613804565b610ac6565b610290610306366004613804565b610b52565b61031e6103193660046133ad565b610b7e565b6040516101d392919061381f565b6102c361033a3660046133ad565b610c17565b61020361034d366004613417565b610d1f565b610365610360366004613849565b610d7f565b6040516101d39190613a30565b61031e610380366004613aff565b610f40565b610398610393366004613b95565b610ff2565b604080516001600160a01b0390941684526020840192909252908201526060016101d3565b6102036103cb366004613417565b61102e565b61031e6103de3660046133ad565b61108e565b6103656103f13660046133ad565b6110e4565b6102c3610404366004613bc6565b61133e565b61041c610417366004613b95565b611464565b6040516101d39190613c37565b6102037f000000000000000000000000000000000000000000000000000000000000000081565b61020361045e366004613417565b6114cf565b61022e610471366004613c91565b61152f565b610489610484366004613417565b6115b4565b6040516101d39190613cf4565b5f7ff99a5e06000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806104d357506104d382611615565b806104e257506104e282611662565b92915050565b61052684848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061169692505050565b50505050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506116f5915050565b9392505050565b5f6105a084860186613849565b5190505f8080806105b386880188613d4c565b9350935093509350606083156105f3576105cd86866117bb565b6040516020016105dd9190613db0565b60405160208183030381529060405290506106a8565b5f865f8151811061060657610606613e13565b602002602001015190508060400151915060048160600151165f1461062d57815160208301fd5b6060810151600216156106485761064382611696565b610689565b81515f0361068957806020015161065e90613e27565b604051637b1c461b60e01b81526001600160e01b031990911660048201526024015b60405180910390fd5b85156106a657818060200190518101906106a39190613eb2565b91505b505b6106f7308483856040516024016106c0929190613ee3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611941565b50505050505050505050565b606061073e6040518060a00160405280606081526020015f81526020015f81526020015f6001600160a01b031681526020015f151581525090565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250604080516020601f89018190048102820181019092528781526107b29189908990819084018382808284375f9201829052509250611966915050565b60408201526001600160a01b03881660608201526107cf81611997565b61083c8186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516001600160a01b038f16602082015289935063b4a8580160e01b9250015b604051602081830303815290604052611a5f565b509695505050505050565b5f80808061085785870187613f07565b935093509350935086515f0361088c57604051637b1c461b60e01b81526001600160e01b031984166004820152602401610680565b83156108a957868060200190518101906108a69190613eb2565b96505b6108c1308389846040516024016106c0929190613ee3565b50505050505050565b60605f80806108db85870187613fc0565b90506108e987890189613b95565b935083515f03610912576060015160408051602081019091525f80825290945092509050610a21565b5f61091f61041786611dcb565b9050610a1e81603c84602001511461099d5782604001518460200151604051602401610955929190918252602082015260400190565b60408051601f198184030181529190526020810180516001600160e01b03167ff1cb7e06000000000000000000000000000000000000000000000000000000001790526109f8565b82604001516040516024016109b491815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f3b3b57de000000000000000000000000000000000000000000000000000000001790525b84604001516394fbfa8760e01b868a876060015160405160200161082893929190614048565b50505b9450945094915050565b60605f5f610ab78686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663093a86d36040518163ffffffff1660e01b81526004015f60405180830381865afa158015610a90573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104049190810190614104565b92509250925093509350939050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610b2e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e29190614135565b60606104e27f000000000000000000000000000000000000000000000000000000000000000083611f88565b60605f610c0a868686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663093a86d36040518163ffffffff1660e01b81526004015f60405180830381865afa158015610be3573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526103809190810190614104565b9150915094509492505050565b60605f5f610c4d6040518060800160405280606081526020015f8152602001606081526020015f6001600160a01b031681525090565b610c5985870187614150565b60208301519196509450909150606090603b1901610cb7575f610c7e898b018b613804565b6040516bffffffffffffffffffffffff19606083901b166020820152909150603401604051602081830303815290604052915050610cc6565b610cc3888a018a613b95565b90505b8151610cd29082612157565b610d0c5784816040517fef9c03ce000000000000000000000000000000000000000000000000000000008152600401610680929190613ee3565b8160600151925050509450945094915050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920182905250925061217b915050565b60408051808201909152606080825260208201525f5b825151811015610f32575f835f01518281518110610db557610db5613e13565b6020026020010151905060408160600151165f14610dd35750610f2a565b60608101516030165f03610e7d575f610dee825f0151612239565b610df9576010610dfc565b60205b9050825b855151811015610e7a57825f01516001600160a01b0316865f01518281518110610e2c57610e2c613e13565b60200260200101515f01516001600160a01b031603610e725781865f01518281518110610e5b57610e5b613e13565b602002602001015160600181815117915081815250505b600101610e00565b50505b5f60208260600151165f1490505f5f610e9f8315855f0151866020015161226b565b9150915081158015610ec95750630556f18360e41b610ebd82613e27565b6001600160e01b031916145b15610ede576060840180516001179052610f1e565b6060840180516040179052828015610ef557508051155b610f0a5781610f0a5760608401805160021790525b80515f03610f1e5760608401805160081790525b60409093019290925250505b600101610d95565b50610f3c826122fe565b5090565b60605f5f610f8288888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061146492505050565b9050610fe78187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050506060840151604080516001600160a01b039092166020830152889163b4a8580160e01b9101610828565b509550959350505050565b5f5f5f6110207f0000000000000000000000000000000000000000000000000000000000000000855f6124e8565b919790965090945092505050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061265492505050565b60605f858561109f85870187613804565b82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929c939b50929950505050505050505050565b60408051808201909152606080825260208201525f80611106868801886141c6565b91509150805182511461112c5760405163252e18f560e11b815260040160405180910390fd5b61113884860186613849565b92505f5f5b845151811015611308575f855f0151828151811061115d5761115d613e13565b6020026020010151905060408160600151165f036112ff5783518310156112f3575f84848151811061119157611191613e13565b602002602001015190508584815181106111ad576111ad613e13565b6020026020010151156111ca5760608201805160441790526112ed565b5f6111d883604001516126a4565b90505f815f01516001600160a01b03168260600151848460800151604051602401611204929190613ee3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516112429190614296565b5f60405180830381855afa9150503d805f811461127a576040519150601f19603f3d011682016040523d82523d5f602084013e61127f565b606091505b509350905080806112a95750630556f18360e41b61129c84613e27565b6001600160e01b03191614155b156112ea5760608401805160401790528015806112c557508251155b156112d65760608401805160021790525b82515f036112ea5760608401805160081790525b50505b60408201525b6112fc836142b5565b92505b5060010161113d565b508151811461132a5760405163252e18f560e11b815260040160405180910390fd5b611333846122fe565b505050949350505050565b60605f5f5f61138e6104176113898a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c92506126e8915050565b611dcb565b90506114598182604001516040516024016113ab91815260200190565b60405160208183030381529060405263691f343160e01b6020820180516001600160e01b0383818316178352505050508763575de75060e01b60405180608001604052808e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060208082018e905260408083018e905260608a8101516001600160a01b031693019290925290516108289291016142cd565b509450945094915050565b61149d6040518060a00160405280606081526020015f81526020015f81526020015f6001600160a01b031681526020015f151581525090565b6114a682610ff2565b602084015260408301526001600160a01b031660608201528181526114ca81611997565b919050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920182905250925061282d915050565b5f8180602001905181019061154491906142f5565b90506115af815f01518260200151858460400151604051602401611569929190613ee3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a0860151612859565b505050565b606061058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612a1c915050565b5f7f6cd2d09b000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806104e257506301ffc9a760e01b6001600160e01b03198316146104e2565b5f6001600160e01b0319821663379ffb9360e11b14806104e257506301ffc9a760e01b6001600160e01b03198316146104e2565b637b1c461b60e01b6116a782613e27565b6001600160e01b031916036116be57805160208201fd5b806040517f95c0c7520000000000000000000000000000000000000000000000000000000081526004016106809190613712565b50565b5f5f5f6117028585612ac2565b90925090508161171657859250505061058c565b5f6117228787846116f5565b90506001600160a01b038116156117b1575f61173e8787612aef565b50604051631ad7b10b60e11b81529091506001600160a01b038316906335af62169061176e908490600401613712565b602060405180830381865afa158015611789573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117ad91906143cd565b9450505b5050509392505050565b606082516001600160401b038111156117d6576117d6613469565b60405190808252806020026020018201604052801561180957816020015b60608152602001906001900390816117f45790505b5090505f5b835181101561193a575f84828151811061182a5761182a613e13565b60209081029190910101516040810151606082015191925090600e165f0361186e57841561186957808060200190518101906118669190613eb2565b90505b611912565b805115611912578051601f1660048114611910575f6004821061189b576118966004836143e8565b6118a6565b6118a68260046143e8565b6001600160401b038111156118bd576118bd613469565b6040519080825280601f01601f1916602001820160405280156118e7576020820181803683370190505b50905082816040516020016118fd9291906143fb565b6040516020818303038152906040529250505b505b8084848151811061192557611925613e13565b6020908102919091010152505060010161180e565b5092915050565b61196282825f60e01b5f60e01b60405180602001604052805f815250612859565b5050565b5f6119718383612ac2565b9250905080156104e25761058c6119888484611966565b825f9182526020526040902090565b60608101516001600160a01b03166119c5578051604051630ee413fd60e31b81526106809190600401613712565b6119da8160600151639061b92360e01b612b6b565b156119e9576001608082015250565b602081015115611a0f578051604051630ee413fd60e31b81526106809190600401613712565b80606001516001600160a01b03163b5f036116f257805160608201516040517f1e9535f200000000000000000000000000000000000000000000000000000000815261068092919060040161381f565b5f7fac9650d800000000000000000000000000000000000000000000000000000000611a8a86613e27565b6001600160e01b031916149050611aac866060015163582de3e760e01b612b6b565b8015611b535750801580611b53575085608001518015611b535750606086015160405163582de3e760e01b81527f96b62db80000000000000000000000000000000000000000000000000000000060048201526001600160a01b039091169063582de3e790602401602060405180830381865afa158015611b2f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b539190614135565b15611c2957611c2986606001518760800151611b6f5786611bae565b8751604051611b8391908990602401613ee3565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b1790525b60808901517f55391bb800000000000000000000000000000000000000000000000000000000907f3c6cbda80000000000000000000000000000000000000000000000000000000090611c008b613e27565b8989604051602001611c15949392919061440f565b604051602081830303815290604052612859565b60608115611c6357611c49866004808951611c4491906143e8565b612bf1565b806020019051810190611c5c9190614453565b9050611cae565b60408051600180825281830190925290816020015b6060815260200190600190039081611c7857905050905085815f81518110611ca257611ca2613e13565b60200260200101819052505b866080015115611d45575f5b8151811015611d4357875f0151828281518110611cd957611cd9613e13565b6020026020010151604051602401611cf2929190613ee3565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b1790528251839083908110611d3057611d30613e13565b6020908102919091010152600101611cba565b505b6108c130306001600160a01b0316639f28e99d611d678b60600151868b612c45565b604051602401611d779190613a30565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505063491fc4f960e01b5f60e01b8b60800151878a8a604051602001611c1594939291906144f7565b80516060905f819003611df357505060408051808201909152600181525f6020820152919050565b806002016001600160401b03811115611e0e57611e0e613469565b6040519080825280601f01601f191660200182016040528015611e38576020820181803683370190505b509150611e4c602183016020850183612d59565b5f5f5f5b83811015611f0957858181518110611e6a57611e6a613e13565b01602001516001600160f81b031916601760f91b03611f01578281039150815f1480611e96575060ff82115b15611eb65785604051639a4c3e3b60e01b81526004016106809190613712565b8160f81b858481518110611ecc57611ecc613e13565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053508060010192505b600101611e50565b505080820382821480611f1c575060ff81115b15611f3c5784604051639a4c3e3b60e01b81526004016106809190613712565b8060f81b848381518110611f5257611f52613e13565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350505050919050565b60606001600160a01b038216611fac575060408051602081019091525f81526104e2565b826001600160a01b0316826001600160a01b031603611fee57805f604051602001611fd8929190614529565b60405160208183030381529060405290506104e2565b5f5f836001600160a01b03166380f760216040518163ffffffff1660e01b81526004015f60405180830381865afa15801561202b573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526120529190810190614550565b90925090506001600160a01b03821661207d5760405180602001604052805f815250925050506104e2565b604051631ad7b10b60e11b81525f906001600160a01b038416906335af6216906120ab908590600401613712565b602060405180830381865afa1580156120c6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120ea91906143cd565b9050846001600160a01b0316816001600160a01b03161461211e5760405180602001604052805f81525093505050506104e2565b8361212883612da2565b8360405160200161213b93929190614593565b6040516020818303038152906040529350829450505050611fac565b5f8151835114801561058c5750508051602091820120825192909101919091201490565b5f5f61218885858561282d565b90506001600160a01b038116158015906121ae57506121ae816331ab054760e11b612e1c565b15612231575f6121be8585612aef565b506040516331ab054760e11b81529091506001600160a01b038316906363560a8e906121ee908490600401613712565b602060405180830381865afa158015612209573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061222d91906143cd565b9250505b509392505050565b5f306001600160a01b0383160361225257506001919050565b6113885a5f5f5f5f8786fa50815a909103109392505050565b5f6060836001600160a01b0316856122a3577f00000000000000000000000000000000000000000000000000000000000000006122a5565b5a5b846040516122b39190614296565b5f604051808303818686fa925050503d805f81146122ec576040519150601f19603f3d011682016040523d82523d5f602084013e6122f1565b606091505b5090969095509350505050565b8051515f906001600160401b0381111561231a5761231a613469565b60405190808252806020026020018201604052801561237757816020015b61236460405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816123385790505b5090505f5f5b835151811015612428575f845f0151828151811061239d5761239d613e13565b6020026020010151905060408160600151165f0361241f575f6123c382604001516126a4565b90506040518060600160405280825f01516001600160a01b03168152602001826020015181526020018260400151815250858580612400906142b5565b96508151811061241257612412613e13565b6020026020010181905250505b5060010161237d565b5080156115af578082523083602001518360405160240161244991906145bb565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af7600000000000000000000000000000000000000000000000000000000916124bd91899101613a30565b60408051601f1981840301815290829052630556f18360e41b8252610680959493929160040161464c565b5f5f5f5f5f5f6124f88888612ac2565b90925090508161251657508794505f935083925085915061264b9050565b6125218989836124e8565b929850909650945092506001600160a01b0386161561263c575f6125458989612aef565b5090505f876001600160a01b031663e4ae7d77836040518263ffffffff1660e01b81526004016125759190613712565b602060405180830381865afa158015612590573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125b491906143cd565b90506001600160a01b038116156125cc578096508894505b604051631ad7b10b60e11b81526001600160a01b038916906335af6216906125f8908590600401613712565b602060405180830381865afa158015612613573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061263791906143cd565b975050505b505f9283526020526040909120905b93509350935093565b5f5f61266184845f6116f5565b90506001600160a01b038116158015906126905750825160208401206126878583611f88565b80519060200120145b61269a575f61269c565b805b949350505050565b6040805160a0810182525f8082526060602083018190529282018390528282015260808101919091526104e26126e3836004808651611c4491906143e8565b612e37565b606082515f03612724576040517f7138356f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61272d83612ea2565b601760f91b603c8414612790576380000000841461275557612750846001612f0a565b6127c7565b6040518060400160405280600781526020017f64656661756c74000000000000000000000000000000000000000000000000008152506127c7565b6040518060400160405280600481526020017f61646472000000000000000000000000000000000000000000000000000000008152505b601760f91b6040518060400160405280600781526020017f72657665727365000000000000000000000000000000000000000000000000008152506040516020016128169594939291906146af565b604051602081830303815290604052905092915050565b5f5f5f61283a8585612ac2565b909250905081156128505761222d8686836116f5565b50509392505050565b5f5f61286e61286788612239565b888861226b565b91509150811580156128985750630556f18360e41b61288c82613e27565b6001600160e01b031916145b15612946575f6128a7826126a4565b9050876001600160a01b0316815f01516001600160a01b03160361294457308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b0319168152602001898152506040516020016124bd91906146f0565b505b5f826129525784612954565b855b90506001600160e01b0319811615612a0657306001600160a01b0316818386604051602401612984929190613ee3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516129c29190614296565b5f60405180830381855afa9150503d805f81146129fa576040519150601f19603f3d011682016040523d82523d5f602084013e6129ff565b606091505b5090935091505b8215612a1457815160208301f35b815160208301fd5b6060612a288383612fdb565b612a33906001614777565b6001600160401b03811115612a4a57612a4a613469565b604051908082528060200260200182016040528015612a73578160200160208202803683370190505b509050838160018351612a8691906143e8565b81518110612a9657612a96613e13565b60200260200101906001600160a01b031690816001600160a01b0316815250506122318383835f613005565b5f5f5f612acf8585613120565b9250905060ff811615612ae757806021858701012092505b509250929050565b60605f5f612afd8585613120565b925090505f60ff82166001600160401b03811115612b1d57612b1d613469565b6040519080825280601f01601f191660200182016040528015612b47576020820181803683370190505b509050612b606020820160218888010160ff8516612d59565b959194509092505050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f519050828015612bdb575060208210155b8015612be657505f81115b979650505050505050565b6060816001600160401b03811115612c0b57612c0b613469565b6040519080825280601f01601f191660200182016040528015612c35576020820181803683370190505b50905061058c8484835f866131a4565b60408051808201909152606080825260208201525f83516001600160401b03811115612c7357612c73613469565b604051908082528060200260200182016040528015612cd657816020015b612cc360405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b815260200190600190039081612c915790505b5090505f5b8451811015612d3c575f828281518110612cf757612cf7613e13565b60209081029190910101516001600160a01b03881681528651909150869083908110612d2557612d25613e13565b602090810291909101810151910152600101612cdb565b506040805180820190915290815260208101929092525092915050565b5b601f811115612d7a578151835260209283019290910190601f1901612d5a565b80156115af5790518251600160209390930360031b9290921b5f190180199091169116179052565b80515f90808203612ddf576040517fbf9a274000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff8111156104e257826040517fdab6c73c0000000000000000000000000000000000000000000000000000000081526004016106809190613712565b5f612e26836131e1565b801561058c575061058c8383613213565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915281806020019051810190612e74919061478a565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b805160609060011b806001600160401b03811115612ec257612ec2613469565b6040519080825280601f01601f191660200182016040528015612eec576020820181803683370190505b5091506020838101908301612f02828285613295565b505050919050565b6060825f60805b60088110612f42576001811b831015612f3557612f2e8183614777565b9150612f3a565b91821c915b60011c612f11565b50838015612f505750601082105b15612f6357612f60600482614777565b90505b5f612f73600283901c60406143e8565b9050806001600160401b03811115612f8d57612f8d613469565b6040519080825280601f01601f191660200182016040528015612fb7576020820181803683370190505b5093505f86831b5f52602085019050612fd15f8284613295565b5050505092915050565b5f5f5b612fe88484613120565b9350905060ff81161561193a57612ffe826142b5565b9150612fde565b5f5f5f6130128787612aef565b9150915081515f0361304e57846001865161302d91906143e8565b8151811061303d5761303d613e13565b60200260200101519250505061269c565b61306487828761305f886001614777565b613005565b92506001600160a01b0383161561311657604051631ad7b10b60e11b81526001600160a01b038416906335af6216906130a1908590600401613712565b602060405180830381865afa1580156130bc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130e091906143cd565b9250828585815181106130f5576130f5613e13565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050949350505050565b5f5f83518310613145578360405163ba4adc2360e01b81526004016106809190613712565b83838151811061315757613157613e13565b016020015160f81c9150508181016001018161317757835181141561317d565b83518110155b1561319d578360405163ba4adc2360e01b81526004016106809190613712565b9250929050565b6131b7856131b28387614777565b6132f8565b6131c5836131b28385614777565b6131da82602085010185602088010183612d59565b5050505050565b5f6131f3826301ffc9a760e01b613213565b80156104e2575061320c826001600160e01b0319613213565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015612bdb575060208210158015612be6575015159695505050505050565b8181015b808310156105265783516101005b82851080156132b557505f81115b156132eb5760031901600f82821c16600a81106132d557806057016132da565b806030015b9050808653506001909401936132a7565b5050602084019350613299565b81518111156119625781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610680918391600401918252602082015260400190565b6001600160e01b0319811681146116f2575f5ffd5b5f60208284031215613365575f5ffd5b813561269a81613340565b5f5f83601f840112613380575f5ffd5b5081356001600160401b03811115613396575f5ffd5b60208301915083602082850101111561319d575f5ffd5b5f5f5f5f604085870312156133c0575f5ffd5b84356001600160401b038111156133d5575f5ffd5b6133e187828801613370565b90955093505060208501356001600160401b038111156133ff575f5ffd5b61340b87828801613370565b95989497509550505050565b5f5f60208385031215613428575f5ffd5b82356001600160401b0381111561343d575f5ffd5b61344985828601613370565b90969095509350505050565b6001600160a01b03811681146116f2575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b038111828210171561349f5761349f613469565b60405290565b604051608081016001600160401b038111828210171561349f5761349f613469565b60405160c081016001600160401b038111828210171561349f5761349f613469565b604051601f8201601f191681016001600160401b038111828210171561351157613511613469565b604052919050565b5f6001600160401b0382111561353157613531613469565b5060051b60200190565b5f6001600160401b0382111561355357613553613469565b50601f01601f191660200190565b5f82601f830112613570575f5ffd5b8135602083015f6135886135838461353b565b6134e9565b905082815285838301111561359b575f5ffd5b828260208301375f92810160200192909252509392505050565b5f82601f8301126135c4575f5ffd5b81356135d261358382613519565b8082825260208201915060208360051b8601019250858311156135f3575f5ffd5b602085015b838110156136335780356001600160401b03811115613615575f5ffd5b613624886020838a0101613561565b845250602092830192016135f8565b5095945050505050565b5f5f5f5f5f5f60808789031215613652575f5ffd5b863561365d81613455565b955060208701356001600160401b03811115613677575f5ffd5b61368389828a01613370565b90965094505060408701356001600160401b038111156136a1575f5ffd5b6136ad89828a01613370565b90945092505060608701356001600160401b038111156136cb575f5ffd5b6136d789828a016135b5565b9150509295509295509295565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61058c60208301846136e4565b5f5f5f60408486031215613736575f5ffd5b83356001600160401b0381111561374b575f5ffd5b61375786828701613561565b93505060208401356001600160401b03811115613772575f5ffd5b61377e86828701613370565b9497909650939450505050565b606081525f61379d60608301866136e4565b6001600160a01b0394851660208401529290931660409091015292915050565b5f5f5f604084860312156137cf575f5ffd5b83356001600160401b038111156137e4575f5ffd5b6137f086828701613370565b909790965060209590950135949350505050565b5f60208284031215613814575f5ffd5b813561269a81613455565b604081525f61383160408301856136e4565b90506001600160a01b03831660208301529392505050565b5f60208284031215613859575f5ffd5b81356001600160401b0381111561386e575f5ffd5b82016040818503121561387f575f5ffd5b61388761347d565b81356001600160401b0381111561389c575f5ffd5b8201601f810186136138ac575f5ffd5b80356138ba61358382613519565b8082825260208201915060208360051b8501019250888311156138db575f5ffd5b602084015b8381101561399e5780356001600160401b038111156138fd575f5ffd5b85016080818c03601f19011215613912575f5ffd5b61391a6134a5565b602082013561392881613455565b815260408201356001600160401b03811115613942575f5ffd5b6139518d602083860101613561565b60208301525060608201356001600160401b0381111561396f575f5ffd5b61397e8d602083860101613561565b6040830152506080919091013560608201528352602092830192016138e0565b50845250505060208201356001600160401b038111156139bc575f5ffd5b6139c8868285016135b5565b602083015250949350505050565b5f82825180855260208501945060208160051b830101602085015f5b83811015613a2457601f19858403018852613a0e8383516136e4565b60209889019890935091909101906001016139f2565b50909695505050505050565b602081525f6060820183516040602085015281815180845260808601915060808160051b87010193506020830192505f5b81811015613ad757607f1987860301835283516001600160a01b038151168652602081015160806020880152613a9a60808801826136e4565b905060408201518782036040890152613ab382826136e4565b60609384015198909301979097525094506020938401939290920191600101613a61565b505050506020840151838203601f19016040850152613af682826139d6565b95945050505050565b5f5f5f5f5f60608688031215613b13575f5ffd5b85356001600160401b03811115613b28575f5ffd5b613b3488828901613370565b90965094505060208601356001600160401b03811115613b52575f5ffd5b613b5e88828901613370565b90945092505060408601356001600160401b03811115613b7c575f5ffd5b613b88888289016135b5565b9150509295509295909350565b5f60208284031215613ba5575f5ffd5b81356001600160401b03811115613bba575f5ffd5b61269c84828501613561565b5f5f5f5f60608587031215613bd9575f5ffd5b84356001600160401b03811115613bee575f5ffd5b613bfa87828801613370565b9095509350506020850135915060408501356001600160401b03811115613c1f575f5ffd5b613c2b878288016135b5565b91505092959194509250565b602081525f825160a06020840152613c5260c08401826136e4565b905060208401516040840152604084015160608401526001600160a01b0360608501511660808401526080840151151560a08401528091505092915050565b5f5f60408385031215613ca2575f5ffd5b82356001600160401b03811115613cb7575f5ffd5b613cc385828601613561565b92505060208301356001600160401b03811115613cde575f5ffd5b613cea85828601613561565b9150509250929050565b602080825282518282018190525f918401906040840190835b81811015613d345783516001600160a01b0316835260209384019390920191600101613d0d565b509095945050505050565b80151581146116f2575f5ffd5b5f5f5f5f60808587031215613d5f575f5ffd5b8435613d6a81613d3f565b93506020850135613d7a81613d3f565b92506040850135613d8a81613340565b915060608501356001600160401b03811115613da4575f5ffd5b613c2b87828801613561565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015613e0757603f19878603018452613df28583516136e4565b94506020938401939190910190600101613dd6565b50929695505050505050565b634e487b7160e01b5f52603260045260245ffd5b805160208201516001600160e01b0319811691906004821015613e5c576001600160e01b0319808360040360031b1b82161692505b5050919050565b5f82601f830112613e72575f5ffd5b8151602083015f613e856135838461353b565b9050828152858383011115613e98575f5ffd5b8282602083015e5f92810160200192909252509392505050565b5f60208284031215613ec2575f5ffd5b81516001600160401b03811115613ed7575f5ffd5b61269c84828501613e63565b604081525f613ef560408301856136e4565b8281036020840152613af681856136e4565b5f5f5f5f60808587031215613f1a575f5ffd5b8435613f2581613d3f565b93506020850135613d7a81613340565b5f60808284031215613f45575f5ffd5b613f4d6134a5565b905081356001600160401b03811115613f64575f5ffd5b613f7084828501613561565b8252506020828101359082015260408201356001600160401b03811115613f95575f5ffd5b613fa1848285016135b5565b6040830152506060820135613fb581613455565b606082015292915050565b5f60208284031215613fd0575f5ffd5b81356001600160401b03811115613fe5575f5ffd5b61269c84828501613f35565b5f81516080845261400560808501826136e4565b9050602083015160208501526040830151848203604086015261402882826139d6565b9150506001600160a01b0360608401511660608501528091505092915050565b606081525f61405a6060830186613ff1565b828103602084015261406c81866136e4565b9150506001600160a01b0383166040830152949350505050565b5f82601f830112614095575f5ffd5b81516140a361358382613519565b8082825260208201915060208360051b8601019250858311156140c4575f5ffd5b602085015b838110156136335780516001600160401b038111156140e6575f5ffd5b6140f5886020838a0101613e63565b845250602092830192016140c9565b5f60208284031215614114575f5ffd5b81516001600160401b03811115614129575f5ffd5b61269c84828501614086565b5f60208284031215614145575f5ffd5b815161269a81613d3f565b5f5f5f60608486031215614162575f5ffd5b83356001600160401b03811115614177575f5ffd5b61418386828701613f35565b93505060208401356001600160401b0381111561419e575f5ffd5b6141aa86828701613561565b92505060408401356141bb81613455565b809150509250925092565b5f5f604083850312156141d7575f5ffd5b82356001600160401b038111156141ec575f5ffd5b8301601f810185136141fc575f5ffd5b803561420a61358382613519565b8082825260208201915060208360051b85010192508783111561422b575f5ffd5b6020840193505b8284101561425657833561424581613d3f565b825260209384019390910190614232565b945050505060208301356001600160401b03811115614273575f5ffd5b613cea858286016135b5565b5f81518060208401855e5f93019283525090919050565b5f61058c828461427f565b634e487b7160e01b5f52601160045260245ffd5b5f600182016142c6576142c66142a1565b5060010190565b602081525f61058c6020830184613ff1565b80516114ca81613455565b80516114ca81613340565b5f60208284031215614305575f5ffd5b81516001600160401b0381111561431a575f5ffd5b820160c0818503121561432b575f5ffd5b6143336134c7565b61433c826142df565b815261434a602083016142ea565b602082015260408201516001600160401b03811115614367575f5ffd5b61437386828501613e63565b604083015250614385606083016142ea565b6060820152614396608083016142ea565b608082015260a08201516001600160401b038111156143b3575f5ffd5b6143bf86828501613e63565b60a083015250949350505050565b5f602082840312156143dd575f5ffd5b815161269a81613455565b818103818111156104e2576104e26142a1565b5f61269c614409838661427f565b8461427f565b84151581526001600160e01b0319841660208201526001600160e01b031983166040820152608060608201525f61444960808301846136e4565b9695505050505050565b5f60208284031215614463575f5ffd5b81516001600160401b03811115614478575f5ffd5b8201601f81018413614488575f5ffd5b805161449661358382613519565b8082825260208201915060208360051b8501019250868311156144b7575f5ffd5b602084015b8381101561083c5780516001600160401b038111156144d9575f5ffd5b6144e889602083890101613e63565b845250602092830192016144bc565b841515815283151560208201526001600160e01b031983166040820152608060608201525f61444960808301846136e4565b5f614534828561427f565b60f89390931b6001600160f81b03191683525050600101919050565b5f5f60408385031215614561575f5ffd5b825161456c81613455565b60208401519092506001600160401b03811115614587575f5ffd5b613cea85828601613e63565b5f61459e828661427f565b6001600160f81b03198560f81b168152614449600182018561427f565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015613e0757603f1987860301845281516001600160a01b03815116865260208101516060602088015261461a60608801826139d6565b905060408201519150868103604088015261463581836136e4565b9650505060209384019391909101906001016145e1565b6001600160a01b038616815260a060208201525f61466d60a08301876139d6565b828103604084015261467f81876136e4565b90506001600160e01b03198516606084015282810360808401526146a381856136e4565b98975050505050505050565b5f6146ba828861427f565b6001600160f81b0319871681526146d4600182018761427f565b90506001600160f81b0319851681526146a3600182018561427f565b602081526001600160a01b0382511660208201526001600160e01b031960208301511660408201525f604083015160c0606084015261473260e08401826136e4565b90506001600160e01b031960608501511660808401526001600160e01b031960808501511660a084015260a0840151601f198483030160c0850152613af682826136e4565b808201808211156104e2576104e26142a1565b5f5f5f5f5f60a0868803121561479e575f5ffd5b85516147a981613455565b60208701519095506001600160401b038111156147c4575f5ffd5b6147d088828901614086565b94505060408601516001600160401b038111156147eb575f5ffd5b6147f788828901613e63565b935050606086015161480881613340565b60808701519092506001600160401b03811115614823575f5ffd5b613b8888828901613e6356fea2646970667358221220a810213f72c025ed7e2f586fc79d7ac5c267b37d425f63ac8108a9d0c4e037d164736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106101b0575f3560e01c806394fbfa87116100f3578063b536af7611610093578063c92cc49a1161006e578063c92cc49a14610429578063e4f8ce0514610450578063ef46c0b814610463578063f272e2af14610476575f5ffd5b8063b536af76146103e3578063b7d6ca64146103f6578063c285238a14610409575f5ffd5b8063a1472844116100ce578063a147284414610372578063a1cbcbaf14610385578063b363cc73146103bd578063b4a85801146103d0575f5ffd5b806394fbfa871461032c57806397ad3b3b1461033f5780639f28e99d14610352575f5ffd5b80634a3e39941161015e5780635d78a217116101395780635d78a217146102d25780636f3ff726146102e557806383a64339146102f85780639061b9231461030b575f5ffd5b80634a3e39941461027d57806355391bb81461029d578063575de750146102b0575f5ffd5b80634878c6dd1161018e5780634878c6dd1461023057806348ee1bcc14610243578063491fc4f91461026a575f5ffd5b806301ffc9a7146101b457806302cf2578146101dc5780633c6cbda81461021b575b5f5ffd5b6101c76101c2366004613355565b610496565b60405190151581526020015b60405180910390f35b6102037f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101d3565b61022e6102293660046133ad565b6104e8565b005b61020361023e366004613417565b61052c565b6102037f000000000000000000000000000000000000000000000000000000000000000081565b61022e6102783660046133ad565b610593565b61029061028b36600461363d565b610703565b6040516101d39190613712565b61022e6102ab366004613724565b610847565b6102c36102be3660046133ad565b6108ca565b6040516101d39392919061378b565b6102c36102e03660046137bd565b610a2b565b6101c76102f3366004613804565b610ac6565b610290610306366004613804565b610b52565b61031e6103193660046133ad565b610b7e565b6040516101d392919061381f565b6102c361033a3660046133ad565b610c17565b61020361034d366004613417565b610d1f565b610365610360366004613849565b610d7f565b6040516101d39190613a30565b61031e610380366004613aff565b610f40565b610398610393366004613b95565b610ff2565b604080516001600160a01b0390941684526020840192909252908201526060016101d3565b6102036103cb366004613417565b61102e565b61031e6103de3660046133ad565b61108e565b6103656103f13660046133ad565b6110e4565b6102c3610404366004613bc6565b61133e565b61041c610417366004613b95565b611464565b6040516101d39190613c37565b6102037f000000000000000000000000000000000000000000000000000000000000000081565b61020361045e366004613417565b6114cf565b61022e610471366004613c91565b61152f565b610489610484366004613417565b6115b4565b6040516101d39190613cf4565b5f7ff99a5e06000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806104d357506104d382611615565b806104e257506104e282611662565b92915050565b61052684848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061169692505050565b50505050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506116f5915050565b9392505050565b5f6105a084860186613849565b5190505f8080806105b386880188613d4c565b9350935093509350606083156105f3576105cd86866117bb565b6040516020016105dd9190613db0565b60405160208183030381529060405290506106a8565b5f865f8151811061060657610606613e13565b602002602001015190508060400151915060048160600151165f1461062d57815160208301fd5b6060810151600216156106485761064382611696565b610689565b81515f0361068957806020015161065e90613e27565b604051637b1c461b60e01b81526001600160e01b031990911660048201526024015b60405180910390fd5b85156106a657818060200190518101906106a39190613eb2565b91505b505b6106f7308483856040516024016106c0929190613ee3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611941565b50505050505050505050565b606061073e6040518060a00160405280606081526020015f81526020015f81526020015f6001600160a01b031681526020015f151581525090565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250604080516020601f89018190048102820181019092528781526107b29189908990819084018382808284375f9201829052509250611966915050565b60408201526001600160a01b03881660608201526107cf81611997565b61083c8186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516001600160a01b038f16602082015289935063b4a8580160e01b9250015b604051602081830303815290604052611a5f565b509695505050505050565b5f80808061085785870187613f07565b935093509350935086515f0361088c57604051637b1c461b60e01b81526001600160e01b031984166004820152602401610680565b83156108a957868060200190518101906108a69190613eb2565b96505b6108c1308389846040516024016106c0929190613ee3565b50505050505050565b60605f80806108db85870187613fc0565b90506108e987890189613b95565b935083515f03610912576060015160408051602081019091525f80825290945092509050610a21565b5f61091f61041786611dcb565b9050610a1e81603c84602001511461099d5782604001518460200151604051602401610955929190918252602082015260400190565b60408051601f198184030181529190526020810180516001600160e01b03167ff1cb7e06000000000000000000000000000000000000000000000000000000001790526109f8565b82604001516040516024016109b491815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f3b3b57de000000000000000000000000000000000000000000000000000000001790525b84604001516394fbfa8760e01b868a876060015160405160200161082893929190614048565b50505b9450945094915050565b60605f5f610ab78686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663093a86d36040518163ffffffff1660e01b81526004015f60405180830381865afa158015610a90573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104049190810190614104565b92509250925093509350939050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610b2e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e29190614135565b60606104e27f000000000000000000000000000000000000000000000000000000000000000083611f88565b60605f610c0a868686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663093a86d36040518163ffffffff1660e01b81526004015f60405180830381865afa158015610be3573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526103809190810190614104565b9150915094509492505050565b60605f5f610c4d6040518060800160405280606081526020015f8152602001606081526020015f6001600160a01b031681525090565b610c5985870187614150565b60208301519196509450909150606090603b1901610cb7575f610c7e898b018b613804565b6040516bffffffffffffffffffffffff19606083901b166020820152909150603401604051602081830303815290604052915050610cc6565b610cc3888a018a613b95565b90505b8151610cd29082612157565b610d0c5784816040517fef9c03ce000000000000000000000000000000000000000000000000000000008152600401610680929190613ee3565b8160600151925050509450945094915050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920182905250925061217b915050565b60408051808201909152606080825260208201525f5b825151811015610f32575f835f01518281518110610db557610db5613e13565b6020026020010151905060408160600151165f14610dd35750610f2a565b60608101516030165f03610e7d575f610dee825f0151612239565b610df9576010610dfc565b60205b9050825b855151811015610e7a57825f01516001600160a01b0316865f01518281518110610e2c57610e2c613e13565b60200260200101515f01516001600160a01b031603610e725781865f01518281518110610e5b57610e5b613e13565b602002602001015160600181815117915081815250505b600101610e00565b50505b5f60208260600151165f1490505f5f610e9f8315855f0151866020015161226b565b9150915081158015610ec95750630556f18360e41b610ebd82613e27565b6001600160e01b031916145b15610ede576060840180516001179052610f1e565b6060840180516040179052828015610ef557508051155b610f0a5781610f0a5760608401805160021790525b80515f03610f1e5760608401805160081790525b60409093019290925250505b600101610d95565b50610f3c826122fe565b5090565b60605f5f610f8288888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061146492505050565b9050610fe78187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050506060840151604080516001600160a01b039092166020830152889163b4a8580160e01b9101610828565b509550959350505050565b5f5f5f6110207f0000000000000000000000000000000000000000000000000000000000000000855f6124e8565b919790965090945092505050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061265492505050565b60605f858561109f85870187613804565b82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929c939b50929950505050505050505050565b60408051808201909152606080825260208201525f80611106868801886141c6565b91509150805182511461112c5760405163252e18f560e11b815260040160405180910390fd5b61113884860186613849565b92505f5f5b845151811015611308575f855f0151828151811061115d5761115d613e13565b6020026020010151905060408160600151165f036112ff5783518310156112f3575f84848151811061119157611191613e13565b602002602001015190508584815181106111ad576111ad613e13565b6020026020010151156111ca5760608201805160441790526112ed565b5f6111d883604001516126a4565b90505f815f01516001600160a01b03168260600151848460800151604051602401611204929190613ee3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516112429190614296565b5f60405180830381855afa9150503d805f811461127a576040519150601f19603f3d011682016040523d82523d5f602084013e61127f565b606091505b509350905080806112a95750630556f18360e41b61129c84613e27565b6001600160e01b03191614155b156112ea5760608401805160401790528015806112c557508251155b156112d65760608401805160021790525b82515f036112ea5760608401805160081790525b50505b60408201525b6112fc836142b5565b92505b5060010161113d565b508151811461132a5760405163252e18f560e11b815260040160405180910390fd5b611333846122fe565b505050949350505050565b60605f5f5f61138e6104176113898a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c92506126e8915050565b611dcb565b90506114598182604001516040516024016113ab91815260200190565b60405160208183030381529060405263691f343160e01b6020820180516001600160e01b0383818316178352505050508763575de75060e01b60405180608001604052808e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060208082018e905260408083018e905260608a8101516001600160a01b031693019290925290516108289291016142cd565b509450945094915050565b61149d6040518060a00160405280606081526020015f81526020015f81526020015f6001600160a01b031681526020015f151581525090565b6114a682610ff2565b602084015260408301526001600160a01b031660608201528181526114ca81611997565b919050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920182905250925061282d915050565b5f8180602001905181019061154491906142f5565b90506115af815f01518260200151858460400151604051602401611569929190613ee3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a0860151612859565b505050565b606061058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612a1c915050565b5f7f6cd2d09b000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806104e257506301ffc9a760e01b6001600160e01b03198316146104e2565b5f6001600160e01b0319821663379ffb9360e11b14806104e257506301ffc9a760e01b6001600160e01b03198316146104e2565b637b1c461b60e01b6116a782613e27565b6001600160e01b031916036116be57805160208201fd5b806040517f95c0c7520000000000000000000000000000000000000000000000000000000081526004016106809190613712565b50565b5f5f5f6117028585612ac2565b90925090508161171657859250505061058c565b5f6117228787846116f5565b90506001600160a01b038116156117b1575f61173e8787612aef565b50604051631ad7b10b60e11b81529091506001600160a01b038316906335af62169061176e908490600401613712565b602060405180830381865afa158015611789573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117ad91906143cd565b9450505b5050509392505050565b606082516001600160401b038111156117d6576117d6613469565b60405190808252806020026020018201604052801561180957816020015b60608152602001906001900390816117f45790505b5090505f5b835181101561193a575f84828151811061182a5761182a613e13565b60209081029190910101516040810151606082015191925090600e165f0361186e57841561186957808060200190518101906118669190613eb2565b90505b611912565b805115611912578051601f1660048114611910575f6004821061189b576118966004836143e8565b6118a6565b6118a68260046143e8565b6001600160401b038111156118bd576118bd613469565b6040519080825280601f01601f1916602001820160405280156118e7576020820181803683370190505b50905082816040516020016118fd9291906143fb565b6040516020818303038152906040529250505b505b8084848151811061192557611925613e13565b6020908102919091010152505060010161180e565b5092915050565b61196282825f60e01b5f60e01b60405180602001604052805f815250612859565b5050565b5f6119718383612ac2565b9250905080156104e25761058c6119888484611966565b825f9182526020526040902090565b60608101516001600160a01b03166119c5578051604051630ee413fd60e31b81526106809190600401613712565b6119da8160600151639061b92360e01b612b6b565b156119e9576001608082015250565b602081015115611a0f578051604051630ee413fd60e31b81526106809190600401613712565b80606001516001600160a01b03163b5f036116f257805160608201516040517f1e9535f200000000000000000000000000000000000000000000000000000000815261068092919060040161381f565b5f7fac9650d800000000000000000000000000000000000000000000000000000000611a8a86613e27565b6001600160e01b031916149050611aac866060015163582de3e760e01b612b6b565b8015611b535750801580611b53575085608001518015611b535750606086015160405163582de3e760e01b81527f96b62db80000000000000000000000000000000000000000000000000000000060048201526001600160a01b039091169063582de3e790602401602060405180830381865afa158015611b2f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b539190614135565b15611c2957611c2986606001518760800151611b6f5786611bae565b8751604051611b8391908990602401613ee3565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b1790525b60808901517f55391bb800000000000000000000000000000000000000000000000000000000907f3c6cbda80000000000000000000000000000000000000000000000000000000090611c008b613e27565b8989604051602001611c15949392919061440f565b604051602081830303815290604052612859565b60608115611c6357611c49866004808951611c4491906143e8565b612bf1565b806020019051810190611c5c9190614453565b9050611cae565b60408051600180825281830190925290816020015b6060815260200190600190039081611c7857905050905085815f81518110611ca257611ca2613e13565b60200260200101819052505b866080015115611d45575f5b8151811015611d4357875f0151828281518110611cd957611cd9613e13565b6020026020010151604051602401611cf2929190613ee3565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b1790528251839083908110611d3057611d30613e13565b6020908102919091010152600101611cba565b505b6108c130306001600160a01b0316639f28e99d611d678b60600151868b612c45565b604051602401611d779190613a30565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505063491fc4f960e01b5f60e01b8b60800151878a8a604051602001611c1594939291906144f7565b80516060905f819003611df357505060408051808201909152600181525f6020820152919050565b806002016001600160401b03811115611e0e57611e0e613469565b6040519080825280601f01601f191660200182016040528015611e38576020820181803683370190505b509150611e4c602183016020850183612d59565b5f5f5f5b83811015611f0957858181518110611e6a57611e6a613e13565b01602001516001600160f81b031916601760f91b03611f01578281039150815f1480611e96575060ff82115b15611eb65785604051639a4c3e3b60e01b81526004016106809190613712565b8160f81b858481518110611ecc57611ecc613e13565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053508060010192505b600101611e50565b505080820382821480611f1c575060ff81115b15611f3c5784604051639a4c3e3b60e01b81526004016106809190613712565b8060f81b848381518110611f5257611f52613e13565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350505050919050565b60606001600160a01b038216611fac575060408051602081019091525f81526104e2565b826001600160a01b0316826001600160a01b031603611fee57805f604051602001611fd8929190614529565b60405160208183030381529060405290506104e2565b5f5f836001600160a01b03166380f760216040518163ffffffff1660e01b81526004015f60405180830381865afa15801561202b573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526120529190810190614550565b90925090506001600160a01b03821661207d5760405180602001604052805f815250925050506104e2565b604051631ad7b10b60e11b81525f906001600160a01b038416906335af6216906120ab908590600401613712565b602060405180830381865afa1580156120c6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120ea91906143cd565b9050846001600160a01b0316816001600160a01b03161461211e5760405180602001604052805f81525093505050506104e2565b8361212883612da2565b8360405160200161213b93929190614593565b6040516020818303038152906040529350829450505050611fac565b5f8151835114801561058c5750508051602091820120825192909101919091201490565b5f5f61218885858561282d565b90506001600160a01b038116158015906121ae57506121ae816331ab054760e11b612e1c565b15612231575f6121be8585612aef565b506040516331ab054760e11b81529091506001600160a01b038316906363560a8e906121ee908490600401613712565b602060405180830381865afa158015612209573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061222d91906143cd565b9250505b509392505050565b5f306001600160a01b0383160361225257506001919050565b6113885a5f5f5f5f8786fa50815a909103109392505050565b5f6060836001600160a01b0316856122a3577f00000000000000000000000000000000000000000000000000000000000000006122a5565b5a5b846040516122b39190614296565b5f604051808303818686fa925050503d805f81146122ec576040519150601f19603f3d011682016040523d82523d5f602084013e6122f1565b606091505b5090969095509350505050565b8051515f906001600160401b0381111561231a5761231a613469565b60405190808252806020026020018201604052801561237757816020015b61236460405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816123385790505b5090505f5f5b835151811015612428575f845f0151828151811061239d5761239d613e13565b6020026020010151905060408160600151165f0361241f575f6123c382604001516126a4565b90506040518060600160405280825f01516001600160a01b03168152602001826020015181526020018260400151815250858580612400906142b5565b96508151811061241257612412613e13565b6020026020010181905250505b5060010161237d565b5080156115af578082523083602001518360405160240161244991906145bb565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af7600000000000000000000000000000000000000000000000000000000916124bd91899101613a30565b60408051601f1981840301815290829052630556f18360e41b8252610680959493929160040161464c565b5f5f5f5f5f5f6124f88888612ac2565b90925090508161251657508794505f935083925085915061264b9050565b6125218989836124e8565b929850909650945092506001600160a01b0386161561263c575f6125458989612aef565b5090505f876001600160a01b031663e4ae7d77836040518263ffffffff1660e01b81526004016125759190613712565b602060405180830381865afa158015612590573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125b491906143cd565b90506001600160a01b038116156125cc578096508894505b604051631ad7b10b60e11b81526001600160a01b038916906335af6216906125f8908590600401613712565b602060405180830381865afa158015612613573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061263791906143cd565b975050505b505f9283526020526040909120905b93509350935093565b5f5f61266184845f6116f5565b90506001600160a01b038116158015906126905750825160208401206126878583611f88565b80519060200120145b61269a575f61269c565b805b949350505050565b6040805160a0810182525f8082526060602083018190529282018390528282015260808101919091526104e26126e3836004808651611c4491906143e8565b612e37565b606082515f03612724576040517f7138356f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61272d83612ea2565b601760f91b603c8414612790576380000000841461275557612750846001612f0a565b6127c7565b6040518060400160405280600781526020017f64656661756c74000000000000000000000000000000000000000000000000008152506127c7565b6040518060400160405280600481526020017f61646472000000000000000000000000000000000000000000000000000000008152505b601760f91b6040518060400160405280600781526020017f72657665727365000000000000000000000000000000000000000000000000008152506040516020016128169594939291906146af565b604051602081830303815290604052905092915050565b5f5f5f61283a8585612ac2565b909250905081156128505761222d8686836116f5565b50509392505050565b5f5f61286e61286788612239565b888861226b565b91509150811580156128985750630556f18360e41b61288c82613e27565b6001600160e01b031916145b15612946575f6128a7826126a4565b9050876001600160a01b0316815f01516001600160a01b03160361294457308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b0319168152602001898152506040516020016124bd91906146f0565b505b5f826129525784612954565b855b90506001600160e01b0319811615612a0657306001600160a01b0316818386604051602401612984929190613ee3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516129c29190614296565b5f60405180830381855afa9150503d805f81146129fa576040519150601f19603f3d011682016040523d82523d5f602084013e6129ff565b606091505b5090935091505b8215612a1457815160208301f35b815160208301fd5b6060612a288383612fdb565b612a33906001614777565b6001600160401b03811115612a4a57612a4a613469565b604051908082528060200260200182016040528015612a73578160200160208202803683370190505b509050838160018351612a8691906143e8565b81518110612a9657612a96613e13565b60200260200101906001600160a01b031690816001600160a01b0316815250506122318383835f613005565b5f5f5f612acf8585613120565b9250905060ff811615612ae757806021858701012092505b509250929050565b60605f5f612afd8585613120565b925090505f60ff82166001600160401b03811115612b1d57612b1d613469565b6040519080825280601f01601f191660200182016040528015612b47576020820181803683370190505b509050612b606020820160218888010160ff8516612d59565b959194509092505050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f519050828015612bdb575060208210155b8015612be657505f81115b979650505050505050565b6060816001600160401b03811115612c0b57612c0b613469565b6040519080825280601f01601f191660200182016040528015612c35576020820181803683370190505b50905061058c8484835f866131a4565b60408051808201909152606080825260208201525f83516001600160401b03811115612c7357612c73613469565b604051908082528060200260200182016040528015612cd657816020015b612cc360405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b815260200190600190039081612c915790505b5090505f5b8451811015612d3c575f828281518110612cf757612cf7613e13565b60209081029190910101516001600160a01b03881681528651909150869083908110612d2557612d25613e13565b602090810291909101810151910152600101612cdb565b506040805180820190915290815260208101929092525092915050565b5b601f811115612d7a578151835260209283019290910190601f1901612d5a565b80156115af5790518251600160209390930360031b9290921b5f190180199091169116179052565b80515f90808203612ddf576040517fbf9a274000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff8111156104e257826040517fdab6c73c0000000000000000000000000000000000000000000000000000000081526004016106809190613712565b5f612e26836131e1565b801561058c575061058c8383613213565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915281806020019051810190612e74919061478a565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b805160609060011b806001600160401b03811115612ec257612ec2613469565b6040519080825280601f01601f191660200182016040528015612eec576020820181803683370190505b5091506020838101908301612f02828285613295565b505050919050565b6060825f60805b60088110612f42576001811b831015612f3557612f2e8183614777565b9150612f3a565b91821c915b60011c612f11565b50838015612f505750601082105b15612f6357612f60600482614777565b90505b5f612f73600283901c60406143e8565b9050806001600160401b03811115612f8d57612f8d613469565b6040519080825280601f01601f191660200182016040528015612fb7576020820181803683370190505b5093505f86831b5f52602085019050612fd15f8284613295565b5050505092915050565b5f5f5b612fe88484613120565b9350905060ff81161561193a57612ffe826142b5565b9150612fde565b5f5f5f6130128787612aef565b9150915081515f0361304e57846001865161302d91906143e8565b8151811061303d5761303d613e13565b60200260200101519250505061269c565b61306487828761305f886001614777565b613005565b92506001600160a01b0383161561311657604051631ad7b10b60e11b81526001600160a01b038416906335af6216906130a1908590600401613712565b602060405180830381865afa1580156130bc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130e091906143cd565b9250828585815181106130f5576130f5613e13565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050949350505050565b5f5f83518310613145578360405163ba4adc2360e01b81526004016106809190613712565b83838151811061315757613157613e13565b016020015160f81c9150508181016001018161317757835181141561317d565b83518110155b1561319d578360405163ba4adc2360e01b81526004016106809190613712565b9250929050565b6131b7856131b28387614777565b6132f8565b6131c5836131b28385614777565b6131da82602085010185602088010183612d59565b5050505050565b5f6131f3826301ffc9a760e01b613213565b80156104e2575061320c826001600160e01b0319613213565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015612bdb575060208210158015612be6575015159695505050505050565b8181015b808310156105265783516101005b82851080156132b557505f81115b156132eb5760031901600f82821c16600a81106132d557806057016132da565b806030015b9050808653506001909401936132a7565b5050602084019350613299565b81518111156119625781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610680918391600401918252602082015260400190565b6001600160e01b0319811681146116f2575f5ffd5b5f60208284031215613365575f5ffd5b813561269a81613340565b5f5f83601f840112613380575f5ffd5b5081356001600160401b03811115613396575f5ffd5b60208301915083602082850101111561319d575f5ffd5b5f5f5f5f604085870312156133c0575f5ffd5b84356001600160401b038111156133d5575f5ffd5b6133e187828801613370565b90955093505060208501356001600160401b038111156133ff575f5ffd5b61340b87828801613370565b95989497509550505050565b5f5f60208385031215613428575f5ffd5b82356001600160401b0381111561343d575f5ffd5b61344985828601613370565b90969095509350505050565b6001600160a01b03811681146116f2575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b038111828210171561349f5761349f613469565b60405290565b604051608081016001600160401b038111828210171561349f5761349f613469565b60405160c081016001600160401b038111828210171561349f5761349f613469565b604051601f8201601f191681016001600160401b038111828210171561351157613511613469565b604052919050565b5f6001600160401b0382111561353157613531613469565b5060051b60200190565b5f6001600160401b0382111561355357613553613469565b50601f01601f191660200190565b5f82601f830112613570575f5ffd5b8135602083015f6135886135838461353b565b6134e9565b905082815285838301111561359b575f5ffd5b828260208301375f92810160200192909252509392505050565b5f82601f8301126135c4575f5ffd5b81356135d261358382613519565b8082825260208201915060208360051b8601019250858311156135f3575f5ffd5b602085015b838110156136335780356001600160401b03811115613615575f5ffd5b613624886020838a0101613561565b845250602092830192016135f8565b5095945050505050565b5f5f5f5f5f5f60808789031215613652575f5ffd5b863561365d81613455565b955060208701356001600160401b03811115613677575f5ffd5b61368389828a01613370565b90965094505060408701356001600160401b038111156136a1575f5ffd5b6136ad89828a01613370565b90945092505060608701356001600160401b038111156136cb575f5ffd5b6136d789828a016135b5565b9150509295509295509295565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61058c60208301846136e4565b5f5f5f60408486031215613736575f5ffd5b83356001600160401b0381111561374b575f5ffd5b61375786828701613561565b93505060208401356001600160401b03811115613772575f5ffd5b61377e86828701613370565b9497909650939450505050565b606081525f61379d60608301866136e4565b6001600160a01b0394851660208401529290931660409091015292915050565b5f5f5f604084860312156137cf575f5ffd5b83356001600160401b038111156137e4575f5ffd5b6137f086828701613370565b909790965060209590950135949350505050565b5f60208284031215613814575f5ffd5b813561269a81613455565b604081525f61383160408301856136e4565b90506001600160a01b03831660208301529392505050565b5f60208284031215613859575f5ffd5b81356001600160401b0381111561386e575f5ffd5b82016040818503121561387f575f5ffd5b61388761347d565b81356001600160401b0381111561389c575f5ffd5b8201601f810186136138ac575f5ffd5b80356138ba61358382613519565b8082825260208201915060208360051b8501019250888311156138db575f5ffd5b602084015b8381101561399e5780356001600160401b038111156138fd575f5ffd5b85016080818c03601f19011215613912575f5ffd5b61391a6134a5565b602082013561392881613455565b815260408201356001600160401b03811115613942575f5ffd5b6139518d602083860101613561565b60208301525060608201356001600160401b0381111561396f575f5ffd5b61397e8d602083860101613561565b6040830152506080919091013560608201528352602092830192016138e0565b50845250505060208201356001600160401b038111156139bc575f5ffd5b6139c8868285016135b5565b602083015250949350505050565b5f82825180855260208501945060208160051b830101602085015f5b83811015613a2457601f19858403018852613a0e8383516136e4565b60209889019890935091909101906001016139f2565b50909695505050505050565b602081525f6060820183516040602085015281815180845260808601915060808160051b87010193506020830192505f5b81811015613ad757607f1987860301835283516001600160a01b038151168652602081015160806020880152613a9a60808801826136e4565b905060408201518782036040890152613ab382826136e4565b60609384015198909301979097525094506020938401939290920191600101613a61565b505050506020840151838203601f19016040850152613af682826139d6565b95945050505050565b5f5f5f5f5f60608688031215613b13575f5ffd5b85356001600160401b03811115613b28575f5ffd5b613b3488828901613370565b90965094505060208601356001600160401b03811115613b52575f5ffd5b613b5e88828901613370565b90945092505060408601356001600160401b03811115613b7c575f5ffd5b613b88888289016135b5565b9150509295509295909350565b5f60208284031215613ba5575f5ffd5b81356001600160401b03811115613bba575f5ffd5b61269c84828501613561565b5f5f5f5f60608587031215613bd9575f5ffd5b84356001600160401b03811115613bee575f5ffd5b613bfa87828801613370565b9095509350506020850135915060408501356001600160401b03811115613c1f575f5ffd5b613c2b878288016135b5565b91505092959194509250565b602081525f825160a06020840152613c5260c08401826136e4565b905060208401516040840152604084015160608401526001600160a01b0360608501511660808401526080840151151560a08401528091505092915050565b5f5f60408385031215613ca2575f5ffd5b82356001600160401b03811115613cb7575f5ffd5b613cc385828601613561565b92505060208301356001600160401b03811115613cde575f5ffd5b613cea85828601613561565b9150509250929050565b602080825282518282018190525f918401906040840190835b81811015613d345783516001600160a01b0316835260209384019390920191600101613d0d565b509095945050505050565b80151581146116f2575f5ffd5b5f5f5f5f60808587031215613d5f575f5ffd5b8435613d6a81613d3f565b93506020850135613d7a81613d3f565b92506040850135613d8a81613340565b915060608501356001600160401b03811115613da4575f5ffd5b613c2b87828801613561565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015613e0757603f19878603018452613df28583516136e4565b94506020938401939190910190600101613dd6565b50929695505050505050565b634e487b7160e01b5f52603260045260245ffd5b805160208201516001600160e01b0319811691906004821015613e5c576001600160e01b0319808360040360031b1b82161692505b5050919050565b5f82601f830112613e72575f5ffd5b8151602083015f613e856135838461353b565b9050828152858383011115613e98575f5ffd5b8282602083015e5f92810160200192909252509392505050565b5f60208284031215613ec2575f5ffd5b81516001600160401b03811115613ed7575f5ffd5b61269c84828501613e63565b604081525f613ef560408301856136e4565b8281036020840152613af681856136e4565b5f5f5f5f60808587031215613f1a575f5ffd5b8435613f2581613d3f565b93506020850135613d7a81613340565b5f60808284031215613f45575f5ffd5b613f4d6134a5565b905081356001600160401b03811115613f64575f5ffd5b613f7084828501613561565b8252506020828101359082015260408201356001600160401b03811115613f95575f5ffd5b613fa1848285016135b5565b6040830152506060820135613fb581613455565b606082015292915050565b5f60208284031215613fd0575f5ffd5b81356001600160401b03811115613fe5575f5ffd5b61269c84828501613f35565b5f81516080845261400560808501826136e4565b9050602083015160208501526040830151848203604086015261402882826139d6565b9150506001600160a01b0360608401511660608501528091505092915050565b606081525f61405a6060830186613ff1565b828103602084015261406c81866136e4565b9150506001600160a01b0383166040830152949350505050565b5f82601f830112614095575f5ffd5b81516140a361358382613519565b8082825260208201915060208360051b8601019250858311156140c4575f5ffd5b602085015b838110156136335780516001600160401b038111156140e6575f5ffd5b6140f5886020838a0101613e63565b845250602092830192016140c9565b5f60208284031215614114575f5ffd5b81516001600160401b03811115614129575f5ffd5b61269c84828501614086565b5f60208284031215614145575f5ffd5b815161269a81613d3f565b5f5f5f60608486031215614162575f5ffd5b83356001600160401b03811115614177575f5ffd5b61418386828701613f35565b93505060208401356001600160401b0381111561419e575f5ffd5b6141aa86828701613561565b92505060408401356141bb81613455565b809150509250925092565b5f5f604083850312156141d7575f5ffd5b82356001600160401b038111156141ec575f5ffd5b8301601f810185136141fc575f5ffd5b803561420a61358382613519565b8082825260208201915060208360051b85010192508783111561422b575f5ffd5b6020840193505b8284101561425657833561424581613d3f565b825260209384019390910190614232565b945050505060208301356001600160401b03811115614273575f5ffd5b613cea858286016135b5565b5f81518060208401855e5f93019283525090919050565b5f61058c828461427f565b634e487b7160e01b5f52601160045260245ffd5b5f600182016142c6576142c66142a1565b5060010190565b602081525f61058c6020830184613ff1565b80516114ca81613455565b80516114ca81613340565b5f60208284031215614305575f5ffd5b81516001600160401b0381111561431a575f5ffd5b820160c0818503121561432b575f5ffd5b6143336134c7565b61433c826142df565b815261434a602083016142ea565b602082015260408201516001600160401b03811115614367575f5ffd5b61437386828501613e63565b604083015250614385606083016142ea565b6060820152614396608083016142ea565b608082015260a08201516001600160401b038111156143b3575f5ffd5b6143bf86828501613e63565b60a083015250949350505050565b5f602082840312156143dd575f5ffd5b815161269a81613455565b818103818111156104e2576104e26142a1565b5f61269c614409838661427f565b8461427f565b84151581526001600160e01b0319841660208201526001600160e01b031983166040820152608060608201525f61444960808301846136e4565b9695505050505050565b5f60208284031215614463575f5ffd5b81516001600160401b03811115614478575f5ffd5b8201601f81018413614488575f5ffd5b805161449661358382613519565b8082825260208201915060208360051b8501019250868311156144b7575f5ffd5b602084015b8381101561083c5780516001600160401b038111156144d9575f5ffd5b6144e889602083890101613e63565b845250602092830192016144bc565b841515815283151560208201526001600160e01b031983166040820152608060608201525f61444960808301846136e4565b5f614534828561427f565b60f89390931b6001600160f81b03191683525050600101919050565b5f5f60408385031215614561575f5ffd5b825161456c81613455565b60208401519092506001600160401b03811115614587575f5ffd5b613cea85828601613e63565b5f61459e828661427f565b6001600160f81b03198560f81b168152614449600182018561427f565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015613e0757603f1987860301845281516001600160a01b03815116865260208101516060602088015261461a60608801826139d6565b905060408201519150868103604088015261463581836136e4565b9650505060209384019391909101906001016145e1565b6001600160a01b038616815260a060208201525f61466d60a08301876139d6565b828103604084015261467f81876136e4565b90506001600160e01b03198516606084015282810360808401526146a381856136e4565b98975050505050505050565b5f6146ba828861427f565b6001600160f81b0319871681526146d4600182018761427f565b90506001600160f81b0319851681526146a3600182018561427f565b602081526001600160a01b0382511660208201526001600160e01b031960208301511660408201525f604083015160c0606084015261473260e08401826136e4565b90506001600160e01b031960608501511660808401526001600160e01b031960808501511660a084015260a0840151601f198483030160c0850152613af682826136e4565b808201808211156104e2576104e26142a1565b5f5f5f5f5f60a0868803121561479e575f5ffd5b85516147a981613455565b60208701519095506001600160401b038111156147c4575f5ffd5b6147d088828901614086565b94505060408601516001600160401b038111156147eb575f5ffd5b6147f788828901613e63565b935050606086015161480881613340565b60808701519092506001600160401b03811115614823575f5ffd5b613b8888828901613e6356fea2646970667358221220a810213f72c025ed7e2f586fc79d7ac5c267b37d425f63ac8108a9d0c4e037d164736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "1210": [ + { + "length": 32, + "start": 8831 + } + ], + "17763": [ + { + "length": 32, + "start": 481 + }, + { + "length": 32, + "start": 2615 + }, + { + "length": 32, + "start": 2954 + } + ], + "73954": [ + { + "length": 32, + "start": 1070 + }, + { + "length": 32, + "start": 1330 + }, + { + "length": 32, + "start": 2905 + }, + { + "length": 32, + "start": 3365 + }, + { + "length": 32, + "start": 4090 + }, + { + "length": 32, + "start": 4148 + }, + { + "length": 32, + "start": 5333 + }, + { + "length": 32, + "start": 5563 + } + ], + "75212": [ + { + "length": 32, + "start": 584 + }, + { + "length": 32, + "start": 2791 + } + ] + }, + "inputSourceName": "project/src/universalResolver/UniversalResolverV2.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "DNSEncodingFailed(string)": [ + { + "details": "A label of the ENS name has an invalid size. Error selector: `0x9a4c3e3b`" + } + ], + "EmptyAddress()": [ + { + "details": "The supplied address was `0x`. Error selector: `0x7138356f`" + } + ], + "HttpError(uint16,string)": [ + { + "details": "Error selector: `0x01800152`" + } + ], + "InvalidBatchGatewayResponse()": [ + { + "details": "Error selector: `0x4a5c31ea`" + } + ], + "LabelIsEmpty()": [ + { + "details": "The label was empty. Error selector: `0xbf9a2740`" + } + ], + "LabelIsTooLong(string)": [ + { + "details": "The label was more than 255 bytes. Error selector: `0xdab6c73c`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "ResolverError(bytes)": [ + { + "details": "Error selector: `0x95c0c752`" + } + ], + "ResolverNotContract(bytes,address)": [ + { + "details": "Error selector: `0x1e9535f2`" + } + ], + "ResolverNotFound(bytes)": [ + { + "details": "Error selector: `0x77209fe8`" + } + ], + "ReverseAddressMismatch(string,bytes)": [ + { + "details": "Error selector: `0xef9c03ce`" + } + ], + "UnsupportedResolverProfile(bytes4)": [ + { + "details": "Error selector: `0x7b1c461b`" + } + ] + }, + "kind": "dev", + "methods": { + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": { + "details": "Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`." + }, + "ccipBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \"done\".", + "params": { + "extraData": "The contextual data passed from `ccipBatch()`.", + "response": "The response from the batch gateway." + }, + "returns": { + "batch": "The batch where every lookup is \"done\"." + } + }, + "ccipReadCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.", + "params": { + "extraData": "The contextual data passed from `ccipRead()`.", + "response": "The response from offchain." + } + }, + "constructor": { + "params": { + "batchGatewayProvider": "The batch gateway provider.", + "contractNamer": "Delegated contract namer.", + "rootRegistry": "The root registry." + } + }, + "findCanonicalName(address)": { + "params": { + "registry": "The registry to name." + }, + "returns": { + "_0": "The DNS-encoded name or empty if not canonical." + } + }, + "findCanonicalRegistry(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The canonical registry or null if not canonical." + } + }, + "findExactRegistry(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The registry or null if not found." + } + }, + "findOwner(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The owner address or null if unowned or not found." + } + }, + "findParentRegistry(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The parent registry or null if not found." + } + }, + "findRegistries(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "Array of registries in label-order." + } + }, + "findResolver(bytes)": { + "params": { + "name": "The name to search." + }, + "returns": { + "node": "The namehash of `name`.", + "offset": "The offset into `name` corresponding to `resolver`.", + "resolver": "The found resolver, or null if not found." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "requireResolver(bytes)": { + "details": "Returns a valid resolver for `name` or reverts.", + "params": { + "name": "The name to search." + }, + "returns": { + "info": "The resolver information." + } + }, + "resolveBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `_callResolver()` from calling the batch gateway successfully." + }, + "resolveCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `resolveWithGateways()`.", + "params": { + "extraData": "The contextual data passed from `resolveWith*()`.", + "response": "The response from the resolver." + } + }, + "resolveDirectCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `_callResolver()` from calling the resolver successfully." + }, + "resolveDirectCallbackError(bytes,bytes)": { + "details": "CCIP-Read callback for `_callResolver()` from calling the resolver unsuccessfully." + }, + "resolveWithGateways(bytes,bytes,string[])": { + "details": "This function executes over multiple steps.", + "params": { + "data": "The ABI-encoded resolver calldata.", + "gateways": "The list of batch gateway URLs to use.", + "name": "The DNS-encoded name to resolve." + }, + "returns": { + "resolver": "The resolver that was used to resolve the name.", + "result": "The ABI-encoded response for the calldata." + } + }, + "reverseAddressCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `reverseNameCallback()`. Reverts `ReverseAddressMismatch`.", + "params": { + "extraData": "The contextual data passed from `reverseNameCallback()`.", + "response": "The abi-encoded `addr()` response from the forward resolver." + } + }, + "reverseNameCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `reverseWithGateways()`.", + "params": { + "extraData": "The contextual data passed from `reverseWithGateways()`.", + "response": "The abi-encoded `name()` response from the reverse resolver." + } + }, + "reverseWithGateways(bytes,uint256,string[])": { + "details": "This function executes over multiple steps.", + "params": { + "coinType": "The coin type.", + "gateways": "The list of batch gateway URLs to use.", + "lookupAddress": "The input address." + }, + "returns": { + "primary": "The resolved primary name.", + "resolver": "The resolver address for primary name.", + "reverseResolver": "The resolver address for the reverse name." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "3706600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "ROOT_REGISTRY()": "infinite", + "batchGatewayProvider()": "infinite", + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": "infinite", + "ccipBatchCallback(bytes,bytes)": "infinite", + "ccipReadCallback(bytes,bytes)": "infinite", + "findCanonicalName(address)": "infinite", + "findCanonicalRegistry(bytes)": "infinite", + "findExactRegistry(bytes)": "infinite", + "findOwner(bytes)": "infinite", + "findParentRegistry(bytes)": "infinite", + "findRegistries(bytes)": "infinite", + "findResolver(bytes)": "infinite", + "isContractNamer(address)": "infinite", + "requireResolver(bytes)": "infinite", + "resolve(bytes,bytes)": "infinite", + "resolveBatchCallback(bytes,bytes)": "infinite", + "resolveCallback(bytes,bytes)": "infinite", + "resolveDirectCallback(bytes,bytes)": "infinite", + "resolveDirectCallbackError(bytes,bytes)": "infinite", + "resolveWithGateways(bytes,bytes,string[])": "infinite", + "resolveWithResolver(address,bytes,bytes,string[])": "infinite", + "reverse(bytes,uint256)": "infinite", + "reverseAddressCallback(bytes,bytes)": "infinite", + "reverseNameCallback(bytes,bytes)": "infinite", + "reverseWithGateways(bytes,uint256,string[])": "infinite", + "supportsInterface(bytes4)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"rootRegistry\",\"type\":\"address\"},{\"internalType\":\"contract IGatewayProvider\",\"name\":\"batchGatewayProvider\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"ens\",\"type\":\"string\"}],\"name\":\"DNSEncodingFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"status\",\"type\":\"uint16\"},{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"HttpError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBatchGatewayResponse\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LabelIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelIsTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorData\",\"type\":\"bytes\"}],\"name\":\"ResolverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"ResolverNotContract\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"ResolverNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"primaryAddress\",\"type\":\"bytes\"}],\"name\":\"ReverseAddressMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"selector\",\"type\":\"bytes4\"}],\"name\":\"UnsupportedResolverProfile\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batchGatewayProvider\",\"outputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"name\":\"ccipBatch\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipBatchCallback\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipReadCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"findCanonicalName\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findCanonicalRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findExactRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findParentRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findRegistries\",\"outputs\":[{\"internalType\":\"contract IRegistry[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"requireResolver\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"extended\",\"type\":\"bool\"}],\"internalType\":\"struct AbstractUniversalResolver.ResolverInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveBatchCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveDirectCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"resolveDirectCallbackError\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"name\":\"resolveWithGateways\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"name\":\"resolveWithResolver\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"lookupAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"reverse\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"reverseAddressCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"reverseResolver\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"reverseNameCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"lookupAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"name\":\"reverseWithGateways\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"reverseResolver\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"DNSEncodingFailed(string)\":[{\"details\":\"A label of the ENS name has an invalid size. Error selector: `0x9a4c3e3b`\"}],\"EmptyAddress()\":[{\"details\":\"The supplied address was `0x`. Error selector: `0x7138356f`\"}],\"HttpError(uint16,string)\":[{\"details\":\"Error selector: `0x01800152`\"}],\"InvalidBatchGatewayResponse()\":[{\"details\":\"Error selector: `0x4a5c31ea`\"}],\"LabelIsEmpty()\":[{\"details\":\"The label was empty. Error selector: `0xbf9a2740`\"}],\"LabelIsTooLong(string)\":[{\"details\":\"The label was more than 255 bytes. Error selector: `0xdab6c73c`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"ResolverError(bytes)\":[{\"details\":\"Error selector: `0x95c0c752`\"}],\"ResolverNotContract(bytes,address)\":[{\"details\":\"Error selector: `0x1e9535f2`\"}],\"ResolverNotFound(bytes)\":[{\"details\":\"Error selector: `0x77209fe8`\"}],\"ReverseAddressMismatch(string,bytes)\":[{\"details\":\"Error selector: `0xef9c03ce`\"}],\"UnsupportedResolverProfile(bytes4)\":[{\"details\":\"Error selector: `0x7b1c461b`\"}]},\"kind\":\"dev\",\"methods\":{\"ccipBatch(((address,bytes,bytes,uint256)[],string[]))\":{\"details\":\"Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`.\"},\"ccipBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\",\"params\":{\"extraData\":\"The contextual data passed from `ccipBatch()`.\",\"response\":\"The response from the batch gateway.\"},\"returns\":{\"batch\":\"The batch where every lookup is \\\"done\\\".\"}},\"ccipReadCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.\",\"params\":{\"extraData\":\"The contextual data passed from `ccipRead()`.\",\"response\":\"The response from offchain.\"}},\"constructor\":{\"params\":{\"batchGatewayProvider\":\"The batch gateway provider.\",\"contractNamer\":\"Delegated contract namer.\",\"rootRegistry\":\"The root registry.\"}},\"findCanonicalName(address)\":{\"params\":{\"registry\":\"The registry to name.\"},\"returns\":{\"_0\":\"The DNS-encoded name or empty if not canonical.\"}},\"findCanonicalRegistry(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The canonical registry or null if not canonical.\"}},\"findExactRegistry(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The registry or null if not found.\"}},\"findOwner(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The owner address or null if unowned or not found.\"}},\"findParentRegistry(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The parent registry or null if not found.\"}},\"findRegistries(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"Array of registries in label-order.\"}},\"findResolver(bytes)\":{\"params\":{\"name\":\"The name to search.\"},\"returns\":{\"node\":\"The namehash of `name`.\",\"offset\":\"The offset into `name` corresponding to `resolver`.\",\"resolver\":\"The found resolver, or null if not found.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"requireResolver(bytes)\":{\"details\":\"Returns a valid resolver for `name` or reverts.\",\"params\":{\"name\":\"The name to search.\"},\"returns\":{\"info\":\"The resolver information.\"}},\"resolveBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `_callResolver()` from calling the batch gateway successfully.\"},\"resolveCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `resolveWithGateways()`.\",\"params\":{\"extraData\":\"The contextual data passed from `resolveWith*()`.\",\"response\":\"The response from the resolver.\"}},\"resolveDirectCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `_callResolver()` from calling the resolver successfully.\"},\"resolveDirectCallbackError(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `_callResolver()` from calling the resolver unsuccessfully.\"},\"resolveWithGateways(bytes,bytes,string[])\":{\"details\":\"This function executes over multiple steps.\",\"params\":{\"data\":\"The ABI-encoded resolver calldata.\",\"gateways\":\"The list of batch gateway URLs to use.\",\"name\":\"The DNS-encoded name to resolve.\"},\"returns\":{\"resolver\":\"The resolver that was used to resolve the name.\",\"result\":\"The ABI-encoded response for the calldata.\"}},\"reverseAddressCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `reverseNameCallback()`. Reverts `ReverseAddressMismatch`.\",\"params\":{\"extraData\":\"The contextual data passed from `reverseNameCallback()`.\",\"response\":\"The abi-encoded `addr()` response from the forward resolver.\"}},\"reverseNameCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `reverseWithGateways()`.\",\"params\":{\"extraData\":\"The contextual data passed from `reverseWithGateways()`.\",\"response\":\"The abi-encoded `name()` response from the reverse resolver.\"}},\"reverseWithGateways(bytes,uint256,string[])\":{\"details\":\"This function executes over multiple steps.\",\"params\":{\"coinType\":\"The coin type.\",\"gateways\":\"The list of batch gateway URLs to use.\",\"lookupAddress\":\"The input address.\"},\"returns\":{\"primary\":\"The resolved primary name.\",\"resolver\":\"The resolver address for primary name.\",\"reverseResolver\":\"The resolver address for the reverse name.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"HttpError(uint16,string)\":[{\"notice\":\"An HTTP error occurred on a resolving gateway.\"}],\"InvalidBatchGatewayResponse()\":[{\"notice\":\"The batch gateway supplied an incorrect number of responses.\"}],\"ResolverError(bytes)\":[{\"notice\":\"The resolver returned an error.\"}],\"ResolverNotContract(bytes,address)\":[{\"notice\":\"The resolver is not a contract.\"}],\"ResolverNotFound(bytes)\":[{\"notice\":\"A resolver could not be found for the supplied name.\"}],\"ReverseAddressMismatch(string,bytes)\":[{\"notice\":\"The resolved address from reverse resolution does not match the supplied address.\"}],\"UnsupportedResolverProfile(bytes4)\":[{\"notice\":\"The resolver did not respond.\"}]},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"ROOT_REGISTRY()\":{\"notice\":\"The ENSv2 root registry.\"},\"findCanonicalName(address)\":{\"notice\":\"Construct the canonical name for `registry`.\"},\"findCanonicalRegistry(bytes)\":{\"notice\":\"Find the canonical registry for `name`.\"},\"findExactRegistry(bytes)\":{\"notice\":\"Find the exact registry for `name`.\"},\"findOwner(bytes)\":{\"notice\":\"Find the owner for `name`.\"},\"findParentRegistry(bytes)\":{\"notice\":\"Find the parent registry for `name`.\"},\"findRegistries(bytes)\":{\"notice\":\"Find all registries in the ancestry of `name`. * `findRegistries(\\\"\\\") = []` * `findRegistries(\\\"eth\\\") = [, ]` * `findRegistries(\\\"nick.eth\\\") = [, , ]` * `findRegistries(\\\"sub.nick.eth\\\") = [null, , , ]`\"},\"findResolver(bytes)\":{\"notice\":\"Find the resolver address for `name`. Does not perform any validity checks on the resolver.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"resolve(bytes,bytes)\":{\"notice\":\"Same as `resolveWithGateways()` but uses default batch gateways.\"},\"resolveWithGateways(bytes,bytes,string[])\":{\"notice\":\"Performs ENS forward resolution for the supplied name and data. Caller should enable EIP-3668.\"},\"resolveWithResolver(address,bytes,bytes,string[])\":{\"notice\":\"Same as `resolveWithGateways()` but uses the supplied resolver.\"},\"reverse(bytes,uint256)\":{\"notice\":\"Same as `reverseWithGateways()` but uses default batch gateways.\"},\"reverseWithGateways(bytes,uint256,string[])\":{\"notice\":\"Performs ENS reverse resolution for the supplied address and coin type. Caller should enable EIP-3668.\"}},\"notice\":\"Universal Resolver that traverses the namechain registry hierarchy to locate resolvers and registries for any DNS-encoded name.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/universalResolver/UniversalResolverV2.sol\":\"UniversalResolverV2\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/CCIPBatcher.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {IBatchGateway} from \\\"./IBatchGateway.sol\\\";\\nimport {CCIPReader, EIP3668, OffchainLookup} from \\\"./CCIPReader.sol\\\";\\n\\n/// @dev CCIP-Read batch gateway client implementation.\\n///\\n/// Since requests are read-only, empty responses are considered an error.\\n///\\n/// Usage: `ccipRead(address(this), abi.encodeCall(this.ccipBatch, (createBatch(...))), ...)`\\n///\\nabstract contract CCIPBatcher is CCIPReader {\\n /// @notice The batch gateway supplied an incorrect number of responses.\\n /// @dev Error selector: `0x4a5c31ea`\\n error InvalidBatchGatewayResponse();\\n\\n uint256 constant FLAG_OFFCHAIN = 1 << 0; // the lookup reverted `OffchainLookup`\\n uint256 constant FLAG_CALL_ERROR = 1 << 1; // the initial call or callback reverted\\n uint256 constant FLAG_BATCH_ERROR = 1 << 2; // `OffchainLookup` failed on the batch gateway\\n uint256 constant FLAG_EMPTY_RESPONSE = 1 << 3; // the initial call or callback returned `0x`\\n uint256 constant FLAG_EIP140_BEFORE = 1 << 4; // does not have revert op code\\n uint256 constant FLAG_EIP140_AFTER = 1 << 5; // has revert op code\\n uint256 constant FLAG_DONE = 1 << 6; // the lookup has finished processing (private)\\n\\n uint256 constant FLAGS_ANY_ERROR =\\n FLAG_CALL_ERROR | FLAG_BATCH_ERROR | FLAG_EMPTY_RESPONSE;\\n uint256 constant FLAGS_ANY_EIP140 = FLAG_EIP140_BEFORE | FLAG_EIP140_AFTER;\\n\\n /// @dev An independent `OffchainLookup` session.\\n struct Lookup {\\n address target; // contract to call\\n bytes call; // initial calldata\\n bytes data; // response or error\\n uint256 flags; // see: FLAG_*\\n }\\n\\n /// @dev A batch gateway session.\\n struct Batch {\\n Lookup[] lookups;\\n string[] gateways;\\n }\\n\\n /// @dev Create a batch for a single target with multiple calls.\\n /// @param target The target contract.\\n /// @param calls The list of calldata.\\n /// @param gateways The batch gateway URLs.\\n function createBatch(\\n address target,\\n bytes[] memory calls,\\n string[] memory gateways\\n ) internal pure returns (Batch memory) {\\n Lookup[] memory lookups = new Lookup[](calls.length);\\n for (uint256 i; i < calls.length; ++i) {\\n Lookup memory lu = lookups[i];\\n lu.target = target;\\n lu.call = calls[i];\\n }\\n return Batch(lookups, gateways);\\n }\\n\\n /// @dev Use `ccipRead()` to call this function with a batch.\\n /// The callback response will be `abi.encode(batch)`.\\n function ccipBatch(\\n Batch memory batch\\n ) external view returns (Batch memory) {\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) != 0) {\\n continue; // don't call a lookup that's already done\\n }\\n if ((lu.flags & FLAGS_ANY_EIP140) == 0) {\\n uint256 flags = detectEIP140(lu.target)\\n ? FLAG_EIP140_AFTER\\n : FLAG_EIP140_BEFORE;\\n for (uint256 j = i; j < batch.lookups.length; ++j) {\\n if (batch.lookups[j].target == lu.target) {\\n batch.lookups[j].flags |= flags;\\n }\\n }\\n }\\n bool unsafe = (lu.flags & FLAG_EIP140_AFTER) == 0;\\n (bool ok, bytes memory v) = safeCall(!unsafe, lu.target, lu.call);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n lu.flags |= FLAG_OFFCHAIN;\\n } else {\\n lu.flags |= FLAG_DONE;\\n if (unsafe && v.length == 0) {\\n // unsafe contracts appear the same for throw and unimplemented fallback\\n // decision: interpret like an unimplemented function selector response\\n } else if (!ok) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n lu.data = v;\\n }\\n _revertBatchGateway(batch); // reverts if any offchain\\n return batch;\\n }\\n\\n /// @dev Check if the batch is \\\"done\\\". If not, revert `OffchainLookup` for batch gateway.\\n function _revertBatchGateway(Batch memory batch) internal view {\\n IBatchGateway.Request[] memory requests = new IBatchGateway.Request[](\\n batch.lookups.length\\n );\\n uint256 count;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n requests[count++] = IBatchGateway.Request(\\n p.sender,\\n p.urls,\\n p.callData\\n );\\n }\\n }\\n if (count > 0) {\\n assembly {\\n mstore(requests, count) // truncate to number of offchain requests\\n }\\n revert OffchainLookup(\\n address(this),\\n batch.gateways,\\n abi.encodeCall(IBatchGateway.query, (requests)),\\n this.ccipBatchCallback.selector,\\n abi.encode(batch)\\n );\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipBatch()`.\\n /// Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\\n /// @param response The response from the batch gateway.\\n /// @param extraData The contextual data passed from `ccipBatch()`.\\n /// @return batch The batch where every lookup is \\\"done\\\".\\n function ccipBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (Batch memory batch) {\\n (bool[] memory failures, bytes[] memory responses) = abi.decode(\\n response,\\n (bool[], bytes[])\\n );\\n if (failures.length != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n batch = abi.decode(extraData, (Batch));\\n uint256 expected;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n if (expected < responses.length) {\\n bytes memory v = responses[expected];\\n if (failures[expected]) {\\n lu.flags |= FLAG_DONE | FLAG_BATCH_ERROR;\\n } else {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n bool ok;\\n // assumption: unsafe contracts don't revert OffchainLookup()\\n (ok, v) = p.sender.staticcall(\\n abi.encodeWithSelector(\\n p.callbackFunction,\\n v,\\n p.extraData\\n )\\n );\\n if (ok || bytes4(v) != OffchainLookup.selector) {\\n lu.flags |= FLAG_DONE;\\n // decision: promote empty response from the callback => call error\\n // ie. the initial function was implemented but the callback was not\\n // this can be detected via FLAG_OFFCHAIN\\n if (!ok || v.length == 0) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n }\\n lu.data = v;\\n }\\n ++expected;\\n }\\n }\\n if (expected != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n _revertBatchGateway(batch);\\n }\\n\\n /// @dev Safely collapse `Lookup[]` into `bytes[]`.\\n /// If `FLAGS_ANY_ERROR` and response is non-empty, the response is zero-padded so that `length % 32 == 4`.\\n /// @param lookups Array of completed lookups.\\n /// @param wrapped If `true`, successful responses are unwrapped as `bytes`.\\n /// @return arr Array of call responses.\\n function _toResponseArray(Lookup[] memory lookups, bool wrapped) internal pure returns (bytes[] memory arr) {\\n arr = new bytes[](lookups.length);\\n for (uint256 i; i < lookups.length; ++i) {\\n Lookup memory lu = lookups[i];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) == 0) {\\n if (wrapped) {\\n v = abi.decode(v, (bytes));\\n }\\n } else if (v.length != 0) {\\n uint256 rem = v.length & 31;\\n if (rem != 4) {\\n bytes memory pad = new bytes(rem < 4 ? 4 - rem : rem - 4);\\n v = abi.encodePacked(v, pad); \\n }\\n }\\n arr[i] = v;\\n }\\n return arr;\\n }\\n}\",\"keccak256\":\"0x0979783da5e97d3024259857fc414d325874abd7ea1a68838b177003b511dc5d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/CCIPReader.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n/// @author Modified from https://github.com/unruggable-labs/CCIPReader.sol/blob/341576fe7ff2b6e0c93fc08f37740cf6439f5873/contracts/CCIPReader.sol\\n\\n/// MIT License\\n/// Portions Copyright (c) 2025 Unruggable\\n/// Portions Copyright (c) 2025 ENS Labs Ltd\\n\\n/// @dev Instructions:\\n/// 1. inherit this contract\\n/// 2. call `ccipRead()` similar to `staticcall()`\\n/// 3. do not put logic after this invocation\\n/// 4. implement all response logic in callback\\n/// 5. ensure that return type of calling function == callback function\\n\\nimport {EIP3668, OffchainLookup} from \\\"./EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\n\\ncontract CCIPReader {\\n /// @dev Default unsafe call gas (sufficient for legacy ENS resolver profiles).\\n uint256 constant DEFAULT_UNSAFE_CALL_GAS = 50000;\\n\\n /// @dev Special-purpose value for identity callback: `f(x) = x`.\\n bytes4 constant IDENTITY_FUNCTION = bytes4(0);\\n\\n /// @dev The gas limit for calling functions on unsafe contracts.\\n uint256 immutable unsafeCallGas;\\n\\n constructor(uint256 _unsafeCallGas) {\\n unsafeCallGas = _unsafeCallGas;\\n }\\n\\n /// @dev A recursive CCIP-Read session.\\n struct Context {\\n address target;\\n bytes4 callbackFunction;\\n bytes extraData;\\n bytes4 successCallbackFunction;\\n bytes4 failureCallbackFunction;\\n bytes myExtraData;\\n }\\n\\n /// @dev Same as `ccipRead()` but the callback function is the identity.\\n function ccipRead(address target, bytes memory call) internal view {\\n ccipRead(target, call, IDENTITY_FUNCTION, IDENTITY_FUNCTION, \\\"\\\");\\n }\\n\\n /// @dev Performs a CCIP-Read and handles internal recursion.\\n /// Reverts `OffchainLookup` if necessary.\\n /// Use `IDENTITY_FUNCTION` as the callback function selector for return/revert behavior.\\n /// @param target The contract address.\\n /// @param call The calldata to `staticcall()` on `target`.\\n /// @param successCallbackFunction The function selector of callback on success.\\n /// @param failureCallbackFunction The function selector of callback on failure.\\n /// @param extraData The contextual data relayed to callback function.\\n function ccipRead(\\n address target,\\n bytes memory call,\\n bytes4 successCallbackFunction,\\n bytes4 failureCallbackFunction,\\n bytes memory extraData\\n ) internal view {\\n // We call the intended function that **could** revert with an `OffchainLookup`\\n // We destructure the response into an execution status bool and our return bytes\\n (bool ok, bytes memory v) = safeCall(\\n detectEIP140(target),\\n target,\\n call\\n );\\n // IF the function reverted with an `OffchainLookup`\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n // We decode the response error into a tuple\\n // tuples allow flexibility noting stack too deep constraints\\n EIP3668.Params memory p = decodeOffchainLookup(v);\\n if (p.sender == target) {\\n // We then wrap the error data in an `OffchainLookup` sent/'owned' by this contract\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n this.ccipReadCallback.selector,\\n abi.encode(\\n Context(\\n target,\\n p.callbackFunction,\\n p.extraData,\\n successCallbackFunction,\\n failureCallbackFunction,\\n extraData\\n )\\n )\\n );\\n }\\n }\\n // IF we have gotten here, the 'real' target does not revert with an `OffchainLookup` error\\n // figure out what callback to call\\n bytes4 callbackFunction = ok\\n ? successCallbackFunction\\n : failureCallbackFunction;\\n if (callbackFunction != IDENTITY_FUNCTION) {\\n // The exit point of this architecture is OUR callback in the 'real'\\n // We pass through the response to that callback\\n (ok, v) = address(this).staticcall(\\n abi.encodeWithSelector(callbackFunction, v, extraData)\\n );\\n }\\n // OR the call to the 'real' target reverts with a different error selector\\n // OR the call to OUR callback reverts with ANY error selector\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipRead()`.\\n /// @param response The response from offchain.\\n /// @param extraData The contextual data passed from `ccipRead()`.\\n /// @dev The return type of this function is polymorphic depending on the caller.\\n function ccipReadCallback(\\n bytes memory response,\\n bytes memory extraData\\n ) external view {\\n Context memory ctx = abi.decode(extraData, (Context));\\n // Since the callback can revert too (but has the same return structure)\\n // We can reuse the calling infrastructure to call the callback\\n ccipRead(\\n ctx.target,\\n abi.encodeWithSelector(\\n ctx.callbackFunction,\\n response,\\n ctx.extraData\\n ),\\n ctx.successCallbackFunction,\\n ctx.failureCallbackFunction,\\n ctx.myExtraData\\n );\\n }\\n\\n /// @dev Decode `OffchainLookup` error data into a struct.\\n /// @param v The error data of the revert.\\n /// @return p The decoded `OffchainLookup` params.\\n function decodeOffchainLookup(\\n bytes memory v\\n ) internal pure returns (EIP3668.Params memory p) {\\n p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n }\\n\\n /// @dev Determine if `target` uses `revert()` instead of `invalid()`.\\n // Assumption: only newer contracts revert `OffchainLookup`.\\n /// @param target The contract to test.\\n /// @return safe True if safe to call.\\n function detectEIP140(address target) internal view returns (bool safe) {\\n if (target == address(this)) return true;\\n // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md\\n assembly {\\n let G := 5000\\n let g := gas()\\n pop(staticcall(G, target, 0, 0, 0, 0))\\n safe := lt(sub(g, gas()), G)\\n }\\n }\\n\\n /// @dev Same as `staticcall()` but prevents OOG when not `safe`.\\n function safeCall(\\n bool safe,\\n address target,\\n bytes memory call\\n ) internal view returns (bool ok, bytes memory v) {\\n (ok, v) = target.staticcall{gas: safe ? gasleft() : unsafeCallGas}(\\n call\\n );\\n }\\n}\\n\",\"keccak256\":\"0xa6f483e89e779385c2b7ea6376d92cd3c05c98f91d1a3c7c43dc7422fe6b014f\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IBatchGateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for Batch Gateway Offchain Lookup Protocol.\\n/// https://docs.ens.domains/ensip/21/\\n/// @dev Interface selector: `0xa780bab6`\\ninterface IBatchGateway {\\n /// @notice An HTTP error occurred.\\n /// @dev Error selector: `0x01800152`\\n error HttpError(uint16 status, string message);\\n\\n /// @dev Information extracted from an `OffchainLookup` revert.\\n struct Request {\\n address sender;\\n string[] urls;\\n bytes data;\\n }\\n\\n /// @notice Perform multiple `OffchainLookup` in parallel.\\n /// Callers should enable EIP-3668.\\n /// @param requests The array of requests to lookup in parallel.\\n /// @return failures The failure status of the corresponding request.\\n /// @return responses The response or error data of the corresponding request.\\n function query(\\n Request[] memory requests\\n ) external view returns (bool[] memory failures, bytes[] memory responses);\\n}\\n\",\"keccak256\":\"0xfd7f0c7bdc29fc732ec54da2ebaea241873e55082e484729901811bc9374d6f6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IGatewayProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for shared gateway URLs.\\n/// @dev Interface selector: `0x093a86d3`\\ninterface IGatewayProvider {\\n /// @notice Get the gateways.\\n /// @return The gateway URLs.\\n function gateways() external view returns (string[] memory);\\n}\\n\",\"keccak256\":\"0x7c169843cfb65657a88fb4d5f7ec44612994d7d87cb7b1a67cbfdb18758823e0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverFeatures.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary ResolverFeatures {\\n /// @notice Implements `resolve(multicall([...]))`.\\n /// @dev Feature: `0x96b62db8`\\n bytes4 constant RESOLVE_MULTICALL =\\n bytes4(keccak256(\\\"eth.ens.resolver.extended.multicall\\\"));\\n\\n /// @notice Returns the same records independent of name or node.\\n /// @dev Feature: `0x86fb8da8`\\n bytes4 constant SINGULAR = bytes4(keccak256(\\\"eth.ens.resolver.singular\\\"));\\n}\\n\",\"keccak256\":\"0x87d131fcbdd7951a17b0a94f7f02470ec3f62c6004cf91c2d2acc54098373be6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the legacy (ETH-only) addr function.\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /// Returns the address associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated address.\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x91dd0c350698c505d6c7e4c919da9f981d4b8d7ad062e25073fa1f6af7cb79d1\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the new (multicoin) addr function.\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x8da5dd0fc1c5ab4f47e03c23126976a86d4b2dbeac161e70e3af9e2a13330cf0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x3ab986332e0baad7aeb4b426aace3aa1c235be5efff8db4b6f1ce501bcdd9e68\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/AbstractUniversalResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IUniversalResolver} from \\\"./IUniversalResolver.sol\\\";\\nimport {CCIPBatcher, CCIPReader} from \\\"../ccipRead/CCIPBatcher.sol\\\";\\nimport {IGatewayProvider} from \\\"../ccipRead/IGatewayProvider.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\nimport {ENSIP19, COIN_TYPE_ETH, COIN_TYPE_DEFAULT} from \\\"../utils/ENSIP19.sol\\\";\\nimport {IERC7996} from \\\"../utils/IERC7996.sol\\\";\\nimport {ResolverFeatures} from \\\"../resolvers/ResolverFeatures.sol\\\";\\n\\n// resolver profiles\\nimport {IExtendedResolver} from \\\"../resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {INameResolver} from \\\"../resolvers/profiles/INameResolver.sol\\\";\\nimport {IAddrResolver} from \\\"../resolvers/profiles/IAddrResolver.sol\\\";\\nimport {IAddressResolver} from \\\"../resolvers/profiles/IAddressResolver.sol\\\";\\nimport {IMulticallable} from \\\"../resolvers/IMulticallable.sol\\\";\\n\\nabstract contract AbstractUniversalResolver is\\n IUniversalResolver,\\n CCIPBatcher,\\n ERC165\\n{\\n /// @dev The default batch gateways.\\n IGatewayProvider public immutable batchGatewayProvider;\\n\\n constructor(\\n IGatewayProvider _batchGatewayProvider\\n ) CCIPReader(DEFAULT_UNSAFE_CALL_GAS) {\\n batchGatewayProvider = _batchGatewayProvider;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public view virtual override(ERC165) returns (bool) {\\n return\\n type(IUniversalResolver).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /// @inheritdoc IUniversalResolver\\n function findResolver(\\n bytes memory name\\n ) public view virtual returns (address, bytes32, uint256);\\n\\n /// @dev A valid resolver and its relevant properties.\\n struct ResolverInfo {\\n bytes name; // dns-encoded name (safe to decode)\\n uint256 offset; // byte offset into name used for resolver\\n bytes32 node; // namehash(name)\\n address resolver;\\n bool extended; // IExtendedResolver\\n }\\n\\n /// @dev Returns a valid resolver for `name` or reverts.\\n /// @param name The name to search.\\n /// @return info The resolver information.\\n function requireResolver(\\n bytes memory name\\n ) public view returns (ResolverInfo memory info) {\\n // https://docs.ens.domains/ensip/10\\n (info.resolver, info.node, info.offset) = findResolver(name);\\n info.name = name;\\n _checkResolver(info);\\n }\\n\\n /// @dev Asserts that the resolver information is valid.\\n function _checkResolver(ResolverInfo memory info) internal view {\\n if (info.resolver == address(0)) {\\n revert ResolverNotFound(info.name);\\n } else if (\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n info.resolver,\\n type(IExtendedResolver).interfaceId\\n )\\n ) {\\n info.extended = true;\\n } else if (info.offset != 0) {\\n revert ResolverNotFound(info.name); // immediate resolver requires exact match\\n } else if (info.resolver.code.length == 0) {\\n revert ResolverNotContract(info.name, info.resolver);\\n }\\n }\\n\\n /// @notice Same as `resolveWithGateways()` but uses default batch gateways.\\n function resolve(\\n bytes calldata name,\\n bytes calldata data\\n ) external view returns (bytes memory, address) {\\n return resolveWithGateways(name, data, batchGatewayProvider.gateways());\\n }\\n\\n /// @notice Performs ENS forward resolution for the supplied name and data.\\n /// Caller should enable EIP-3668.\\n /// @dev This function executes over multiple steps.\\n /// @param name The DNS-encoded name to resolve.\\n /// @param data The ABI-encoded resolver calldata.\\n /// @param gateways The list of batch gateway URLs to use.\\n /// @return result The ABI-encoded response for the calldata.\\n /// @return resolver The resolver that was used to resolve the name.\\n function resolveWithGateways(\\n bytes calldata name,\\n bytes calldata data,\\n string[] memory gateways\\n ) public view returns (bytes memory result, address resolver) {\\n result;\\n resolver;\\n ResolverInfo memory info = requireResolver(name);\\n _callResolver(\\n info,\\n data,\\n gateways,\\n this.resolveCallback.selector, // ==> step 2\\n abi.encode(info.resolver)\\n );\\n }\\n\\n /// @notice Same as `resolveWithGateways()` but uses the supplied resolver.\\n function resolveWithResolver(\\n address resolver,\\n bytes calldata name,\\n bytes calldata data,\\n string[] memory gateways\\n ) external view returns (bytes memory) {\\n ResolverInfo memory info;\\n info.name = name;\\n info.node = NameCoder.namehash(name, 0);\\n info.resolver = resolver;\\n _checkResolver(info);\\n _callResolver(\\n info,\\n data,\\n gateways,\\n this.resolveCallback.selector, // ==> step 2\\n abi.encode(resolver) // this value is ignored\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `resolveWithGateways()`.\\n /// @param response The response from the resolver.\\n /// @param extraData The contextual data passed from `resolveWith*()`.\\n function resolveCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external pure returns (bytes memory, address) {\\n return (response, abi.decode(extraData, (address)));\\n }\\n\\n /// @notice Same as `reverseWithGateways()` but uses default batch gateways.\\n function reverse(\\n bytes calldata lookupAddress,\\n uint256 coinType\\n ) external view returns (string memory, address, address) {\\n return\\n reverseWithGateways(\\n lookupAddress,\\n coinType,\\n batchGatewayProvider.gateways()\\n );\\n }\\n\\n struct ReverseArgs {\\n bytes lookupAddress; // parsed input address\\n uint256 coinType; // parsed coinType\\n string[] gateways; // supplied gateways\\n address resolver; // valid reverse resolver\\n }\\n\\n /// @notice Performs ENS reverse resolution for the supplied address and coin type.\\n /// Caller should enable EIP-3668.\\n /// @dev This function executes over multiple steps.\\n /// @param lookupAddress The input address.\\n /// @param coinType The coin type.\\n /// @param gateways The list of batch gateway URLs to use.\\n /// @return primary The resolved primary name.\\n /// @return resolver The resolver address for primary name.\\n /// @return reverseResolver The resolver address for the reverse name.\\n function reverseWithGateways(\\n bytes calldata lookupAddress,\\n uint256 coinType,\\n string[] memory gateways\\n )\\n public\\n view\\n returns (\\n string memory primary,\\n address resolver,\\n address reverseResolver\\n )\\n {\\n primary;\\n resolver;\\n reverseResolver;\\n // https://docs.ens.domains/ensip/19\\n ResolverInfo memory info = requireResolver(\\n NameCoder.encode(ENSIP19.reverseName(lookupAddress, coinType)) // reverts EmptyAddress\\n );\\n _callResolver(\\n info,\\n abi.encodeCall(INameResolver.name, (info.node)),\\n gateways,\\n this.reverseNameCallback.selector, // ==> step 2\\n abi.encode(\\n ReverseArgs(lookupAddress, coinType, gateways, info.resolver)\\n )\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `reverseWithGateways()`.\\n /// @param response The abi-encoded `name()` response from the reverse resolver.\\n /// @param extraData The contextual data passed from `reverseWithGateways()`.\\n function reverseNameCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (string memory primary, address, address) {\\n ReverseArgs memory args = abi.decode(extraData, (ReverseArgs));\\n primary = abi.decode(response, (string));\\n if (bytes(primary).length == 0) {\\n return (\\\"\\\", address(0), args.resolver);\\n }\\n ResolverInfo memory info = requireResolver(NameCoder.encode(primary));\\n _callResolver(\\n info,\\n args.coinType == COIN_TYPE_ETH\\n ? abi.encodeCall(IAddrResolver.addr, (info.node))\\n : abi.encodeCall(\\n IAddressResolver.addr,\\n (info.node, args.coinType)\\n ),\\n args.gateways,\\n this.reverseAddressCallback.selector, // ==> step 3\\n abi.encode(args, primary, info.resolver)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `reverseNameCallback()`.\\n /// Reverts `ReverseAddressMismatch`.\\n /// @param response The abi-encoded `addr()` response from the forward resolver.\\n /// @param extraData The contextual data passed from `reverseNameCallback()`.\\n function reverseAddressCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n )\\n external\\n pure\\n returns (\\n string memory primary,\\n address resolver,\\n address reverseResolver\\n )\\n {\\n ReverseArgs memory args;\\n (args, primary, resolver) = abi.decode(\\n extraData,\\n (ReverseArgs, string, address)\\n );\\n bytes memory primaryAddress;\\n if (args.coinType == COIN_TYPE_ETH) {\\n address addr = abi.decode(response, (address));\\n primaryAddress = abi.encodePacked(addr);\\n } else {\\n primaryAddress = abi.decode(response, (bytes));\\n }\\n if (!BytesUtils.equals(args.lookupAddress, primaryAddress)) {\\n revert ReverseAddressMismatch(primary, primaryAddress);\\n }\\n reverseResolver = args.resolver;\\n }\\n\\n /// @dev Efficiently call a resolver.\\n /// If ENSIP-22 is supported, performs a direct call.\\n /// Otherwise, uses the batch gateway.\\n /// @param info The resolver to call.\\n /// @param call The resolution calldata.\\n /// @param gateways The list of batch gateway URLs to use.\\n /// @param callbackFunction The function selector to call after resolution.\\n /// @param extraData The contextual data passed to `callbackFunction`.\\n function _callResolver(\\n ResolverInfo memory info,\\n bytes memory call,\\n string[] memory gateways,\\n bytes4 callbackFunction,\\n bytes memory extraData\\n ) internal view {\\n bool multi = bytes4(call) == IMulticallable.multicall.selector;\\n if (\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n info.resolver,\\n type(IERC7996).interfaceId\\n ) &&\\n (!multi ||\\n (info.extended &&\\n IERC7996(info.resolver).supportsFeature(\\n ResolverFeatures.RESOLVE_MULTICALL\\n )))\\n ) {\\n ccipRead(\\n address(info.resolver),\\n info.extended\\n ? abi.encodeCall(\\n IExtendedResolver.resolve,\\n (info.name, call)\\n )\\n : call,\\n this.resolveDirectCallback.selector,\\n this.resolveDirectCallbackError.selector,\\n abi.encode(\\n info.extended,\\n bytes4(call),\\n callbackFunction,\\n extraData\\n )\\n );\\n }\\n bytes[] memory calls;\\n if (multi) {\\n calls = abi.decode(\\n BytesUtils.substring(call, 4, call.length - 4),\\n (bytes[])\\n );\\n } else {\\n calls = new bytes[](1);\\n calls[0] = call;\\n }\\n if (info.extended) {\\n for (uint256 i; i < calls.length; ++i) {\\n calls[i] = abi.encodeCall(\\n IExtendedResolver.resolve,\\n (info.name, calls[i])\\n );\\n }\\n }\\n ccipRead(\\n address(this),\\n abi.encodeCall(\\n this.ccipBatch,\\n (createBatch(info.resolver, calls, gateways))\\n ),\\n this.resolveBatchCallback.selector,\\n IDENTITY_FUNCTION,\\n abi.encode(info.extended, multi, callbackFunction, extraData)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `_callResolver()` from calling the resolver successfully.\\n function resolveDirectCallback(\\n bytes memory response,\\n bytes calldata extraData\\n ) external view {\\n (\\n bool extended,\\n bytes4 callSelector,\\n bytes4 callbackFunction,\\n bytes memory extraData_\\n ) = abi.decode(extraData, (bool, bytes4, bytes4, bytes));\\n if (response.length == 0) {\\n revert UnsupportedResolverProfile(callSelector);\\n }\\n if (extended) {\\n response = abi.decode(response, (bytes)); // unwrap resolve()\\n }\\n ccipRead(\\n address(this),\\n abi.encodeWithSelector(callbackFunction, response, extraData_)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `_callResolver()` from calling the resolver unsuccessfully.\\n function resolveDirectCallbackError(\\n bytes calldata response,\\n bytes calldata\\n ) external pure {\\n _propagateResolverError(response);\\n }\\n\\n /// @dev CCIP-Read callback for `_callResolver()` from calling the batch gateway successfully.\\n function resolveBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view {\\n Lookup[] memory lookups = abi.decode(response, (Batch)).lookups;\\n (\\n bool extended,\\n bool multi,\\n bytes4 callbackFunction,\\n bytes memory extraData_\\n ) = abi.decode(extraData, (bool, bool, bytes4, bytes));\\n bytes memory answer;\\n if (multi) {\\n answer = abi.encode(_toResponseArray(lookups, extended));\\n } else {\\n Lookup memory lu = lookups[0];\\n answer = lu.data;\\n if ((lu.flags & FLAG_BATCH_ERROR) != 0) {\\n assembly {\\n revert(add(answer, 32), mload(answer)) // propagate batch gateway errors\\n }\\n } else if ((lu.flags & FLAG_CALL_ERROR) != 0) {\\n _propagateResolverError(answer);\\n } else if (answer.length == 0) {\\n revert UnsupportedResolverProfile(bytes4(lu.call));\\n }\\n if (extended) {\\n answer = abi.decode(answer, (bytes)); // unwrap resolve()\\n }\\n }\\n ccipRead(\\n address(this),\\n abi.encodeWithSelector(callbackFunction, answer, extraData_)\\n );\\n }\\n\\n /// @dev Propagate the revert from the resolver.\\n /// @param v The error data.\\n function _propagateResolverError(bytes memory v) internal pure {\\n if (bytes4(v) == UnsupportedResolverProfile.selector) {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n } else {\\n revert ResolverError(v);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28ebdcf6a76a2c013ce3549d3ca711307e09765ee55bed190848641d3aac86df\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/IUniversalResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for the UniversalResolver.\\n/// @dev Interface selector: `0xcd191b34`\\ninterface IUniversalResolver {\\n /// @notice A resolver could not be found for the supplied name.\\n /// @dev Error selector: `0x77209fe8`\\n error ResolverNotFound(bytes name);\\n\\n /// @notice The resolver is not a contract.\\n /// @dev Error selector: `0x1e9535f2`\\n error ResolverNotContract(bytes name, address resolver);\\n\\n /// @notice The resolver did not respond.\\n /// @dev Error selector: `0x7b1c461b`\\n error UnsupportedResolverProfile(bytes4 selector);\\n\\n /// @notice The resolver returned an error.\\n /// @dev Error selector: `0x95c0c752`\\n error ResolverError(bytes errorData);\\n\\n /// @notice The resolved address from reverse resolution does not match the supplied address.\\n /// @dev Error selector: `0xef9c03ce`\\n error ReverseAddressMismatch(string primary, bytes primaryAddress);\\n\\n /// @notice An HTTP error occurred on a resolving gateway.\\n /// @dev Error selector: `0x01800152`\\n error HttpError(uint16 status, string message);\\n\\n /// @notice Find the resolver address for `name`.\\n /// Does not perform any validity checks on the resolver.\\n /// @param name The name to search.\\n /// @return resolver The found resolver, or null if not found.\\n /// @return node The namehash of `name`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(\\n bytes memory name\\n )\\n external\\n view\\n returns (address resolver, bytes32 node, uint256 resolverOffset);\\n\\n /// @notice Performs ENS forward resolution for the supplied name and data.\\n /// Caller should enable EIP-3668.\\n /// @param name The DNS-encoded name to resolve.\\n /// @param data The ABI-encoded resolver calldata.\\n /// For a multicall, encode as `multicall(bytes[])`.\\n /// @return result The ABI-encoded response for the calldata.\\n /// For a multicall, the results are encoded as `(bytes[])`.\\n /// @return resolver The resolver that was used to resolve the name.\\n function resolve(\\n bytes calldata name,\\n bytes calldata data\\n ) external view returns (bytes memory result, address resolver);\\n\\n /// @notice Performs ENS primary name resolution for the supplied address and coin type, as specified in ENSIP-19.\\n /// Caller should enable EIP-3668.\\n /// @param lookupAddress The byte-encoded address to resolve.\\n /// @param coinType The coin type of the address to resolve.\\n /// @return primary The verified primary name, or null if not set.\\n /// @return resolver The resolver that was used to resolve the primary name.\\n /// @return reverseResolver The resolver that was used to resolve the reverse name.\\n function reverse(\\n bytes calldata lookupAddress,\\n uint256 coinType\\n )\\n external\\n view\\n returns (\\n string memory primary,\\n address resolver,\\n address reverseResolver\\n );\\n}\\n\",\"keccak256\":\"0x61f9fe7140591d0ba238685d391c30ed00950e4b9c328229616ffc00eab6ac8a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/ENSIP19.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {HexUtils} from \\\"../utils/HexUtils.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\n\\nuint32 constant CHAIN_ID_ETH = 1;\\n\\nuint256 constant COIN_TYPE_ETH = 60;\\nuint256 constant COIN_TYPE_DEFAULT = 1 << 31; // 0x8000_0000\\n\\nstring constant SLUG_ETH = \\\"addr\\\"; // <=> COIN_TYPE_ETH\\nstring constant SLUG_DEFAULT = \\\"default\\\"; // <=> COIN_TYPE_DEFAULT\\nstring constant TLD_REVERSE = \\\"reverse\\\";\\n\\n/// @dev Library for generating reverse names according to ENSIP-19.\\n/// https://docs.ens.domains/ensip/19\\nlibrary ENSIP19 {\\n /// @dev The supplied address was `0x`.\\n /// Error selector: `0x7138356f`\\n error EmptyAddress();\\n\\n /// @dev Extract Chain ID from `coinType`.\\n /// @param coinType The coin type.\\n /// @return The Chain ID or 0 if non-EVM Chain.\\n function chainFromCoinType(\\n uint256 coinType\\n ) internal pure returns (uint32) {\\n if (coinType == COIN_TYPE_ETH) return CHAIN_ID_ETH;\\n coinType ^= COIN_TYPE_DEFAULT;\\n return uint32(coinType < COIN_TYPE_DEFAULT ? coinType : 0);\\n }\\n\\n /// @dev Determine if Coin Type is for an EVM address.\\n /// @param coinType The coin type.\\n /// @return True if coin type represents an EVM address.\\n function isEVMCoinType(uint256 coinType) internal pure returns (bool) {\\n return coinType == COIN_TYPE_DEFAULT || chainFromCoinType(coinType) > 0;\\n }\\n\\n /// @dev Generate Reverse Name from Address + Coin Type.\\n /// Reverts `EmptyAddress` if `addressBytes` is `0x`.\\n /// @param addressBytes The input address.\\n /// @param coinType The coin type.\\n /// @return The ENS reverse name, eg. `1234abcd.addr.reverse`.\\n function reverseName(\\n bytes memory addressBytes,\\n uint256 coinType\\n ) internal pure returns (string memory) {\\n if (addressBytes.length == 0) {\\n revert EmptyAddress();\\n }\\n return\\n string(\\n abi.encodePacked(\\n HexUtils.bytesToHex(addressBytes),\\n bytes1(\\\".\\\"),\\n coinType == COIN_TYPE_ETH\\n ? SLUG_ETH\\n : coinType == COIN_TYPE_DEFAULT\\n ? SLUG_DEFAULT\\n : HexUtils.unpaddedUintToHex(coinType, true),\\n bytes1(\\\".\\\"),\\n TLD_REVERSE\\n )\\n );\\n }\\n\\n /// @dev Parse Reverse Name into Address + Coin Type.\\n /// Matches: `/^[0-9a-fA-F]+\\\\.([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @return addressBytes The address or empty if invalid.\\n /// @return coinType The coin type.\\n function parse(\\n bytes memory name\\n ) internal pure returns (bytes memory addressBytes, uint256 coinType) {\\n (, uint256 offset) = NameCoder.readLabel(name, 0);\\n bool valid;\\n (addressBytes, valid) = HexUtils.hexToBytes(name, 1, offset);\\n if (!valid || addressBytes.length == 0) return (\\\"\\\", 0); // addressBytes not 1+ hex\\n (valid, coinType) = parseNamespace(name, offset);\\n if (!valid) return (\\\"\\\", 0); // invalid namespace\\n }\\n\\n /// @dev Parse Reverse Namespace into Coin Type.\\n /// Matches: `/^([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset to begin parsing.\\n /// @return valid True if a valid reverse namespace.\\n /// @return coinType The coin type.\\n function parseNamespace(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bool valid, uint256 coinType) {\\n (bytes32 labelHash, uint256 offsetTLD) = NameCoder.readLabel(\\n name,\\n offset\\n );\\n if (labelHash == keccak256(bytes(SLUG_ETH))) {\\n coinType = COIN_TYPE_ETH;\\n } else if (labelHash == keccak256(bytes(SLUG_DEFAULT))) {\\n coinType = COIN_TYPE_DEFAULT;\\n } else if (labelHash == bytes32(0)) {\\n return (false, 0); // no slug\\n } else {\\n (bytes32 word, bool validHex) = HexUtils.hexStringToBytes32(\\n name,\\n 1 + offset,\\n offsetTLD\\n );\\n if (!validHex) return (false, 0); // invalid coinType or too long\\n coinType = uint256(word);\\n }\\n (labelHash, offset) = NameCoder.readLabel(name, offsetTLD);\\n if (labelHash != keccak256(bytes(TLD_REVERSE))) return (false, 0); // invalid tld\\n (labelHash, ) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) return (false, 0); // not tld\\n valid = true;\\n }\\n}\\n\",\"keccak256\":\"0xd1af09b014028de4c50489bd58ae424273180bb96d95353d8eefd14845f31824\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/IERC7996.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for expressing contract features not visible from the ABI.\\n/// @dev Interface selector: `0x582de3e7`\\ninterface IERC7996 {\\n /// @notice Check if a feature is supported.\\n /// @param featureId The feature identifier.\\n /// @return `true` if the feature is supported by the contract.\\n function supportsFeature(bytes4 featureId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf499a48e4e879ec7775f375d2cb5af047720ab6ae4b6f89a40a578c4e0f51631\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x5a08ad61f4e82b8a3323562661a86fb10b10190848073fdc13d4ac43710ffba5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/universalResolver/UniversalResolverV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {\\n AbstractUniversalResolver\\n} from \\\"@ens/contracts/universalResolver/AbstractUniversalResolver.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {IUniversalResolverV2} from \\\"./interfaces/IUniversalResolverV2.sol\\\";\\nimport {LibRegistry} from \\\"./libraries/LibRegistry.sol\\\";\\n\\n/// @notice Universal Resolver that traverses the namechain registry hierarchy to locate\\n/// resolvers and registries for any DNS-encoded name.\\ncontract UniversalResolverV2 is\\n AbstractUniversalResolver,\\n DelegatedContractNamer,\\n IUniversalResolverV2\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 root registry.\\n IPermissionedRegistry public immutable ROOT_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param rootRegistry The root registry.\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n IPermissionedRegistry rootRegistry,\\n IGatewayProvider batchGatewayProvider,\\n IContractNamer contractNamer\\n )\\n AbstractUniversalResolver(batchGatewayProvider)\\n DelegatedContractNamer(contractNamer)\\n {\\n ROOT_REGISTRY = rootRegistry;\\n }\\n\\n /// @inheritdoc AbstractUniversalResolver\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(AbstractUniversalResolver, DelegatedContractNamer)\\n returns (bool)\\n {\\n // note: this is some kind of compiler bug probably due to oz v4/v5\\n return\\n type(IUniversalResolverV2).interfaceId == interfaceId ||\\n AbstractUniversalResolver.supportsInterface(interfaceId) ||\\n DelegatedContractNamer.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findOwner(bytes calldata name) external view returns (address) {\\n return LibRegistry.findOwner(ROOT_REGISTRY, name, 0);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findCanonicalName(IRegistry registry) external view returns (bytes memory) {\\n return LibRegistry.findCanonicalName(ROOT_REGISTRY, registry);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findCanonicalRegistry(bytes calldata name) external view returns (IRegistry) {\\n return LibRegistry.findCanonicalRegistry(ROOT_REGISTRY, name);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findExactRegistry(bytes calldata name) external view returns (IRegistry) {\\n return LibRegistry.findExactRegistry(ROOT_REGISTRY, name, 0);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findParentRegistry(bytes calldata name) external view returns (IRegistry) {\\n return LibRegistry.findParentRegistry(ROOT_REGISTRY, name, 0);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findRegistries(bytes calldata name) external view returns (IRegistry[] memory) {\\n return LibRegistry.findRegistries(ROOT_REGISTRY, name, 0);\\n }\\n\\n /// @inheritdoc AbstractUniversalResolver\\n function findResolver(bytes memory name)\\n public\\n view\\n override\\n returns (address resolver, bytes32 node, uint256 offset)\\n {\\n (, resolver, node, offset) = LibRegistry.findResolver(ROOT_REGISTRY, name, 0);\\n }\\n}\\n\",\"keccak256\":\"0xb67ebee7a5c7d07725b4a5d1fa8fb3f71d819801f91528eba00f66c57e2844da\",\"license\":\"MIT\"},\"project/src/universalResolver/interfaces/IUniversalResolverV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @notice Interface for ENSv2-specific UniversalResolver helper functions.\\n/// @dev Interface selector: `0xf99a5e06`\\ninterface IUniversalResolverV2 {\\n /// @notice Find the owner for `name`.\\n /// @param name The DNS-encoded name.\\n /// @return The owner address or null if unowned or not found.\\n function findOwner(bytes calldata name) external view returns (address);\\n\\n /// @notice Construct the canonical name for `registry`.\\n /// @param registry The registry to name.\\n /// @return The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry registry) external view returns (bytes memory);\\n\\n /// @notice Find the canonical registry for `name`.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(bytes calldata name) external view returns (IRegistry);\\n\\n /// @notice Find the exact registry for `name`.\\n /// @param name The DNS-encoded name.\\n /// @return The registry or null if not found.\\n function findExactRegistry(bytes calldata name) external view returns (IRegistry);\\n\\n /// @notice Find the parent registry for `name`.\\n /// @param name The DNS-encoded name.\\n /// @return The parent registry or null if not found.\\n function findParentRegistry(bytes calldata name) external view returns (IRegistry);\\n\\n /// @notice Find all registries in the ancestry of `name`.\\n /// * `findRegistries(\\\"\\\") = []`\\n /// * `findRegistries(\\\"eth\\\") = [, ]`\\n /// * `findRegistries(\\\"nick.eth\\\") = [, , ]`\\n /// * `findRegistries(\\\"sub.nick.eth\\\") = [null, , , ]`\\n ///\\n /// @param name The DNS-encoded name.\\n /// @return Array of registries in label-order.\\n function findRegistries(bytes calldata name) external view returns (IRegistry[] memory);\\n}\\n\",\"keccak256\":\"0x50933f37ecc0ec711b159aefdbd4cc66e951a9312c44ce66a28e3ca116dd2227\",\"license\":\"MIT\"},\"project/src/universalResolver/libraries/LibRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"../../registry/interfaces/IOwnedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Recursive traversal helpers for the namechain registry tree \\u2014 resolver lookup, registry\\n/// discovery, canonical name construction, and ancestry enumeration.\\nlibrary LibRegistry {\\n /// @dev Find the resolver address for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return exactRegistry The exact registry or null if not exact.\\n /// @return resolver The resolver or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n // supply if end of name\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return (rootRegistry, address(0), bytes32(0), offset);\\n }\\n // lookup parent name\\n (exactRegistry, resolver, node, resolverOffset) = findResolver(rootRegistry, name, next);\\n // if there was a parent registry...\\n if (address(exactRegistry) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n // remember the resolver (if it exists)\\n address res = exactRegistry.getResolver(label);\\n if (res != address(0)) {\\n resolver = res;\\n resolverOffset = offset;\\n }\\n exactRegistry = exactRegistry.getSubregistry(label);\\n }\\n node = NameCoder.namehash(node, labelHash); // update namehash\\n }\\n\\n /// @dev Find the owner for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return owner The owner address or null if unowned or not found.\\n function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (address owner)\\n {\\n IRegistry registry = findParentRegistry(rootRegistry, name, offset);\\n if (\\n address(registry) != address(0) &&\\n ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId)\\n ) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n owner = IOwnedRegistry(address(registry)).findOwner(label);\\n }\\n }\\n\\n /// @dev Construct the canonical name for `registry`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param registry The registry to name.\\n /// @return name The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry rootRegistry, IRegistry registry)\\n internal\\n view\\n returns (bytes memory name)\\n {\\n if (address(registry) == address(0)) {\\n return \\\"\\\";\\n }\\n for (;;) {\\n if (address(registry) == address(rootRegistry)) {\\n return abi.encodePacked(name, uint8(0)); // add terminator\\n }\\n (IRegistry parent, string memory label) = registry.getParent();\\n if (address(parent) == address(0)) {\\n return \\\"\\\"; // no canonical parent\\n }\\n IRegistry child = parent.getSubregistry(label);\\n if (address(child) != address(registry)) {\\n return \\\"\\\"; // wrong canonical child\\n }\\n name = abi.encodePacked(name, NameCoder.assertLabelSize(label), label); // reverts if invalid label\\n registry = parent;\\n }\\n }\\n\\n /// @dev Find the registry for `name` and return it iff it is canonical for that name.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name)\\n internal\\n view\\n returns (IRegistry)\\n {\\n IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0);\\n return\\n address(registry) != address(0) &&\\n keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) ==\\n keccak256(name)\\n ? registry\\n : IRegistry(address(0));\\n }\\n\\n /// @dev Find the exact registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return exactRegistry The exact registry or null if not found.\\n function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return rootRegistry;\\n }\\n IRegistry parent = findExactRegistry(rootRegistry, name, next);\\n if (address(parent) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n exactRegistry = parent.getSubregistry(label);\\n }\\n }\\n\\n /// @dev Find the parent registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return parentRegistry The parent registry or null if not found.\\n function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry parentRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n parentRegistry = findExactRegistry(rootRegistry, name, next);\\n }\\n }\\n\\n /// @dev Find all registries in the ancestry of `name`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return registries Array of registries in label-order.\\n function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry[] memory registries)\\n {\\n registries = new IRegistry[](1 + NameCoder.countLabels(name, offset));\\n registries[registries.length - 1] = rootRegistry;\\n _findRegistries(name, offset, registries, 0);\\n }\\n\\n /// @dev Recursive function for building ancestry.\\n function _findRegistries(\\n bytes memory name,\\n uint256 offset,\\n IRegistry[] memory registries,\\n uint256 index\\n )\\n private\\n view\\n returns (IRegistry registry)\\n {\\n (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset);\\n if (bytes(label).length == 0) {\\n return registries[registries.length - 1];\\n }\\n registry = _findRegistries(name, nextOffset, registries, index + 1);\\n if (address(registry) != address(0)) {\\n registry = registry.getSubregistry(label);\\n registries[index] = registry;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0b5f34bcc76ee3e49d300444fbcbe1ed152faee49a91c87eaea5f6d61ce6fb0b\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "HttpError(uint16,string)": [ + { + "notice": "An HTTP error occurred on a resolving gateway." + } + ], + "InvalidBatchGatewayResponse()": [ + { + "notice": "The batch gateway supplied an incorrect number of responses." + } + ], + "ResolverError(bytes)": [ + { + "notice": "The resolver returned an error." + } + ], + "ResolverNotContract(bytes,address)": [ + { + "notice": "The resolver is not a contract." + } + ], + "ResolverNotFound(bytes)": [ + { + "notice": "A resolver could not be found for the supplied name." + } + ], + "ReverseAddressMismatch(string,bytes)": [ + { + "notice": "The resolved address from reverse resolution does not match the supplied address." + } + ], + "UnsupportedResolverProfile(bytes4)": [ + { + "notice": "The resolver did not respond." + } + ] + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "ROOT_REGISTRY()": { + "notice": "The ENSv2 root registry." + }, + "findCanonicalName(address)": { + "notice": "Construct the canonical name for `registry`." + }, + "findCanonicalRegistry(bytes)": { + "notice": "Find the canonical registry for `name`." + }, + "findExactRegistry(bytes)": { + "notice": "Find the exact registry for `name`." + }, + "findOwner(bytes)": { + "notice": "Find the owner for `name`." + }, + "findParentRegistry(bytes)": { + "notice": "Find the parent registry for `name`." + }, + "findRegistries(bytes)": { + "notice": "Find all registries in the ancestry of `name`. * `findRegistries(\"\") = []` * `findRegistries(\"eth\") = [, ]` * `findRegistries(\"nick.eth\") = [, , ]` * `findRegistries(\"sub.nick.eth\") = [null, , , ]`" + }, + "findResolver(bytes)": { + "notice": "Find the resolver address for `name`. Does not perform any validity checks on the resolver." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "resolve(bytes,bytes)": { + "notice": "Same as `resolveWithGateways()` but uses default batch gateways." + }, + "resolveWithGateways(bytes,bytes,string[])": { + "notice": "Performs ENS forward resolution for the supplied name and data. Caller should enable EIP-3668." + }, + "resolveWithResolver(address,bytes,bytes,string[])": { + "notice": "Same as `resolveWithGateways()` but uses the supplied resolver." + }, + "reverse(bytes,uint256)": { + "notice": "Same as `reverseWithGateways()` but uses default batch gateways." + }, + "reverseWithGateways(bytes,uint256,string[])": { + "notice": "Performs ENS reverse resolution for the supplied address and coin type. Caller should enable EIP-3668." + } + }, + "notice": "Universal Resolver that traverses the namechain registry hierarchy to locate resolvers and registries for any DNS-encoded name.", + "version": 1 + }, + "argsData": "0x000000000000000000000000c960f7217d3643b525ef36bec8adf86953cd9ab8000000000000000000000000e4e7245716d12d0f6aea01dfe0e635c43d7d083c000000000000000000000000fc8bf9234969d6b85729b756fa9e14bb84a06754", + "transaction": { + "hash": "0x64113e9da7f9d61b84f3df4ba9f8bb4210ef6e8666de70a5f61ad051763260b5", + "nonce": "0x1ea4", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x7bdb706d4301e5c4974f620892ea1a5c2ab438142c100984e4296411ea29be07", + "blockNumber": "0xa6a819", + "transactionIndex": "0x40" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/UnlockedMigrationController.json b/contracts/deployments/sepolia-official-v1-20260525-r2/UnlockedMigrationController.json new file mode 100644 index 000000000..713e1e6a5 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/UnlockedMigrationController.json @@ -0,0 +1,634 @@ +{ + "address": "0x056138ef5660f7113a3b0adc08ac3683310e7fbc", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "address", + "name": "graveyard", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameDataMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameIsLocked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GRAVEYARD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[]", + "name": "mds", + "type": "tuple[]" + } + ], + "name": "finishERC1155Migration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "UnlockedMigrationController", + "sourceName": "src/migration/UnlockedMigrationController.sol", + "bytecode": "0x610140604052348015610010575f5ffd5b50604051611c33380380611c3383398101604081905261002f91610154565b6001600160a01b03808516608081905290841660a05260408051633f15457f60e01b81529051839287928792633f15457f916004808201926020929091908290030181865afa158015610084573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a891906101b0565b6001600160a01b0390811660c05292831660e05250508281166101005260408051632b20e39760e01b8152905191861691632b20e397916004808201926020929091908290030181865afa158015610102573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061012691906101b0565b6001600160a01b031661012052506101d292505050565b6001600160a01b0381168114610151575f5ffd5b50565b5f5f5f5f60808587031215610167575f5ffd5b84516101728161013d565b60208601519094506101838161013d565b60408601519093506101948161013d565b60608601519092506101a58161013d565b939692955090935050565b5f602082840312156101c0575f5ffd5b81516101cb8161013d565b9392505050565b60805160a05160c05160e05161010051610120516119c661026d5f395f81816102490152818161032101526104cf01525f81816101550152610aaa01525f818161017c01526105dc01525f61038801525f81816101a30152818161040a015281816104a00152610d9c01525f8181610116015281816106530152818161080201528181610b6901528181610d080152610dcb01526119c65ff3fe608060405234801561000f575f5ffd5b50600436106100b9575f3560e01c80635c1a6b68116100725780636f3ff726116100585780636f3ff726146101da578063bc197c81146101ed578063f23a6e6114610200575f5ffd5b80635c1a6b681461019e5780635d05f049146101c5575f5ffd5b8063192cf07d116100a2578063192cf07d14610111578063475007081461015057806348ee1bcc14610177575f5ffd5b806301ffc9a7146100bd578063150b7a02146100e5575b5f5ffd5b6100d06100cb36600461107a565b610213565b60405190151581526020015b60405180910390f35b6100f86100f3366004611114565b61023d565b6040516001600160e01b031990911681526020016100dc565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100dc565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101d86101d33660046111c3565b610544565b005b6100d06101e836600461122f565b6105bb565b6100f86101fb36600461124a565b610647565b6100f861020e36600461130d565b6107f6565b5f6001600160e01b03198216630a85bd0160e11b1480610237575061023782610a01565b92915050565b5f336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461028e5760405163d86ad9cf60e01b81523360048201526024015b60405180910390fd5b60e08210156102b057604051635cb045db60e01b815260040160405180910390fd5b5f6102bd838501856114c4565b8051805160209091012090915085146102ec5760405163edec356960e01b815260048101869052602401610285565b6040517f28ed4f6c000000000000000000000000000000000000000000000000000000008152600481018690523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906328ed4f6c906044015f604051808303815f87803b15801561036a575f5ffd5b505af115801561037c573d5f5f3e3d5ffd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063cf40882390506103e47f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae885f9182526020526040902090565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201525f6044820181905260648201526084015f604051808303815f87803b158015610456575f5ffd5b505af1158015610468573d5f5f3e3d5ffd5b50506040517f42842e0e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018990527f00000000000000000000000000000000000000000000000000000000000000001692506342842e0e91506064015f604051808303815f87803b158015610512575f5ffd5b505af1158015610524573d5f5f3e3d5ffd5b5050505061053181610a25565b50630a85bd0160e11b9695505050505050565b3330146105665760405163d86ad9cf60e01b8152336004820152602401610285565b8281146105a9576040517f5b0599910000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610285565b6105b584848484610b40565b50505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610623573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023791906114fe565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106c9576040513360248201526106c99063d86ad9cf60e01b906044015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610e6e565b82826106d660e089611531565b6106e1906040611548565b8082101561071b576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261071b90610e6e565b5f6107288688018861155b565b604051635d05f04960e01b81529091503090635d05f04990610752908e908e9086906004016116e6565b5f604051808303815f87803b158015610769575f5ffd5b505af192505050801561077a575060015b6107bc573d8080156107a7576040519150601f19603f3d011682016040523d82523d5f602084013e6107ac565b606091505b506107b681610e6e565b506107e5565b507fbc197c810000000000000000000000000000000000000000000000000000000093506107e7565b505b50505098975050505050505050565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610845576040513360248201526108459063d86ad9cf60e01b90604401610692565b828260e080821015610883576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261088390610e6e565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f199092019101816108bb57905050905089825f815181106109035761090361174d565b602090810291909101015261091a878901896114c4565b815f8151811061092c5761092c61174d565b6020908102919091010152604051635d05f04960e01b81523090635d05f0499061095c9085908590600401611761565b5f604051808303815f87803b158015610973575f5ffd5b505af1925050508015610984575060015b6109c6573d8080156109b1576040519150601f19603f3d011682016040523d82523d5f602084013e6109b6565b606091505b506109c081610e6e565b506109f1565b507ff23a6e610000000000000000000000000000000000000000000000000000000094506109f49050565b50505b5050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b1480610237575061023782610e81565b60208101516001600160a01b0316610a69576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516020820151604080840151606085015191517f85f3e6430000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016946385f3e64394610afc9491939092909190731110000000000000000000000000000001100000905f906004016117ae565b6020604051808303815f875af1158015610b18573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3c9190611810565b5050565b5f5b83811015610e67575f858583818110610b5d57610b5d61174d565b9050602002013590505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630178fe3f836040518263ffffffff1660e01b8152600401610bb591815260200190565b606060405180830381865afa158015610bd0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf49190611827565b509150506001811615610c36576040517fe7c290e200000000000000000000000000000000000000000000000000000000815260048101839052602401610285565b5f858585818110610c4957610c4961174d565b9050602002810190610c5b9190611885565b610c6590806118a3565b604051610c739291906118e6565b6040519081900390209050610cb17f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae825f9182526020526040902090565b8314610cd35760405163edec356960e01b815260048101849052602401610285565b6040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018490525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015610d51575f5ffd5b505af1158015610d63573d5f5f3e3d5ffd5b50506040517f8b4dfa75000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830181905260448301527f0000000000000000000000000000000000000000000000000000000000000000169250638b4dfa7591506064015f604051808303815f87803b158015610e0e575f5ffd5b505af1158015610e20573d5f5f3e3d5ffd5b50505050610e59868686818110610e3957610e3961174d565b9050602002810190610e4b9190611885565b610e54906118f5565b610a25565b505050806001019050610b42565b5050505050565b610e7781610ee7565b9050805160208201fd5b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061023757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610237565b60605f8251118015610f11575062461bcd60e51b610f0483611900565b6001600160e01b03191614155b15610faa5762461bcd60e51b7f577261707065644572726f723a3a307800000000000000000000000000000000610f4784610fae565b604051602001610f5892919061193c565b60408051601f1981840301815290829052610f759160240161197e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b805160609060011b8067ffffffffffffffff811115610fcf57610fcf611384565b6040519080825280601f01601f191660200182016040528015610ff9576020820181803683370190505b509150602083810190830161100f828285611017565b505050919050565b8181015b808310156105b55783516101005b828510801561103757505f81115b1561106d5760031901600f82821c16600a8110611057578060570161105c565b806030015b905080865350600190940193611029565b505060208401935061101b565b5f6020828403121561108a575f5ffd5b81356001600160e01b0319811681146110a1575f5ffd5b9392505050565b6001600160a01b03811681146110bc575f5ffd5b50565b80356110ca816110a8565b919050565b5f5f83601f8401126110df575f5ffd5b50813567ffffffffffffffff8111156110f6575f5ffd5b60208301915083602082850101111561110d575f5ffd5b9250929050565b5f5f5f5f5f60808688031215611128575f5ffd5b8535611133816110a8565b94506020860135611143816110a8565b935060408601359250606086013567ffffffffffffffff811115611165575f5ffd5b611171888289016110cf565b969995985093965092949392505050565b5f5f83601f840112611192575f5ffd5b50813567ffffffffffffffff8111156111a9575f5ffd5b6020830191508360208260051b850101111561110d575f5ffd5b5f5f5f5f604085870312156111d6575f5ffd5b843567ffffffffffffffff8111156111ec575f5ffd5b6111f887828801611182565b909550935050602085013567ffffffffffffffff811115611217575f5ffd5b61122387828801611182565b95989497509550505050565b5f6020828403121561123f575f5ffd5b81356110a1816110a8565b5f5f5f5f5f5f5f5f60a0898b031215611261575f5ffd5b883561126c816110a8565b9750602089013561127c816110a8565b9650604089013567ffffffffffffffff811115611297575f5ffd5b6112a38b828c01611182565b909750955050606089013567ffffffffffffffff8111156112c2575f5ffd5b6112ce8b828c01611182565b909550935050608089013567ffffffffffffffff8111156112ed575f5ffd5b6112f98b828c016110cf565b999c989b5096995094979396929594505050565b5f5f5f5f5f5f60a08789031215611322575f5ffd5b863561132d816110a8565b9550602087013561133d816110a8565b94506040870135935060608701359250608087013567ffffffffffffffff811115611366575f5ffd5b61137289828a016110cf565b979a9699509497509295939492505050565b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff811182821017156113bb576113bb611384565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156113ea576113ea611384565b604052919050565b5f60808284031215611402575f5ffd5b61140a611398565b9050813567ffffffffffffffff811115611422575f5ffd5b8201601f81018413611432575f5ffd5b803567ffffffffffffffff81111561144c5761144c611384565b61145f601f8201601f19166020016113c1565b818152856020838501011115611473575f5ffd5b816020840160208301375f60208383010152808452505050611497602083016110bf565b60208201526114a8604083016110bf565b60408201526114b9606083016110bf565b606082015292915050565b5f602082840312156114d4575f5ffd5b813567ffffffffffffffff8111156114ea575f5ffd5b6114f6848285016113f2565b949350505050565b5f6020828403121561150e575f5ffd5b815180151581146110a1575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176102375761023761151d565b808201808211156102375761023761151d565b5f6020828403121561156b575f5ffd5b813567ffffffffffffffff811115611581575f5ffd5b8201601f81018413611591575f5ffd5b803567ffffffffffffffff8111156115ab576115ab611384565b8060051b6115bb602082016113c1565b918252602081840181019290810190878411156115d6575f5ffd5b6020850192505b8383101561161c57823567ffffffffffffffff8111156115fb575f5ffd5b61160a896020838901016113f2565b835250602092830192909101906115dd565b979650505050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b838110156116da57601f1985840301885281518051608085526116976080860182611627565b6020838101516001600160a01b03908116888301526040808601518216908901526060948501511693909601929092525097830197929190910190600101611671565b50909695505050505050565b604081528260408201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84111561171d575f5ffd5b8360051b8086606085013782018281036060908101602085015261174390820185611655565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b604080825283519082018190525f9060208501906060840190835b8181101561179a57835183526020938401939092019160010161177c565b505083810360208501526117438186611655565b60c081525f6117c060c0830189611627565b90506001600160a01b03871660208301526001600160a01b03861660408301526001600160a01b038516606083015283608083015267ffffffffffffffff831660a0830152979650505050505050565b5f60208284031215611820575f5ffd5b5051919050565b5f5f5f60608486031215611839575f5ffd5b8351611844816110a8565b602085015190935063ffffffff8116811461185d575f5ffd5b604085015190925067ffffffffffffffff8116811461187a575f5ffd5b809150509250925092565b5f8235607e19833603018112611899575f5ffd5b9190910192915050565b5f5f8335601e198436030181126118b8575f5ffd5b83018035915067ffffffffffffffff8211156118d2575f5ffd5b60200191503681900382131561110d575f5ffd5b818382375f9101908152919050565b5f61023736836113f2565b805160208201516001600160e01b0319811691906004821015611935576001600160e01b0319808360040360031b1b82161692505b5050919050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000831681525f82518060208501601085015e5f92016010019182525092915050565b602081525f6110a1602083018461162756fea26469706673582212203d8ae9104a93dea3e9cbadef10d268de1d1ebda4164a73bd867fd232ccdab99a64736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106100b9575f3560e01c80635c1a6b68116100725780636f3ff726116100585780636f3ff726146101da578063bc197c81146101ed578063f23a6e6114610200575f5ffd5b80635c1a6b681461019e5780635d05f049146101c5575f5ffd5b8063192cf07d116100a2578063192cf07d14610111578063475007081461015057806348ee1bcc14610177575f5ffd5b806301ffc9a7146100bd578063150b7a02146100e5575b5f5ffd5b6100d06100cb36600461107a565b610213565b60405190151581526020015b60405180910390f35b6100f86100f3366004611114565b61023d565b6040516001600160e01b031990911681526020016100dc565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100dc565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101d86101d33660046111c3565b610544565b005b6100d06101e836600461122f565b6105bb565b6100f86101fb36600461124a565b610647565b6100f861020e36600461130d565b6107f6565b5f6001600160e01b03198216630a85bd0160e11b1480610237575061023782610a01565b92915050565b5f336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461028e5760405163d86ad9cf60e01b81523360048201526024015b60405180910390fd5b60e08210156102b057604051635cb045db60e01b815260040160405180910390fd5b5f6102bd838501856114c4565b8051805160209091012090915085146102ec5760405163edec356960e01b815260048101869052602401610285565b6040517f28ed4f6c000000000000000000000000000000000000000000000000000000008152600481018690523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906328ed4f6c906044015f604051808303815f87803b15801561036a575f5ffd5b505af115801561037c573d5f5f3e3d5ffd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063cf40882390506103e47f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae885f9182526020526040902090565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201525f6044820181905260648201526084015f604051808303815f87803b158015610456575f5ffd5b505af1158015610468573d5f5f3e3d5ffd5b50506040517f42842e0e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018990527f00000000000000000000000000000000000000000000000000000000000000001692506342842e0e91506064015f604051808303815f87803b158015610512575f5ffd5b505af1158015610524573d5f5f3e3d5ffd5b5050505061053181610a25565b50630a85bd0160e11b9695505050505050565b3330146105665760405163d86ad9cf60e01b8152336004820152602401610285565b8281146105a9576040517f5b0599910000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610285565b6105b584848484610b40565b50505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610623573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023791906114fe565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106c9576040513360248201526106c99063d86ad9cf60e01b906044015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610e6e565b82826106d660e089611531565b6106e1906040611548565b8082101561071b576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261071b90610e6e565b5f6107288688018861155b565b604051635d05f04960e01b81529091503090635d05f04990610752908e908e9086906004016116e6565b5f604051808303815f87803b158015610769575f5ffd5b505af192505050801561077a575060015b6107bc573d8080156107a7576040519150601f19603f3d011682016040523d82523d5f602084013e6107ac565b606091505b506107b681610e6e565b506107e5565b507fbc197c810000000000000000000000000000000000000000000000000000000093506107e7565b505b50505098975050505050505050565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610845576040513360248201526108459063d86ad9cf60e01b90604401610692565b828260e080821015610883576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261088390610e6e565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f199092019101816108bb57905050905089825f815181106109035761090361174d565b602090810291909101015261091a878901896114c4565b815f8151811061092c5761092c61174d565b6020908102919091010152604051635d05f04960e01b81523090635d05f0499061095c9085908590600401611761565b5f604051808303815f87803b158015610973575f5ffd5b505af1925050508015610984575060015b6109c6573d8080156109b1576040519150601f19603f3d011682016040523d82523d5f602084013e6109b6565b606091505b506109c081610e6e565b506109f1565b507ff23a6e610000000000000000000000000000000000000000000000000000000094506109f49050565b50505b5050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b1480610237575061023782610e81565b60208101516001600160a01b0316610a69576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516020820151604080840151606085015191517f85f3e6430000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016946385f3e64394610afc9491939092909190731110000000000000000000000000000001100000905f906004016117ae565b6020604051808303815f875af1158015610b18573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3c9190611810565b5050565b5f5b83811015610e67575f858583818110610b5d57610b5d61174d565b9050602002013590505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630178fe3f836040518263ffffffff1660e01b8152600401610bb591815260200190565b606060405180830381865afa158015610bd0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf49190611827565b509150506001811615610c36576040517fe7c290e200000000000000000000000000000000000000000000000000000000815260048101839052602401610285565b5f858585818110610c4957610c4961174d565b9050602002810190610c5b9190611885565b610c6590806118a3565b604051610c739291906118e6565b6040519081900390209050610cb17f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae825f9182526020526040902090565b8314610cd35760405163edec356960e01b815260048101849052602401610285565b6040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018490525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015610d51575f5ffd5b505af1158015610d63573d5f5f3e3d5ffd5b50506040517f8b4dfa75000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830181905260448301527f0000000000000000000000000000000000000000000000000000000000000000169250638b4dfa7591506064015f604051808303815f87803b158015610e0e575f5ffd5b505af1158015610e20573d5f5f3e3d5ffd5b50505050610e59868686818110610e3957610e3961174d565b9050602002810190610e4b9190611885565b610e54906118f5565b610a25565b505050806001019050610b42565b5050505050565b610e7781610ee7565b9050805160208201fd5b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061023757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610237565b60605f8251118015610f11575062461bcd60e51b610f0483611900565b6001600160e01b03191614155b15610faa5762461bcd60e51b7f577261707065644572726f723a3a307800000000000000000000000000000000610f4784610fae565b604051602001610f5892919061193c565b60408051601f1981840301815290829052610f759160240161197e565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b805160609060011b8067ffffffffffffffff811115610fcf57610fcf611384565b6040519080825280601f01601f191660200182016040528015610ff9576020820181803683370190505b509150602083810190830161100f828285611017565b505050919050565b8181015b808310156105b55783516101005b828510801561103757505f81115b1561106d5760031901600f82821c16600a8110611057578060570161105c565b806030015b905080865350600190940193611029565b505060208401935061101b565b5f6020828403121561108a575f5ffd5b81356001600160e01b0319811681146110a1575f5ffd5b9392505050565b6001600160a01b03811681146110bc575f5ffd5b50565b80356110ca816110a8565b919050565b5f5f83601f8401126110df575f5ffd5b50813567ffffffffffffffff8111156110f6575f5ffd5b60208301915083602082850101111561110d575f5ffd5b9250929050565b5f5f5f5f5f60808688031215611128575f5ffd5b8535611133816110a8565b94506020860135611143816110a8565b935060408601359250606086013567ffffffffffffffff811115611165575f5ffd5b611171888289016110cf565b969995985093965092949392505050565b5f5f83601f840112611192575f5ffd5b50813567ffffffffffffffff8111156111a9575f5ffd5b6020830191508360208260051b850101111561110d575f5ffd5b5f5f5f5f604085870312156111d6575f5ffd5b843567ffffffffffffffff8111156111ec575f5ffd5b6111f887828801611182565b909550935050602085013567ffffffffffffffff811115611217575f5ffd5b61122387828801611182565b95989497509550505050565b5f6020828403121561123f575f5ffd5b81356110a1816110a8565b5f5f5f5f5f5f5f5f60a0898b031215611261575f5ffd5b883561126c816110a8565b9750602089013561127c816110a8565b9650604089013567ffffffffffffffff811115611297575f5ffd5b6112a38b828c01611182565b909750955050606089013567ffffffffffffffff8111156112c2575f5ffd5b6112ce8b828c01611182565b909550935050608089013567ffffffffffffffff8111156112ed575f5ffd5b6112f98b828c016110cf565b999c989b5096995094979396929594505050565b5f5f5f5f5f5f60a08789031215611322575f5ffd5b863561132d816110a8565b9550602087013561133d816110a8565b94506040870135935060608701359250608087013567ffffffffffffffff811115611366575f5ffd5b61137289828a016110cf565b979a9699509497509295939492505050565b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff811182821017156113bb576113bb611384565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156113ea576113ea611384565b604052919050565b5f60808284031215611402575f5ffd5b61140a611398565b9050813567ffffffffffffffff811115611422575f5ffd5b8201601f81018413611432575f5ffd5b803567ffffffffffffffff81111561144c5761144c611384565b61145f601f8201601f19166020016113c1565b818152856020838501011115611473575f5ffd5b816020840160208301375f60208383010152808452505050611497602083016110bf565b60208201526114a8604083016110bf565b60408201526114b9606083016110bf565b606082015292915050565b5f602082840312156114d4575f5ffd5b813567ffffffffffffffff8111156114ea575f5ffd5b6114f6848285016113f2565b949350505050565b5f6020828403121561150e575f5ffd5b815180151581146110a1575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176102375761023761151d565b808201808211156102375761023761151d565b5f6020828403121561156b575f5ffd5b813567ffffffffffffffff811115611581575f5ffd5b8201601f81018413611591575f5ffd5b803567ffffffffffffffff8111156115ab576115ab611384565b8060051b6115bb602082016113c1565b918252602081840181019290810190878411156115d6575f5ffd5b6020850192505b8383101561161c57823567ffffffffffffffff8111156115fb575f5ffd5b61160a896020838901016113f2565b835250602092830192909101906115dd565b979650505050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b838110156116da57601f1985840301885281518051608085526116976080860182611627565b6020838101516001600160a01b03908116888301526040808601518216908901526060948501511693909601929092525097830197929190910190600101611671565b50909695505050505050565b604081528260408201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84111561171d575f5ffd5b8360051b8086606085013782018281036060908101602085015261174390820185611655565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b604080825283519082018190525f9060208501906060840190835b8181101561179a57835183526020938401939092019160010161177c565b505083810360208501526117438186611655565b60c081525f6117c060c0830189611627565b90506001600160a01b03871660208301526001600160a01b03861660408301526001600160a01b038516606083015283608083015267ffffffffffffffff831660a0830152979650505050505050565b5f60208284031215611820575f5ffd5b5051919050565b5f5f5f60608486031215611839575f5ffd5b8351611844816110a8565b602085015190935063ffffffff8116811461185d575f5ffd5b604085015190925067ffffffffffffffff8116811461187a575f5ffd5b809150509250925092565b5f8235607e19833603018112611899575f5ffd5b9190910192915050565b5f5f8335601e198436030181126118b8575f5ffd5b83018035915067ffffffffffffffff8211156118d2575f5ffd5b60200191503681900382131561110d575f5ffd5b818382375f9101908152919050565b5f61023736836113f2565b805160208201516001600160e01b0319811691906004821015611935576001600160e01b0319808360040360031b1b82161692505b5050919050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000831681525f82518060208501601085015e5f92016010019182525092915050565b602081525f6110a1602083018461162756fea26469706673582212203d8ae9104a93dea3e9cbadef10d268de1d1ebda4164a73bd867fd232ccdab99a64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "60938": [ + { + "length": 32, + "start": 278 + }, + { + "length": 32, + "start": 1619 + }, + { + "length": 32, + "start": 2050 + }, + { + "length": 32, + "start": 2921 + }, + { + "length": 32, + "start": 3336 + }, + { + "length": 32, + "start": 3531 + } + ], + "60941": [ + { + "length": 32, + "start": 419 + }, + { + "length": 32, + "start": 1034 + }, + { + "length": 32, + "start": 1184 + }, + { + "length": 32, + "start": 3484 + } + ], + "60945": [ + { + "length": 32, + "start": 904 + } + ], + "63018": [ + { + "length": 32, + "start": 341 + }, + { + "length": 32, + "start": 2730 + } + ], + "63022": [ + { + "length": 32, + "start": 585 + }, + { + "length": 32, + "start": 801 + }, + { + "length": 32, + "start": 1231 + } + ], + "75212": [ + { + "length": 32, + "start": 380 + }, + { + "length": 32, + "start": 1500 + } + ] + }, + "inputSourceName": "project/src/migration/UnlockedMigrationController.sol", + "devdoc": { + "errors": { + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "InvalidData()": [ + { + "details": "Error selector: `0x5cb045db`" + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "NameDataMismatch(uint256)": [ + { + "details": "Error selector: `0xedec3569`" + } + ], + "NameIsLocked(uint256)": [ + { + "details": "Error selector: `0xe7c290e2`" + } + ], + "UnauthorizedCaller(address)": [ + { + "details": "Error selector: `0xd86ad9cf`", + "params": { + "caller": "The address that attempted the unauthorized operation" + } + } + ] + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "ethRegistry": "The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.", + "graveyard": "The ENSv1 `BaseRegistrar` token graveyard.", + "nameWrapper": "The ENSv1 `NameWrapper` contract." + } + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "details": "Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts", + "params": { + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated.", + "mds": "The migration parameters for each name, indexed in parallel with `ids`." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.", + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed" + } + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data` struct containing migration parameters.", + "id": "The NameWrapper token ID (namehash) of the name being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed" + } + }, + "onERC721Received(address,address,uint256,bytes)": { + "params": { + "": "{from} Ignored.", + "data": "ABI-encoded `LibMigration.Data` struct containing migration parameters.", + "tokenId": "The BaseRegistrar token ID (labelhash) of the name being migrated." + }, + "returns": { + "_0": "The selector of the `onERC721Received` function." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "stateVariables": { + "_BASE_REGISTRAR": { + "details": "The ENSv1 `BaseRegistrar` contract." + } + }, + "title": "UnlockedMigrationController", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1319600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "ETH_REGISTRY()": "infinite", + "GRAVEYARD()": "infinite", + "NAME_WRAPPER()": "infinite", + "finishERC1155Migration(uint256[],(string,address,address,address)[])": "infinite", + "isContractNamer(address)": "infinite", + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": "infinite", + "onERC1155Received(address,address,uint256,uint256,bytes)": "infinite", + "onERC721Received(address,address,uint256,bytes)": "infinite", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_inject(struct LibMigration.Data memory)": "infinite", + "_migrateWrapped(uint256[] calldata,struct LibMigration.Data calldata[] calldata)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"graveyard\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameIsLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GRAVEYARD\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[]\",\"name\":\"mds\",\"type\":\"tuple[]\"}],\"name\":\"finishERC1155Migration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"InvalidData()\":[{\"details\":\"Error selector: `0x5cb045db`\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"NameDataMismatch(uint256)\":[{\"details\":\"Error selector: `0xedec3569`\"}],\"NameIsLocked(uint256)\":[{\"details\":\"Error selector: `0xe7c290e2`\"}],\"UnauthorizedCaller(address)\":[{\"details\":\"Error selector: `0xd86ad9cf`\",\"params\":{\"caller\":\"The address that attempted the unauthorized operation\"}}]},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"ethRegistry\":\"The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\",\"graveyard\":\"The ENSv1 `BaseRegistrar` token graveyard.\",\"nameWrapper\":\"The ENSv1 `NameWrapper` contract.\"}},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"details\":\"Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts\",\"params\":{\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\",\"mds\":\"The migration parameters for each name, indexed in parallel with `ids`.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\",\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\"}},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data` struct containing migration parameters.\",\"id\":\"The NameWrapper token ID (namehash) of the name being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\"}},\"onERC721Received(address,address,uint256,bytes)\":{\"params\":{\"\":\"{from} Ignored.\",\"data\":\"ABI-encoded `LibMigration.Data` struct containing migration parameters.\",\"tokenId\":\"The BaseRegistrar token ID (labelhash) of the name being migrated.\"},\"returns\":{\"_0\":\"The selector of the `onERC721Received` function.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"_BASE_REGISTRAR\":{\"details\":\"The ENSv1 `BaseRegistrar` contract.\"}},\"title\":\"UnlockedMigrationController\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidData()\":[{\"notice\":\"The encoded data is invalid.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"NameDataMismatch(uint256)\":[{\"notice\":\"NameWrapper or BaseRegistrar token does not match supplied data.\"}],\"NameIsLocked(uint256)\":[{\"notice\":\"NameWrapper token is locked.\"}],\"UnauthorizedCaller(address)\":[{\"notice\":\"Thrown when a caller is not authorized to perform the requested operation\"}]},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"ETH_REGISTRY()\":{\"notice\":\"The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\"},\"GRAVEYARD()\":{\"notice\":\"The ENSv1 `BaseRegistrar` token graveyard.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\"},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"notice\":\"Convert NameWrapper tokens to their equivalent ENSv2 form.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"notice\":\"Migrate one NameWrapper token via `safeTransferFrom()`.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"notice\":\"Receives an unwrapped .eth name via ERC721 `safeTransferFrom` from the `BaseRegistrar`. Decodes a single `LibMigration.Data` from `data` and registers the equivalent name in ENSv2.\"}},\"notice\":\"Migration controller for handling unwrapped and unlocked .eth names. Assumes premigration has `RESERVED` existing ENSv1 names. Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration. Supports (2) token sources: 1. NameWrapper (ERC-1155) but unlocked only. Reverts with `NameIsWrapped` if `LibMigration.isLocked()` => use LockedMigrationController instead. 2. BaseRegistrar (ERC-721) Unlike locked migration, no subregistry is deployed and no fuse-to-role translation is performed. The name is registered in the .eth registry with the roles and subregistry specified in the caller-provided `LibMigration.Data`.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/migration/UnlockedMigrationController.sol\":\"UnlockedMigrationController\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n /*\\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n * 0xb0202a11 ===\\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n */\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @param data Additional data with no specified format, sent in call to `spender`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\",\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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 /**\\n * @dev An operation with an ERC-20 token failed.\\n */\\n error SafeERC20FailedOperation(address token);\\n\\n /**\\n * @dev Indicates a failed `decreaseAllowance` request.\\n */\\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n forceApprove(token, spender, oldAllowance + value);\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n * value, non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n unchecked {\\n uint256 currentAllowance = token.allowance(address(this), spender);\\n if (currentAllowance < requestedDecrease) {\\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n }\\n forceApprove(token, spender, currentAllowance - requestedDecrease);\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n *\\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n * set here.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n safeTransfer(token, to, value);\\n } else if (!token.transferAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferFromAndCallRelaxed(\\n IERC1363 token,\\n address from,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length == 0) {\\n safeTransferFrom(token, from, to, value);\\n } else if (!token.transferFromAndCall(from, to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n * once without retrying, and relies on the returned value to be true.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n forceApprove(token, to, value);\\n } else if (!token.approveAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n // bubble errors\\n if iszero(success) {\\n let ptr := mload(0x40)\\n returndatacopy(ptr, 0, returndatasize())\\n revert(ptr, returndatasize())\\n }\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n\\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\n }\\n}\\n\",\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @title ERC-721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC-721 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\\n * 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\":\"0xb5afb8e8eebc4d1c6404df2f5e1e6d2c3d24fd01e5dfc855314951ecfaae462d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/migration/AbstractWrapperReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {IERC1155Receiver} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport {ERC165, IERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {UnauthorizedCaller} from \\\"../CommonErrors.sol\\\";\\nimport {WrappedErrorLib} from \\\"../utils/WrappedErrorLib.sol\\\";\\n\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title AbstractWrapperReceiver\\n/// @dev Abstract IERC1155Receiver which handles NameWrapper token migration via transfer.\\n///\\n/// NameWrapper only allows `Error(string)` exceptions during transfer and squelches typed errors.\\n/// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L317-L335\\n/// This contract, with the aid of WrappedErrorLib, embeds errors that occur during migration into `Error(string)`.\\n///\\n/// There are (2) AbstractWrapperReceiver implementations:\\n/// 1. UnlockedMigrationController accepts unlocked tokens.\\n/// 2. LockedWrapperReceiver accepts locked tokens.\\n///\\n/// `LibMigration.isLocked()` determines lock status.\\n///\\nabstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice The ENSv1 `BaseRegistrar` token graveyard.\\n address public immutable GRAVEYARD;\\n\\n /// @dev The ENSv1 `ENSRegistry` contract.\\n ENS internal immutable _REGISTRY_V1;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Restrict `msg.sender` to NameWrapper.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier onlyWrapper() {\\n if (msg.sender != address(NAME_WRAPPER)) {\\n WrappedErrorLib.wrapAndRevert(\\n abi.encodeWithSelector(UnauthorizedCaller.selector, msg.sender)\\n );\\n }\\n _;\\n }\\n\\n /// @dev Avoid `abi.decode()` failure for obviously invalid data.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier withData(bytes calldata data, uint256 minimumSize) {\\n if (data.length < minimumSize) {\\n WrappedErrorLib.wrapAndRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector));\\n }\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n constructor(INameWrapper nameWrapper, address graveyard) {\\n NAME_WRAPPER = nameWrapper;\\n GRAVEYARD = graveyard;\\n _REGISTRY_V1 = nameWrapper.ens();\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate one NameWrapper token via `safeTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param id The NameWrapper token ID (namehash) of the name being migrated.\\n /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters.\\n function onERC1155Received(\\n address /*operator*/,\\n address /*from*/,\\n uint256 id,\\n uint256 /*amount*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (amount != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L293\\n uint256[] memory ids = new uint256[](1);\\n LibMigration.Data[] memory mds = new LibMigration.Data[](1);\\n ids[0] = id;\\n mds[0] = abi.decode(data, (LibMigration.Data)); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155Received.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param data ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\\n function onERC1155BatchReceived(\\n address /*operator*/,\\n address /*from*/,\\n uint256[] calldata ids,\\n uint256[] calldata /*amounts*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, 64 + ids.length * LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (ids.length != amounts.length) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L162\\n // if (amounts[i] != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L182\\n LibMigration.Data[] memory mds = abi.decode(data, (LibMigration.Data[])); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155BatchReceived.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @notice Convert NameWrapper tokens to their equivalent ENSv2 form.\\n /// @dev Only callable by ourself and invoked by our `IERC1155Receiver` handlers.\\n ///\\n /// TODO: gas analysis and optimization\\n /// NOTE: converting this to an internal call requires catching many reverts\\n ///\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param mds The migration parameters for each name, indexed in parallel with `ids`.\\n function finishERC1155Migration(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n external\\n {\\n if (msg.sender != address(this)) {\\n revert UnauthorizedCaller(msg.sender);\\n }\\n if (ids.length != mds.length) {\\n revert IERC1155Errors.ERC1155InvalidArrayLength(ids.length, mds.length);\\n }\\n _migrateWrapped(ids, mds);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Migrate received NameWrapper tokens.\\n /// Token owner is this contract.\\n /// Token is not expired.\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n virtual;\\n}\\n\",\"keccak256\":\"0x0c15f9f657ba58bf5081cbff88c385c9e673ba87aed2032397ec2c5448d7fe1a\",\"license\":\"MIT\"},\"project/src/migration/UnlockedMigrationController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IBaseRegistrar} from \\\"@ens/contracts/ethregistrar/IBaseRegistrar.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\nimport {InvalidOwner, UnauthorizedCaller} from \\\"../CommonErrors.sol\\\";\\nimport {REGISTRATION_ROLE_BITMAP} from \\\"../registrar/ETHRegistrar.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {AbstractWrapperReceiver} from \\\"./AbstractWrapperReceiver.sol\\\";\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title UnlockedMigrationController\\n/// @notice Migration controller for handling unwrapped and unlocked .eth names.\\n///\\n/// Assumes premigration has `RESERVED` existing ENSv1 names.\\n/// Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration.\\n///\\n/// Supports (2) token sources:\\n/// 1. NameWrapper (ERC-1155) but unlocked only.\\n/// Reverts with `NameIsWrapped` if `LibMigration.isLocked()` => use LockedMigrationController instead.\\n/// 2. BaseRegistrar (ERC-721)\\n///\\n/// Unlike locked migration, no subregistry is deployed and no fuse-to-role translation is\\n/// performed. The name is registered in the .eth registry with the roles and subregistry\\n/// specified in the caller-provided `LibMigration.Data`.\\n///\\ncontract UnlockedMigrationController is\\n AbstractWrapperReceiver,\\n IERC721Receiver,\\n DelegatedContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @dev The ENSv1 `BaseRegistrar` contract.\\n IBaseRegistrar internal immutable _BASE_REGISTRAR;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n /// @param ethRegistry The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n INameWrapper nameWrapper,\\n address graveyard,\\n IPermissionedRegistry ethRegistry,\\n IContractNamer contractNamer\\n )\\n AbstractWrapperReceiver(nameWrapper, graveyard)\\n DelegatedContractNamer(contractNamer)\\n {\\n ETH_REGISTRY = ethRegistry;\\n _BASE_REGISTRAR = nameWrapper.registrar();\\n }\\n\\n /// @inheritdoc DelegatedContractNamer\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(AbstractWrapperReceiver, DelegatedContractNamer)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC721Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Receives an unwrapped .eth name via ERC721 `safeTransferFrom` from the `BaseRegistrar`.\\n /// Decodes a single `LibMigration.Data` from `data` and registers the equivalent name in ENSv2.\\n /// @param {operator} Ignored.\\n /// @param {from} Ignored.\\n /// @param tokenId The BaseRegistrar token ID (labelhash) of the name being migrated.\\n /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters.\\n /// @return The selector of the `onERC721Received` function.\\n function onERC721Received(\\n address /*operator*/,\\n address /*from*/,\\n uint256 tokenId,\\n bytes calldata data\\n )\\n external\\n returns (bytes4)\\n {\\n if (msg.sender != address(_BASE_REGISTRAR)) {\\n revert UnauthorizedCaller(msg.sender);\\n }\\n if (data.length < LibMigration.MIN_DATA_SIZE) {\\n revert LibMigration.InvalidData();\\n }\\n LibMigration.Data memory md = abi.decode(data, (LibMigration.Data)); // reverts if invalid\\n if (tokenId != uint256(keccak256(bytes(md.label)))) {\\n revert LibMigration.NameDataMismatch(tokenId);\\n }\\n _BASE_REGISTRAR.reclaim(tokenId, address(this));\\n _REGISTRY_V1.setRecord(\\n NameCoder.namehash(NameCoder.ETH_NODE, bytes32(tokenId)),\\n GRAVEYARD, // transfer ownership to graveyard\\n address(0), // clear ENSv1 resolver\\n 0\\n );\\n _BASE_REGISTRAR.safeTransferFrom(address(this), GRAVEYARD, tokenId); // transfer token to graveyard\\n _inject(md);\\n return this.onERC721Received.selector;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc AbstractWrapperReceiver\\n /// @dev Reverts `NameIsLocked` if any token is locked.\\n /// Reverts `NameDataMismatch` if any token is mislabeled.\\n /// @param ids The NameWrapper token IDs (namehash) of the names to migrate.\\n /// @param mds The migration parameters for each name, indexed in parallel with `ids`.\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n override\\n {\\n for (uint256 i; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n (, uint32 fuses, ) = NAME_WRAPPER.getData(id);\\n if (LibMigration.isLocked(fuses)) {\\n revert LibMigration.NameIsLocked(id);\\n }\\n bytes32 labelHash = keccak256(bytes(mds[i].label));\\n if (bytes32(id) != NameCoder.namehash(NameCoder.ETH_NODE, labelHash)) {\\n revert LibMigration.NameDataMismatch(id);\\n }\\n NAME_WRAPPER.setResolver(bytes32(id), address(0)); // clear ENSv1 resolver\\n NAME_WRAPPER.unwrapETH2LD(labelHash, GRAVEYARD, GRAVEYARD); // unwrap and transfer to graveyard\\n _inject(mds[i]);\\n }\\n }\\n\\n /// @dev Claim premigrated reservation.\\n function _inject(LibMigration.Data memory md) internal {\\n if (md.owner == address(0)) {\\n revert InvalidOwner();\\n }\\n // Register the name in the ETH registry\\n ETH_REGISTRY.register(\\n md.label,\\n md.owner,\\n md.subregistry,\\n md.resolver,\\n REGISTRATION_ROLE_BITMAP,\\n 0 // use reserved expiry\\n ); // reverts if not RESERVED\\n }\\n}\\n\",\"keccak256\":\"0x0045c5fc93efc668307847e587fc6c4d889309d6b5459d256c85a6fd6d0adca3\",\"license\":\"MIT\"},\"project/src/migration/libraries/LibMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n CANNOT_BURN_FUSES,\\n CANNOT_UNWRAP,\\n IS_DOT_ETH,\\n PARENT_CANNOT_CONTROL\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Primitives for migration.\\nlibrary LibMigration {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Typed arguments for migration via transfer payload.\\n struct Data {\\n /// @dev Subdomain being migrated.\\n string label;\\n /// @dev Address that will own the name in the v2 registry.\\n address owner;\\n /// @dev Address of the child registry.\\n /// Ignored by locked migration.\\n IRegistry subregistry;\\n /// @dev Resolver address to set for the migrated name.\\n /// Ignored if locked and `CANNOT_SET_RESOLVER`.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Minimum size of `abi.encode(Data({...}))`.\\n uint256 internal constant MIN_DATA_SIZE = 7 * 32;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be registered because unmigrated NameWrapper token exists.\\n /// @dev Error selector: `0x408fa1b8`\\n error NameRequiresMigration();\\n\\n /// @notice NameWrapper token is unlocked.\\n /// @dev Error selector: `0x1bfe8f0a`\\n error NameNotLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper token is locked.\\n /// @dev Error selector: `0xe7c290e2`\\n error NameIsLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper or BaseRegistrar token does not match supplied data.\\n /// @dev Error selector: `0xedec3569`\\n error NameDataMismatch(uint256 tokenId);\\n\\n /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\\n /// @dev Error selector: `0xa4f07713`\\n error FrozenTokenApproval(uint256 tokenId);\\n\\n /// @notice The encoded data is invalid.\\n /// @dev Error selector: `0x5cb045db`\\n error InvalidData();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns `true` if the NameWrapper token is locked.\\n function isLocked(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient\\n // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()`\\n return (fuses & CANNOT_UNWRAP) != 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token fuses are not frozen.\\n function notFrozen(uint32 fuses) internal pure returns (bool) {\\n return (fuses & CANNOT_BURN_FUSES) == 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth.\\n function isEmancipatedChild(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL must be set for the entire ancestory.\\n // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()`\\n return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL;\\n }\\n}\\n\",\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\"},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`.\\nabstract contract AbstractETHRegistrar is Ownable, HCAContext, ERC165, IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Minimum renew duration, in seconds.\\n uint64 public constant MIN_RENEW_DURATION = 1;\\n\\n /// @notice ENSv2 .eth `PermissionedRegistry`.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice Address that receives payments.\\n address public immutable BENEFICIARY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Oracle for registration and renewal costs.\\n IRentPriceOracle public rentPriceOracle;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `IRentPriceOracle` was replaced.\\n /// @param oracle The new `IRentPriceOracle` contract.\\n event RentPriceOracleUpdated(IRentPriceOracle oracle);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param hcaFactory HCA factory.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n constructor(\\n address owner_,\\n IHCAFactoryBasic hcaFactory,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle\\n )\\n Ownable(owner_)\\n HCAEquivalence(hcaFactory)\\n {\\n ETH_REGISTRY = ethRegistry;\\n BENEFICIARY = beneficiary;\\n\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Change the rent price oracle.\\n /// @param oracle The new `IRentPriceOracle` instance.\\n function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner {\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external\\n {\\n IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not\\n uint64 newExpiry = state.expiry + duration; // reverts if overflow\\n uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, amount); // reverts if payment failed\\n ETH_REGISTRY.renew(state.tokenId, newExpiry);\\n _onRenew(label, duration);\\n emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function isRenewable(string calldata label) external view returns (bool) {\\n return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n public\\n view\\n returns (uint256)\\n {\\n return\\n rentPriceOracle.getRenewPrice(\\n label,\\n _requireRenewable(label, duration).expiry,\\n duration,\\n paymentToken\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Callback for when a name is renewed.\\n function _onRenew(string calldata label, uint64 duration) internal virtual {}\\n\\n /// @dev Returns whether the name is renewable by this contract.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n virtual\\n returns (bool);\\n\\n /// @dev Ensure name is renewable.\\n function _requireRenewable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isRenewable(state)) {\\n revert NameNotRenewable(label);\\n }\\n if (duration < MIN_RENEW_DURATION) {\\n revert DurationTooShort(duration, MIN_RENEW_DURATION);\\n }\\n }\\n\\n /// @inheritdoc HCAContext\\n function _msgSender() internal view override(Context, HCAContext) returns (address) {\\n return super._msgSender();\\n }\\n}\\n\",\"keccak256\":\"0xb1cf6d7413558f8d257bdf8f734aaa57d4323e27854ae3ce79b7f017ff133510\",\"license\":\"MIT\"},\"project/src/registrar/ETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"../registry/libraries/RegistryRolesLib.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {AbstractETHRegistrar} from \\\"./AbstractETHRegistrar.sol\\\";\\nimport {IETHRegistrar} from \\\"./interfaces/IETHRegistrar.sol\\\";\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Roles assigned to owners at registration. Includes set-subregistry, set-resolver, and can-transfer (with admin variants).\\nuint256 constant REGISTRATION_ROLE_BITMAP =\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY |\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN |\\n RegistryRolesLib.ROLE_SET_RESOLVER |\\n RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN |\\n RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN;\\n\\n/// @notice Commit-reveal registrar for .eth names. Registration requires two transactions: first\\n/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment\\n/// age but before the maximum commitment age has elapsed. The commitment hash binds all\\n/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer)\\n/// to prevent front-running.\\n///\\n/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed\\n/// set of roles (set subregistry, set resolver, and transfer \\u2014 each with their admin\\n/// counterpart).\\n///\\n/// Pricing and payment are delegated to a swappable `IRentPriceOracle`.\\n///\\ncontract ETHRegistrar is AbstractETHRegistrar, IETHRegistrar {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRenewer\\n uint64 public immutable GRACE_PERIOD;\\n\\n /// @notice Minimum seconds a commitment must age before registration can proceed.\\n /// @dev If zero, front-running protection is disabled.\\n uint64 public immutable MIN_COMMITMENT_AGE;\\n\\n /// @notice Maximum seconds a commitment remains valid; expired commitments are rejected.\\n uint64 public immutable MAX_COMMITMENT_AGE;\\n\\n /// @notice Minimum register duration, in seconds.\\n uint64 public immutable MIN_REGISTER_DURATION;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n mapping(bytes32 commitment => uint64 commitTime) public commitmentAt;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`.\\n /// @dev Error selector: `0x3e5aa838`\\n error MaxCommitmentAgeTooLow();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param hcaFactory HCA factory.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n /// @param gracePeriod Post-expiry period where still renewable and not available, in seconds.\\n /// @param minCommitmentAge Minimum seconds a commitment must age before registration can proceed.\\n /// @param maxCommitmentAge Maximum seconds a commitment remains valid; expired commitments are rejected.\\n /// @param minRegisterDuration Minimum register duration, in seconds.\\n constructor(\\n address owner_,\\n IHCAFactoryBasic hcaFactory,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle,\\n uint64 gracePeriod,\\n uint64 minCommitmentAge,\\n uint64 maxCommitmentAge,\\n uint64 minRegisterDuration\\n )\\n AbstractETHRegistrar(owner_, hcaFactory, ethRegistry, beneficiary, oracle)\\n {\\n if (maxCommitmentAge <= minCommitmentAge) {\\n revert MaxCommitmentAgeTooLow();\\n }\\n GRACE_PERIOD = gracePeriod;\\n MIN_COMMITMENT_AGE = minCommitmentAge;\\n MAX_COMMITMENT_AGE = maxCommitmentAge;\\n MIN_REGISTER_DURATION = minRegisterDuration;\\n }\\n\\n /// @inheritdoc AbstractETHRegistrar\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return\\n interfaceId == type(IETHRegistrar).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n function commit(bytes32 commitment) external {\\n if (commitmentAt[commitment] + MAX_COMMITMENT_AGE > block.timestamp) {\\n revert UnexpiredCommitmentExists(commitment);\\n }\\n commitmentAt[commitment] = uint64(block.timestamp);\\n emit CommitmentMade(commitment);\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function register(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256 tokenId)\\n {\\n if (owner == address(0)) {\\n revert InvalidOwner();\\n }\\n _consumeCommitment(\\n makeCommitment(label, owner, secret, subregistry, resolver, duration, referrer)\\n ); // reverts if no commitment\\n IPermissionedRegistry.State memory state = _requireAvailable(label, duration); // reverts if not\\n (uint256 base, uint256 premium) =\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(state.expiry),\\n duration,\\n paymentToken\\n ); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, base + premium); // reverts if payment failed\\n tokenId = ETH_REGISTRY.register(\\n label,\\n owner,\\n subregistry,\\n resolver,\\n REGISTRATION_ROLE_BITMAP,\\n uint64(block.timestamp) + duration // new expiry\\n ); // should not revert\\n emit NameRegistered(\\n tokenId,\\n label,\\n owner,\\n subregistry,\\n resolver,\\n duration,\\n paymentToken,\\n referrer,\\n base,\\n premium\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function isAvailable(string calldata label) external view returns (bool) {\\n return _isAvailable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 bae, uint256 premium)\\n {\\n return\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(_requireAvailable(label, duration).expiry),\\n duration,\\n paymentToken\\n );\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n return\\n uint64(\\n _isRenewableGrace(state)\\n ? GRACE_PERIOD - (block.timestamp - state.expiry)\\n : 0\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n public\\n pure\\n override\\n returns (bytes32)\\n {\\n return\\n keccak256(abi.encode(label, owner, secret, subregistry, resolver, duration, referrer));\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates that the given `commitment` was recorded within the allowed time window\\n /// (between minimum and maximum commitment age), then deletes it so it cannot be reused.\\n /// @param commitment The commitment hash to validate and consume.\\n function _consumeCommitment(bytes32 commitment) internal {\\n uint64 t = uint64(block.timestamp);\\n uint64 t0 = commitmentAt[commitment];\\n uint64 tMin = t0 + MIN_COMMITMENT_AGE;\\n if (t < tMin) {\\n revert CommitmentTooNew(commitment, tMin, t);\\n }\\n uint64 tMax = t0 + MAX_COMMITMENT_AGE;\\n if (t >= tMax) {\\n revert CommitmentTooOld(commitment, tMax, t);\\n }\\n delete commitmentAt[commitment];\\n }\\n\\n /// @dev Ensure name is registerable.\\n function _requireAvailable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isAvailable(state)) {\\n revert NameNotAvailable(label);\\n }\\n if (duration < MIN_REGISTER_DURATION) {\\n revert DurationTooShort(duration, MIN_REGISTER_DURATION);\\n }\\n }\\n\\n /// @dev Determine if `AVAILABLE` and not in grace.\\n function _isAvailable(IPermissionedRegistry.State memory state) internal view returns (bool) {\\n return _checkGrace(state, false);\\n }\\n\\n /// @dev Determine if `REGISTERED` or in grace was `REGISTERED`.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n override\\n returns (bool)\\n {\\n return state.status == IPermissionedRegistry.Status.REGISTERED || _isRenewableGrace(state);\\n }\\n\\n /// @dev Determine if was `REGISTERED` and in grace.\\n function _isRenewableGrace(IPermissionedRegistry.State memory state)\\n internal\\n view\\n returns (bool)\\n {\\n return state.latestOwner != address(0) && _checkGrace(state, true);\\n }\\n\\n /// @dev Check if `AVAILABLE` and conditionally in grace.\\n function _checkGrace(IPermissionedRegistry.State memory state, bool grace)\\n internal\\n view\\n returns (bool)\\n {\\n return\\n state.status == IPermissionedRegistry.Status.AVAILABLE &&\\n (grace == (block.timestamp - state.expiry) < GRACE_PERIOD);\\n }\\n\\n /// @dev Determine duration name has been available.\\n function _availablePeriod(uint64 expiry) internal view returns (uint64) {\\n uint64 t = uint64(block.timestamp);\\n if (expiry == 0) {\\n return t; // never registered\\n }\\n expiry += GRACE_PERIOD;\\n return t > expiry ? t - expiry : 0;\\n }\\n}\\n\",\"keccak256\":\"0x98448c1cb629eec852d9e6ba65ab8b1d46b68f813c2687b0c84d115fbc84b91c\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./IETHRenewer.sol\\\";\\n\\n/// @notice Interface for registering \\\".eth\\\" names.\\n/// @dev Interface selector: `0xc1401b80`\\ninterface IETHRegistrar is IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` was recorded onchain at `block.timestamp`.\\n /// @param commitment The commitment hash from `makeCommitment()`.\\n event CommitmentMade(bytes32 commitment);\\n\\n /// @notice A name was registered.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the registration.\\n /// @param owner The owner address.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param base The amount of `paymentToken` for the registration.\\n /// @param premium The amount of `paymentToken` due to premium.\\n event NameRegistered(\\n uint256 indexed tokenId,\\n string label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 base,\\n uint256 premium\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` is still usable for registration.\\n /// @dev Error selector: `0x0a059d71`\\n error UnexpiredCommitmentExists(bytes32 commitment);\\n\\n /// @notice `commitment` cannot be consumed yet.\\n /// @dev Error selector: `0x6be614e3`\\n error CommitmentTooNew(bytes32 commitment, uint64 validFrom, uint64 blockTimestamp);\\n\\n /// @notice `commitment` has expired.\\n /// @dev Error selector: `0x0cb9df3f`\\n error CommitmentTooOld(bytes32 commitment, uint64 validTo, uint64 blockTimestamp);\\n\\n /// @notice `label` cannot be registered.\\n /// @dev Error selector: `0x477707e8`\\n error NameNotAvailable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registration step #1: record intent to register without revealing any information.\\n /// @dev Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.\\n /// @param commitment The commitment hash.\\n function commit(bytes32 commitment) external;\\n\\n /// @notice Register a name.\\n /// @param label The name from commitment.\\n /// @param owner The owner from commitment.\\n /// @param secret The secret from commitment.\\n /// @param subregistry The registry from commitment.\\n /// @param resolver The resolver from commitment.\\n /// @param duration The registration from commitment.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @return The registered token ID.\\n function register(\\n string memory label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256);\\n\\n /// @notice Get timestamp of a prior commitment.\\n /// @param commitment The commitment hash.\\n /// @return The commitment time, in seconds, or 0 if unknown.\\n function commitmentAt(bytes32 commitment) external view returns (uint64);\\n\\n /// @notice Determine register price for a name.\\n /// @param label The name to register.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Check if name is available.\\n /// @param label The name to check.\\n /// @return `true` if registerable.\\n function isAvailable(string memory label) external view returns (bool);\\n\\n /// @notice Compute hash of registration parameters.\\n /// @param label The name to register.\\n /// @param owner The owner address.\\n /// @param secret The secret for the registration.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param referrer The referrer hash.\\n /// @return The commitment hash.\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n external\\n pure\\n returns (bytes32);\\n}\\n\",\"keccak256\":\"0x7e824c5019f8eb7d7a283451700234716353e01d649c811b5ced5cf58b476289\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for renewing \\\".eth\\\" names.\\n/// @dev Interface selector: `0x06aaeb32`\\ninterface IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A name was extended by `duration`.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the renewal.\\n /// @param duration The duration extension, in seconds.\\n /// @param newExpiry The new expiry, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param amount The amount of `paymentToken`.\\n event NameRenewed(\\n uint256 indexed tokenId,\\n string label,\\n uint64 duration,\\n uint64 newExpiry,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 amount\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `duration` less than `minDuration`.\\n /// @dev Error selector: `0xa096b844`\\n error DurationTooShort(uint64 duration, uint64 minDuration);\\n\\n /// @notice `label` cannot be renewed.\\n /// @dev Error selector: `0x1caefaa0`\\n error NameNotRenewable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Renew a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external;\\n\\n /// @notice Determine renew price for a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice Check if name is renewable.\\n /// @param label The name to check.\\n /// @return `true` if renewable.\\n function isRenewable(string calldata label) external view returns (bool);\\n\\n /// @notice Determine remaining grace period.\\n /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`.\\n /// @param label The name to check.\\n /// @return The remaining grace period, in seconds.\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64);\\n\\n /// @notice Post-expiry period where still renewable and not available, in seconds.\\n function GRACE_PERIOD() external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 7: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x6bd37001025ec90ffe9b852fcfdf68be81a9f70f8777d80136bea1c04da30041\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/WrappedErrorLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {HexUtils} from \\\"@ens/contracts/utils/HexUtils.sol\\\";\\n\\n/// @dev Library to wrap and unwrap typed error data inside of `Error(string)`.\\n/// Uses hex to embed arbitrary data and avoid invalid unicode.\\nlibrary WrappedErrorLib {\\n /// @dev Error selector for `Error(string)`.\\n bytes4 internal constant ERROR_STRING_SELECTOR = 0x08c379a0;\\n\\n /// @dev The detectable human-readable error prefix.\\n /// Must be exactly 16 bytes.\\n bytes16 internal constant WRAPPED_ERROR_PREFIX = \\\"WrappedError::0x\\\";\\n\\n /// @dev Wrap an error and then revert.\\n function wrapAndRevert(bytes memory err) internal pure {\\n err = wrap(err);\\n assembly {\\n revert(add(err, 32), mload(err))\\n }\\n }\\n\\n /// @dev Embed a typed error into `Error(string)`.\\n /// Does nothing if already `Error(string)`.\\n /// For detection, `WRAPPED_ERROR_PREFIX` is leading bytes the error string.\\n function wrap(bytes memory err) internal pure returns (bytes memory) {\\n if (err.length > 0 && bytes4(err) != ERROR_STRING_SELECTOR) {\\n // assert((err.length & 31) == 4);\\n err = abi.encodeWithSelector(\\n ERROR_STRING_SELECTOR,\\n abi.encodePacked(WRAPPED_ERROR_PREFIX, HexUtils.bytesToHex(err))\\n );\\n }\\n return err;\\n }\\n\\n /// @dev Unwrap a typed error from `Error(string)`.\\n /// Does nothing if detection and extracton fails.\\n /// @param err The error data to unwrap.\\n /// @return The unwrapped error data, or unmodified if not wrapped.\\n function unwrap(bytes memory err) internal pure returns (bytes memory) {\\n if (bytes4(err) == ERROR_STRING_SELECTOR) {\\n bytes memory v;\\n assembly {\\n v := add(err, 4) // skip selector\\n }\\n v = abi.decode(v, (bytes));\\n if (bytes16(v) == WRAPPED_ERROR_PREFIX) {\\n (bytes memory inner, bool ok) = HexUtils.hexToBytes(v, 16, v.length);\\n if (ok) {\\n return inner;\\n }\\n }\\n }\\n return err;\\n }\\n}\\n\",\"keccak256\":\"0xf92862b6509cf553bd542925617318a2509bfdc6457e8b5d102c8e9658c610e4\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "InvalidData()": [ + { + "notice": "The encoded data is invalid." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "NameDataMismatch(uint256)": [ + { + "notice": "NameWrapper or BaseRegistrar token does not match supplied data." + } + ], + "NameIsLocked(uint256)": [ + { + "notice": "NameWrapper token is locked." + } + ], + "UnauthorizedCaller(address)": [ + { + "notice": "Thrown when a caller is not authorized to perform the requested operation" + } + ] + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "ETH_REGISTRY()": { + "notice": "The ENSv2 .eth `PermissionedRegistry` where migrated names are registered." + }, + "GRAVEYARD()": { + "notice": "The ENSv1 `BaseRegistrar` token graveyard." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens." + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "notice": "Convert NameWrapper tokens to their equivalent ENSv2 form." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "notice": "Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "notice": "Migrate one NameWrapper token via `safeTransferFrom()`." + }, + "onERC721Received(address,address,uint256,bytes)": { + "notice": "Receives an unwrapped .eth name via ERC721 `safeTransferFrom` from the `BaseRegistrar`. Decodes a single `LibMigration.Data` from `data` and registers the equivalent name in ENSv2." + } + }, + "notice": "Migration controller for handling unwrapped and unlocked .eth names. Assumes premigration has `RESERVED` existing ENSv1 names. Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration. Supports (2) token sources: 1. NameWrapper (ERC-1155) but unlocked only. Reverts with `NameIsWrapped` if `LibMigration.isLocked()` => use LockedMigrationController instead. 2. BaseRegistrar (ERC-721) Unlike locked migration, no subregistry is deployed and no fuse-to-role translation is performed. The name is registered in the .eth registry with the roles and subregistry specified in the caller-provided `LibMigration.Data`.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce8000000000000000000000000802453f2f077d5a0c3d0f9a6eb2a36dcfa3c6e0d000000000000000000000000dedb92913a25abe1f7bcdd85d8a344a43b398b67000000000000000000000000fc8bf9234969d6b85729b756fa9e14bb84a06754", + "transaction": { + "hash": "0x0e8cb3425e94500fe002b811aa587d67787b49a6a501dd6a464f20a744052f54", + "nonce": "0x1e93", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x92fd83a10eb6776aca1a65b5bb84a65ae0de82584978fce3e83bcb3e1b4448ea", + "blockNumber": "0xa6a808", + "transactionIndex": "0x52" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/UpgradableUniversalResolverProxy.json b/contracts/deployments/sepolia-official-v1-20260525-r2/UpgradableUniversalResolverProxy.json new file mode 100644 index 000000000..790862905 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/UpgradableUniversalResolverProxy.json @@ -0,0 +1,7234 @@ +{ + "address": "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe", + "argsData": "0x", + "contractName": "UpgradableUniversalResolverProxy", + "sourceName": "src/universalResolver/UpgradableUniversalResolverProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidImplementation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [], + "name": "SameImplementation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "AdminRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f5ffd5b50604051610c4d380380610c4d83398101604081905261002e9161019b565b6100378161006e565b5f516020610c2d5f395f51905f5280546001600160a01b0319166001600160a01b038316179055610067826100e6565b50506101cc565b6001600160a01b038116158061008c57506001600160a01b0381163b155b156100aa5760405163340aafcd60e11b815260040160405180910390fd5b6001600160a01b0381166100bc61014d565b6001600160a01b0316036100e357604051634c3b76bf60e01b815260040160405180910390fd5b50565b5f6100ef61016c565b9050815f516020610c0d5f395f51905f5280546001600160a01b0319166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b5f5f516020610c2d5f395f51905f525b546001600160a01b0316919050565b5f5f516020610c0d5f395f51905f5261015d565b80516001600160a01b0381168114610196575f5ffd5b919050565b5f5f604083850312156101ac575f5ffd5b6101b583610180565b91506101c360208401610180565b90509250929050565b610a34806101d95f395ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f5f6100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610698565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106df565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079f565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107ba565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610892565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109eb565b6105a4565b6104308361041d83856109eb565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b805160208201516001600160e01b031981169190600482101561067d576001600160e01b0319808360040360031b1b82161692505b5050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106ab576106ab610684565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b038816835260a0602084015280875180835260c08501915060c08160051b8601019250602089015f5b828110156107455760bf198786030184526107308583516106b1565b94506020938401939190910190600101610714565b50505050828103604084015261075b81876106b1565b6001600160e01b0319861660608501529050828103608084015261077f81856106b1565b98975050505050505050565b6001600160a01b038116811461051a575f5ffd5b5f602082840312156107af575f5ffd5b81356102448161078b565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f7576107f76107ba565b604052919050565b5f5f67ffffffffffffffff841115610819576108196107ba565b50601f8301601f191660200161082e816107ce565b915050828152838383011115610842575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f830112610867575f5ffd5b610244838351602085016107ff565b80516001600160e01b03198116811461088d575f5ffd5b919050565b5f5f5f5f5f60a086880312156108a6575f5ffd5b85516108b18161078b565b602087015190955067ffffffffffffffff8111156108cd575f5ffd5b8601601f810188136108dd575f5ffd5b805167ffffffffffffffff8111156108f7576108f76107ba565b8060051b610907602082016107ce565b9182526020818401810192908101908b841115610922575f5ffd5b6020850192505b8383101561097b57825167ffffffffffffffff811115610947575f5ffd5b8501603f81018d13610957575f5ffd5b6109698d6020830151604084016107ff565b83525060209283019290910190610929565b8098505050505050604086015167ffffffffffffffff81111561099c575f5ffd5b6109a888828901610858565b9350506109b760608701610876565b9150608086015167ffffffffffffffff8111156109d2575f5ffd5b6109de88828901610858565b9150509295509295909350565b808201808211156106ab576106ab61068456fea2646970667358221220279d9d6797af016644e3ccab38510ac50a266b554e0ccfc76c6215c485dcca4264736f6c634300081b0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f5f6100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610698565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106df565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079f565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107ba565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610892565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109eb565b6105a4565b6104308361041d83856109eb565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b805160208201516001600160e01b031981169190600482101561067d576001600160e01b0319808360040360031b1b82161692505b5050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106ab576106ab610684565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b038816835260a0602084015280875180835260c08501915060c08160051b8601019250602089015f5b828110156107455760bf198786030184526107308583516106b1565b94506020938401939190910190600101610714565b50505050828103604084015261075b81876106b1565b6001600160e01b0319861660608501529050828103608084015261077f81856106b1565b98975050505050505050565b6001600160a01b038116811461051a575f5ffd5b5f602082840312156107af575f5ffd5b81356102448161078b565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f7576107f76107ba565b604052919050565b5f5f67ffffffffffffffff841115610819576108196107ba565b50601f8301601f191660200161082e816107ce565b915050828152838383011115610842575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f830112610867575f5ffd5b610244838351602085016107ff565b80516001600160e01b03198116811461088d575f5ffd5b919050565b5f5f5f5f5f60a086880312156108a6575f5ffd5b85516108b18161078b565b602087015190955067ffffffffffffffff8111156108cd575f5ffd5b8601601f810188136108dd575f5ffd5b805167ffffffffffffffff8111156108f7576108f76107ba565b8060051b610907602082016107ce565b9182526020818401810192908101908b841115610922575f5ffd5b6020850192505b8383101561097b57825167ffffffffffffffff811115610947575f5ffd5b8501603f81018d13610957575f5ffd5b6109698d6020830151604084016107ff565b83525060209283019290910190610929565b8098505050505050604086015167ffffffffffffffff81111561099c575f5ffd5b6109a888828901610858565b9350506109b760608701610876565b9150608086015167ffffffffffffffff8111156109d2575f5ffd5b6109de88828901610858565b9150509295509295909350565b808201808211156106ab576106ab61068456fea2646970667358221220279d9d6797af016644e3ccab38510ac50a266b554e0ccfc76c6215c485dcca4264736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/src/universalResolver/UpgradableUniversalResolverProxy.sol", + "devdoc": { + "errors": { + "CallerNotAdmin()": [ + { + "details": "Error selector: `0x06d919f2`" + } + ], + "InvalidImplementation()": [ + { + "details": "Error selector: `0x68155f9a`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "SameImplementation()": [ + { + "details": "Error selector: `0x4c3b76bf`" + } + ] + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new admin address", + "previousAdmin": "The previous admin address" + } + }, + "AdminRemoved(address)": { + "params": { + "admin": "The admin address that was removed" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The new implementation address" + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "admin_": "The address of the admin", + "implementation_": "The address of the implementation" + } + }, + "upgradeTo(address)": { + "params": { + "newImplementation": "Address of the new implementation" + } + } + }, + "stateVariables": { + "_ADMIN_SLOT": { + "details": "Storage slot for admin (EIP-1967 compatible)" + }, + "_IMPLEMENTATION_SLOT": { + "details": "Storage slot for implementation address (EIP-1967 compatible)" + } + }, + "title": "UpgradableUniversalResolverProxy", + "version": 1 + }, + "evm": { + "bytecode": { + "functionDebugData": { + "@_74213": { + "entryPoint": null, + "id": 74213, + "parameterSlots": 2, + "returnSlots": 0 + }, + "@_getAdmin_74410": { + "entryPoint": 364, + "id": 74410, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_getImplementation_74397": { + "entryPoint": 333, + "id": 74397, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_setAdmin_74452": { + "entryPoint": 230, + "id": 74452, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_setImplementation_74426": { + "entryPoint": null, + "id": 74426, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_validateImplementation_74384": { + "entryPoint": 110, + "id": 74384, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@getAddressSlot_43156": { + "entryPoint": null, + "id": 43156, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_address_fromMemory": { + "entryPoint": 384, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_tuple_t_addresst_address_fromMemory": { + "entryPoint": 411, + "id": null, + "parameterSlots": 2, + "returnSlots": 2 + } + }, + "generatedSources": [ + { + "ast": { + "nativeSrc": "0:491:389", + "nodeType": "YulBlock", + "src": "0:491:389", + "statements": [ + { + "nativeSrc": "6:3:389", + "nodeType": "YulBlock", + "src": "6:3:389", + "statements": [] + }, + { + "body": { + "nativeSrc": "74:117:389", + "nodeType": "YulBlock", + "src": "74:117:389", + "statements": [ + { + "nativeSrc": "84:22:389", + "nodeType": "YulAssignment", + "src": "84:22:389", + "value": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "99:6:389", + "nodeType": "YulIdentifier", + "src": "99:6:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "93:5:389", + "nodeType": "YulIdentifier", + "src": "93:5:389" + }, + "nativeSrc": "93:13:389", + "nodeType": "YulFunctionCall", + "src": "93:13:389" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "84:5:389", + "nodeType": "YulIdentifier", + "src": "84:5:389" + } + ] + }, + { + "body": { + "nativeSrc": "169:16:389", + "nodeType": "YulBlock", + "src": "169:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "178:1:389", + "nodeType": "YulLiteral", + "src": "178:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "181:1:389", + "nodeType": "YulLiteral", + "src": "181:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "171:6:389", + "nodeType": "YulIdentifier", + "src": "171:6:389" + }, + "nativeSrc": "171:12:389", + "nodeType": "YulFunctionCall", + "src": "171:12:389" + }, + "nativeSrc": "171:12:389", + "nodeType": "YulExpressionStatement", + "src": "171:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "128:5:389", + "nodeType": "YulIdentifier", + "src": "128:5:389" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "139:5:389", + "nodeType": "YulIdentifier", + "src": "139:5:389" + }, + { + "arguments": [ + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "154:3:389", + "nodeType": "YulLiteral", + "src": "154:3:389", + "type": "", + "value": "160" + }, + { + "kind": "number", + "nativeSrc": "159:1:389", + "nodeType": "YulLiteral", + "src": "159:1:389", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "150:3:389", + "nodeType": "YulIdentifier", + "src": "150:3:389" + }, + "nativeSrc": "150:11:389", + "nodeType": "YulFunctionCall", + "src": "150:11:389" + }, + { + "kind": "number", + "nativeSrc": "163:1:389", + "nodeType": "YulLiteral", + "src": "163:1:389", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "146:3:389", + "nodeType": "YulIdentifier", + "src": "146:3:389" + }, + "nativeSrc": "146:19:389", + "nodeType": "YulFunctionCall", + "src": "146:19:389" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "135:3:389", + "nodeType": "YulIdentifier", + "src": "135:3:389" + }, + "nativeSrc": "135:31:389", + "nodeType": "YulFunctionCall", + "src": "135:31:389" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "125:2:389", + "nodeType": "YulIdentifier", + "src": "125:2:389" + }, + "nativeSrc": "125:42:389", + "nodeType": "YulFunctionCall", + "src": "125:42:389" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "118:6:389", + "nodeType": "YulIdentifier", + "src": "118:6:389" + }, + "nativeSrc": "118:50:389", + "nodeType": "YulFunctionCall", + "src": "118:50:389" + }, + "nativeSrc": "115:70:389", + "nodeType": "YulIf", + "src": "115:70:389" + } + ] + }, + "name": "abi_decode_address_fromMemory", + "nativeSrc": "14:177:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "53:6:389", + "nodeType": "YulTypedName", + "src": "53:6:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "64:5:389", + "nodeType": "YulTypedName", + "src": "64:5:389", + "type": "" + } + ], + "src": "14:177:389" + }, + { + "body": { + "nativeSrc": "294:195:389", + "nodeType": "YulBlock", + "src": "294:195:389", + "statements": [ + { + "body": { + "nativeSrc": "340:16:389", + "nodeType": "YulBlock", + "src": "340:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "349:1:389", + "nodeType": "YulLiteral", + "src": "349:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "352:1:389", + "nodeType": "YulLiteral", + "src": "352:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "342:6:389", + "nodeType": "YulIdentifier", + "src": "342:6:389" + }, + "nativeSrc": "342:12:389", + "nodeType": "YulFunctionCall", + "src": "342:12:389" + }, + "nativeSrc": "342:12:389", + "nodeType": "YulExpressionStatement", + "src": "342:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "315:7:389", + "nodeType": "YulIdentifier", + "src": "315:7:389" + }, + { + "name": "headStart", + "nativeSrc": "324:9:389", + "nodeType": "YulIdentifier", + "src": "324:9:389" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "311:3:389", + "nodeType": "YulIdentifier", + "src": "311:3:389" + }, + "nativeSrc": "311:23:389", + "nodeType": "YulFunctionCall", + "src": "311:23:389" + }, + { + "kind": "number", + "nativeSrc": "336:2:389", + "nodeType": "YulLiteral", + "src": "336:2:389", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "307:3:389", + "nodeType": "YulIdentifier", + "src": "307:3:389" + }, + "nativeSrc": "307:32:389", + "nodeType": "YulFunctionCall", + "src": "307:32:389" + }, + "nativeSrc": "304:52:389", + "nodeType": "YulIf", + "src": "304:52:389" + }, + { + "nativeSrc": "365:50:389", + "nodeType": "YulAssignment", + "src": "365:50:389", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "405:9:389", + "nodeType": "YulIdentifier", + "src": "405:9:389" + } + ], + "functionName": { + "name": "abi_decode_address_fromMemory", + "nativeSrc": "375:29:389", + "nodeType": "YulIdentifier", + "src": "375:29:389" + }, + "nativeSrc": "375:40:389", + "nodeType": "YulFunctionCall", + "src": "375:40:389" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "365:6:389", + "nodeType": "YulIdentifier", + "src": "365:6:389" + } + ] + }, + { + "nativeSrc": "424:59:389", + "nodeType": "YulAssignment", + "src": "424:59:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "468:9:389", + "nodeType": "YulIdentifier", + "src": "468:9:389" + }, + { + "kind": "number", + "nativeSrc": "479:2:389", + "nodeType": "YulLiteral", + "src": "479:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "464:3:389", + "nodeType": "YulIdentifier", + "src": "464:3:389" + }, + "nativeSrc": "464:18:389", + "nodeType": "YulFunctionCall", + "src": "464:18:389" + } + ], + "functionName": { + "name": "abi_decode_address_fromMemory", + "nativeSrc": "434:29:389", + "nodeType": "YulIdentifier", + "src": "434:29:389" + }, + "nativeSrc": "434:49:389", + "nodeType": "YulFunctionCall", + "src": "434:49:389" + }, + "variableNames": [ + { + "name": "value1", + "nativeSrc": "424:6:389", + "nodeType": "YulIdentifier", + "src": "424:6:389" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_addresst_address_fromMemory", + "nativeSrc": "196:293:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "252:9:389", + "nodeType": "YulTypedName", + "src": "252:9:389", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "263:7:389", + "nodeType": "YulTypedName", + "src": "263:7:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "275:6:389", + "nodeType": "YulTypedName", + "src": "275:6:389", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "283:6:389", + "nodeType": "YulTypedName", + "src": "283:6:389", + "type": "" + } + ], + "src": "196:293:389" + } + ] + }, + "contents": "{\n { }\n function abi_decode_address_fromMemory(offset) -> value\n {\n value := mload(offset)\n if iszero(eq(value, and(value, sub(shl(160, 1), 1)))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_addresst_address_fromMemory(headStart, dataEnd) -> value0, value1\n {\n if slt(sub(dataEnd, headStart), 64) { revert(0, 0) }\n value0 := abi_decode_address_fromMemory(headStart)\n value1 := abi_decode_address_fromMemory(add(headStart, 32))\n }\n}", + "id": 389, + "language": "Yul", + "name": "#utility.yul" + } + ], + "linkReferences": {}, + "object": "608060405234801561000f575f5ffd5b50604051610c4d380380610c4d83398101604081905261002e9161019b565b6100378161006e565b5f516020610c2d5f395f51905f5280546001600160a01b0319166001600160a01b038316179055610067826100e6565b50506101cc565b6001600160a01b038116158061008c57506001600160a01b0381163b155b156100aa5760405163340aafcd60e11b815260040160405180910390fd5b6001600160a01b0381166100bc61014d565b6001600160a01b0316036100e357604051634c3b76bf60e01b815260040160405180910390fd5b50565b5f6100ef61016c565b9050815f516020610c0d5f395f51905f5280546001600160a01b0319166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b5f5f516020610c2d5f395f51905f525b546001600160a01b0316919050565b5f5f516020610c0d5f395f51905f5261015d565b80516001600160a01b0381168114610196575f5ffd5b919050565b5f5f604083850312156101ac575f5ffd5b6101b583610180565b91506101c360208401610180565b90509250929050565b610a34806101d95f395ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f5f6100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610698565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106df565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079f565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107ba565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610892565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109eb565b6105a4565b6104308361041d83856109eb565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b805160208201516001600160e01b031981169190600482101561067d576001600160e01b0319808360040360031b1b82161692505b5050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106ab576106ab610684565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b038816835260a0602084015280875180835260c08501915060c08160051b8601019250602089015f5b828110156107455760bf198786030184526107308583516106b1565b94506020938401939190910190600101610714565b50505050828103604084015261075b81876106b1565b6001600160e01b0319861660608501529050828103608084015261077f81856106b1565b98975050505050505050565b6001600160a01b038116811461051a575f5ffd5b5f602082840312156107af575f5ffd5b81356102448161078b565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f7576107f76107ba565b604052919050565b5f5f67ffffffffffffffff841115610819576108196107ba565b50601f8301601f191660200161082e816107ce565b915050828152838383011115610842575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f830112610867575f5ffd5b610244838351602085016107ff565b80516001600160e01b03198116811461088d575f5ffd5b919050565b5f5f5f5f5f60a086880312156108a6575f5ffd5b85516108b18161078b565b602087015190955067ffffffffffffffff8111156108cd575f5ffd5b8601601f810188136108dd575f5ffd5b805167ffffffffffffffff8111156108f7576108f76107ba565b8060051b610907602082016107ce565b9182526020818401810192908101908b841115610922575f5ffd5b6020850192505b8383101561097b57825167ffffffffffffffff811115610947575f5ffd5b8501603f81018d13610957575f5ffd5b6109698d6020830151604084016107ff565b83525060209283019290910190610929565b8098505050505050604086015167ffffffffffffffff81111561099c575f5ffd5b6109a888828901610858565b9350506109b760608701610876565b9150608086015167ffffffffffffffff8111156109d2575f5ffd5b6109de88828901610858565b9150509295509295909350565b808201808211156106ab576106ab61068456fea2646970667358221220279d9d6797af016644e3ccab38510ac50a266b554e0ccfc76c6215c485dcca4264736f6c634300081b0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH2 0xC4D CODESIZE SUB DUP1 PUSH2 0xC4D DUP4 CODECOPY DUP2 ADD PUSH1 0x40 DUP2 SWAP1 MSTORE PUSH2 0x2E SWAP2 PUSH2 0x19B JUMP JUMPDEST PUSH2 0x37 DUP2 PUSH2 0x6E JUMP JUMPDEST PUSH0 MLOAD PUSH1 0x20 PUSH2 0xC2D PUSH0 CODECOPY PUSH0 MLOAD SWAP1 PUSH0 MSTORE DUP1 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH2 0x67 DUP3 PUSH2 0xE6 JUMP JUMPDEST POP POP PUSH2 0x1CC JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x8C JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0xAA JUMPI PUSH1 0x40 MLOAD PUSH4 0x340AAFCD PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND PUSH2 0xBC PUSH2 0x14D JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0xE3 JUMPI PUSH1 0x40 MLOAD PUSH4 0x4C3B76BF PUSH1 0xE0 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0xEF PUSH2 0x16C JUMP JUMPDEST SWAP1 POP DUP2 PUSH0 MLOAD PUSH1 0x20 PUSH2 0xC0D PUSH0 CODECOPY PUSH0 MLOAD SWAP1 PUSH0 MSTORE DUP1 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST PUSH0 PUSH0 MLOAD PUSH1 0x20 PUSH2 0xC2D PUSH0 CODECOPY PUSH0 MLOAD SWAP1 PUSH0 MSTORE JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH0 MLOAD PUSH1 0x20 PUSH2 0xC0D PUSH0 CODECOPY PUSH0 MLOAD SWAP1 PUSH0 MSTORE PUSH2 0x15D JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x196 JUMPI PUSH0 PUSH0 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH0 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1AC JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x1B5 DUP4 PUSH2 0x180 JUMP JUMPDEST SWAP2 POP PUSH2 0x1C3 PUSH1 0x20 DUP5 ADD PUSH2 0x180 JUMP JUMPDEST SWAP1 POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH2 0xA34 DUP1 PUSH2 0x1D9 PUSH0 CODECOPY PUSH0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4A JUMPI PUSH0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x3659CFE6 EQ PUSH2 0x176 JUMPI DUP1 PUSH4 0x5C60DA1B EQ PUSH2 0x189 JUMPI DUP1 PUSH4 0x8BAD0C0A EQ PUSH2 0x1AD JUMPI DUP1 PUSH4 0xF851A440 EQ PUSH2 0x1B5 JUMPI JUMPDEST PUSH0 PUSH0 PUSH2 0x54 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH0 CALLDATASIZE PUSH1 0x40 MLOAD PUSH2 0x6D SWAP3 SWAP2 SWAP1 PUSH2 0x639 JUMP JUMPDEST PUSH0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 GAS STATICCALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH0 DUP2 EQ PUSH2 0xA5 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0xAA JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 ISZERO DUP1 ISZERO PUSH2 0xD5 JUMPI POP PUSH4 0x556F183 PUSH1 0xE4 SHL PUSH2 0xC9 DUP3 PUSH2 0x648 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND EQ JUMPDEST ISZERO PUSH2 0x15E JUMPI PUSH0 PUSH2 0xFB PUSH2 0xF6 DUP4 PUSH1 0x4 DUP1 DUP7 MLOAD PUSH2 0xF1 SWAP2 SWAP1 PUSH2 0x698 JUMP JUMPDEST PUSH2 0x1EF JUMP JUMPDEST PUSH2 0x24B JUMP JUMPDEST SWAP1 POP PUSH2 0x105 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 PUSH0 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x15C JUMPI ADDRESS DUP2 PUSH1 0x20 ADD MLOAD DUP3 PUSH1 0x40 ADD MLOAD DUP4 PUSH1 0x60 ADD MLOAD DUP5 PUSH1 0x80 ADD MLOAD PUSH1 0x40 MLOAD PUSH4 0x556F183 PUSH1 0xE4 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x153 SWAP6 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x6DF JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMPDEST DUP2 ISZERO PUSH2 0x16C JUMPI DUP1 MLOAD PUSH1 0x20 DUP3 ADD RETURN JUMPDEST DUP1 MLOAD PUSH1 0x20 DUP3 ADD REVERT JUMPDEST STOP JUMPDEST PUSH2 0x174 PUSH2 0x184 CALLDATASIZE PUSH1 0x4 PUSH2 0x79F JUMP JUMPDEST PUSH2 0x2B6 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x375 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x174 PUSH2 0x383 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x406 JUMP JUMPDEST PUSH0 PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 DUP2 PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x20A JUMPI PUSH2 0x20A PUSH2 0x7BA JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x1F ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x234 JUMPI PUSH1 0x20 DUP3 ADD DUP2 DUP1 CALLDATASIZE DUP4 CALLDATACOPY ADD SWAP1 POP JUMPDEST POP SWAP1 POP PUSH2 0x244 DUP5 DUP5 DUP4 PUSH0 DUP7 PUSH2 0x40F JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0xA0 DUP2 ADD DUP3 MSTORE PUSH0 DUP1 DUP3 MSTORE PUSH1 0x60 PUSH1 0x20 DUP4 ADD DUP2 SWAP1 MSTORE SWAP3 DUP3 ADD DUP4 SWAP1 MSTORE DUP3 DUP3 ADD MSTORE PUSH1 0x80 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP2 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD DUP2 ADD SWAP1 PUSH2 0x288 SWAP2 SWAP1 PUSH2 0x892 JUMP JUMPDEST PUSH1 0x80 DUP7 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND PUSH1 0x60 DUP6 ADD MSTORE PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x20 DUP4 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x2BE PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x2EF JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0x2F8 DUP2 PUSH2 0x473 JUMP JUMPDEST PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xBC7CD75A20EE27FD9ADEBAB32041F755214DBC6BFFA90CC0225B39DA2E5C2D3B SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x1BD JUMP JUMPDEST SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x38B PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x3BC JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH0 PUSH2 0x3C5 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP PUSH2 0x3D0 PUSH0 PUSH2 0x51D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xA3B62BC36326052D97EA62D63C3D60308ED4C3EA8AC079DD8499F1E9C4F80C0F SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x44C JUMP JUMPDEST PUSH2 0x422 DUP6 PUSH2 0x41D DUP4 DUP8 PUSH2 0x9EB JUMP JUMPDEST PUSH2 0x5A4 JUMP JUMPDEST PUSH2 0x430 DUP4 PUSH2 0x41D DUP4 DUP6 PUSH2 0x9EB JUMP JUMPDEST PUSH2 0x445 DUP3 PUSH1 0x20 DUP6 ADD ADD DUP6 PUSH1 0x20 DUP9 ADD ADD DUP4 PUSH2 0x5F0 JUMP JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH0 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 PUSH2 0x1E0 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x491 JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0x4C8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x68155F9A00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH2 0x4DA PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x51A JUMPI PUSH1 0x40 MLOAD PUSH32 0x4C3B76BF00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0x526 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP DUP2 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST DUP2 MLOAD DUP2 GT ISZERO PUSH2 0x5EC JUMPI DUP2 MLOAD PUSH1 0x40 MLOAD PUSH32 0x8A3C1CFB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x153 SWAP2 DUP4 SWAP2 PUSH1 0x4 ADD SWAP2 DUP3 MSTORE PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST POP POP JUMP JUMPDEST JUMPDEST PUSH1 0x1F DUP2 GT ISZERO PUSH2 0x611 JUMPI DUP2 MLOAD DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1F NOT ADD PUSH2 0x5F1 JUMP JUMPDEST DUP1 ISZERO PUSH2 0x634 JUMPI DUP2 MLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0x20 DUP5 SWAP1 SUB PUSH1 0x3 SHL SHL PUSH0 NOT ADD DUP1 NOT SWAP1 SWAP3 AND SWAP2 AND OR DUP4 MSTORE JUMPDEST POP POP POP JUMP JUMPDEST DUP2 DUP4 DUP3 CALLDATACOPY PUSH0 SWAP2 ADD SWAP1 DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST DUP1 MLOAD PUSH1 0x20 DUP3 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP2 AND SWAP2 SWAP1 PUSH1 0x4 DUP3 LT ISZERO PUSH2 0x67D JUMPI PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP1 DUP4 PUSH1 0x4 SUB PUSH1 0x3 SHL SHL DUP3 AND AND SWAP3 POP JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x11 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST DUP2 DUP2 SUB DUP2 DUP2 GT ISZERO PUSH2 0x6AB JUMPI PUSH2 0x6AB PUSH2 0x684 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 DUP2 MLOAD DUP1 DUP5 MSTORE DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP7 ADD MCOPY PUSH0 PUSH1 0x20 DUP3 DUP7 ADD ADD MSTORE PUSH1 0x20 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 PUSH1 0xA0 DUP3 ADD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP9 AND DUP4 MSTORE PUSH1 0xA0 PUSH1 0x20 DUP5 ADD MSTORE DUP1 DUP8 MLOAD DUP1 DUP4 MSTORE PUSH1 0xC0 DUP6 ADD SWAP2 POP PUSH1 0xC0 DUP2 PUSH1 0x5 SHL DUP7 ADD ADD SWAP3 POP PUSH1 0x20 DUP10 ADD PUSH0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x745 JUMPI PUSH1 0xBF NOT DUP8 DUP7 SUB ADD DUP5 MSTORE PUSH2 0x730 DUP6 DUP4 MLOAD PUSH2 0x6B1 JUMP JUMPDEST SWAP5 POP PUSH1 0x20 SWAP4 DUP5 ADD SWAP4 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x714 JUMP JUMPDEST POP POP POP POP DUP3 DUP2 SUB PUSH1 0x40 DUP5 ADD MSTORE PUSH2 0x75B DUP2 DUP8 PUSH2 0x6B1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP7 AND PUSH1 0x60 DUP6 ADD MSTORE SWAP1 POP DUP3 DUP2 SUB PUSH1 0x80 DUP5 ADD MSTORE PUSH2 0x77F DUP2 DUP6 PUSH2 0x6B1 JUMP JUMPDEST SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x51A JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x7AF JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x244 DUP2 PUSH2 0x78B JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x41 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1F DUP3 ADD PUSH1 0x1F NOT AND DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x7F7 JUMPI PUSH2 0x7F7 PUSH2 0x7BA JUMP JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH0 PUSH8 0xFFFFFFFFFFFFFFFF DUP5 GT ISZERO PUSH2 0x819 JUMPI PUSH2 0x819 PUSH2 0x7BA JUMP JUMPDEST POP PUSH1 0x1F DUP4 ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD PUSH2 0x82E DUP2 PUSH2 0x7CE JUMP JUMPDEST SWAP2 POP POP DUP3 DUP2 MSTORE DUP4 DUP4 DUP4 ADD GT ISZERO PUSH2 0x842 JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP3 DUP3 PUSH1 0x20 DUP4 ADD MCOPY PUSH0 PUSH1 0x20 DUP5 DUP4 ADD ADD MSTORE SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x867 JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x244 DUP4 DUP4 MLOAD PUSH1 0x20 DUP6 ADD PUSH2 0x7FF JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP2 AND DUP2 EQ PUSH2 0x88D JUMPI PUSH0 PUSH0 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH0 PUSH0 PUSH0 PUSH0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0x8A6 JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP6 MLOAD PUSH2 0x8B1 DUP2 PUSH2 0x78B JUMP JUMPDEST PUSH1 0x20 DUP8 ADD MLOAD SWAP1 SWAP6 POP PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x8CD JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP7 ADD PUSH1 0x1F DUP2 ADD DUP9 SGT PUSH2 0x8DD JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP1 MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x8F7 JUMPI PUSH2 0x8F7 PUSH2 0x7BA JUMP JUMPDEST DUP1 PUSH1 0x5 SHL PUSH2 0x907 PUSH1 0x20 DUP3 ADD PUSH2 0x7CE JUMP JUMPDEST SWAP2 DUP3 MSTORE PUSH1 0x20 DUP2 DUP5 ADD DUP2 ADD SWAP3 SWAP1 DUP2 ADD SWAP1 DUP12 DUP5 GT ISZERO PUSH2 0x922 JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH1 0x20 DUP6 ADD SWAP3 POP JUMPDEST DUP4 DUP4 LT ISZERO PUSH2 0x97B JUMPI DUP3 MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x947 JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP6 ADD PUSH1 0x3F DUP2 ADD DUP14 SGT PUSH2 0x957 JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x969 DUP14 PUSH1 0x20 DUP4 ADD MLOAD PUSH1 0x40 DUP5 ADD PUSH2 0x7FF JUMP JUMPDEST DUP4 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP1 SWAP2 ADD SWAP1 PUSH2 0x929 JUMP JUMPDEST DUP1 SWAP9 POP POP POP POP POP POP PUSH1 0x40 DUP7 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x99C JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x9A8 DUP9 DUP3 DUP10 ADD PUSH2 0x858 JUMP JUMPDEST SWAP4 POP POP PUSH2 0x9B7 PUSH1 0x60 DUP8 ADD PUSH2 0x876 JUMP JUMPDEST SWAP2 POP PUSH1 0x80 DUP7 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x9D2 JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x9DE DUP9 DUP3 DUP10 ADD PUSH2 0x858 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 POP SWAP3 SWAP6 SWAP1 SWAP4 POP JUMP JUMPDEST DUP1 DUP3 ADD DUP1 DUP3 GT ISZERO PUSH2 0x6AB JUMPI PUSH2 0x6AB PUSH2 0x684 JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0x27 SWAP14 SWAP14 PUSH8 0x97AF016644E3CCAB CODESIZE MLOAD EXP 0xC5 EXP 0x26 PUSH12 0x554E0CCFC76C6215C485DCCA TIMESTAMP PUSH5 0x736F6C6343 STOP ADDMOD SHL STOP CALLER 0xB5 BALANCE 0x27 PUSH9 0x4A568B3173AE13B9F8 0xA6 ADD PUSH15 0x243E63B6E8EE1178D6A717850B5D61 SUB CALLDATASIZE ADDMOD SWAP5 LOG1 EXTCODESIZE LOG1 LOG3 0x21 MOD PUSH8 0xC828492DB98DCA3E KECCAK256 PUSH23 0xCC3735A920A3CA505D382BBC0000000000000000000000 ", + "sourceMap": "490:6212:367:-:0;;;2878:182;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2941:40;2965:15;2941:23;:40::i;:::-;-1:-1:-1;;;;;;;;;;;6350:74:367;;-1:-1:-1;;;;;;6350:74:367;-1:-1:-1;;;;;6350:74:367;;;;;3036:17;3046:6;3036:9;:17::i;:::-;2878:182;;490:6212;;5307:328;-1:-1:-1;;;;;5395:31:367;;;;:69;;-1:-1:-1;;;;;;5430:29:367;;;:34;5395:69;5391:130;;;5487:23;;-1:-1:-1;;;5487:23:367;;;;;;;;;;;5391:130;-1:-1:-1;;;;;5534:41:367;;:20;:18;:20::i;:::-;-1:-1:-1;;;;;5534:41:367;;5530:99;;5598:20;;-1:-1:-1;;;5598:20:367;;;;;;;;;;;5530:99;5307:328;:::o;6485:215::-;6540:21;6564:11;:9;:11::i;:::-;6540:35;-1:-1:-1;6633:8:367;-1:-1:-1;;;;;;;;;;;6585:56:367;;-1:-1:-1;;;;;;6585:56:367;-1:-1:-1;;;;;6585:56:367;;;;;;6656:37;;;;;;;;;;;-1:-1:-1;;6656:37:367;6530:170;6485:215;:::o;5708:140::-;5761:7;-1:-1:-1;;;;;;;;;;;5787:48:367;:54;-1:-1:-1;;;;;5787:54:367;;5708:140;-1:-1:-1;5708:140:367:o;5912:122::-;5956:7;-1:-1:-1;;;;;;;;;;;5982:39:367;1899:163:254;14:177:389;93:13;;-1:-1:-1;;;;;135:31:389;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:293::-;275:6;283;336:2;324:9;315:7;311:23;307:32;304:52;;;352:1;349;342:12;304:52;375:40;405:9;375:40;:::i;:::-;365:50;;434:49;479:2;468:9;464:18;434:49;:::i;:::-;424:59;;196:293;;;;;:::o;:::-;490:6212:367;;;;;;" + }, + "deployedBytecode": { + "functionDebugData": { + "@_74287": { + "entryPoint": null, + "id": 74287, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@_checkBound_20023": { + "entryPoint": 1444, + "id": 20023, + "parameterSlots": 2, + "returnSlots": 0 + }, + "@_getAdmin_74410": { + "entryPoint": 1100, + "id": 74410, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_getImplementation_74397": { + "entryPoint": 445, + "id": 74397, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_setAdmin_74452": { + "entryPoint": 1309, + "id": 74452, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_setImplementation_74426": { + "entryPoint": null, + "id": 74426, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_validateImplementation_74384": { + "entryPoint": 1139, + "id": 74384, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@admin_74351": { + "entryPoint": 1030, + "id": 74351, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@copyBytes_20522": { + "entryPoint": 1039, + "id": 20522, + "parameterSlots": 5, + "returnSlots": 0 + }, + "@copy_21729": { + "entryPoint": 1520, + "id": 21729, + "parameterSlots": 3, + "returnSlots": 0 + }, + "@decode_1550": { + "entryPoint": 587, + "id": 1550, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@getAddressSlot_43156": { + "entryPoint": null, + "id": 43156, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@implementation_74341": { + "entryPoint": 885, + "id": 74341, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@ptr_21739": { + "entryPoint": null, + "id": 21739, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@renounceAdmin_74331": { + "entryPoint": 899, + "id": 74331, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@substring_20550": { + "entryPoint": 495, + "id": 20550, + "parameterSlots": 3, + "returnSlots": 1 + }, + "@upgradeTo_74308": { + "entryPoint": 694, + "id": 74308, + "parameterSlots": 1, + "returnSlots": 0 + }, + "abi_decode_available_length_string_fromMemory": { + "entryPoint": 2047, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "abi_decode_bytes4_fromMemory": { + "entryPoint": 2166, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_bytes_fromMemory": { + "entryPoint": 2136, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_decode_tuple_t_address": { + "entryPoint": 1951, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory": { + "entryPoint": 2194, + "id": null, + "parameterSlots": 2, + "returnSlots": 5 + }, + "abi_encode_bytes4": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 0 + }, + "abi_encode_string": { + "entryPoint": 1713, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed": { + "entryPoint": 1593, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "abi_encode_tuple_t_address__to_t_address__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed": { + "entryPoint": 1759, + "id": null, + "parameterSlots": 6, + "returnSlots": 1 + }, + "abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "allocate_memory": { + "entryPoint": 1998, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "checked_add_t_uint256": { + "entryPoint": 2539, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "checked_sub_t_uint256": { + "entryPoint": 1688, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4": { + "entryPoint": 1608, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "panic_error_0x11": { + "entryPoint": 1668, + "id": null, + "parameterSlots": 0, + "returnSlots": 0 + }, + "panic_error_0x41": { + "entryPoint": 1978, + "id": null, + "parameterSlots": 0, + "returnSlots": 0 + }, + "validator_revert_address": { + "entryPoint": 1931, + "id": null, + "parameterSlots": 1, + "returnSlots": 0 + } + }, + "generatedSources": [ + { + "ast": { + "nativeSrc": "0:7179:389", + "nodeType": "YulBlock", + "src": "0:7179:389", + "statements": [ + { + "nativeSrc": "6:3:389", + "nodeType": "YulBlock", + "src": "6:3:389", + "statements": [] + }, + { + "body": { + "nativeSrc": "161:124:389", + "nodeType": "YulBlock", + "src": "161:124:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "184:3:389", + "nodeType": "YulIdentifier", + "src": "184:3:389" + }, + { + "name": "value0", + "nativeSrc": "189:6:389", + "nodeType": "YulIdentifier", + "src": "189:6:389" + }, + { + "name": "value1", + "nativeSrc": "197:6:389", + "nodeType": "YulIdentifier", + "src": "197:6:389" + } + ], + "functionName": { + "name": "calldatacopy", + "nativeSrc": "171:12:389", + "nodeType": "YulIdentifier", + "src": "171:12:389" + }, + "nativeSrc": "171:33:389", + "nodeType": "YulFunctionCall", + "src": "171:33:389" + }, + "nativeSrc": "171:33:389", + "nodeType": "YulExpressionStatement", + "src": "171:33:389" + }, + { + "nativeSrc": "213:26:389", + "nodeType": "YulVariableDeclaration", + "src": "213:26:389", + "value": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "227:3:389", + "nodeType": "YulIdentifier", + "src": "227:3:389" + }, + { + "name": "value1", + "nativeSrc": "232:6:389", + "nodeType": "YulIdentifier", + "src": "232:6:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "223:3:389", + "nodeType": "YulIdentifier", + "src": "223:3:389" + }, + "nativeSrc": "223:16:389", + "nodeType": "YulFunctionCall", + "src": "223:16:389" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "217:2:389", + "nodeType": "YulTypedName", + "src": "217:2:389", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "255:2:389", + "nodeType": "YulIdentifier", + "src": "255:2:389" + }, + { + "kind": "number", + "nativeSrc": "259:1:389", + "nodeType": "YulLiteral", + "src": "259:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "248:6:389", + "nodeType": "YulIdentifier", + "src": "248:6:389" + }, + "nativeSrc": "248:13:389", + "nodeType": "YulFunctionCall", + "src": "248:13:389" + }, + "nativeSrc": "248:13:389", + "nodeType": "YulExpressionStatement", + "src": "248:13:389" + }, + { + "nativeSrc": "270:9:389", + "nodeType": "YulAssignment", + "src": "270:9:389", + "value": { + "name": "_1", + "nativeSrc": "277:2:389", + "nodeType": "YulIdentifier", + "src": "277:2:389" + }, + "variableNames": [ + { + "name": "end", + "nativeSrc": "270:3:389", + "nodeType": "YulIdentifier", + "src": "270:3:389" + } + ] + } + ] + }, + "name": "abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed", + "nativeSrc": "14:271:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "pos", + "nativeSrc": "129:3:389", + "nodeType": "YulTypedName", + "src": "129:3:389", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "134:6:389", + "nodeType": "YulTypedName", + "src": "134:6:389", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "142:6:389", + "nodeType": "YulTypedName", + "src": "142:6:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "end", + "nativeSrc": "153:3:389", + "nodeType": "YulTypedName", + "src": "153:3:389", + "type": "" + } + ], + "src": "14:271:389" + }, + { + "body": { + "nativeSrc": "383:421:389", + "nodeType": "YulBlock", + "src": "383:421:389", + "statements": [ + { + "nativeSrc": "393:26:389", + "nodeType": "YulVariableDeclaration", + "src": "393:26:389", + "value": { + "arguments": [ + { + "name": "array", + "nativeSrc": "413:5:389", + "nodeType": "YulIdentifier", + "src": "413:5:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "407:5:389", + "nodeType": "YulIdentifier", + "src": "407:5:389" + }, + "nativeSrc": "407:12:389", + "nodeType": "YulFunctionCall", + "src": "407:12:389" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "397:6:389", + "nodeType": "YulTypedName", + "src": "397:6:389", + "type": "" + } + ] + }, + { + "nativeSrc": "428:33:389", + "nodeType": "YulVariableDeclaration", + "src": "428:33:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "448:5:389", + "nodeType": "YulIdentifier", + "src": "448:5:389" + }, + { + "kind": "number", + "nativeSrc": "455:4:389", + "nodeType": "YulLiteral", + "src": "455:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "444:3:389", + "nodeType": "YulIdentifier", + "src": "444:3:389" + }, + "nativeSrc": "444:16:389", + "nodeType": "YulFunctionCall", + "src": "444:16:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "438:5:389", + "nodeType": "YulIdentifier", + "src": "438:5:389" + }, + "nativeSrc": "438:23:389", + "nodeType": "YulFunctionCall", + "src": "438:23:389" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "432:2:389", + "nodeType": "YulTypedName", + "src": "432:2:389", + "type": "" + } + ] + }, + { + "nativeSrc": "470:84:389", + "nodeType": "YulAssignment", + "src": "470:84:389", + "value": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "483:2:389", + "nodeType": "YulIdentifier", + "src": "483:2:389" + }, + { + "kind": "number", + "nativeSrc": "487:66:389", + "nodeType": "YulLiteral", + "src": "487:66:389", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "479:3:389", + "nodeType": "YulIdentifier", + "src": "479:3:389" + }, + "nativeSrc": "479:75:389", + "nodeType": "YulFunctionCall", + "src": "479:75:389" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "470:5:389", + "nodeType": "YulIdentifier", + "src": "470:5:389" + } + ] + }, + { + "body": { + "nativeSrc": "588:210:389", + "nodeType": "YulBlock", + "src": "588:210:389", + "statements": [ + { + "nativeSrc": "602:186:389", + "nodeType": "YulAssignment", + "src": "602:186:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_1", + "nativeSrc": "619:2:389", + "nodeType": "YulIdentifier", + "src": "619:2:389" + }, + { + "arguments": [ + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "631:1:389", + "nodeType": "YulLiteral", + "src": "631:1:389", + "type": "", + "value": "3" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "638:1:389", + "nodeType": "YulLiteral", + "src": "638:1:389", + "type": "", + "value": "4" + }, + { + "name": "length", + "nativeSrc": "641:6:389", + "nodeType": "YulIdentifier", + "src": "641:6:389" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "634:3:389", + "nodeType": "YulIdentifier", + "src": "634:3:389" + }, + "nativeSrc": "634:14:389", + "nodeType": "YulFunctionCall", + "src": "634:14:389" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "627:3:389", + "nodeType": "YulIdentifier", + "src": "627:3:389" + }, + "nativeSrc": "627:22:389", + "nodeType": "YulFunctionCall", + "src": "627:22:389" + }, + { + "kind": "number", + "nativeSrc": "651:66:389", + "nodeType": "YulLiteral", + "src": "651:66:389", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "623:3:389", + "nodeType": "YulIdentifier", + "src": "623:3:389" + }, + "nativeSrc": "623:95:389", + "nodeType": "YulFunctionCall", + "src": "623:95:389" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "615:3:389", + "nodeType": "YulIdentifier", + "src": "615:3:389" + }, + "nativeSrc": "615:104:389", + "nodeType": "YulFunctionCall", + "src": "615:104:389" + }, + { + "kind": "number", + "nativeSrc": "721:66:389", + "nodeType": "YulLiteral", + "src": "721:66:389", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "611:3:389", + "nodeType": "YulIdentifier", + "src": "611:3:389" + }, + "nativeSrc": "611:177:389", + "nodeType": "YulFunctionCall", + "src": "611:177:389" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "602:5:389", + "nodeType": "YulIdentifier", + "src": "602:5:389" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "length", + "nativeSrc": "569:6:389", + "nodeType": "YulIdentifier", + "src": "569:6:389" + }, + { + "kind": "number", + "nativeSrc": "577:1:389", + "nodeType": "YulLiteral", + "src": "577:1:389", + "type": "", + "value": "4" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "566:2:389", + "nodeType": "YulIdentifier", + "src": "566:2:389" + }, + "nativeSrc": "566:13:389", + "nodeType": "YulFunctionCall", + "src": "566:13:389" + }, + "nativeSrc": "563:235:389", + "nodeType": "YulIf", + "src": "563:235:389" + } + ] + }, + "name": "convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4", + "nativeSrc": "290:514:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "array", + "nativeSrc": "363:5:389", + "nodeType": "YulTypedName", + "src": "363:5:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "373:5:389", + "nodeType": "YulTypedName", + "src": "373:5:389", + "type": "" + } + ], + "src": "290:514:389" + }, + { + "body": { + "nativeSrc": "841:152:389", + "nodeType": "YulBlock", + "src": "841:152:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "858:1:389", + "nodeType": "YulLiteral", + "src": "858:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "861:77:389", + "nodeType": "YulLiteral", + "src": "861:77:389", + "type": "", + "value": "35408467139433450592217433187231851964531694900788300625387963629091585785856" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "851:6:389", + "nodeType": "YulIdentifier", + "src": "851:6:389" + }, + "nativeSrc": "851:88:389", + "nodeType": "YulFunctionCall", + "src": "851:88:389" + }, + "nativeSrc": "851:88:389", + "nodeType": "YulExpressionStatement", + "src": "851:88:389" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "955:1:389", + "nodeType": "YulLiteral", + "src": "955:1:389", + "type": "", + "value": "4" + }, + { + "kind": "number", + "nativeSrc": "958:4:389", + "nodeType": "YulLiteral", + "src": "958:4:389", + "type": "", + "value": "0x11" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "948:6:389", + "nodeType": "YulIdentifier", + "src": "948:6:389" + }, + "nativeSrc": "948:15:389", + "nodeType": "YulFunctionCall", + "src": "948:15:389" + }, + "nativeSrc": "948:15:389", + "nodeType": "YulExpressionStatement", + "src": "948:15:389" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "979:1:389", + "nodeType": "YulLiteral", + "src": "979:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "982:4:389", + "nodeType": "YulLiteral", + "src": "982:4:389", + "type": "", + "value": "0x24" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "972:6:389", + "nodeType": "YulIdentifier", + "src": "972:6:389" + }, + "nativeSrc": "972:15:389", + "nodeType": "YulFunctionCall", + "src": "972:15:389" + }, + "nativeSrc": "972:15:389", + "nodeType": "YulExpressionStatement", + "src": "972:15:389" + } + ] + }, + "name": "panic_error_0x11", + "nativeSrc": "809:184:389", + "nodeType": "YulFunctionDefinition", + "src": "809:184:389" + }, + { + "body": { + "nativeSrc": "1047:79:389", + "nodeType": "YulBlock", + "src": "1047:79:389", + "statements": [ + { + "nativeSrc": "1057:17:389", + "nodeType": "YulAssignment", + "src": "1057:17:389", + "value": { + "arguments": [ + { + "name": "x", + "nativeSrc": "1069:1:389", + "nodeType": "YulIdentifier", + "src": "1069:1:389" + }, + { + "name": "y", + "nativeSrc": "1072:1:389", + "nodeType": "YulIdentifier", + "src": "1072:1:389" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "1065:3:389", + "nodeType": "YulIdentifier", + "src": "1065:3:389" + }, + "nativeSrc": "1065:9:389", + "nodeType": "YulFunctionCall", + "src": "1065:9:389" + }, + "variableNames": [ + { + "name": "diff", + "nativeSrc": "1057:4:389", + "nodeType": "YulIdentifier", + "src": "1057:4:389" + } + ] + }, + { + "body": { + "nativeSrc": "1098:22:389", + "nodeType": "YulBlock", + "src": "1098:22:389", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x11", + "nativeSrc": "1100:16:389", + "nodeType": "YulIdentifier", + "src": "1100:16:389" + }, + "nativeSrc": "1100:18:389", + "nodeType": "YulFunctionCall", + "src": "1100:18:389" + }, + "nativeSrc": "1100:18:389", + "nodeType": "YulExpressionStatement", + "src": "1100:18:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "diff", + "nativeSrc": "1089:4:389", + "nodeType": "YulIdentifier", + "src": "1089:4:389" + }, + { + "name": "x", + "nativeSrc": "1095:1:389", + "nodeType": "YulIdentifier", + "src": "1095:1:389" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "1086:2:389", + "nodeType": "YulIdentifier", + "src": "1086:2:389" + }, + "nativeSrc": "1086:11:389", + "nodeType": "YulFunctionCall", + "src": "1086:11:389" + }, + "nativeSrc": "1083:37:389", + "nodeType": "YulIf", + "src": "1083:37:389" + } + ] + }, + "name": "checked_sub_t_uint256", + "nativeSrc": "998:128:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "x", + "nativeSrc": "1029:1:389", + "nodeType": "YulTypedName", + "src": "1029:1:389", + "type": "" + }, + { + "name": "y", + "nativeSrc": "1032:1:389", + "nodeType": "YulTypedName", + "src": "1032:1:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "diff", + "nativeSrc": "1038:4:389", + "nodeType": "YulTypedName", + "src": "1038:4:389", + "type": "" + } + ], + "src": "998:128:389" + }, + { + "body": { + "nativeSrc": "1181:239:389", + "nodeType": "YulBlock", + "src": "1181:239:389", + "statements": [ + { + "nativeSrc": "1191:26:389", + "nodeType": "YulVariableDeclaration", + "src": "1191:26:389", + "value": { + "arguments": [ + { + "name": "value", + "nativeSrc": "1211:5:389", + "nodeType": "YulIdentifier", + "src": "1211:5:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "1205:5:389", + "nodeType": "YulIdentifier", + "src": "1205:5:389" + }, + "nativeSrc": "1205:12:389", + "nodeType": "YulFunctionCall", + "src": "1205:12:389" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "1195:6:389", + "nodeType": "YulTypedName", + "src": "1195:6:389", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1233:3:389", + "nodeType": "YulIdentifier", + "src": "1233:3:389" + }, + { + "name": "length", + "nativeSrc": "1238:6:389", + "nodeType": "YulIdentifier", + "src": "1238:6:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1226:6:389", + "nodeType": "YulIdentifier", + "src": "1226:6:389" + }, + "nativeSrc": "1226:19:389", + "nodeType": "YulFunctionCall", + "src": "1226:19:389" + }, + "nativeSrc": "1226:19:389", + "nodeType": "YulExpressionStatement", + "src": "1226:19:389" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1264:3:389", + "nodeType": "YulIdentifier", + "src": "1264:3:389" + }, + { + "kind": "number", + "nativeSrc": "1269:4:389", + "nodeType": "YulLiteral", + "src": "1269:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1260:3:389", + "nodeType": "YulIdentifier", + "src": "1260:3:389" + }, + "nativeSrc": "1260:14:389", + "nodeType": "YulFunctionCall", + "src": "1260:14:389" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "1280:5:389", + "nodeType": "YulIdentifier", + "src": "1280:5:389" + }, + { + "kind": "number", + "nativeSrc": "1287:4:389", + "nodeType": "YulLiteral", + "src": "1287:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1276:3:389", + "nodeType": "YulIdentifier", + "src": "1276:3:389" + }, + "nativeSrc": "1276:16:389", + "nodeType": "YulFunctionCall", + "src": "1276:16:389" + }, + { + "name": "length", + "nativeSrc": "1294:6:389", + "nodeType": "YulIdentifier", + "src": "1294:6:389" + } + ], + "functionName": { + "name": "mcopy", + "nativeSrc": "1254:5:389", + "nodeType": "YulIdentifier", + "src": "1254:5:389" + }, + "nativeSrc": "1254:47:389", + "nodeType": "YulFunctionCall", + "src": "1254:47:389" + }, + "nativeSrc": "1254:47:389", + "nodeType": "YulExpressionStatement", + "src": "1254:47:389" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1325:3:389", + "nodeType": "YulIdentifier", + "src": "1325:3:389" + }, + { + "name": "length", + "nativeSrc": "1330:6:389", + "nodeType": "YulIdentifier", + "src": "1330:6:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1321:3:389", + "nodeType": "YulIdentifier", + "src": "1321:3:389" + }, + "nativeSrc": "1321:16:389", + "nodeType": "YulFunctionCall", + "src": "1321:16:389" + }, + { + "kind": "number", + "nativeSrc": "1339:4:389", + "nodeType": "YulLiteral", + "src": "1339:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1317:3:389", + "nodeType": "YulIdentifier", + "src": "1317:3:389" + }, + "nativeSrc": "1317:27:389", + "nodeType": "YulFunctionCall", + "src": "1317:27:389" + }, + { + "kind": "number", + "nativeSrc": "1346:1:389", + "nodeType": "YulLiteral", + "src": "1346:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1310:6:389", + "nodeType": "YulIdentifier", + "src": "1310:6:389" + }, + "nativeSrc": "1310:38:389", + "nodeType": "YulFunctionCall", + "src": "1310:38:389" + }, + "nativeSrc": "1310:38:389", + "nodeType": "YulExpressionStatement", + "src": "1310:38:389" + }, + { + "nativeSrc": "1357:57:389", + "nodeType": "YulAssignment", + "src": "1357:57:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1372:3:389", + "nodeType": "YulIdentifier", + "src": "1372:3:389" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "length", + "nativeSrc": "1385:6:389", + "nodeType": "YulIdentifier", + "src": "1385:6:389" + }, + { + "kind": "number", + "nativeSrc": "1393:2:389", + "nodeType": "YulLiteral", + "src": "1393:2:389", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1381:3:389", + "nodeType": "YulIdentifier", + "src": "1381:3:389" + }, + "nativeSrc": "1381:15:389", + "nodeType": "YulFunctionCall", + "src": "1381:15:389" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "1402:2:389", + "nodeType": "YulLiteral", + "src": "1402:2:389", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "1398:3:389", + "nodeType": "YulIdentifier", + "src": "1398:3:389" + }, + "nativeSrc": "1398:7:389", + "nodeType": "YulFunctionCall", + "src": "1398:7:389" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1377:3:389", + "nodeType": "YulIdentifier", + "src": "1377:3:389" + }, + "nativeSrc": "1377:29:389", + "nodeType": "YulFunctionCall", + "src": "1377:29:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1368:3:389", + "nodeType": "YulIdentifier", + "src": "1368:3:389" + }, + "nativeSrc": "1368:39:389", + "nodeType": "YulFunctionCall", + "src": "1368:39:389" + }, + { + "kind": "number", + "nativeSrc": "1409:4:389", + "nodeType": "YulLiteral", + "src": "1409:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1364:3:389", + "nodeType": "YulIdentifier", + "src": "1364:3:389" + }, + "nativeSrc": "1364:50:389", + "nodeType": "YulFunctionCall", + "src": "1364:50:389" + }, + "variableNames": [ + { + "name": "end", + "nativeSrc": "1357:3:389", + "nodeType": "YulIdentifier", + "src": "1357:3:389" + } + ] + } + ] + }, + "name": "abi_encode_string", + "nativeSrc": "1131:289:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "1158:5:389", + "nodeType": "YulTypedName", + "src": "1158:5:389", + "type": "" + }, + { + "name": "pos", + "nativeSrc": "1165:3:389", + "nodeType": "YulTypedName", + "src": "1165:3:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "end", + "nativeSrc": "1173:3:389", + "nodeType": "YulTypedName", + "src": "1173:3:389", + "type": "" + } + ], + "src": "1131:289:389" + }, + { + "body": { + "nativeSrc": "1468:107:389", + "nodeType": "YulBlock", + "src": "1468:107:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1485:3:389", + "nodeType": "YulIdentifier", + "src": "1485:3:389" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "1494:5:389", + "nodeType": "YulIdentifier", + "src": "1494:5:389" + }, + { + "kind": "number", + "nativeSrc": "1501:66:389", + "nodeType": "YulLiteral", + "src": "1501:66:389", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1490:3:389", + "nodeType": "YulIdentifier", + "src": "1490:3:389" + }, + "nativeSrc": "1490:78:389", + "nodeType": "YulFunctionCall", + "src": "1490:78:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1478:6:389", + "nodeType": "YulIdentifier", + "src": "1478:6:389" + }, + "nativeSrc": "1478:91:389", + "nodeType": "YulFunctionCall", + "src": "1478:91:389" + }, + "nativeSrc": "1478:91:389", + "nodeType": "YulExpressionStatement", + "src": "1478:91:389" + } + ] + }, + "name": "abi_encode_bytes4", + "nativeSrc": "1425:150:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "1452:5:389", + "nodeType": "YulTypedName", + "src": "1452:5:389", + "type": "" + }, + { + "name": "pos", + "nativeSrc": "1459:3:389", + "nodeType": "YulTypedName", + "src": "1459:3:389", + "type": "" + } + ], + "src": "1425:150:389" + }, + { + "body": { + "nativeSrc": "1897:964:389", + "nodeType": "YulBlock", + "src": "1897:964:389", + "statements": [ + { + "nativeSrc": "1907:33:389", + "nodeType": "YulVariableDeclaration", + "src": "1907:33:389", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "1925:9:389", + "nodeType": "YulIdentifier", + "src": "1925:9:389" + }, + { + "kind": "number", + "nativeSrc": "1936:3:389", + "nodeType": "YulLiteral", + "src": "1936:3:389", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1921:3:389", + "nodeType": "YulIdentifier", + "src": "1921:3:389" + }, + "nativeSrc": "1921:19:389", + "nodeType": "YulFunctionCall", + "src": "1921:19:389" + }, + "variables": [ + { + "name": "tail_1", + "nativeSrc": "1911:6:389", + "nodeType": "YulTypedName", + "src": "1911:6:389", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "1956:9:389", + "nodeType": "YulIdentifier", + "src": "1956:9:389" + }, + { + "arguments": [ + { + "name": "value0", + "nativeSrc": "1971:6:389", + "nodeType": "YulIdentifier", + "src": "1971:6:389" + }, + { + "kind": "number", + "nativeSrc": "1979:42:389", + "nodeType": "YulLiteral", + "src": "1979:42:389", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1967:3:389", + "nodeType": "YulIdentifier", + "src": "1967:3:389" + }, + "nativeSrc": "1967:55:389", + "nodeType": "YulFunctionCall", + "src": "1967:55:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1949:6:389", + "nodeType": "YulIdentifier", + "src": "1949:6:389" + }, + "nativeSrc": "1949:74:389", + "nodeType": "YulFunctionCall", + "src": "1949:74:389" + }, + "nativeSrc": "1949:74:389", + "nodeType": "YulExpressionStatement", + "src": "1949:74:389" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2043:9:389", + "nodeType": "YulIdentifier", + "src": "2043:9:389" + }, + { + "kind": "number", + "nativeSrc": "2054:2:389", + "nodeType": "YulLiteral", + "src": "2054:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2039:3:389", + "nodeType": "YulIdentifier", + "src": "2039:3:389" + }, + "nativeSrc": "2039:18:389", + "nodeType": "YulFunctionCall", + "src": "2039:18:389" + }, + { + "kind": "number", + "nativeSrc": "2059:3:389", + "nodeType": "YulLiteral", + "src": "2059:3:389", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2032:6:389", + "nodeType": "YulIdentifier", + "src": "2032:6:389" + }, + "nativeSrc": "2032:31:389", + "nodeType": "YulFunctionCall", + "src": "2032:31:389" + }, + "nativeSrc": "2032:31:389", + "nodeType": "YulExpressionStatement", + "src": "2032:31:389" + }, + { + "nativeSrc": "2072:17:389", + "nodeType": "YulVariableDeclaration", + "src": "2072:17:389", + "value": { + "name": "tail_1", + "nativeSrc": "2083:6:389", + "nodeType": "YulIdentifier", + "src": "2083:6:389" + }, + "variables": [ + { + "name": "pos", + "nativeSrc": "2076:3:389", + "nodeType": "YulTypedName", + "src": "2076:3:389", + "type": "" + } + ] + }, + { + "nativeSrc": "2098:27:389", + "nodeType": "YulVariableDeclaration", + "src": "2098:27:389", + "value": { + "arguments": [ + { + "name": "value1", + "nativeSrc": "2118:6:389", + "nodeType": "YulIdentifier", + "src": "2118:6:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "2112:5:389", + "nodeType": "YulIdentifier", + "src": "2112:5:389" + }, + "nativeSrc": "2112:13:389", + "nodeType": "YulFunctionCall", + "src": "2112:13:389" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "2102:6:389", + "nodeType": "YulTypedName", + "src": "2102:6:389", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "tail_1", + "nativeSrc": "2141:6:389", + "nodeType": "YulIdentifier", + "src": "2141:6:389" + }, + { + "name": "length", + "nativeSrc": "2149:6:389", + "nodeType": "YulIdentifier", + "src": "2149:6:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2134:6:389", + "nodeType": "YulIdentifier", + "src": "2134:6:389" + }, + "nativeSrc": "2134:22:389", + "nodeType": "YulFunctionCall", + "src": "2134:22:389" + }, + "nativeSrc": "2134:22:389", + "nodeType": "YulExpressionStatement", + "src": "2134:22:389" + }, + { + "nativeSrc": "2165:26:389", + "nodeType": "YulAssignment", + "src": "2165:26:389", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2176:9:389", + "nodeType": "YulIdentifier", + "src": "2176:9:389" + }, + { + "kind": "number", + "nativeSrc": "2187:3:389", + "nodeType": "YulLiteral", + "src": "2187:3:389", + "type": "", + "value": "192" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2172:3:389", + "nodeType": "YulIdentifier", + "src": "2172:3:389" + }, + "nativeSrc": "2172:19:389", + "nodeType": "YulFunctionCall", + "src": "2172:19:389" + }, + "variableNames": [ + { + "name": "pos", + "nativeSrc": "2165:3:389", + "nodeType": "YulIdentifier", + "src": "2165:3:389" + } + ] + }, + { + "nativeSrc": "2200:54:389", + "nodeType": "YulVariableDeclaration", + "src": "2200:54:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2222:9:389", + "nodeType": "YulIdentifier", + "src": "2222:9:389" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "2237:1:389", + "nodeType": "YulLiteral", + "src": "2237:1:389", + "type": "", + "value": "5" + }, + { + "name": "length", + "nativeSrc": "2240:6:389", + "nodeType": "YulIdentifier", + "src": "2240:6:389" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "2233:3:389", + "nodeType": "YulIdentifier", + "src": "2233:3:389" + }, + "nativeSrc": "2233:14:389", + "nodeType": "YulFunctionCall", + "src": "2233:14:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2218:3:389", + "nodeType": "YulIdentifier", + "src": "2218:3:389" + }, + "nativeSrc": "2218:30:389", + "nodeType": "YulFunctionCall", + "src": "2218:30:389" + }, + { + "kind": "number", + "nativeSrc": "2250:3:389", + "nodeType": "YulLiteral", + "src": "2250:3:389", + "type": "", + "value": "192" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2214:3:389", + "nodeType": "YulIdentifier", + "src": "2214:3:389" + }, + "nativeSrc": "2214:40:389", + "nodeType": "YulFunctionCall", + "src": "2214:40:389" + }, + "variables": [ + { + "name": "tail_2", + "nativeSrc": "2204:6:389", + "nodeType": "YulTypedName", + "src": "2204:6:389", + "type": "" + } + ] + }, + { + "nativeSrc": "2263:29:389", + "nodeType": "YulVariableDeclaration", + "src": "2263:29:389", + "value": { + "arguments": [ + { + "name": "value1", + "nativeSrc": "2281:6:389", + "nodeType": "YulIdentifier", + "src": "2281:6:389" + }, + { + "kind": "number", + "nativeSrc": "2289:2:389", + "nodeType": "YulLiteral", + "src": "2289:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2277:3:389", + "nodeType": "YulIdentifier", + "src": "2277:3:389" + }, + "nativeSrc": "2277:15:389", + "nodeType": "YulFunctionCall", + "src": "2277:15:389" + }, + "variables": [ + { + "name": "srcPtr", + "nativeSrc": "2267:6:389", + "nodeType": "YulTypedName", + "src": "2267:6:389", + "type": "" + } + ] + }, + { + "nativeSrc": "2301:10:389", + "nodeType": "YulVariableDeclaration", + "src": "2301:10:389", + "value": { + "kind": "number", + "nativeSrc": "2310:1:389", + "nodeType": "YulLiteral", + "src": "2310:1:389", + "type": "", + "value": "0" + }, + "variables": [ + { + "name": "i", + "nativeSrc": "2305:1:389", + "nodeType": "YulTypedName", + "src": "2305:1:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "2369:207:389", + "nodeType": "YulBlock", + "src": "2369:207:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "2390:3:389", + "nodeType": "YulIdentifier", + "src": "2390:3:389" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "tail_2", + "nativeSrc": "2403:6:389", + "nodeType": "YulIdentifier", + "src": "2403:6:389" + }, + { + "name": "headStart", + "nativeSrc": "2411:9:389", + "nodeType": "YulIdentifier", + "src": "2411:9:389" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2399:3:389", + "nodeType": "YulIdentifier", + "src": "2399:3:389" + }, + "nativeSrc": "2399:22:389", + "nodeType": "YulFunctionCall", + "src": "2399:22:389" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "2427:3:389", + "nodeType": "YulLiteral", + "src": "2427:3:389", + "type": "", + "value": "191" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "2423:3:389", + "nodeType": "YulIdentifier", + "src": "2423:3:389" + }, + "nativeSrc": "2423:8:389", + "nodeType": "YulFunctionCall", + "src": "2423:8:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2395:3:389", + "nodeType": "YulIdentifier", + "src": "2395:3:389" + }, + "nativeSrc": "2395:37:389", + "nodeType": "YulFunctionCall", + "src": "2395:37:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2383:6:389", + "nodeType": "YulIdentifier", + "src": "2383:6:389" + }, + "nativeSrc": "2383:50:389", + "nodeType": "YulFunctionCall", + "src": "2383:50:389" + }, + "nativeSrc": "2383:50:389", + "nodeType": "YulExpressionStatement", + "src": "2383:50:389" + }, + { + "nativeSrc": "2446:50:389", + "nodeType": "YulAssignment", + "src": "2446:50:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "srcPtr", + "nativeSrc": "2480:6:389", + "nodeType": "YulIdentifier", + "src": "2480:6:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "2474:5:389", + "nodeType": "YulIdentifier", + "src": "2474:5:389" + }, + "nativeSrc": "2474:13:389", + "nodeType": "YulFunctionCall", + "src": "2474:13:389" + }, + { + "name": "tail_2", + "nativeSrc": "2489:6:389", + "nodeType": "YulIdentifier", + "src": "2489:6:389" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2456:17:389", + "nodeType": "YulIdentifier", + "src": "2456:17:389" + }, + "nativeSrc": "2456:40:389", + "nodeType": "YulFunctionCall", + "src": "2456:40:389" + }, + "variableNames": [ + { + "name": "tail_2", + "nativeSrc": "2446:6:389", + "nodeType": "YulIdentifier", + "src": "2446:6:389" + } + ] + }, + { + "nativeSrc": "2509:25:389", + "nodeType": "YulAssignment", + "src": "2509:25:389", + "value": { + "arguments": [ + { + "name": "srcPtr", + "nativeSrc": "2523:6:389", + "nodeType": "YulIdentifier", + "src": "2523:6:389" + }, + { + "kind": "number", + "nativeSrc": "2531:2:389", + "nodeType": "YulLiteral", + "src": "2531:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2519:3:389", + "nodeType": "YulIdentifier", + "src": "2519:3:389" + }, + "nativeSrc": "2519:15:389", + "nodeType": "YulFunctionCall", + "src": "2519:15:389" + }, + "variableNames": [ + { + "name": "srcPtr", + "nativeSrc": "2509:6:389", + "nodeType": "YulIdentifier", + "src": "2509:6:389" + } + ] + }, + { + "nativeSrc": "2547:19:389", + "nodeType": "YulAssignment", + "src": "2547:19:389", + "value": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "2558:3:389", + "nodeType": "YulIdentifier", + "src": "2558:3:389" + }, + { + "kind": "number", + "nativeSrc": "2563:2:389", + "nodeType": "YulLiteral", + "src": "2563:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2554:3:389", + "nodeType": "YulIdentifier", + "src": "2554:3:389" + }, + "nativeSrc": "2554:12:389", + "nodeType": "YulFunctionCall", + "src": "2554:12:389" + }, + "variableNames": [ + { + "name": "pos", + "nativeSrc": "2547:3:389", + "nodeType": "YulIdentifier", + "src": "2547:3:389" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "i", + "nativeSrc": "2331:1:389", + "nodeType": "YulIdentifier", + "src": "2331:1:389" + }, + { + "name": "length", + "nativeSrc": "2334:6:389", + "nodeType": "YulIdentifier", + "src": "2334:6:389" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "2328:2:389", + "nodeType": "YulIdentifier", + "src": "2328:2:389" + }, + "nativeSrc": "2328:13:389", + "nodeType": "YulFunctionCall", + "src": "2328:13:389" + }, + "nativeSrc": "2320:256:389", + "nodeType": "YulForLoop", + "post": { + "nativeSrc": "2342:18:389", + "nodeType": "YulBlock", + "src": "2342:18:389", + "statements": [ + { + "nativeSrc": "2344:14:389", + "nodeType": "YulAssignment", + "src": "2344:14:389", + "value": { + "arguments": [ + { + "name": "i", + "nativeSrc": "2353:1:389", + "nodeType": "YulIdentifier", + "src": "2353:1:389" + }, + { + "kind": "number", + "nativeSrc": "2356:1:389", + "nodeType": "YulLiteral", + "src": "2356:1:389", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2349:3:389", + "nodeType": "YulIdentifier", + "src": "2349:3:389" + }, + "nativeSrc": "2349:9:389", + "nodeType": "YulFunctionCall", + "src": "2349:9:389" + }, + "variableNames": [ + { + "name": "i", + "nativeSrc": "2344:1:389", + "nodeType": "YulIdentifier", + "src": "2344:1:389" + } + ] + } + ] + }, + "pre": { + "nativeSrc": "2324:3:389", + "nodeType": "YulBlock", + "src": "2324:3:389", + "statements": [] + }, + "src": "2320:256:389" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2596:9:389", + "nodeType": "YulIdentifier", + "src": "2596:9:389" + }, + { + "kind": "number", + "nativeSrc": "2607:2:389", + "nodeType": "YulLiteral", + "src": "2607:2:389", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2592:3:389", + "nodeType": "YulIdentifier", + "src": "2592:3:389" + }, + "nativeSrc": "2592:18:389", + "nodeType": "YulFunctionCall", + "src": "2592:18:389" + }, + { + "arguments": [ + { + "name": "tail_2", + "nativeSrc": "2616:6:389", + "nodeType": "YulIdentifier", + "src": "2616:6:389" + }, + { + "name": "headStart", + "nativeSrc": "2624:9:389", + "nodeType": "YulIdentifier", + "src": "2624:9:389" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2612:3:389", + "nodeType": "YulIdentifier", + "src": "2612:3:389" + }, + "nativeSrc": "2612:22:389", + "nodeType": "YulFunctionCall", + "src": "2612:22:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2585:6:389", + "nodeType": "YulIdentifier", + "src": "2585:6:389" + }, + "nativeSrc": "2585:50:389", + "nodeType": "YulFunctionCall", + "src": "2585:50:389" + }, + "nativeSrc": "2585:50:389", + "nodeType": "YulExpressionStatement", + "src": "2585:50:389" + }, + { + "nativeSrc": "2644:47:389", + "nodeType": "YulVariableDeclaration", + "src": "2644:47:389", + "value": { + "arguments": [ + { + "name": "value2", + "nativeSrc": "2676:6:389", + "nodeType": "YulIdentifier", + "src": "2676:6:389" + }, + { + "name": "tail_2", + "nativeSrc": "2684:6:389", + "nodeType": "YulIdentifier", + "src": "2684:6:389" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2658:17:389", + "nodeType": "YulIdentifier", + "src": "2658:17:389" + }, + "nativeSrc": "2658:33:389", + "nodeType": "YulFunctionCall", + "src": "2658:33:389" + }, + "variables": [ + { + "name": "tail_3", + "nativeSrc": "2648:6:389", + "nodeType": "YulTypedName", + "src": "2648:6:389", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value3", + "nativeSrc": "2718:6:389", + "nodeType": "YulIdentifier", + "src": "2718:6:389" + }, + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2730:9:389", + "nodeType": "YulIdentifier", + "src": "2730:9:389" + }, + { + "kind": "number", + "nativeSrc": "2741:2:389", + "nodeType": "YulLiteral", + "src": "2741:2:389", + "type": "", + "value": "96" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2726:3:389", + "nodeType": "YulIdentifier", + "src": "2726:3:389" + }, + "nativeSrc": "2726:18:389", + "nodeType": "YulFunctionCall", + "src": "2726:18:389" + } + ], + "functionName": { + "name": "abi_encode_bytes4", + "nativeSrc": "2700:17:389", + "nodeType": "YulIdentifier", + "src": "2700:17:389" + }, + "nativeSrc": "2700:45:389", + "nodeType": "YulFunctionCall", + "src": "2700:45:389" + }, + "nativeSrc": "2700:45:389", + "nodeType": "YulExpressionStatement", + "src": "2700:45:389" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2765:9:389", + "nodeType": "YulIdentifier", + "src": "2765:9:389" + }, + { + "kind": "number", + "nativeSrc": "2776:3:389", + "nodeType": "YulLiteral", + "src": "2776:3:389", + "type": "", + "value": "128" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2761:3:389", + "nodeType": "YulIdentifier", + "src": "2761:3:389" + }, + "nativeSrc": "2761:19:389", + "nodeType": "YulFunctionCall", + "src": "2761:19:389" + }, + { + "arguments": [ + { + "name": "tail_3", + "nativeSrc": "2786:6:389", + "nodeType": "YulIdentifier", + "src": "2786:6:389" + }, + { + "name": "headStart", + "nativeSrc": "2794:9:389", + "nodeType": "YulIdentifier", + "src": "2794:9:389" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2782:3:389", + "nodeType": "YulIdentifier", + "src": "2782:3:389" + }, + "nativeSrc": "2782:22:389", + "nodeType": "YulFunctionCall", + "src": "2782:22:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2754:6:389", + "nodeType": "YulIdentifier", + "src": "2754:6:389" + }, + "nativeSrc": "2754:51:389", + "nodeType": "YulFunctionCall", + "src": "2754:51:389" + }, + "nativeSrc": "2754:51:389", + "nodeType": "YulExpressionStatement", + "src": "2754:51:389" + }, + { + "nativeSrc": "2814:41:389", + "nodeType": "YulAssignment", + "src": "2814:41:389", + "value": { + "arguments": [ + { + "name": "value4", + "nativeSrc": "2840:6:389", + "nodeType": "YulIdentifier", + "src": "2840:6:389" + }, + { + "name": "tail_3", + "nativeSrc": "2848:6:389", + "nodeType": "YulIdentifier", + "src": "2848:6:389" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2822:17:389", + "nodeType": "YulIdentifier", + "src": "2822:17:389" + }, + "nativeSrc": "2822:33:389", + "nodeType": "YulFunctionCall", + "src": "2822:33:389" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "2814:4:389", + "nodeType": "YulIdentifier", + "src": "2814:4:389" + } + ] + } + ] + }, + "name": "abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed", + "nativeSrc": "1580:1281:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "1834:9:389", + "nodeType": "YulTypedName", + "src": "1834:9:389", + "type": "" + }, + { + "name": "value4", + "nativeSrc": "1845:6:389", + "nodeType": "YulTypedName", + "src": "1845:6:389", + "type": "" + }, + { + "name": "value3", + "nativeSrc": "1853:6:389", + "nodeType": "YulTypedName", + "src": "1853:6:389", + "type": "" + }, + { + "name": "value2", + "nativeSrc": "1861:6:389", + "nodeType": "YulTypedName", + "src": "1861:6:389", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "1869:6:389", + "nodeType": "YulTypedName", + "src": "1869:6:389", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "1877:6:389", + "nodeType": "YulTypedName", + "src": "1877:6:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "1888:4:389", + "nodeType": "YulTypedName", + "src": "1888:4:389", + "type": "" + } + ], + "src": "1580:1281:389" + }, + { + "body": { + "nativeSrc": "2911:109:389", + "nodeType": "YulBlock", + "src": "2911:109:389", + "statements": [ + { + "body": { + "nativeSrc": "2998:16:389", + "nodeType": "YulBlock", + "src": "2998:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3007:1:389", + "nodeType": "YulLiteral", + "src": "3007:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3010:1:389", + "nodeType": "YulLiteral", + "src": "3010:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "3000:6:389", + "nodeType": "YulIdentifier", + "src": "3000:6:389" + }, + "nativeSrc": "3000:12:389", + "nodeType": "YulFunctionCall", + "src": "3000:12:389" + }, + "nativeSrc": "3000:12:389", + "nodeType": "YulExpressionStatement", + "src": "3000:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "2934:5:389", + "nodeType": "YulIdentifier", + "src": "2934:5:389" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "2945:5:389", + "nodeType": "YulIdentifier", + "src": "2945:5:389" + }, + { + "kind": "number", + "nativeSrc": "2952:42:389", + "nodeType": "YulLiteral", + "src": "2952:42:389", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "2941:3:389", + "nodeType": "YulIdentifier", + "src": "2941:3:389" + }, + "nativeSrc": "2941:54:389", + "nodeType": "YulFunctionCall", + "src": "2941:54:389" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "2931:2:389", + "nodeType": "YulIdentifier", + "src": "2931:2:389" + }, + "nativeSrc": "2931:65:389", + "nodeType": "YulFunctionCall", + "src": "2931:65:389" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "2924:6:389", + "nodeType": "YulIdentifier", + "src": "2924:6:389" + }, + "nativeSrc": "2924:73:389", + "nodeType": "YulFunctionCall", + "src": "2924:73:389" + }, + "nativeSrc": "2921:93:389", + "nodeType": "YulIf", + "src": "2921:93:389" + } + ] + }, + "name": "validator_revert_address", + "nativeSrc": "2866:154:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "2900:5:389", + "nodeType": "YulTypedName", + "src": "2900:5:389", + "type": "" + } + ], + "src": "2866:154:389" + }, + { + "body": { + "nativeSrc": "3095:177:389", + "nodeType": "YulBlock", + "src": "3095:177:389", + "statements": [ + { + "body": { + "nativeSrc": "3141:16:389", + "nodeType": "YulBlock", + "src": "3141:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3150:1:389", + "nodeType": "YulLiteral", + "src": "3150:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3153:1:389", + "nodeType": "YulLiteral", + "src": "3153:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "3143:6:389", + "nodeType": "YulIdentifier", + "src": "3143:6:389" + }, + "nativeSrc": "3143:12:389", + "nodeType": "YulFunctionCall", + "src": "3143:12:389" + }, + "nativeSrc": "3143:12:389", + "nodeType": "YulExpressionStatement", + "src": "3143:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "3116:7:389", + "nodeType": "YulIdentifier", + "src": "3116:7:389" + }, + { + "name": "headStart", + "nativeSrc": "3125:9:389", + "nodeType": "YulIdentifier", + "src": "3125:9:389" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "3112:3:389", + "nodeType": "YulIdentifier", + "src": "3112:3:389" + }, + "nativeSrc": "3112:23:389", + "nodeType": "YulFunctionCall", + "src": "3112:23:389" + }, + { + "kind": "number", + "nativeSrc": "3137:2:389", + "nodeType": "YulLiteral", + "src": "3137:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "3108:3:389", + "nodeType": "YulIdentifier", + "src": "3108:3:389" + }, + "nativeSrc": "3108:32:389", + "nodeType": "YulFunctionCall", + "src": "3108:32:389" + }, + "nativeSrc": "3105:52:389", + "nodeType": "YulIf", + "src": "3105:52:389" + }, + { + "nativeSrc": "3166:36:389", + "nodeType": "YulVariableDeclaration", + "src": "3166:36:389", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3192:9:389", + "nodeType": "YulIdentifier", + "src": "3192:9:389" + } + ], + "functionName": { + "name": "calldataload", + "nativeSrc": "3179:12:389", + "nodeType": "YulIdentifier", + "src": "3179:12:389" + }, + "nativeSrc": "3179:23:389", + "nodeType": "YulFunctionCall", + "src": "3179:23:389" + }, + "variables": [ + { + "name": "value", + "nativeSrc": "3170:5:389", + "nodeType": "YulTypedName", + "src": "3170:5:389", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value", + "nativeSrc": "3236:5:389", + "nodeType": "YulIdentifier", + "src": "3236:5:389" + } + ], + "functionName": { + "name": "validator_revert_address", + "nativeSrc": "3211:24:389", + "nodeType": "YulIdentifier", + "src": "3211:24:389" + }, + "nativeSrc": "3211:31:389", + "nodeType": "YulFunctionCall", + "src": "3211:31:389" + }, + "nativeSrc": "3211:31:389", + "nodeType": "YulExpressionStatement", + "src": "3211:31:389" + }, + { + "nativeSrc": "3251:15:389", + "nodeType": "YulAssignment", + "src": "3251:15:389", + "value": { + "name": "value", + "nativeSrc": "3261:5:389", + "nodeType": "YulIdentifier", + "src": "3261:5:389" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "3251:6:389", + "nodeType": "YulIdentifier", + "src": "3251:6:389" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_address", + "nativeSrc": "3025:247:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "3061:9:389", + "nodeType": "YulTypedName", + "src": "3061:9:389", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "3072:7:389", + "nodeType": "YulTypedName", + "src": "3072:7:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "3084:6:389", + "nodeType": "YulTypedName", + "src": "3084:6:389", + "type": "" + } + ], + "src": "3025:247:389" + }, + { + "body": { + "nativeSrc": "3378:125:389", + "nodeType": "YulBlock", + "src": "3378:125:389", + "statements": [ + { + "nativeSrc": "3388:26:389", + "nodeType": "YulAssignment", + "src": "3388:26:389", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3400:9:389", + "nodeType": "YulIdentifier", + "src": "3400:9:389" + }, + { + "kind": "number", + "nativeSrc": "3411:2:389", + "nodeType": "YulLiteral", + "src": "3411:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3396:3:389", + "nodeType": "YulIdentifier", + "src": "3396:3:389" + }, + "nativeSrc": "3396:18:389", + "nodeType": "YulFunctionCall", + "src": "3396:18:389" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "3388:4:389", + "nodeType": "YulIdentifier", + "src": "3388:4:389" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3430:9:389", + "nodeType": "YulIdentifier", + "src": "3430:9:389" + }, + { + "arguments": [ + { + "name": "value0", + "nativeSrc": "3445:6:389", + "nodeType": "YulIdentifier", + "src": "3445:6:389" + }, + { + "kind": "number", + "nativeSrc": "3453:42:389", + "nodeType": "YulLiteral", + "src": "3453:42:389", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "3441:3:389", + "nodeType": "YulIdentifier", + "src": "3441:3:389" + }, + "nativeSrc": "3441:55:389", + "nodeType": "YulFunctionCall", + "src": "3441:55:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3423:6:389", + "nodeType": "YulIdentifier", + "src": "3423:6:389" + }, + "nativeSrc": "3423:74:389", + "nodeType": "YulFunctionCall", + "src": "3423:74:389" + }, + "nativeSrc": "3423:74:389", + "nodeType": "YulExpressionStatement", + "src": "3423:74:389" + } + ] + }, + "name": "abi_encode_tuple_t_address__to_t_address__fromStack_reversed", + "nativeSrc": "3277:226:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "3347:9:389", + "nodeType": "YulTypedName", + "src": "3347:9:389", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "3358:6:389", + "nodeType": "YulTypedName", + "src": "3358:6:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "3369:4:389", + "nodeType": "YulTypedName", + "src": "3369:4:389", + "type": "" + } + ], + "src": "3277:226:389" + }, + { + "body": { + "nativeSrc": "3540:152:389", + "nodeType": "YulBlock", + "src": "3540:152:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3557:1:389", + "nodeType": "YulLiteral", + "src": "3557:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3560:77:389", + "nodeType": "YulLiteral", + "src": "3560:77:389", + "type": "", + "value": "35408467139433450592217433187231851964531694900788300625387963629091585785856" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3550:6:389", + "nodeType": "YulIdentifier", + "src": "3550:6:389" + }, + "nativeSrc": "3550:88:389", + "nodeType": "YulFunctionCall", + "src": "3550:88:389" + }, + "nativeSrc": "3550:88:389", + "nodeType": "YulExpressionStatement", + "src": "3550:88:389" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3654:1:389", + "nodeType": "YulLiteral", + "src": "3654:1:389", + "type": "", + "value": "4" + }, + { + "kind": "number", + "nativeSrc": "3657:4:389", + "nodeType": "YulLiteral", + "src": "3657:4:389", + "type": "", + "value": "0x41" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3647:6:389", + "nodeType": "YulIdentifier", + "src": "3647:6:389" + }, + "nativeSrc": "3647:15:389", + "nodeType": "YulFunctionCall", + "src": "3647:15:389" + }, + "nativeSrc": "3647:15:389", + "nodeType": "YulExpressionStatement", + "src": "3647:15:389" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3678:1:389", + "nodeType": "YulLiteral", + "src": "3678:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3681:4:389", + "nodeType": "YulLiteral", + "src": "3681:4:389", + "type": "", + "value": "0x24" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "3671:6:389", + "nodeType": "YulIdentifier", + "src": "3671:6:389" + }, + "nativeSrc": "3671:15:389", + "nodeType": "YulFunctionCall", + "src": "3671:15:389" + }, + "nativeSrc": "3671:15:389", + "nodeType": "YulExpressionStatement", + "src": "3671:15:389" + } + ] + }, + "name": "panic_error_0x41", + "nativeSrc": "3508:184:389", + "nodeType": "YulFunctionDefinition", + "src": "3508:184:389" + }, + { + "body": { + "nativeSrc": "3742:230:389", + "nodeType": "YulBlock", + "src": "3742:230:389", + "statements": [ + { + "nativeSrc": "3752:19:389", + "nodeType": "YulAssignment", + "src": "3752:19:389", + "value": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3768:2:389", + "nodeType": "YulLiteral", + "src": "3768:2:389", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "3762:5:389", + "nodeType": "YulIdentifier", + "src": "3762:5:389" + }, + "nativeSrc": "3762:9:389", + "nodeType": "YulFunctionCall", + "src": "3762:9:389" + }, + "variableNames": [ + { + "name": "memPtr", + "nativeSrc": "3752:6:389", + "nodeType": "YulIdentifier", + "src": "3752:6:389" + } + ] + }, + { + "nativeSrc": "3780:58:389", + "nodeType": "YulVariableDeclaration", + "src": "3780:58:389", + "value": { + "arguments": [ + { + "name": "memPtr", + "nativeSrc": "3802:6:389", + "nodeType": "YulIdentifier", + "src": "3802:6:389" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "size", + "nativeSrc": "3818:4:389", + "nodeType": "YulIdentifier", + "src": "3818:4:389" + }, + { + "kind": "number", + "nativeSrc": "3824:2:389", + "nodeType": "YulLiteral", + "src": "3824:2:389", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3814:3:389", + "nodeType": "YulIdentifier", + "src": "3814:3:389" + }, + "nativeSrc": "3814:13:389", + "nodeType": "YulFunctionCall", + "src": "3814:13:389" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3833:2:389", + "nodeType": "YulLiteral", + "src": "3833:2:389", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "3829:3:389", + "nodeType": "YulIdentifier", + "src": "3829:3:389" + }, + "nativeSrc": "3829:7:389", + "nodeType": "YulFunctionCall", + "src": "3829:7:389" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "3810:3:389", + "nodeType": "YulIdentifier", + "src": "3810:3:389" + }, + "nativeSrc": "3810:27:389", + "nodeType": "YulFunctionCall", + "src": "3810:27:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3798:3:389", + "nodeType": "YulIdentifier", + "src": "3798:3:389" + }, + "nativeSrc": "3798:40:389", + "nodeType": "YulFunctionCall", + "src": "3798:40:389" + }, + "variables": [ + { + "name": "newFreePtr", + "nativeSrc": "3784:10:389", + "nodeType": "YulTypedName", + "src": "3784:10:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "3913:22:389", + "nodeType": "YulBlock", + "src": "3913:22:389", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "3915:16:389", + "nodeType": "YulIdentifier", + "src": "3915:16:389" + }, + "nativeSrc": "3915:18:389", + "nodeType": "YulFunctionCall", + "src": "3915:18:389" + }, + "nativeSrc": "3915:18:389", + "nodeType": "YulExpressionStatement", + "src": "3915:18:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "newFreePtr", + "nativeSrc": "3856:10:389", + "nodeType": "YulIdentifier", + "src": "3856:10:389" + }, + { + "kind": "number", + "nativeSrc": "3868:18:389", + "nodeType": "YulLiteral", + "src": "3868:18:389", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "3853:2:389", + "nodeType": "YulIdentifier", + "src": "3853:2:389" + }, + "nativeSrc": "3853:34:389", + "nodeType": "YulFunctionCall", + "src": "3853:34:389" + }, + { + "arguments": [ + { + "name": "newFreePtr", + "nativeSrc": "3892:10:389", + "nodeType": "YulIdentifier", + "src": "3892:10:389" + }, + { + "name": "memPtr", + "nativeSrc": "3904:6:389", + "nodeType": "YulIdentifier", + "src": "3904:6:389" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "3889:2:389", + "nodeType": "YulIdentifier", + "src": "3889:2:389" + }, + "nativeSrc": "3889:22:389", + "nodeType": "YulFunctionCall", + "src": "3889:22:389" + } + ], + "functionName": { + "name": "or", + "nativeSrc": "3850:2:389", + "nodeType": "YulIdentifier", + "src": "3850:2:389" + }, + "nativeSrc": "3850:62:389", + "nodeType": "YulFunctionCall", + "src": "3850:62:389" + }, + "nativeSrc": "3847:88:389", + "nodeType": "YulIf", + "src": "3847:88:389" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3951:2:389", + "nodeType": "YulLiteral", + "src": "3951:2:389", + "type": "", + "value": "64" + }, + { + "name": "newFreePtr", + "nativeSrc": "3955:10:389", + "nodeType": "YulIdentifier", + "src": "3955:10:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3944:6:389", + "nodeType": "YulIdentifier", + "src": "3944:6:389" + }, + "nativeSrc": "3944:22:389", + "nodeType": "YulFunctionCall", + "src": "3944:22:389" + }, + "nativeSrc": "3944:22:389", + "nodeType": "YulExpressionStatement", + "src": "3944:22:389" + } + ] + }, + "name": "allocate_memory", + "nativeSrc": "3697:275:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "size", + "nativeSrc": "3722:4:389", + "nodeType": "YulTypedName", + "src": "3722:4:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "memPtr", + "nativeSrc": "3731:6:389", + "nodeType": "YulTypedName", + "src": "3731:6:389", + "type": "" + } + ], + "src": "3697:275:389" + }, + { + "body": { + "nativeSrc": "4063:368:389", + "nodeType": "YulBlock", + "src": "4063:368:389", + "statements": [ + { + "nativeSrc": "4073:13:389", + "nodeType": "YulVariableDeclaration", + "src": "4073:13:389", + "value": { + "kind": "number", + "nativeSrc": "4085:1:389", + "nodeType": "YulLiteral", + "src": "4085:1:389", + "type": "", + "value": "0" + }, + "variables": [ + { + "name": "size", + "nativeSrc": "4077:4:389", + "nodeType": "YulTypedName", + "src": "4077:4:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "4129:22:389", + "nodeType": "YulBlock", + "src": "4129:22:389", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "4131:16:389", + "nodeType": "YulIdentifier", + "src": "4131:16:389" + }, + "nativeSrc": "4131:18:389", + "nodeType": "YulFunctionCall", + "src": "4131:18:389" + }, + "nativeSrc": "4131:18:389", + "nodeType": "YulExpressionStatement", + "src": "4131:18:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "length", + "nativeSrc": "4101:6:389", + "nodeType": "YulIdentifier", + "src": "4101:6:389" + }, + { + "kind": "number", + "nativeSrc": "4109:18:389", + "nodeType": "YulLiteral", + "src": "4109:18:389", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "4098:2:389", + "nodeType": "YulIdentifier", + "src": "4098:2:389" + }, + "nativeSrc": "4098:30:389", + "nodeType": "YulFunctionCall", + "src": "4098:30:389" + }, + "nativeSrc": "4095:56:389", + "nodeType": "YulIf", + "src": "4095:56:389" + }, + { + "nativeSrc": "4160:48:389", + "nodeType": "YulAssignment", + "src": "4160:48:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "length", + "nativeSrc": "4180:6:389", + "nodeType": "YulIdentifier", + "src": "4180:6:389" + }, + { + "kind": "number", + "nativeSrc": "4188:2:389", + "nodeType": "YulLiteral", + "src": "4188:2:389", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4176:3:389", + "nodeType": "YulIdentifier", + "src": "4176:3:389" + }, + "nativeSrc": "4176:15:389", + "nodeType": "YulFunctionCall", + "src": "4176:15:389" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4197:2:389", + "nodeType": "YulLiteral", + "src": "4197:2:389", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "4193:3:389", + "nodeType": "YulIdentifier", + "src": "4193:3:389" + }, + "nativeSrc": "4193:7:389", + "nodeType": "YulFunctionCall", + "src": "4193:7:389" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "4172:3:389", + "nodeType": "YulIdentifier", + "src": "4172:3:389" + }, + "nativeSrc": "4172:29:389", + "nodeType": "YulFunctionCall", + "src": "4172:29:389" + }, + { + "kind": "number", + "nativeSrc": "4203:4:389", + "nodeType": "YulLiteral", + "src": "4203:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4168:3:389", + "nodeType": "YulIdentifier", + "src": "4168:3:389" + }, + "nativeSrc": "4168:40:389", + "nodeType": "YulFunctionCall", + "src": "4168:40:389" + }, + "variableNames": [ + { + "name": "size", + "nativeSrc": "4160:4:389", + "nodeType": "YulIdentifier", + "src": "4160:4:389" + } + ] + }, + { + "nativeSrc": "4217:30:389", + "nodeType": "YulAssignment", + "src": "4217:30:389", + "value": { + "arguments": [ + { + "name": "size", + "nativeSrc": "4242:4:389", + "nodeType": "YulIdentifier", + "src": "4242:4:389" + } + ], + "functionName": { + "name": "allocate_memory", + "nativeSrc": "4226:15:389", + "nodeType": "YulIdentifier", + "src": "4226:15:389" + }, + "nativeSrc": "4226:21:389", + "nodeType": "YulFunctionCall", + "src": "4226:21:389" + }, + "variableNames": [ + { + "name": "array", + "nativeSrc": "4217:5:389", + "nodeType": "YulIdentifier", + "src": "4217:5:389" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "array", + "nativeSrc": "4263:5:389", + "nodeType": "YulIdentifier", + "src": "4263:5:389" + }, + { + "name": "length", + "nativeSrc": "4270:6:389", + "nodeType": "YulIdentifier", + "src": "4270:6:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "4256:6:389", + "nodeType": "YulIdentifier", + "src": "4256:6:389" + }, + "nativeSrc": "4256:21:389", + "nodeType": "YulFunctionCall", + "src": "4256:21:389" + }, + "nativeSrc": "4256:21:389", + "nodeType": "YulExpressionStatement", + "src": "4256:21:389" + }, + { + "body": { + "nativeSrc": "4315:16:389", + "nodeType": "YulBlock", + "src": "4315:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4324:1:389", + "nodeType": "YulLiteral", + "src": "4324:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4327:1:389", + "nodeType": "YulLiteral", + "src": "4327:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4317:6:389", + "nodeType": "YulIdentifier", + "src": "4317:6:389" + }, + "nativeSrc": "4317:12:389", + "nodeType": "YulFunctionCall", + "src": "4317:12:389" + }, + "nativeSrc": "4317:12:389", + "nodeType": "YulExpressionStatement", + "src": "4317:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "src", + "nativeSrc": "4296:3:389", + "nodeType": "YulIdentifier", + "src": "4296:3:389" + }, + { + "name": "length", + "nativeSrc": "4301:6:389", + "nodeType": "YulIdentifier", + "src": "4301:6:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4292:3:389", + "nodeType": "YulIdentifier", + "src": "4292:3:389" + }, + "nativeSrc": "4292:16:389", + "nodeType": "YulFunctionCall", + "src": "4292:16:389" + }, + { + "name": "end", + "nativeSrc": "4310:3:389", + "nodeType": "YulIdentifier", + "src": "4310:3:389" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "4289:2:389", + "nodeType": "YulIdentifier", + "src": "4289:2:389" + }, + "nativeSrc": "4289:25:389", + "nodeType": "YulFunctionCall", + "src": "4289:25:389" + }, + "nativeSrc": "4286:45:389", + "nodeType": "YulIf", + "src": "4286:45:389" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "4350:5:389", + "nodeType": "YulIdentifier", + "src": "4350:5:389" + }, + { + "kind": "number", + "nativeSrc": "4357:4:389", + "nodeType": "YulLiteral", + "src": "4357:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4346:3:389", + "nodeType": "YulIdentifier", + "src": "4346:3:389" + }, + "nativeSrc": "4346:16:389", + "nodeType": "YulFunctionCall", + "src": "4346:16:389" + }, + { + "name": "src", + "nativeSrc": "4364:3:389", + "nodeType": "YulIdentifier", + "src": "4364:3:389" + }, + { + "name": "length", + "nativeSrc": "4369:6:389", + "nodeType": "YulIdentifier", + "src": "4369:6:389" + } + ], + "functionName": { + "name": "mcopy", + "nativeSrc": "4340:5:389", + "nodeType": "YulIdentifier", + "src": "4340:5:389" + }, + "nativeSrc": "4340:36:389", + "nodeType": "YulFunctionCall", + "src": "4340:36:389" + }, + "nativeSrc": "4340:36:389", + "nodeType": "YulExpressionStatement", + "src": "4340:36:389" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "4400:5:389", + "nodeType": "YulIdentifier", + "src": "4400:5:389" + }, + { + "name": "length", + "nativeSrc": "4407:6:389", + "nodeType": "YulIdentifier", + "src": "4407:6:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4396:3:389", + "nodeType": "YulIdentifier", + "src": "4396:3:389" + }, + "nativeSrc": "4396:18:389", + "nodeType": "YulFunctionCall", + "src": "4396:18:389" + }, + { + "kind": "number", + "nativeSrc": "4416:4:389", + "nodeType": "YulLiteral", + "src": "4416:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4392:3:389", + "nodeType": "YulIdentifier", + "src": "4392:3:389" + }, + "nativeSrc": "4392:29:389", + "nodeType": "YulFunctionCall", + "src": "4392:29:389" + }, + { + "kind": "number", + "nativeSrc": "4423:1:389", + "nodeType": "YulLiteral", + "src": "4423:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "4385:6:389", + "nodeType": "YulIdentifier", + "src": "4385:6:389" + }, + "nativeSrc": "4385:40:389", + "nodeType": "YulFunctionCall", + "src": "4385:40:389" + }, + "nativeSrc": "4385:40:389", + "nodeType": "YulExpressionStatement", + "src": "4385:40:389" + } + ] + }, + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "3977:454:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "src", + "nativeSrc": "4032:3:389", + "nodeType": "YulTypedName", + "src": "4032:3:389", + "type": "" + }, + { + "name": "length", + "nativeSrc": "4037:6:389", + "nodeType": "YulTypedName", + "src": "4037:6:389", + "type": "" + }, + { + "name": "end", + "nativeSrc": "4045:3:389", + "nodeType": "YulTypedName", + "src": "4045:3:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "array", + "nativeSrc": "4053:5:389", + "nodeType": "YulTypedName", + "src": "4053:5:389", + "type": "" + } + ], + "src": "3977:454:389" + }, + { + "body": { + "nativeSrc": "4499:173:389", + "nodeType": "YulBlock", + "src": "4499:173:389", + "statements": [ + { + "body": { + "nativeSrc": "4548:16:389", + "nodeType": "YulBlock", + "src": "4548:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4557:1:389", + "nodeType": "YulLiteral", + "src": "4557:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4560:1:389", + "nodeType": "YulLiteral", + "src": "4560:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4550:6:389", + "nodeType": "YulIdentifier", + "src": "4550:6:389" + }, + "nativeSrc": "4550:12:389", + "nodeType": "YulFunctionCall", + "src": "4550:12:389" + }, + "nativeSrc": "4550:12:389", + "nodeType": "YulExpressionStatement", + "src": "4550:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4527:6:389", + "nodeType": "YulIdentifier", + "src": "4527:6:389" + }, + { + "kind": "number", + "nativeSrc": "4535:4:389", + "nodeType": "YulLiteral", + "src": "4535:4:389", + "type": "", + "value": "0x1f" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4523:3:389", + "nodeType": "YulIdentifier", + "src": "4523:3:389" + }, + "nativeSrc": "4523:17:389", + "nodeType": "YulFunctionCall", + "src": "4523:17:389" + }, + { + "name": "end", + "nativeSrc": "4542:3:389", + "nodeType": "YulIdentifier", + "src": "4542:3:389" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "4519:3:389", + "nodeType": "YulIdentifier", + "src": "4519:3:389" + }, + "nativeSrc": "4519:27:389", + "nodeType": "YulFunctionCall", + "src": "4519:27:389" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "4512:6:389", + "nodeType": "YulIdentifier", + "src": "4512:6:389" + }, + "nativeSrc": "4512:35:389", + "nodeType": "YulFunctionCall", + "src": "4512:35:389" + }, + "nativeSrc": "4509:55:389", + "nodeType": "YulIf", + "src": "4509:55:389" + }, + { + "nativeSrc": "4573:93:389", + "nodeType": "YulAssignment", + "src": "4573:93:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4632:6:389", + "nodeType": "YulIdentifier", + "src": "4632:6:389" + }, + { + "kind": "number", + "nativeSrc": "4640:4:389", + "nodeType": "YulLiteral", + "src": "4640:4:389", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4628:3:389", + "nodeType": "YulIdentifier", + "src": "4628:3:389" + }, + "nativeSrc": "4628:17:389", + "nodeType": "YulFunctionCall", + "src": "4628:17:389" + }, + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4653:6:389", + "nodeType": "YulIdentifier", + "src": "4653:6:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "4647:5:389", + "nodeType": "YulIdentifier", + "src": "4647:5:389" + }, + "nativeSrc": "4647:13:389", + "nodeType": "YulFunctionCall", + "src": "4647:13:389" + }, + { + "name": "end", + "nativeSrc": "4662:3:389", + "nodeType": "YulIdentifier", + "src": "4662:3:389" + } + ], + "functionName": { + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "4582:45:389", + "nodeType": "YulIdentifier", + "src": "4582:45:389" + }, + "nativeSrc": "4582:84:389", + "nodeType": "YulFunctionCall", + "src": "4582:84:389" + }, + "variableNames": [ + { + "name": "array", + "nativeSrc": "4573:5:389", + "nodeType": "YulIdentifier", + "src": "4573:5:389" + } + ] + } + ] + }, + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "4436:236:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "4473:6:389", + "nodeType": "YulTypedName", + "src": "4473:6:389", + "type": "" + }, + { + "name": "end", + "nativeSrc": "4481:3:389", + "nodeType": "YulTypedName", + "src": "4481:3:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "array", + "nativeSrc": "4489:5:389", + "nodeType": "YulTypedName", + "src": "4489:5:389", + "type": "" + } + ], + "src": "4436:236:389" + }, + { + "body": { + "nativeSrc": "4736:164:389", + "nodeType": "YulBlock", + "src": "4736:164:389", + "statements": [ + { + "nativeSrc": "4746:22:389", + "nodeType": "YulAssignment", + "src": "4746:22:389", + "value": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4761:6:389", + "nodeType": "YulIdentifier", + "src": "4761:6:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "4755:5:389", + "nodeType": "YulIdentifier", + "src": "4755:5:389" + }, + "nativeSrc": "4755:13:389", + "nodeType": "YulFunctionCall", + "src": "4755:13:389" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "4746:5:389", + "nodeType": "YulIdentifier", + "src": "4746:5:389" + } + ] + }, + { + "body": { + "nativeSrc": "4878:16:389", + "nodeType": "YulBlock", + "src": "4878:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4887:1:389", + "nodeType": "YulLiteral", + "src": "4887:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4890:1:389", + "nodeType": "YulLiteral", + "src": "4890:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4880:6:389", + "nodeType": "YulIdentifier", + "src": "4880:6:389" + }, + "nativeSrc": "4880:12:389", + "nodeType": "YulFunctionCall", + "src": "4880:12:389" + }, + "nativeSrc": "4880:12:389", + "nodeType": "YulExpressionStatement", + "src": "4880:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "4790:5:389", + "nodeType": "YulIdentifier", + "src": "4790:5:389" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "4801:5:389", + "nodeType": "YulIdentifier", + "src": "4801:5:389" + }, + { + "kind": "number", + "nativeSrc": "4808:66:389", + "nodeType": "YulLiteral", + "src": "4808:66:389", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "4797:3:389", + "nodeType": "YulIdentifier", + "src": "4797:3:389" + }, + "nativeSrc": "4797:78:389", + "nodeType": "YulFunctionCall", + "src": "4797:78:389" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "4787:2:389", + "nodeType": "YulIdentifier", + "src": "4787:2:389" + }, + "nativeSrc": "4787:89:389", + "nodeType": "YulFunctionCall", + "src": "4787:89:389" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "4780:6:389", + "nodeType": "YulIdentifier", + "src": "4780:6:389" + }, + "nativeSrc": "4780:97:389", + "nodeType": "YulFunctionCall", + "src": "4780:97:389" + }, + "nativeSrc": "4777:117:389", + "nodeType": "YulIf", + "src": "4777:117:389" + } + ] + }, + "name": "abi_decode_bytes4_fromMemory", + "nativeSrc": "4677:223:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "4715:6:389", + "nodeType": "YulTypedName", + "src": "4715:6:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "4726:5:389", + "nodeType": "YulTypedName", + "src": "4726:5:389", + "type": "" + } + ], + "src": "4677:223:389" + }, + { + "body": { + "nativeSrc": "5114:1680:389", + "nodeType": "YulBlock", + "src": "5114:1680:389", + "statements": [ + { + "body": { + "nativeSrc": "5161:16:389", + "nodeType": "YulBlock", + "src": "5161:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5170:1:389", + "nodeType": "YulLiteral", + "src": "5170:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5173:1:389", + "nodeType": "YulLiteral", + "src": "5173:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5163:6:389", + "nodeType": "YulIdentifier", + "src": "5163:6:389" + }, + "nativeSrc": "5163:12:389", + "nodeType": "YulFunctionCall", + "src": "5163:12:389" + }, + "nativeSrc": "5163:12:389", + "nodeType": "YulExpressionStatement", + "src": "5163:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "5135:7:389", + "nodeType": "YulIdentifier", + "src": "5135:7:389" + }, + { + "name": "headStart", + "nativeSrc": "5144:9:389", + "nodeType": "YulIdentifier", + "src": "5144:9:389" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "5131:3:389", + "nodeType": "YulIdentifier", + "src": "5131:3:389" + }, + "nativeSrc": "5131:23:389", + "nodeType": "YulFunctionCall", + "src": "5131:23:389" + }, + { + "kind": "number", + "nativeSrc": "5156:3:389", + "nodeType": "YulLiteral", + "src": "5156:3:389", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "5127:3:389", + "nodeType": "YulIdentifier", + "src": "5127:3:389" + }, + "nativeSrc": "5127:33:389", + "nodeType": "YulFunctionCall", + "src": "5127:33:389" + }, + "nativeSrc": "5124:53:389", + "nodeType": "YulIf", + "src": "5124:53:389" + }, + { + "nativeSrc": "5186:29:389", + "nodeType": "YulVariableDeclaration", + "src": "5186:29:389", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5205:9:389", + "nodeType": "YulIdentifier", + "src": "5205:9:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5199:5:389", + "nodeType": "YulIdentifier", + "src": "5199:5:389" + }, + "nativeSrc": "5199:16:389", + "nodeType": "YulFunctionCall", + "src": "5199:16:389" + }, + "variables": [ + { + "name": "value", + "nativeSrc": "5190:5:389", + "nodeType": "YulTypedName", + "src": "5190:5:389", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value", + "nativeSrc": "5249:5:389", + "nodeType": "YulIdentifier", + "src": "5249:5:389" + } + ], + "functionName": { + "name": "validator_revert_address", + "nativeSrc": "5224:24:389", + "nodeType": "YulIdentifier", + "src": "5224:24:389" + }, + "nativeSrc": "5224:31:389", + "nodeType": "YulFunctionCall", + "src": "5224:31:389" + }, + "nativeSrc": "5224:31:389", + "nodeType": "YulExpressionStatement", + "src": "5224:31:389" + }, + { + "nativeSrc": "5264:15:389", + "nodeType": "YulAssignment", + "src": "5264:15:389", + "value": { + "name": "value", + "nativeSrc": "5274:5:389", + "nodeType": "YulIdentifier", + "src": "5274:5:389" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "5264:6:389", + "nodeType": "YulIdentifier", + "src": "5264:6:389" + } + ] + }, + { + "nativeSrc": "5288:39:389", + "nodeType": "YulVariableDeclaration", + "src": "5288:39:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5312:9:389", + "nodeType": "YulIdentifier", + "src": "5312:9:389" + }, + { + "kind": "number", + "nativeSrc": "5323:2:389", + "nodeType": "YulLiteral", + "src": "5323:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5308:3:389", + "nodeType": "YulIdentifier", + "src": "5308:3:389" + }, + "nativeSrc": "5308:18:389", + "nodeType": "YulFunctionCall", + "src": "5308:18:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5302:5:389", + "nodeType": "YulIdentifier", + "src": "5302:5:389" + }, + "nativeSrc": "5302:25:389", + "nodeType": "YulFunctionCall", + "src": "5302:25:389" + }, + "variables": [ + { + "name": "offset", + "nativeSrc": "5292:6:389", + "nodeType": "YulTypedName", + "src": "5292:6:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5370:16:389", + "nodeType": "YulBlock", + "src": "5370:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5379:1:389", + "nodeType": "YulLiteral", + "src": "5379:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5382:1:389", + "nodeType": "YulLiteral", + "src": "5382:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5372:6:389", + "nodeType": "YulIdentifier", + "src": "5372:6:389" + }, + "nativeSrc": "5372:12:389", + "nodeType": "YulFunctionCall", + "src": "5372:12:389" + }, + "nativeSrc": "5372:12:389", + "nodeType": "YulExpressionStatement", + "src": "5372:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "5342:6:389", + "nodeType": "YulIdentifier", + "src": "5342:6:389" + }, + { + "kind": "number", + "nativeSrc": "5350:18:389", + "nodeType": "YulLiteral", + "src": "5350:18:389", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5339:2:389", + "nodeType": "YulIdentifier", + "src": "5339:2:389" + }, + "nativeSrc": "5339:30:389", + "nodeType": "YulFunctionCall", + "src": "5339:30:389" + }, + "nativeSrc": "5336:50:389", + "nodeType": "YulIf", + "src": "5336:50:389" + }, + { + "nativeSrc": "5395:32:389", + "nodeType": "YulVariableDeclaration", + "src": "5395:32:389", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5409:9:389", + "nodeType": "YulIdentifier", + "src": "5409:9:389" + }, + { + "name": "offset", + "nativeSrc": "5420:6:389", + "nodeType": "YulIdentifier", + "src": "5420:6:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5405:3:389", + "nodeType": "YulIdentifier", + "src": "5405:3:389" + }, + "nativeSrc": "5405:22:389", + "nodeType": "YulFunctionCall", + "src": "5405:22:389" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "5399:2:389", + "nodeType": "YulTypedName", + "src": "5399:2:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5475:16:389", + "nodeType": "YulBlock", + "src": "5475:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5484:1:389", + "nodeType": "YulLiteral", + "src": "5484:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5487:1:389", + "nodeType": "YulLiteral", + "src": "5487:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5477:6:389", + "nodeType": "YulIdentifier", + "src": "5477:6:389" + }, + "nativeSrc": "5477:12:389", + "nodeType": "YulFunctionCall", + "src": "5477:12:389" + }, + "nativeSrc": "5477:12:389", + "nodeType": "YulExpressionStatement", + "src": "5477:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "_1", + "nativeSrc": "5454:2:389", + "nodeType": "YulIdentifier", + "src": "5454:2:389" + }, + { + "kind": "number", + "nativeSrc": "5458:4:389", + "nodeType": "YulLiteral", + "src": "5458:4:389", + "type": "", + "value": "0x1f" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5450:3:389", + "nodeType": "YulIdentifier", + "src": "5450:3:389" + }, + "nativeSrc": "5450:13:389", + "nodeType": "YulFunctionCall", + "src": "5450:13:389" + }, + { + "name": "dataEnd", + "nativeSrc": "5465:7:389", + "nodeType": "YulIdentifier", + "src": "5465:7:389" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "5446:3:389", + "nodeType": "YulIdentifier", + "src": "5446:3:389" + }, + "nativeSrc": "5446:27:389", + "nodeType": "YulFunctionCall", + "src": "5446:27:389" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "5439:6:389", + "nodeType": "YulIdentifier", + "src": "5439:6:389" + }, + "nativeSrc": "5439:35:389", + "nodeType": "YulFunctionCall", + "src": "5439:35:389" + }, + "nativeSrc": "5436:55:389", + "nodeType": "YulIf", + "src": "5436:55:389" + }, + { + "nativeSrc": "5500:23:389", + "nodeType": "YulVariableDeclaration", + "src": "5500:23:389", + "value": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "5520:2:389", + "nodeType": "YulIdentifier", + "src": "5520:2:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5514:5:389", + "nodeType": "YulIdentifier", + "src": "5514:5:389" + }, + "nativeSrc": "5514:9:389", + "nodeType": "YulFunctionCall", + "src": "5514:9:389" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "5504:6:389", + "nodeType": "YulTypedName", + "src": "5504:6:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5566:22:389", + "nodeType": "YulBlock", + "src": "5566:22:389", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "5568:16:389", + "nodeType": "YulIdentifier", + "src": "5568:16:389" + }, + "nativeSrc": "5568:18:389", + "nodeType": "YulFunctionCall", + "src": "5568:18:389" + }, + "nativeSrc": "5568:18:389", + "nodeType": "YulExpressionStatement", + "src": "5568:18:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "length", + "nativeSrc": "5538:6:389", + "nodeType": "YulIdentifier", + "src": "5538:6:389" + }, + { + "kind": "number", + "nativeSrc": "5546:18:389", + "nodeType": "YulLiteral", + "src": "5546:18:389", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5535:2:389", + "nodeType": "YulIdentifier", + "src": "5535:2:389" + }, + "nativeSrc": "5535:30:389", + "nodeType": "YulFunctionCall", + "src": "5535:30:389" + }, + "nativeSrc": "5532:56:389", + "nodeType": "YulIf", + "src": "5532:56:389" + }, + { + "nativeSrc": "5597:24:389", + "nodeType": "YulVariableDeclaration", + "src": "5597:24:389", + "value": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5611:1:389", + "nodeType": "YulLiteral", + "src": "5611:1:389", + "type": "", + "value": "5" + }, + { + "name": "length", + "nativeSrc": "5614:6:389", + "nodeType": "YulIdentifier", + "src": "5614:6:389" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "5607:3:389", + "nodeType": "YulIdentifier", + "src": "5607:3:389" + }, + "nativeSrc": "5607:14:389", + "nodeType": "YulFunctionCall", + "src": "5607:14:389" + }, + "variables": [ + { + "name": "_2", + "nativeSrc": "5601:2:389", + "nodeType": "YulTypedName", + "src": "5601:2:389", + "type": "" + } + ] + }, + { + "nativeSrc": "5630:39:389", + "nodeType": "YulVariableDeclaration", + "src": "5630:39:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_2", + "nativeSrc": "5661:2:389", + "nodeType": "YulIdentifier", + "src": "5661:2:389" + }, + { + "kind": "number", + "nativeSrc": "5665:2:389", + "nodeType": "YulLiteral", + "src": "5665:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5657:3:389", + "nodeType": "YulIdentifier", + "src": "5657:3:389" + }, + "nativeSrc": "5657:11:389", + "nodeType": "YulFunctionCall", + "src": "5657:11:389" + } + ], + "functionName": { + "name": "allocate_memory", + "nativeSrc": "5641:15:389", + "nodeType": "YulIdentifier", + "src": "5641:15:389" + }, + "nativeSrc": "5641:28:389", + "nodeType": "YulFunctionCall", + "src": "5641:28:389" + }, + "variables": [ + { + "name": "dst", + "nativeSrc": "5634:3:389", + "nodeType": "YulTypedName", + "src": "5634:3:389", + "type": "" + } + ] + }, + { + "nativeSrc": "5678:16:389", + "nodeType": "YulVariableDeclaration", + "src": "5678:16:389", + "value": { + "name": "dst", + "nativeSrc": "5691:3:389", + "nodeType": "YulIdentifier", + "src": "5691:3:389" + }, + "variables": [ + { + "name": "array", + "nativeSrc": "5682:5:389", + "nodeType": "YulTypedName", + "src": "5682:5:389", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "5710:3:389", + "nodeType": "YulIdentifier", + "src": "5710:3:389" + }, + { + "name": "length", + "nativeSrc": "5715:6:389", + "nodeType": "YulIdentifier", + "src": "5715:6:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "5703:6:389", + "nodeType": "YulIdentifier", + "src": "5703:6:389" + }, + "nativeSrc": "5703:19:389", + "nodeType": "YulFunctionCall", + "src": "5703:19:389" + }, + "nativeSrc": "5703:19:389", + "nodeType": "YulExpressionStatement", + "src": "5703:19:389" + }, + { + "nativeSrc": "5731:19:389", + "nodeType": "YulAssignment", + "src": "5731:19:389", + "value": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "5742:3:389", + "nodeType": "YulIdentifier", + "src": "5742:3:389" + }, + { + "kind": "number", + "nativeSrc": "5747:2:389", + "nodeType": "YulLiteral", + "src": "5747:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5738:3:389", + "nodeType": "YulIdentifier", + "src": "5738:3:389" + }, + "nativeSrc": "5738:12:389", + "nodeType": "YulFunctionCall", + "src": "5738:12:389" + }, + "variableNames": [ + { + "name": "dst", + "nativeSrc": "5731:3:389", + "nodeType": "YulIdentifier", + "src": "5731:3:389" + } + ] + }, + { + "nativeSrc": "5759:34:389", + "nodeType": "YulVariableDeclaration", + "src": "5759:34:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_1", + "nativeSrc": "5781:2:389", + "nodeType": "YulIdentifier", + "src": "5781:2:389" + }, + { + "name": "_2", + "nativeSrc": "5785:2:389", + "nodeType": "YulIdentifier", + "src": "5785:2:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5777:3:389", + "nodeType": "YulIdentifier", + "src": "5777:3:389" + }, + "nativeSrc": "5777:11:389", + "nodeType": "YulFunctionCall", + "src": "5777:11:389" + }, + { + "kind": "number", + "nativeSrc": "5790:2:389", + "nodeType": "YulLiteral", + "src": "5790:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5773:3:389", + "nodeType": "YulIdentifier", + "src": "5773:3:389" + }, + "nativeSrc": "5773:20:389", + "nodeType": "YulFunctionCall", + "src": "5773:20:389" + }, + "variables": [ + { + "name": "srcEnd", + "nativeSrc": "5763:6:389", + "nodeType": "YulTypedName", + "src": "5763:6:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5825:16:389", + "nodeType": "YulBlock", + "src": "5825:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5834:1:389", + "nodeType": "YulLiteral", + "src": "5834:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5837:1:389", + "nodeType": "YulLiteral", + "src": "5837:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5827:6:389", + "nodeType": "YulIdentifier", + "src": "5827:6:389" + }, + "nativeSrc": "5827:12:389", + "nodeType": "YulFunctionCall", + "src": "5827:12:389" + }, + "nativeSrc": "5827:12:389", + "nodeType": "YulExpressionStatement", + "src": "5827:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "srcEnd", + "nativeSrc": "5808:6:389", + "nodeType": "YulIdentifier", + "src": "5808:6:389" + }, + { + "name": "dataEnd", + "nativeSrc": "5816:7:389", + "nodeType": "YulIdentifier", + "src": "5816:7:389" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5805:2:389", + "nodeType": "YulIdentifier", + "src": "5805:2:389" + }, + "nativeSrc": "5805:19:389", + "nodeType": "YulFunctionCall", + "src": "5805:19:389" + }, + "nativeSrc": "5802:39:389", + "nodeType": "YulIf", + "src": "5802:39:389" + }, + { + "nativeSrc": "5850:22:389", + "nodeType": "YulVariableDeclaration", + "src": "5850:22:389", + "value": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "5865:2:389", + "nodeType": "YulIdentifier", + "src": "5865:2:389" + }, + { + "kind": "number", + "nativeSrc": "5869:2:389", + "nodeType": "YulLiteral", + "src": "5869:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5861:3:389", + "nodeType": "YulIdentifier", + "src": "5861:3:389" + }, + "nativeSrc": "5861:11:389", + "nodeType": "YulFunctionCall", + "src": "5861:11:389" + }, + "variables": [ + { + "name": "src", + "nativeSrc": "5854:3:389", + "nodeType": "YulTypedName", + "src": "5854:3:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5937:375:389", + "nodeType": "YulBlock", + "src": "5937:375:389", + "statements": [ + { + "nativeSrc": "5951:29:389", + "nodeType": "YulVariableDeclaration", + "src": "5951:29:389", + "value": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5976:3:389", + "nodeType": "YulIdentifier", + "src": "5976:3:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5970:5:389", + "nodeType": "YulIdentifier", + "src": "5970:5:389" + }, + "nativeSrc": "5970:10:389", + "nodeType": "YulFunctionCall", + "src": "5970:10:389" + }, + "variables": [ + { + "name": "innerOffset", + "nativeSrc": "5955:11:389", + "nodeType": "YulTypedName", + "src": "5955:11:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6032:16:389", + "nodeType": "YulBlock", + "src": "6032:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6041:1:389", + "nodeType": "YulLiteral", + "src": "6041:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6044:1:389", + "nodeType": "YulLiteral", + "src": "6044:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6034:6:389", + "nodeType": "YulIdentifier", + "src": "6034:6:389" + }, + "nativeSrc": "6034:12:389", + "nodeType": "YulFunctionCall", + "src": "6034:12:389" + }, + "nativeSrc": "6034:12:389", + "nodeType": "YulExpressionStatement", + "src": "6034:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "innerOffset", + "nativeSrc": "5999:11:389", + "nodeType": "YulIdentifier", + "src": "5999:11:389" + }, + { + "kind": "number", + "nativeSrc": "6012:18:389", + "nodeType": "YulLiteral", + "src": "6012:18:389", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5996:2:389", + "nodeType": "YulIdentifier", + "src": "5996:2:389" + }, + "nativeSrc": "5996:35:389", + "nodeType": "YulFunctionCall", + "src": "5996:35:389" + }, + "nativeSrc": "5993:55:389", + "nodeType": "YulIf", + "src": "5993:55:389" + }, + { + "nativeSrc": "6061:30:389", + "nodeType": "YulVariableDeclaration", + "src": "6061:30:389", + "value": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "6075:2:389", + "nodeType": "YulIdentifier", + "src": "6075:2:389" + }, + { + "name": "innerOffset", + "nativeSrc": "6079:11:389", + "nodeType": "YulIdentifier", + "src": "6079:11:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6071:3:389", + "nodeType": "YulIdentifier", + "src": "6071:3:389" + }, + "nativeSrc": "6071:20:389", + "nodeType": "YulFunctionCall", + "src": "6071:20:389" + }, + "variables": [ + { + "name": "_3", + "nativeSrc": "6065:2:389", + "nodeType": "YulTypedName", + "src": "6065:2:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6141:16:389", + "nodeType": "YulBlock", + "src": "6141:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6150:1:389", + "nodeType": "YulLiteral", + "src": "6150:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6153:1:389", + "nodeType": "YulLiteral", + "src": "6153:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6143:6:389", + "nodeType": "YulIdentifier", + "src": "6143:6:389" + }, + "nativeSrc": "6143:12:389", + "nodeType": "YulFunctionCall", + "src": "6143:12:389" + }, + "nativeSrc": "6143:12:389", + "nodeType": "YulExpressionStatement", + "src": "6143:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "_3", + "nativeSrc": "6122:2:389", + "nodeType": "YulIdentifier", + "src": "6122:2:389" + }, + { + "kind": "number", + "nativeSrc": "6126:2:389", + "nodeType": "YulLiteral", + "src": "6126:2:389", + "type": "", + "value": "63" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6118:3:389", + "nodeType": "YulIdentifier", + "src": "6118:3:389" + }, + "nativeSrc": "6118:11:389", + "nodeType": "YulFunctionCall", + "src": "6118:11:389" + }, + { + "name": "dataEnd", + "nativeSrc": "6131:7:389", + "nodeType": "YulIdentifier", + "src": "6131:7:389" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "6114:3:389", + "nodeType": "YulIdentifier", + "src": "6114:3:389" + }, + "nativeSrc": "6114:25:389", + "nodeType": "YulFunctionCall", + "src": "6114:25:389" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "6107:6:389", + "nodeType": "YulIdentifier", + "src": "6107:6:389" + }, + "nativeSrc": "6107:33:389", + "nodeType": "YulFunctionCall", + "src": "6107:33:389" + }, + "nativeSrc": "6104:53:389", + "nodeType": "YulIf", + "src": "6104:53:389" + }, + { + "expression": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "6177:3:389", + "nodeType": "YulIdentifier", + "src": "6177:3:389" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "_3", + "nativeSrc": "6232:2:389", + "nodeType": "YulIdentifier", + "src": "6232:2:389" + }, + { + "kind": "number", + "nativeSrc": "6236:2:389", + "nodeType": "YulLiteral", + "src": "6236:2:389", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6228:3:389", + "nodeType": "YulIdentifier", + "src": "6228:3:389" + }, + "nativeSrc": "6228:11:389", + "nodeType": "YulFunctionCall", + "src": "6228:11:389" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "_3", + "nativeSrc": "6251:2:389", + "nodeType": "YulIdentifier", + "src": "6251:2:389" + }, + { + "kind": "number", + "nativeSrc": "6255:2:389", + "nodeType": "YulLiteral", + "src": "6255:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6247:3:389", + "nodeType": "YulIdentifier", + "src": "6247:3:389" + }, + "nativeSrc": "6247:11:389", + "nodeType": "YulFunctionCall", + "src": "6247:11:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6241:5:389", + "nodeType": "YulIdentifier", + "src": "6241:5:389" + }, + "nativeSrc": "6241:18:389", + "nodeType": "YulFunctionCall", + "src": "6241:18:389" + }, + { + "name": "dataEnd", + "nativeSrc": "6261:7:389", + "nodeType": "YulIdentifier", + "src": "6261:7:389" + } + ], + "functionName": { + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "6182:45:389", + "nodeType": "YulIdentifier", + "src": "6182:45:389" + }, + "nativeSrc": "6182:87:389", + "nodeType": "YulFunctionCall", + "src": "6182:87:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "6170:6:389", + "nodeType": "YulIdentifier", + "src": "6170:6:389" + }, + "nativeSrc": "6170:100:389", + "nodeType": "YulFunctionCall", + "src": "6170:100:389" + }, + "nativeSrc": "6170:100:389", + "nodeType": "YulExpressionStatement", + "src": "6170:100:389" + }, + { + "nativeSrc": "6283:19:389", + "nodeType": "YulAssignment", + "src": "6283:19:389", + "value": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "6294:3:389", + "nodeType": "YulIdentifier", + "src": "6294:3:389" + }, + { + "kind": "number", + "nativeSrc": "6299:2:389", + "nodeType": "YulLiteral", + "src": "6299:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6290:3:389", + "nodeType": "YulIdentifier", + "src": "6290:3:389" + }, + "nativeSrc": "6290:12:389", + "nodeType": "YulFunctionCall", + "src": "6290:12:389" + }, + "variableNames": [ + { + "name": "dst", + "nativeSrc": "6283:3:389", + "nodeType": "YulIdentifier", + "src": "6283:3:389" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5892:3:389", + "nodeType": "YulIdentifier", + "src": "5892:3:389" + }, + { + "name": "srcEnd", + "nativeSrc": "5897:6:389", + "nodeType": "YulIdentifier", + "src": "5897:6:389" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "5889:2:389", + "nodeType": "YulIdentifier", + "src": "5889:2:389" + }, + "nativeSrc": "5889:15:389", + "nodeType": "YulFunctionCall", + "src": "5889:15:389" + }, + "nativeSrc": "5881:431:389", + "nodeType": "YulForLoop", + "post": { + "nativeSrc": "5905:23:389", + "nodeType": "YulBlock", + "src": "5905:23:389", + "statements": [ + { + "nativeSrc": "5907:19:389", + "nodeType": "YulAssignment", + "src": "5907:19:389", + "value": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5918:3:389", + "nodeType": "YulIdentifier", + "src": "5918:3:389" + }, + { + "kind": "number", + "nativeSrc": "5923:2:389", + "nodeType": "YulLiteral", + "src": "5923:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5914:3:389", + "nodeType": "YulIdentifier", + "src": "5914:3:389" + }, + "nativeSrc": "5914:12:389", + "nodeType": "YulFunctionCall", + "src": "5914:12:389" + }, + "variableNames": [ + { + "name": "src", + "nativeSrc": "5907:3:389", + "nodeType": "YulIdentifier", + "src": "5907:3:389" + } + ] + } + ] + }, + "pre": { + "nativeSrc": "5885:3:389", + "nodeType": "YulBlock", + "src": "5885:3:389", + "statements": [] + }, + "src": "5881:431:389" + }, + { + "nativeSrc": "6321:15:389", + "nodeType": "YulAssignment", + "src": "6321:15:389", + "value": { + "name": "array", + "nativeSrc": "6331:5:389", + "nodeType": "YulIdentifier", + "src": "6331:5:389" + }, + "variableNames": [ + { + "name": "value1", + "nativeSrc": "6321:6:389", + "nodeType": "YulIdentifier", + "src": "6321:6:389" + } + ] + }, + { + "nativeSrc": "6345:41:389", + "nodeType": "YulVariableDeclaration", + "src": "6345:41:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6371:9:389", + "nodeType": "YulIdentifier", + "src": "6371:9:389" + }, + { + "kind": "number", + "nativeSrc": "6382:2:389", + "nodeType": "YulLiteral", + "src": "6382:2:389", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6367:3:389", + "nodeType": "YulIdentifier", + "src": "6367:3:389" + }, + "nativeSrc": "6367:18:389", + "nodeType": "YulFunctionCall", + "src": "6367:18:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6361:5:389", + "nodeType": "YulIdentifier", + "src": "6361:5:389" + }, + "nativeSrc": "6361:25:389", + "nodeType": "YulFunctionCall", + "src": "6361:25:389" + }, + "variables": [ + { + "name": "offset_1", + "nativeSrc": "6349:8:389", + "nodeType": "YulTypedName", + "src": "6349:8:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6431:16:389", + "nodeType": "YulBlock", + "src": "6431:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6440:1:389", + "nodeType": "YulLiteral", + "src": "6440:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6443:1:389", + "nodeType": "YulLiteral", + "src": "6443:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6433:6:389", + "nodeType": "YulIdentifier", + "src": "6433:6:389" + }, + "nativeSrc": "6433:12:389", + "nodeType": "YulFunctionCall", + "src": "6433:12:389" + }, + "nativeSrc": "6433:12:389", + "nodeType": "YulExpressionStatement", + "src": "6433:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset_1", + "nativeSrc": "6401:8:389", + "nodeType": "YulIdentifier", + "src": "6401:8:389" + }, + { + "kind": "number", + "nativeSrc": "6411:18:389", + "nodeType": "YulLiteral", + "src": "6411:18:389", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6398:2:389", + "nodeType": "YulIdentifier", + "src": "6398:2:389" + }, + "nativeSrc": "6398:32:389", + "nodeType": "YulFunctionCall", + "src": "6398:32:389" + }, + "nativeSrc": "6395:52:389", + "nodeType": "YulIf", + "src": "6395:52:389" + }, + { + "nativeSrc": "6456:72:389", + "nodeType": "YulAssignment", + "src": "6456:72:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6498:9:389", + "nodeType": "YulIdentifier", + "src": "6498:9:389" + }, + { + "name": "offset_1", + "nativeSrc": "6509:8:389", + "nodeType": "YulIdentifier", + "src": "6509:8:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6494:3:389", + "nodeType": "YulIdentifier", + "src": "6494:3:389" + }, + "nativeSrc": "6494:24:389", + "nodeType": "YulFunctionCall", + "src": "6494:24:389" + }, + { + "name": "dataEnd", + "nativeSrc": "6520:7:389", + "nodeType": "YulIdentifier", + "src": "6520:7:389" + } + ], + "functionName": { + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "6466:27:389", + "nodeType": "YulIdentifier", + "src": "6466:27:389" + }, + "nativeSrc": "6466:62:389", + "nodeType": "YulFunctionCall", + "src": "6466:62:389" + }, + "variableNames": [ + { + "name": "value2", + "nativeSrc": "6456:6:389", + "nodeType": "YulIdentifier", + "src": "6456:6:389" + } + ] + }, + { + "nativeSrc": "6537:58:389", + "nodeType": "YulAssignment", + "src": "6537:58:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6580:9:389", + "nodeType": "YulIdentifier", + "src": "6580:9:389" + }, + { + "kind": "number", + "nativeSrc": "6591:2:389", + "nodeType": "YulLiteral", + "src": "6591:2:389", + "type": "", + "value": "96" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6576:3:389", + "nodeType": "YulIdentifier", + "src": "6576:3:389" + }, + "nativeSrc": "6576:18:389", + "nodeType": "YulFunctionCall", + "src": "6576:18:389" + } + ], + "functionName": { + "name": "abi_decode_bytes4_fromMemory", + "nativeSrc": "6547:28:389", + "nodeType": "YulIdentifier", + "src": "6547:28:389" + }, + "nativeSrc": "6547:48:389", + "nodeType": "YulFunctionCall", + "src": "6547:48:389" + }, + "variableNames": [ + { + "name": "value3", + "nativeSrc": "6537:6:389", + "nodeType": "YulIdentifier", + "src": "6537:6:389" + } + ] + }, + { + "nativeSrc": "6604:42:389", + "nodeType": "YulVariableDeclaration", + "src": "6604:42:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6630:9:389", + "nodeType": "YulIdentifier", + "src": "6630:9:389" + }, + { + "kind": "number", + "nativeSrc": "6641:3:389", + "nodeType": "YulLiteral", + "src": "6641:3:389", + "type": "", + "value": "128" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6626:3:389", + "nodeType": "YulIdentifier", + "src": "6626:3:389" + }, + "nativeSrc": "6626:19:389", + "nodeType": "YulFunctionCall", + "src": "6626:19:389" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6620:5:389", + "nodeType": "YulIdentifier", + "src": "6620:5:389" + }, + "nativeSrc": "6620:26:389", + "nodeType": "YulFunctionCall", + "src": "6620:26:389" + }, + "variables": [ + { + "name": "offset_2", + "nativeSrc": "6608:8:389", + "nodeType": "YulTypedName", + "src": "6608:8:389", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6691:16:389", + "nodeType": "YulBlock", + "src": "6691:16:389", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6700:1:389", + "nodeType": "YulLiteral", + "src": "6700:1:389", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6703:1:389", + "nodeType": "YulLiteral", + "src": "6703:1:389", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6693:6:389", + "nodeType": "YulIdentifier", + "src": "6693:6:389" + }, + "nativeSrc": "6693:12:389", + "nodeType": "YulFunctionCall", + "src": "6693:12:389" + }, + "nativeSrc": "6693:12:389", + "nodeType": "YulExpressionStatement", + "src": "6693:12:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset_2", + "nativeSrc": "6661:8:389", + "nodeType": "YulIdentifier", + "src": "6661:8:389" + }, + { + "kind": "number", + "nativeSrc": "6671:18:389", + "nodeType": "YulLiteral", + "src": "6671:18:389", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6658:2:389", + "nodeType": "YulIdentifier", + "src": "6658:2:389" + }, + "nativeSrc": "6658:32:389", + "nodeType": "YulFunctionCall", + "src": "6658:32:389" + }, + "nativeSrc": "6655:52:389", + "nodeType": "YulIf", + "src": "6655:52:389" + }, + { + "nativeSrc": "6716:72:389", + "nodeType": "YulAssignment", + "src": "6716:72:389", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6758:9:389", + "nodeType": "YulIdentifier", + "src": "6758:9:389" + }, + { + "name": "offset_2", + "nativeSrc": "6769:8:389", + "nodeType": "YulIdentifier", + "src": "6769:8:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6754:3:389", + "nodeType": "YulIdentifier", + "src": "6754:3:389" + }, + "nativeSrc": "6754:24:389", + "nodeType": "YulFunctionCall", + "src": "6754:24:389" + }, + { + "name": "dataEnd", + "nativeSrc": "6780:7:389", + "nodeType": "YulIdentifier", + "src": "6780:7:389" + } + ], + "functionName": { + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "6726:27:389", + "nodeType": "YulIdentifier", + "src": "6726:27:389" + }, + "nativeSrc": "6726:62:389", + "nodeType": "YulFunctionCall", + "src": "6726:62:389" + }, + "variableNames": [ + { + "name": "value4", + "nativeSrc": "6716:6:389", + "nodeType": "YulIdentifier", + "src": "6716:6:389" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory", + "nativeSrc": "4905:1889:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "5048:9:389", + "nodeType": "YulTypedName", + "src": "5048:9:389", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "5059:7:389", + "nodeType": "YulTypedName", + "src": "5059:7:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "5071:6:389", + "nodeType": "YulTypedName", + "src": "5071:6:389", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "5079:6:389", + "nodeType": "YulTypedName", + "src": "5079:6:389", + "type": "" + }, + { + "name": "value2", + "nativeSrc": "5087:6:389", + "nodeType": "YulTypedName", + "src": "5087:6:389", + "type": "" + }, + { + "name": "value3", + "nativeSrc": "5095:6:389", + "nodeType": "YulTypedName", + "src": "5095:6:389", + "type": "" + }, + { + "name": "value4", + "nativeSrc": "5103:6:389", + "nodeType": "YulTypedName", + "src": "5103:6:389", + "type": "" + } + ], + "src": "4905:1889:389" + }, + { + "body": { + "nativeSrc": "6847:77:389", + "nodeType": "YulBlock", + "src": "6847:77:389", + "statements": [ + { + "nativeSrc": "6857:16:389", + "nodeType": "YulAssignment", + "src": "6857:16:389", + "value": { + "arguments": [ + { + "name": "x", + "nativeSrc": "6868:1:389", + "nodeType": "YulIdentifier", + "src": "6868:1:389" + }, + { + "name": "y", + "nativeSrc": "6871:1:389", + "nodeType": "YulIdentifier", + "src": "6871:1:389" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6864:3:389", + "nodeType": "YulIdentifier", + "src": "6864:3:389" + }, + "nativeSrc": "6864:9:389", + "nodeType": "YulFunctionCall", + "src": "6864:9:389" + }, + "variableNames": [ + { + "name": "sum", + "nativeSrc": "6857:3:389", + "nodeType": "YulIdentifier", + "src": "6857:3:389" + } + ] + }, + { + "body": { + "nativeSrc": "6896:22:389", + "nodeType": "YulBlock", + "src": "6896:22:389", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x11", + "nativeSrc": "6898:16:389", + "nodeType": "YulIdentifier", + "src": "6898:16:389" + }, + "nativeSrc": "6898:18:389", + "nodeType": "YulFunctionCall", + "src": "6898:18:389" + }, + "nativeSrc": "6898:18:389", + "nodeType": "YulExpressionStatement", + "src": "6898:18:389" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "x", + "nativeSrc": "6888:1:389", + "nodeType": "YulIdentifier", + "src": "6888:1:389" + }, + { + "name": "sum", + "nativeSrc": "6891:3:389", + "nodeType": "YulIdentifier", + "src": "6891:3:389" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6885:2:389", + "nodeType": "YulIdentifier", + "src": "6885:2:389" + }, + "nativeSrc": "6885:10:389", + "nodeType": "YulFunctionCall", + "src": "6885:10:389" + }, + "nativeSrc": "6882:36:389", + "nodeType": "YulIf", + "src": "6882:36:389" + } + ] + }, + "name": "checked_add_t_uint256", + "nativeSrc": "6799:125:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "x", + "nativeSrc": "6830:1:389", + "nodeType": "YulTypedName", + "src": "6830:1:389", + "type": "" + }, + { + "name": "y", + "nativeSrc": "6833:1:389", + "nodeType": "YulTypedName", + "src": "6833:1:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "sum", + "nativeSrc": "6839:3:389", + "nodeType": "YulTypedName", + "src": "6839:3:389", + "type": "" + } + ], + "src": "6799:125:389" + }, + { + "body": { + "nativeSrc": "7058:119:389", + "nodeType": "YulBlock", + "src": "7058:119:389", + "statements": [ + { + "nativeSrc": "7068:26:389", + "nodeType": "YulAssignment", + "src": "7068:26:389", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "7080:9:389", + "nodeType": "YulIdentifier", + "src": "7080:9:389" + }, + { + "kind": "number", + "nativeSrc": "7091:2:389", + "nodeType": "YulLiteral", + "src": "7091:2:389", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "7076:3:389", + "nodeType": "YulIdentifier", + "src": "7076:3:389" + }, + "nativeSrc": "7076:18:389", + "nodeType": "YulFunctionCall", + "src": "7076:18:389" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "7068:4:389", + "nodeType": "YulIdentifier", + "src": "7068:4:389" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "7110:9:389", + "nodeType": "YulIdentifier", + "src": "7110:9:389" + }, + { + "name": "value0", + "nativeSrc": "7121:6:389", + "nodeType": "YulIdentifier", + "src": "7121:6:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "7103:6:389", + "nodeType": "YulIdentifier", + "src": "7103:6:389" + }, + "nativeSrc": "7103:25:389", + "nodeType": "YulFunctionCall", + "src": "7103:25:389" + }, + "nativeSrc": "7103:25:389", + "nodeType": "YulExpressionStatement", + "src": "7103:25:389" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "7148:9:389", + "nodeType": "YulIdentifier", + "src": "7148:9:389" + }, + { + "kind": "number", + "nativeSrc": "7159:2:389", + "nodeType": "YulLiteral", + "src": "7159:2:389", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "7144:3:389", + "nodeType": "YulIdentifier", + "src": "7144:3:389" + }, + "nativeSrc": "7144:18:389", + "nodeType": "YulFunctionCall", + "src": "7144:18:389" + }, + { + "name": "value1", + "nativeSrc": "7164:6:389", + "nodeType": "YulIdentifier", + "src": "7164:6:389" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "7137:6:389", + "nodeType": "YulIdentifier", + "src": "7137:6:389" + }, + "nativeSrc": "7137:34:389", + "nodeType": "YulFunctionCall", + "src": "7137:34:389" + }, + "nativeSrc": "7137:34:389", + "nodeType": "YulExpressionStatement", + "src": "7137:34:389" + } + ] + }, + "name": "abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed", + "nativeSrc": "6929:248:389", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "7019:9:389", + "nodeType": "YulTypedName", + "src": "7019:9:389", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "7030:6:389", + "nodeType": "YulTypedName", + "src": "7030:6:389", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "7038:6:389", + "nodeType": "YulTypedName", + "src": "7038:6:389", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "7049:4:389", + "nodeType": "YulTypedName", + "src": "7049:4:389", + "type": "" + } + ], + "src": "6929:248:389" + } + ] + }, + "contents": "{\n { }\n function abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed(pos, value1, value0) -> end\n {\n calldatacopy(pos, value0, value1)\n let _1 := add(pos, value1)\n mstore(_1, 0)\n end := _1\n }\n function convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4(array) -> value\n {\n let length := mload(array)\n let _1 := mload(add(array, 0x20))\n value := and(_1, 0xffffffff00000000000000000000000000000000000000000000000000000000)\n if lt(length, 4)\n {\n value := and(and(_1, shl(shl(3, sub(4, length)), 0xffffffff00000000000000000000000000000000000000000000000000000000)), 0xffffffff00000000000000000000000000000000000000000000000000000000)\n }\n }\n function panic_error_0x11()\n {\n mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)\n mstore(4, 0x11)\n revert(0, 0x24)\n }\n function checked_sub_t_uint256(x, y) -> diff\n {\n diff := sub(x, y)\n if gt(diff, x) { panic_error_0x11() }\n }\n function abi_encode_string(value, pos) -> end\n {\n let length := mload(value)\n mstore(pos, length)\n mcopy(add(pos, 0x20), add(value, 0x20), length)\n mstore(add(add(pos, length), 0x20), 0)\n end := add(add(pos, and(add(length, 31), not(31))), 0x20)\n }\n function abi_encode_bytes4(value, pos)\n {\n mstore(pos, and(value, 0xffffffff00000000000000000000000000000000000000000000000000000000))\n }\n function abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed(headStart, value4, value3, value2, value1, value0) -> tail\n {\n let tail_1 := add(headStart, 160)\n mstore(headStart, and(value0, 0xffffffffffffffffffffffffffffffffffffffff))\n mstore(add(headStart, 32), 160)\n let pos := tail_1\n let length := mload(value1)\n mstore(tail_1, length)\n pos := add(headStart, 192)\n let tail_2 := add(add(headStart, shl(5, length)), 192)\n let srcPtr := add(value1, 32)\n let i := 0\n for { } lt(i, length) { i := add(i, 1) }\n {\n mstore(pos, add(sub(tail_2, headStart), not(191)))\n tail_2 := abi_encode_string(mload(srcPtr), tail_2)\n srcPtr := add(srcPtr, 32)\n pos := add(pos, 32)\n }\n mstore(add(headStart, 64), sub(tail_2, headStart))\n let tail_3 := abi_encode_string(value2, tail_2)\n abi_encode_bytes4(value3, add(headStart, 96))\n mstore(add(headStart, 128), sub(tail_3, headStart))\n tail := abi_encode_string(value4, tail_3)\n }\n function validator_revert_address(value)\n {\n if iszero(eq(value, and(value, 0xffffffffffffffffffffffffffffffffffffffff))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_address(headStart, dataEnd) -> value0\n {\n if slt(sub(dataEnd, headStart), 32) { revert(0, 0) }\n let value := calldataload(headStart)\n validator_revert_address(value)\n value0 := value\n }\n function abi_encode_tuple_t_address__to_t_address__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, and(value0, 0xffffffffffffffffffffffffffffffffffffffff))\n }\n function panic_error_0x41()\n {\n mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)\n mstore(4, 0x41)\n revert(0, 0x24)\n }\n function allocate_memory(size) -> memPtr\n {\n memPtr := mload(64)\n let newFreePtr := add(memPtr, and(add(size, 31), not(31)))\n if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }\n mstore(64, newFreePtr)\n }\n function abi_decode_available_length_string_fromMemory(src, length, end) -> array\n {\n let size := 0\n if gt(length, 0xffffffffffffffff) { panic_error_0x41() }\n size := add(and(add(length, 31), not(31)), 0x20)\n array := allocate_memory(size)\n mstore(array, length)\n if gt(add(src, length), end) { revert(0, 0) }\n mcopy(add(array, 0x20), src, length)\n mstore(add(add(array, length), 0x20), 0)\n }\n function abi_decode_bytes_fromMemory(offset, end) -> array\n {\n if iszero(slt(add(offset, 0x1f), end)) { revert(0, 0) }\n array := abi_decode_available_length_string_fromMemory(add(offset, 0x20), mload(offset), end)\n }\n function abi_decode_bytes4_fromMemory(offset) -> value\n {\n value := mload(offset)\n if iszero(eq(value, and(value, 0xffffffff00000000000000000000000000000000000000000000000000000000))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory(headStart, dataEnd) -> value0, value1, value2, value3, value4\n {\n if slt(sub(dataEnd, headStart), 160) { revert(0, 0) }\n let value := mload(headStart)\n validator_revert_address(value)\n value0 := value\n let offset := mload(add(headStart, 32))\n if gt(offset, 0xffffffffffffffff) { revert(0, 0) }\n let _1 := add(headStart, offset)\n if iszero(slt(add(_1, 0x1f), dataEnd)) { revert(0, 0) }\n let length := mload(_1)\n if gt(length, 0xffffffffffffffff) { panic_error_0x41() }\n let _2 := shl(5, length)\n let dst := allocate_memory(add(_2, 32))\n let array := dst\n mstore(dst, length)\n dst := add(dst, 32)\n let srcEnd := add(add(_1, _2), 32)\n if gt(srcEnd, dataEnd) { revert(0, 0) }\n let src := add(_1, 32)\n for { } lt(src, srcEnd) { src := add(src, 32) }\n {\n let innerOffset := mload(src)\n if gt(innerOffset, 0xffffffffffffffff) { revert(0, 0) }\n let _3 := add(_1, innerOffset)\n if iszero(slt(add(_3, 63), dataEnd)) { revert(0, 0) }\n mstore(dst, abi_decode_available_length_string_fromMemory(add(_3, 64), mload(add(_3, 32)), dataEnd))\n dst := add(dst, 32)\n }\n value1 := array\n let offset_1 := mload(add(headStart, 64))\n if gt(offset_1, 0xffffffffffffffff) { revert(0, 0) }\n value2 := abi_decode_bytes_fromMemory(add(headStart, offset_1), dataEnd)\n value3 := abi_decode_bytes4_fromMemory(add(headStart, 96))\n let offset_2 := mload(add(headStart, 128))\n if gt(offset_2, 0xffffffffffffffff) { revert(0, 0) }\n value4 := abi_decode_bytes_fromMemory(add(headStart, offset_2), dataEnd)\n }\n function checked_add_t_uint256(x, y) -> sum\n {\n sum := add(x, y)\n if gt(x, sum) { panic_error_0x11() }\n }\n function abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed(headStart, value1, value0) -> tail\n {\n tail := add(headStart, 64)\n mstore(headStart, value0)\n mstore(add(headStart, 32), value1)\n }\n}", + "id": 389, + "language": "Yul", + "name": "#utility.yul" + } + ], + "immutableReferences": {}, + "linkReferences": {}, + "object": "608060405234801561000f575f5ffd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f5f6100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610698565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106df565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079f565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107ba565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610892565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109eb565b6105a4565b6104308361041d83856109eb565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b805160208201516001600160e01b031981169190600482101561067d576001600160e01b0319808360040360031b1b82161692505b5050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106ab576106ab610684565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b038816835260a0602084015280875180835260c08501915060c08160051b8601019250602089015f5b828110156107455760bf198786030184526107308583516106b1565b94506020938401939190910190600101610714565b50505050828103604084015261075b81876106b1565b6001600160e01b0319861660608501529050828103608084015261077f81856106b1565b98975050505050505050565b6001600160a01b038116811461051a575f5ffd5b5f602082840312156107af575f5ffd5b81356102448161078b565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f7576107f76107ba565b604052919050565b5f5f67ffffffffffffffff841115610819576108196107ba565b50601f8301601f191660200161082e816107ce565b915050828152838383011115610842575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f830112610867575f5ffd5b610244838351602085016107ff565b80516001600160e01b03198116811461088d575f5ffd5b919050565b5f5f5f5f5f60a086880312156108a6575f5ffd5b85516108b18161078b565b602087015190955067ffffffffffffffff8111156108cd575f5ffd5b8601601f810188136108dd575f5ffd5b805167ffffffffffffffff8111156108f7576108f76107ba565b8060051b610907602082016107ce565b9182526020818401810192908101908b841115610922575f5ffd5b6020850192505b8383101561097b57825167ffffffffffffffff811115610947575f5ffd5b8501603f81018d13610957575f5ffd5b6109698d6020830151604084016107ff565b83525060209283019290910190610929565b8098505050505050604086015167ffffffffffffffff81111561099c575f5ffd5b6109a888828901610858565b9350506109b760608701610876565b9150608086015167ffffffffffffffff8111156109d2575f5ffd5b6109de88828901610858565b9150509295509295909350565b808201808211156106ab576106ab61068456fea2646970667358221220279d9d6797af016644e3ccab38510ac50a266b554e0ccfc76c6215c485dcca4264736f6c634300081b0033", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 PUSH0 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4A JUMPI PUSH0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x3659CFE6 EQ PUSH2 0x176 JUMPI DUP1 PUSH4 0x5C60DA1B EQ PUSH2 0x189 JUMPI DUP1 PUSH4 0x8BAD0C0A EQ PUSH2 0x1AD JUMPI DUP1 PUSH4 0xF851A440 EQ PUSH2 0x1B5 JUMPI JUMPDEST PUSH0 PUSH0 PUSH2 0x54 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH0 CALLDATASIZE PUSH1 0x40 MLOAD PUSH2 0x6D SWAP3 SWAP2 SWAP1 PUSH2 0x639 JUMP JUMPDEST PUSH0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 GAS STATICCALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH0 DUP2 EQ PUSH2 0xA5 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0xAA JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 ISZERO DUP1 ISZERO PUSH2 0xD5 JUMPI POP PUSH4 0x556F183 PUSH1 0xE4 SHL PUSH2 0xC9 DUP3 PUSH2 0x648 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND EQ JUMPDEST ISZERO PUSH2 0x15E JUMPI PUSH0 PUSH2 0xFB PUSH2 0xF6 DUP4 PUSH1 0x4 DUP1 DUP7 MLOAD PUSH2 0xF1 SWAP2 SWAP1 PUSH2 0x698 JUMP JUMPDEST PUSH2 0x1EF JUMP JUMPDEST PUSH2 0x24B JUMP JUMPDEST SWAP1 POP PUSH2 0x105 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 PUSH0 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x15C JUMPI ADDRESS DUP2 PUSH1 0x20 ADD MLOAD DUP3 PUSH1 0x40 ADD MLOAD DUP4 PUSH1 0x60 ADD MLOAD DUP5 PUSH1 0x80 ADD MLOAD PUSH1 0x40 MLOAD PUSH4 0x556F183 PUSH1 0xE4 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x153 SWAP6 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x6DF JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMPDEST DUP2 ISZERO PUSH2 0x16C JUMPI DUP1 MLOAD PUSH1 0x20 DUP3 ADD RETURN JUMPDEST DUP1 MLOAD PUSH1 0x20 DUP3 ADD REVERT JUMPDEST STOP JUMPDEST PUSH2 0x174 PUSH2 0x184 CALLDATASIZE PUSH1 0x4 PUSH2 0x79F JUMP JUMPDEST PUSH2 0x2B6 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x375 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x174 PUSH2 0x383 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x406 JUMP JUMPDEST PUSH0 PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 DUP2 PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x20A JUMPI PUSH2 0x20A PUSH2 0x7BA JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x1F ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x234 JUMPI PUSH1 0x20 DUP3 ADD DUP2 DUP1 CALLDATASIZE DUP4 CALLDATACOPY ADD SWAP1 POP JUMPDEST POP SWAP1 POP PUSH2 0x244 DUP5 DUP5 DUP4 PUSH0 DUP7 PUSH2 0x40F JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0xA0 DUP2 ADD DUP3 MSTORE PUSH0 DUP1 DUP3 MSTORE PUSH1 0x60 PUSH1 0x20 DUP4 ADD DUP2 SWAP1 MSTORE SWAP3 DUP3 ADD DUP4 SWAP1 MSTORE DUP3 DUP3 ADD MSTORE PUSH1 0x80 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP2 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD DUP2 ADD SWAP1 PUSH2 0x288 SWAP2 SWAP1 PUSH2 0x892 JUMP JUMPDEST PUSH1 0x80 DUP7 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND PUSH1 0x60 DUP6 ADD MSTORE PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x20 DUP4 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x2BE PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x2EF JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0x2F8 DUP2 PUSH2 0x473 JUMP JUMPDEST PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xBC7CD75A20EE27FD9ADEBAB32041F755214DBC6BFFA90CC0225B39DA2E5C2D3B SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x1BD JUMP JUMPDEST SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x38B PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x3BC JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH0 PUSH2 0x3C5 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP PUSH2 0x3D0 PUSH0 PUSH2 0x51D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xA3B62BC36326052D97EA62D63C3D60308ED4C3EA8AC079DD8499F1E9C4F80C0F SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x44C JUMP JUMPDEST PUSH2 0x422 DUP6 PUSH2 0x41D DUP4 DUP8 PUSH2 0x9EB JUMP JUMPDEST PUSH2 0x5A4 JUMP JUMPDEST PUSH2 0x430 DUP4 PUSH2 0x41D DUP4 DUP6 PUSH2 0x9EB JUMP JUMPDEST PUSH2 0x445 DUP3 PUSH1 0x20 DUP6 ADD ADD DUP6 PUSH1 0x20 DUP9 ADD ADD DUP4 PUSH2 0x5F0 JUMP JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH0 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 PUSH2 0x1E0 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x491 JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0x4C8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x68155F9A00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH2 0x4DA PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x51A JUMPI PUSH1 0x40 MLOAD PUSH32 0x4C3B76BF00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0x526 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP DUP2 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST DUP2 MLOAD DUP2 GT ISZERO PUSH2 0x5EC JUMPI DUP2 MLOAD PUSH1 0x40 MLOAD PUSH32 0x8A3C1CFB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x153 SWAP2 DUP4 SWAP2 PUSH1 0x4 ADD SWAP2 DUP3 MSTORE PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST POP POP JUMP JUMPDEST JUMPDEST PUSH1 0x1F DUP2 GT ISZERO PUSH2 0x611 JUMPI DUP2 MLOAD DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1F NOT ADD PUSH2 0x5F1 JUMP JUMPDEST DUP1 ISZERO PUSH2 0x634 JUMPI DUP2 MLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0x20 DUP5 SWAP1 SUB PUSH1 0x3 SHL SHL PUSH0 NOT ADD DUP1 NOT SWAP1 SWAP3 AND SWAP2 AND OR DUP4 MSTORE JUMPDEST POP POP POP JUMP JUMPDEST DUP2 DUP4 DUP3 CALLDATACOPY PUSH0 SWAP2 ADD SWAP1 DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST DUP1 MLOAD PUSH1 0x20 DUP3 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP2 AND SWAP2 SWAP1 PUSH1 0x4 DUP3 LT ISZERO PUSH2 0x67D JUMPI PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP1 DUP4 PUSH1 0x4 SUB PUSH1 0x3 SHL SHL DUP3 AND AND SWAP3 POP JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x11 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST DUP2 DUP2 SUB DUP2 DUP2 GT ISZERO PUSH2 0x6AB JUMPI PUSH2 0x6AB PUSH2 0x684 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 DUP2 MLOAD DUP1 DUP5 MSTORE DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP7 ADD MCOPY PUSH0 PUSH1 0x20 DUP3 DUP7 ADD ADD MSTORE PUSH1 0x20 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 PUSH1 0xA0 DUP3 ADD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP9 AND DUP4 MSTORE PUSH1 0xA0 PUSH1 0x20 DUP5 ADD MSTORE DUP1 DUP8 MLOAD DUP1 DUP4 MSTORE PUSH1 0xC0 DUP6 ADD SWAP2 POP PUSH1 0xC0 DUP2 PUSH1 0x5 SHL DUP7 ADD ADD SWAP3 POP PUSH1 0x20 DUP10 ADD PUSH0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x745 JUMPI PUSH1 0xBF NOT DUP8 DUP7 SUB ADD DUP5 MSTORE PUSH2 0x730 DUP6 DUP4 MLOAD PUSH2 0x6B1 JUMP JUMPDEST SWAP5 POP PUSH1 0x20 SWAP4 DUP5 ADD SWAP4 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x714 JUMP JUMPDEST POP POP POP POP DUP3 DUP2 SUB PUSH1 0x40 DUP5 ADD MSTORE PUSH2 0x75B DUP2 DUP8 PUSH2 0x6B1 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP7 AND PUSH1 0x60 DUP6 ADD MSTORE SWAP1 POP DUP3 DUP2 SUB PUSH1 0x80 DUP5 ADD MSTORE PUSH2 0x77F DUP2 DUP6 PUSH2 0x6B1 JUMP JUMPDEST SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x51A JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x7AF JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x244 DUP2 PUSH2 0x78B JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x41 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1F DUP3 ADD PUSH1 0x1F NOT AND DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x7F7 JUMPI PUSH2 0x7F7 PUSH2 0x7BA JUMP JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH0 PUSH8 0xFFFFFFFFFFFFFFFF DUP5 GT ISZERO PUSH2 0x819 JUMPI PUSH2 0x819 PUSH2 0x7BA JUMP JUMPDEST POP PUSH1 0x1F DUP4 ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD PUSH2 0x82E DUP2 PUSH2 0x7CE JUMP JUMPDEST SWAP2 POP POP DUP3 DUP2 MSTORE DUP4 DUP4 DUP4 ADD GT ISZERO PUSH2 0x842 JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP3 DUP3 PUSH1 0x20 DUP4 ADD MCOPY PUSH0 PUSH1 0x20 DUP5 DUP4 ADD ADD MSTORE SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x867 JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x244 DUP4 DUP4 MLOAD PUSH1 0x20 DUP6 ADD PUSH2 0x7FF JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP2 AND DUP2 EQ PUSH2 0x88D JUMPI PUSH0 PUSH0 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH0 PUSH0 PUSH0 PUSH0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0x8A6 JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP6 MLOAD PUSH2 0x8B1 DUP2 PUSH2 0x78B JUMP JUMPDEST PUSH1 0x20 DUP8 ADD MLOAD SWAP1 SWAP6 POP PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x8CD JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP7 ADD PUSH1 0x1F DUP2 ADD DUP9 SGT PUSH2 0x8DD JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP1 MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x8F7 JUMPI PUSH2 0x8F7 PUSH2 0x7BA JUMP JUMPDEST DUP1 PUSH1 0x5 SHL PUSH2 0x907 PUSH1 0x20 DUP3 ADD PUSH2 0x7CE JUMP JUMPDEST SWAP2 DUP3 MSTORE PUSH1 0x20 DUP2 DUP5 ADD DUP2 ADD SWAP3 SWAP1 DUP2 ADD SWAP1 DUP12 DUP5 GT ISZERO PUSH2 0x922 JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH1 0x20 DUP6 ADD SWAP3 POP JUMPDEST DUP4 DUP4 LT ISZERO PUSH2 0x97B JUMPI DUP3 MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x947 JUMPI PUSH0 PUSH0 REVERT JUMPDEST DUP6 ADD PUSH1 0x3F DUP2 ADD DUP14 SGT PUSH2 0x957 JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x969 DUP14 PUSH1 0x20 DUP4 ADD MLOAD PUSH1 0x40 DUP5 ADD PUSH2 0x7FF JUMP JUMPDEST DUP4 MSTORE POP PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP1 SWAP2 ADD SWAP1 PUSH2 0x929 JUMP JUMPDEST DUP1 SWAP9 POP POP POP POP POP POP PUSH1 0x40 DUP7 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x99C JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x9A8 DUP9 DUP3 DUP10 ADD PUSH2 0x858 JUMP JUMPDEST SWAP4 POP POP PUSH2 0x9B7 PUSH1 0x60 DUP8 ADD PUSH2 0x876 JUMP JUMPDEST SWAP2 POP PUSH1 0x80 DUP7 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x9D2 JUMPI PUSH0 PUSH0 REVERT JUMPDEST PUSH2 0x9DE DUP9 DUP3 DUP10 ADD PUSH2 0x858 JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 POP SWAP3 SWAP6 SWAP1 SWAP4 POP JUMP JUMPDEST DUP1 DUP3 ADD DUP1 DUP3 GT ISZERO PUSH2 0x6AB JUMPI PUSH2 0x6AB PUSH2 0x684 JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0x27 SWAP14 SWAP14 PUSH8 0x97AF016644E3CCAB CODESIZE MLOAD EXP 0xC5 EXP 0x26 PUSH12 0x554E0CCFC76C6215C485DCCA TIMESTAMP PUSH5 0x736F6C6343 STOP ADDMOD SHL STOP CALLER ", + "sourceMap": "490:6212:367:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3416:7;3425:14;3443:20;:18;:20::i;:::-;-1:-1:-1;;;;;3443:31:367;3475:8;;3443:41;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3415:69;;;;3499:2;3498:3;:43;;;;-1:-1:-1;;;;3505:9:367;3512:1;3505:9;:::i;:::-;-1:-1:-1;;;;;;3505:36:367;;3498:43;3494:447;;;3557:23;3583:56;3598:40;3619:1;3622;3636;3625;:8;:12;;;;:::i;:::-;3598:20;:40::i;:::-;3583:14;:56::i;:::-;3557:82;;3669:20;:18;:20::i;:::-;-1:-1:-1;;;;;3657:32:367;:1;:8;;;-1:-1:-1;;;;;3657:32:367;;3653:278;;3760:4;3787:1;:6;;;3815:1;:10;;;3847:1;:18;;;3887:1;:11;;;3716:200;;-1:-1:-1;;;3716:200:367;;;;;;;;;;;;:::i;:::-;;;;;;;;3653:278;3543:398;3494:447;3955:2;3951:200;;;4025:1;4019:8;4014:2;4011:1;4007:10;4000:28;3951:200;4124:1;4118:8;4113:2;4110:1;4106:10;4099:28;3951:200;3405:752;4280:213;;;;;;:::i;:::-;;:::i;4822:102::-;;;:::i;:::-;;;-1:-1:-1;;;;;3441:55:389;;;3423:74;;3411:2;3396:18;4822:102:367;;;;;;;4589:167;;;:::i;4981:84::-;;;:::i;5708:140::-;5761:7;841:66;5787:48;:54;-1:-1:-1;;;;;5787:54:367;;5708:140;-1:-1:-1;5708:140:367:o;8960:218:130:-;9077:17;9123:3;9113:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9113:14:130;;9106:21;;9137:34;9147:4;9153:3;9158:4;9164:1;9167:3;9137:9;:34::i;:::-;8960:218;;;;;:::o;752:224:3:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;924:1:3;900:69;;;;;;;;;;;;:::i;:::-;885:11;;;834:135;-1:-1:-1;;;;;;834:135:3;865:18;;;834:135;853:10;;;834:135;845:6;;;834:135;-1:-1:-1;;;;;834:135:3;;;835:1;752:224;-1:-1:-1;752:224:3:o;4280:213:367:-;2517:11;:9;:11::i;:::-;-1:-1:-1;;;;;2503:25:367;:10;-1:-1:-1;;;;;2503:25:367;;2499:66;;2549:16;;-1:-1:-1;;;2549:16:367;;;;;;;;;;;2499:66;4355:42:::1;4379:17;4355:23;:42::i;:::-;841:66:::0;6350:74;;-1:-1:-1;;6350:74:367;-1:-1:-1;;;;;6350:74:367;;;;;4459:27:::1;::::0;-1:-1:-1;;;;;4459:27:367;::::1;::::0;::::1;::::0;;;::::1;4280:213:::0;:::o;4822:102::-;4871:7;4897:20;:18;:20::i;:::-;4890:27;;4822:102;:::o;4589:167::-;2517:11;:9;:11::i;:::-;-1:-1:-1;;;;;2503:25:367;:10;-1:-1:-1;;;;;2503:25:367;;2499:66;;2549:16;;-1:-1:-1;;;2549:16:367;;;;;;;;;;;2499:66;4643:20:::1;4666:11;:9;:11::i;:::-;4643:34;;4687:21;4705:1;4687:9;:21::i;:::-;4723:26;::::0;-1:-1:-1;;;;;4723:26:367;::::1;::::0;::::1;::::0;;;::::1;4633:123;4589:167::o:0;4981:84::-;5021:7;5047:11;:9;:11::i;8279:427:130:-;8451:31;8463:4;8469:12;8478:3;8469:6;:12;:::i;:::-;8451:11;:31::i;:::-;8492;8504:4;8510:12;8519:3;8510:6;:12;:::i;8492:31::-;8557:132;8605:6;1271:2:137;1264:10;;8586:25:130;8648:6;1271:2:137;1264:10;;8629:25:130;8672:3;8557:11;:132::i;:::-;8279:427;;;;;:::o;5912:122:367:-;5956:7;1019:66;5982:39;1899:163:254;5307:328:367;-1:-1:-1;;;;;5395:31:367;;;;:69;;-1:-1:-1;;;;;;5430:29:367;;;:34;5395:69;5391:130;;;5487:23;;;;;;;;;;;;;;5391:130;5558:17;-1:-1:-1;;;;;5534:41:367;:20;:18;:20::i;:::-;-1:-1:-1;;;;;5534:41:367;;5530:99;;5598:20;;;;;;;;;;;;;;5530:99;5307:328;:::o;6485:215::-;6540:21;6564:11;:9;:11::i;:::-;6540:35;-1:-1:-1;6633:8:367;1019:66;6585:56;;-1:-1:-1;;6585:56:367;-1:-1:-1;;;;;6585:56:367;;;;;;6656:37;;;;;;;;;;;-1:-1:-1;;6656:37:367;6530:170;6485:215;:::o;338:169:130:-;422:1;:8;416:3;:14;412:89;;;481:8;;453:37;;;;;;;476:3;;453:37;;7103:25:389;;;7159:2;7144:18;;7137:34;7091:2;7076:18;;6929:248;412:89:130;338:169;;:::o;327:671:137:-;512:185;527:2;522:3;519:11;512:185;;;564:10;;552:23;;608:2;599:12;;;;635;;;;-1:-1:-1;;671:12:137;512:185;;;749:3;746:236;;;852:10;;907;;817:1;802:2;798:12;;;795:1;791:20;787:28;-1:-1:-1;;783:36:137;864:9;;848:26;;;903:21;;953:14;941:27;;746:236;327:671;;;:::o;14:271:389:-;197:6;189;184:3;171:33;153:3;223:16;;248:13;;;223:16;14:271;-1:-1:-1;14:271:389:o;290:514::-;407:12;;455:4;444:16;;438:23;-1:-1:-1;;;;;;479:75:389;;;407:12;577:1;566:13;;563:235;;;-1:-1:-1;;;;;;651:66:389;641:6;638:1;634:14;631:1;627:22;623:95;619:2;615:104;611:177;602:186;;563:235;;;290:514;;;:::o;809:184::-;-1:-1:-1;;;858:1:389;851:88;958:4;955:1;948:15;982:4;979:1;972:15;998:128;1065:9;;;1086:11;;;1083:37;;;1100:18;;:::i;:::-;998:128;;;;:::o;1131:289::-;1173:3;1211:5;1205:12;1238:6;1233:3;1226:19;1294:6;1287:4;1280:5;1276:16;1269:4;1264:3;1260:14;1254:47;1346:1;1339:4;1330:6;1325:3;1321:16;1317:27;1310:38;1409:4;1402:2;1398:7;1393:2;1385:6;1381:15;1377:29;1372:3;1368:39;1364:50;1357:57;;;1131:289;;;;:::o;1580:1281::-;1888:4;1936:3;1925:9;1921:19;-1:-1:-1;;;;;1971:6:389;1967:55;1956:9;1949:74;2059:3;2054:2;2043:9;2039:18;2032:31;2083:6;2118;2112:13;2149:6;2141;2134:22;2187:3;2176:9;2172:19;2165:26;;2250:3;2240:6;2237:1;2233:14;2222:9;2218:30;2214:40;2200:54;;2289:2;2281:6;2277:15;2310:1;2320:256;2334:6;2331:1;2328:13;2320:256;;;2427:3;2423:8;2411:9;2403:6;2399:22;2395:37;2390:3;2383:50;2456:40;2489:6;2480;2474:13;2456:40;:::i;:::-;2446:50;-1:-1:-1;2531:2:389;2554:12;;;;2519:15;;;;;2356:1;2349:9;2320:256;;;2324:3;;;;2624:9;2616:6;2612:22;2607:2;2596:9;2592:18;2585:50;2658:33;2684:6;2676;2658:33;:::i;:::-;-1:-1:-1;;;;;;1490:78:389;;2741:2;2726:18;;1478:91;2644:47;-1:-1:-1;2794:9:389;2786:6;2782:22;2776:3;2765:9;2761:19;2754:51;2822:33;2848:6;2840;2822:33;:::i;:::-;2814:41;1580:1281;-1:-1:-1;;;;;;;;1580:1281:389:o;2866:154::-;-1:-1:-1;;;;;2945:5:389;2941:54;2934:5;2931:65;2921:93;;3010:1;3007;3000:12;3025:247;3084:6;3137:2;3125:9;3116:7;3112:23;3108:32;3105:52;;;3153:1;3150;3143:12;3105:52;3192:9;3179:23;3211:31;3236:5;3211:31;:::i;3508:184::-;-1:-1:-1;;;3557:1:389;3550:88;3657:4;3654:1;3647:15;3681:4;3678:1;3671:15;3697:275;3768:2;3762:9;3833:2;3814:13;;-1:-1:-1;;3810:27:389;3798:40;;3868:18;3853:34;;3889:22;;;3850:62;3847:88;;;3915:18;;:::i;:::-;3951:2;3944:22;3697:275;;-1:-1:-1;3697:275:389:o;3977:454::-;4053:5;4085:1;4109:18;4101:6;4098:30;4095:56;;;4131:18;;:::i;:::-;-1:-1:-1;4197:2:389;4176:15;;-1:-1:-1;;4172:29:389;4203:4;4168:40;4226:21;4168:40;4226:21;:::i;:::-;4217:30;;;4270:6;4263:5;4256:21;4310:3;4301:6;4296:3;4292:16;4289:25;4286:45;;;4327:1;4324;4317:12;4286:45;4369:6;4364:3;4357:4;4350:5;4346:16;4340:36;4423:1;4416:4;4407:6;4400:5;4396:18;4392:29;4385:40;3977:454;;;;;:::o;4436:236::-;4489:5;4542:3;4535:4;4527:6;4523:17;4519:27;4509:55;;4560:1;4557;4550:12;4509:55;4582:84;4662:3;4653:6;4647:13;4640:4;4632:6;4628:17;4582:84;:::i;4677:223::-;4755:13;;-1:-1:-1;;;;;;4797:78:389;;4787:89;;4777:117;;4890:1;4887;4880:12;4777:117;4677:223;;;:::o;4905:1889::-;5071:6;5079;5087;5095;5103;5156:3;5144:9;5135:7;5131:23;5127:33;5124:53;;;5173:1;5170;5163:12;5124:53;5205:9;5199:16;5224:31;5249:5;5224:31;:::i;:::-;5323:2;5308:18;;5302:25;5274:5;;-1:-1:-1;5350:18:389;5339:30;;5336:50;;;5382:1;5379;5372:12;5336:50;5405:22;;5458:4;5450:13;;5446:27;-1:-1:-1;5436:55:389;;5487:1;5484;5477:12;5436:55;5520:2;5514:9;5546:18;5538:6;5535:30;5532:56;;;5568:18;;:::i;:::-;5614:6;5611:1;5607:14;5641:28;5665:2;5661;5657:11;5641:28;:::i;:::-;5703:19;;;5747:2;5777:11;;;5773:20;;;5738:12;;;;5805:19;;;5802:39;;;5837:1;5834;5827:12;5802:39;5869:2;5865;5861:11;5850:22;;5881:431;5897:6;5892:3;5889:15;5881:431;;;5976:3;5970:10;6012:18;5999:11;5996:35;5993:55;;;6044:1;6041;6034:12;5993:55;6071:20;;6126:2;6118:11;;6114:25;-1:-1:-1;6104:53:389;;6153:1;6150;6143:12;6104:53;6182:87;6261:7;6255:2;6251;6247:11;6241:18;6236:2;6232;6228:11;6182:87;:::i;:::-;6170:100;;-1:-1:-1;6299:2:389;5914:12;;;;6290;;;;5881:431;;;6331:5;6321:15;;;;;;;6382:2;6371:9;6367:18;6361:25;6411:18;6401:8;6398:32;6395:52;;;6443:1;6440;6433:12;6395:52;6466:62;6520:7;6509:8;6498:9;6494:24;6466:62;:::i;:::-;6456:72;;;6547:48;6591:2;6580:9;6576:18;6547:48;:::i;:::-;6537:58;;6641:3;6630:9;6626:19;6620:26;6671:18;6661:8;6658:32;6655:52;;;6703:1;6700;6693:12;6655:52;6726:62;6780:7;6769:8;6758:9;6754:24;6726:62;:::i;:::-;6716:72;;;4905:1889;;;;;;;;:::o;6799:125::-;6864:9;;;6885:10;;;6882:36;;;6898:18;;:::i" + }, + "gasEstimates": { + "creation": { + "codeDepositCost": "522400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "": "infinite", + "admin()": "2430", + "implementation()": "2375", + "renounceAdmin()": "infinite", + "upgradeTo(address)": "infinite" + }, + "internal": { + "_getAdmin()": "2152", + "_getImplementation()": "2141", + "_setAdmin(address)": "27982", + "_setImplementation(address)": "infinite", + "_validateImplementation(address)": "infinite" + } + }, + "methodIdentifiers": { + "admin()": "f851a440", + "implementation()": "5c60da1b", + "renounceAdmin()": "8bad0c0a", + "upgradeTo(address)": "3659cfe6" + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CallerNotAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SameImplementation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"AdminRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CallerNotAdmin()\":[{\"details\":\"Error selector: `0x06d919f2`\"}],\"InvalidImplementation()\":[{\"details\":\"Error selector: `0x68155f9a`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"SameImplementation()\":[{\"details\":\"Error selector: `0x4c3b76bf`\"}]},\"events\":{\"AdminChanged(address,address)\":{\"params\":{\"newAdmin\":\"The new admin address\",\"previousAdmin\":\"The previous admin address\"}},\"AdminRemoved(address)\":{\"params\":{\"admin\":\"The admin address that was removed\"}},\"Upgraded(address)\":{\"params\":{\"implementation\":\"The new implementation address\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"admin_\":\"The address of the admin\",\"implementation_\":\"The address of the implementation\"}},\"upgradeTo(address)\":{\"params\":{\"newImplementation\":\"Address of the new implementation\"}}},\"stateVariables\":{\"_ADMIN_SLOT\":{\"details\":\"Storage slot for admin (EIP-1967 compatible)\"},\"_IMPLEMENTATION_SLOT\":{\"details\":\"Storage slot for implementation address (EIP-1967 compatible)\"}},\"title\":\"UpgradableUniversalResolverProxy\",\"version\":1},\"userdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"notice\":\"Event emitted when the admin is changed.\"},\"AdminRemoved(address)\":{\"notice\":\"Event emitted when the admin is removed.\"},\"Upgraded(address)\":{\"notice\":\"Event emitted when the implementation is upgraded.\"}},\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Returns the current admin address.\"},\"implementation()\":{\"notice\":\"Returns the current implementation address.\"},\"renounceAdmin()\":{\"notice\":\"Allows admin to revoke their admin rights by setting admin to address(0).\"},\"upgradeTo(address)\":{\"notice\":\"Upgrades to a new implementation.\"}},\"notice\":\"A specialized proxy for UniversalResolver that forwards method calls and properly handles CCIP-Read reverts. Admin can upgrade the implementation.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/universalResolver/UpgradableUniversalResolverProxy.sol\":\"UpgradableUniversalResolverProxy\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/src/universalResolver/UpgradableUniversalResolverProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EIP3668, OffchainLookup} from \\\"@ens/contracts/ccipRead/EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"@ens/contracts/utils/BytesUtils.sol\\\";\\nimport {StorageSlot} from \\\"@openzeppelin/contracts/utils/StorageSlot.sol\\\";\\n\\n/// @title UpgradableUniversalResolverProxy\\n/// @notice A specialized proxy for UniversalResolver that forwards method calls\\n/// and properly handles CCIP-Read reverts. Admin can upgrade the implementation.\\ncontract UpgradableUniversalResolverProxy {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Storage slot for implementation address (EIP-1967 compatible)\\n bytes32 private constant _IMPLEMENTATION_SLOT =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @dev Storage slot for admin (EIP-1967 compatible)\\n bytes32 private constant _ADMIN_SLOT =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Event emitted when the implementation is upgraded.\\n /// @param implementation The new implementation address\\n event Upgraded(address indexed implementation);\\n\\n /// @notice Event emitted when the admin is changed.\\n /// @param previousAdmin The previous admin address\\n /// @param newAdmin The new admin address\\n event AdminChanged(address indexed previousAdmin, address indexed newAdmin);\\n\\n /// @notice Event emitted when the admin is removed.\\n /// @param admin The admin address that was removed\\n event AdminRemoved(address indexed admin);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x06d919f2`\\n error CallerNotAdmin();\\n\\n /// @dev Error selector: `0x68155f9a`\\n error InvalidImplementation();\\n\\n /// @dev Error selector: `0x4c3b76bf`\\n error SameImplementation();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier restricting a function to the admin.\\n modifier onlyAdmin() {\\n if (msg.sender != _getAdmin())\\n revert CallerNotAdmin();\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param admin_ The address of the admin\\n /// @param implementation_ The address of the implementation\\n constructor(address admin_, address implementation_) {\\n _validateImplementation(implementation_);\\n _setImplementation(implementation_);\\n _setAdmin(admin_);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Fallback function that handles forwarding calls to the implementation\\n /// and properly manages CCIP-Read reverts.\\n fallback() external {\\n (bool ok, bytes memory v) = _getImplementation().staticcall(msg.data);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n EIP3668.Params memory p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n if (p.sender == _getImplementation()) {\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n p.callbackFunction,\\n p.extraData\\n );\\n }\\n }\\n\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @notice Upgrades to a new implementation.\\n /// @param newImplementation Address of the new implementation\\n function upgradeTo(address newImplementation) external onlyAdmin {\\n _validateImplementation(newImplementation);\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /// @notice Allows admin to revoke their admin rights by setting admin to address(0).\\n function renounceAdmin() external onlyAdmin {\\n address currentAdmin = _getAdmin();\\n _setAdmin(address(0));\\n emit AdminRemoved(currentAdmin);\\n }\\n\\n /// @notice Returns the current implementation address.\\n function implementation() external view returns (address) {\\n return _getImplementation();\\n }\\n\\n /// @notice Returns the current admin address.\\n function admin() external view returns (address) {\\n return _getAdmin();\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates if the implementation is valid.\\n function _validateImplementation(address newImplementation) internal view {\\n if (newImplementation == address(0) || newImplementation.code.length == 0) {\\n revert InvalidImplementation();\\n }\\n if (_getImplementation() == newImplementation) {\\n revert SameImplementation();\\n }\\n }\\n\\n /// @dev Gets the current implementation address from storage.\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /// @dev Gets the current admin address from storage.\\n function _getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Sets the implementation address in storage.\\n function _setImplementation(address newImplementation) private {\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /// @dev Sets the admin address in storage.\\n function _setAdmin(address newAdmin) private {\\n address previousAdmin = _getAdmin();\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n emit AdminChanged(previousAdmin, newAdmin);\\n }\\n}\\n\",\"keccak256\":\"0x12df288b00cb10a4e94697b04af4203300f5592cf32ab27735d0682078fb6110\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "events": { + "AdminChanged(address,address)": { + "notice": "Event emitted when the admin is changed." + }, + "AdminRemoved(address)": { + "notice": "Event emitted when the admin is removed." + }, + "Upgraded(address)": { + "notice": "Event emitted when the implementation is upgraded." + } + }, + "kind": "user", + "methods": { + "admin()": { + "notice": "Returns the current admin address." + }, + "implementation()": { + "notice": "Returns the current implementation address." + }, + "renounceAdmin()": { + "notice": "Allows admin to revoke their admin rights by setting admin to address(0)." + }, + "upgradeTo(address)": { + "notice": "Upgrades to a new implementation." + } + }, + "notice": "A specialized proxy for UniversalResolver that forwards method calls and properly handles CCIP-Read reverts. Admin can upgrade the implementation.", + "version": 1 + } +} diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/UserRegistryImpl.json b/contracts/deployments/sepolia-official-v1-20260525-r2/UserRegistryImpl.json new file mode 100644 index 000000000..2261523a8 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/UserRegistryImpl.json @@ -0,0 +1,3037 @@ +{ + "address": "0x0f99e7ea74903afcb7224d0354fd7428a6f92917", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "contract ILabelStore", + "name": "labelStore", + "type": "address" + }, + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "oldExpiry", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "CannotReduceExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "CannotSetPastExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "LabelExpired", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "TransferDisallowed", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExpiryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ParentUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RegistryCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ResolverUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SubregistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTokenId", + "type": "uint256" + } + ], + "name": "TokenRegenerated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "TokenResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "renderer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "URIUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LABEL_STORE", + "outputs": [ + { + "internalType": "contract ILabelStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "canUpgradeFrom", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParent", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getResource", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "internalType": "address", + "name": "latestOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "internalType": "struct IPermissionedRegistry.State", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getStatus", + "outputs": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getSubregistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "latestOwnerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setParent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "setSubregistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + }, + { + "internalType": "contract IRegistryURIRenderer", + "name": "renderer", + "type": "address" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "UserRegistry", + "sourceName": "src/registry/UserRegistry.sol", + "bytecode": "0x60e06040523060c052348015610013575f5ffd5b5060405161567038038061567083398101604081905261003291610db7565b6001600160a01b0383166080526040518390839083907f0100000000000000000000000000000001000000000000000000000000000000907fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16001600160a01b03831660a0526100a85f8284826100c3565b50505050506100bb6101d560201b60201c565b505050611007565b5f835f036100d257505f6101cd565b6100db84610272565b6001600160a01b0383166101025760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b03871684529091529020548481178082146101c7575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616610162888260016102bb565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a384156101bb576101bb888785858b6103eb565b600193505050506101cd565b5f925050505b949350505050565b5f6101de6103fb565b805490915068010000000000000000900460ff16156102105760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161461026f5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561026f57604051630153d96960e51b8152600481018290526024015b60405180910390fd5b5f6102c583610425565b9050811561035b575f8481526003602052604090205461030b9082161980195f5160206156505f395f51905f5291909101165f5160206156305f395f51905f5216151590565b1561033357604051631f22ca6960e31b815260048101859052602481018490526044016102b2565b5f8481526003602052604081208054859290610350908490610e15565b909155506103e59050565b5f8481526003602052604090205461039a901982161980195f5160206156505f395f51905f5291909101165f5160206156305f395f51905f5216151590565b156103c257604051631f80c19b60e01b815260048101859052602481018490526044016102b2565b5f84815260036020526040812080548592906103df908490610e28565b90915550505b50505050565b6103f48561043f565b5050505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b5f61042f82610272565b50600181901b17600281901b1790565b801561026f5763ffffffff811681185f9081526101086020526040812090610467838361052b565b5f818152602081905260409020549091506001600160a01b031661048d8183600161054c565b825483906004906104ab90640100000000900463ffffffff16610e3b565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6104da838561052b60201b60201c565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a36103f48282600160405180602001604052805f8152506105b360201b60201c565b80545f9063ffffffff808516851864010000000090920416185b9392505050565b6001600160a01b03831661057457604051626a0d4560e21b81525f60048201526024016102b2565b604080516001808252602082018590528183019081526060820184905260a082019092525f608082018181529192916103f49187918590859083610628565b6001600160a01b0384166105dc57604051632bfa23e760e11b81525f60048201526024016102b2565b6040805160018082526020820186905281830190815260608201859052608082019092529061060f5f8784848784610628565b505050505050565b63ffffffff82811690921891161890565b6106348686868661068b565b6001600160a01b0385161561060f575f61064c610766565b9050811561066757610662818888888888610774565b610682565b6020858101519085015161067f838a8a85858a610895565b50505b50505050505050565b6106978484848461097c565b6001600160a01b038316158015906106b757506001600160a01b03841615155b156103e5575f5b82518110156103f4575f8382815181106106da576106da610e5f565b602002602001015190506106f9816001609c1b88610b8560201b60201c565b610728576040516372c7b6ad60e11b8152600481018290526001600160a01b03871660248201526044016102b2565b5f83838151811061073b5761073b610e5f565b6020026020010151111561075d5761075d61075582610be4565b87875f610c0b565b506001016106be565b5f61076f610c4c565b905090565b6001600160a01b0384163b1561060f5760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906107b89089908990889088908890600401610edb565b6020604051808303815f875af19250505080156107f2575060408051601f3d908101601f191682019092526107ef91810190610f38565b60015b610859573d80801561081f576040519150601f19603f3d011682016040523d82523d5f602084013e610824565b606091505b5080515f0361085157604051632bfa23e760e11b81526001600160a01b03861660048201526024016102b2565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461068257604051632bfa23e760e11b81526001600160a01b03861660048201526024016102b2565b6001600160a01b0384163b1561060f5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906108d99089908990889088908890600401610f5f565b6020604051808303815f875af1925050508015610913575060408051601f3d908101601f1916820190925261091091810190610f38565b60015b610940573d80801561081f576040519150601f19603f3d011682016040523d82523d5f602084013e610824565b6001600160e01b0319811663f23a6e6160e01b1461068257604051632bfa23e760e11b81526001600160a01b03861660048201526024016102b2565b80518251146109ab5781518151604051635b05999160e01b8152600481019290925260248201526044016102b2565b5f6109b4610766565b90505f5b8351811015610aa7576020818102858101820151908501909101518015610a9d575f828152602081905260409020546001600160a01b039081169089168114610a33576040516303dee4c560e01b81526001600160a01b038a1660048201525f602482015260448101839052606481018490526084016102b2565b6001821115610a75576040516303dee4c560e01b81526001600160a01b038a1660048201526001602482015260448101839052606481018490526084016102b2565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0389161790555b50506001016109b8565b508251600103610b275760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051610b18929190918252602082015260400190565b60405180910390a450506103f4565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051610b76929190610fa3565b60405180910390a45050505050565b5f6101cd610b9285610be4565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f61041f82610c068163ffffffff8116185f9081526101086020526040902090565b610ce9565b5f8481526002602090815260408083206001600160a01b038716845290915290205480156103f457610c3f85828685610d37565b5061060f858285856100c3565b6080515f906001600160a01b0316610c6357503390565b60805160405163110ac5cb60e21b81523360048201525f916001600160a01b03169063442b172c90602401602060405180830381865afa158015610ca9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ccd9190610fd0565b90506001600160a01b038116610ce4573391505090565b919050565b5f82610cf657508161041f565b60018201546105459084906001600160401b0316421015610d2457835463ffffffff82811690921891161890565b83546106179063ffffffff166001610feb565b5f610d4184610272565b5f8581526002602090815260408083206001600160a01b0387168452909152902054841981168082146101c7575f8781526002602090815260408083206001600160a01b038916845290915281208290558683169061016290899083906102bb565b6001600160a01b038116811461026f575f5ffd5b5f5f5f60608486031215610dc9575f5ffd5b8351610dd481610da3565b6020850151909350610de581610da3565b6040850151909250610df681610da3565b809150509250925092565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561041f5761041f610e01565b8181038181111561041f5761041f610e01565b5f63ffffffff821663ffffffff8103610e5657610e56610e01565b60010192915050565b634e487b7160e01b5f52603260045260245ffd5b5f8151808452602084019350602083015f5b82811015610ea3578151865260209586019590910190600101610e85565b5093949350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0386811682528516602082015260a0604082018190525f90610f0690830186610e73565b8281036060840152610f188186610e73565b90508281036080840152610f2c8185610ead565b98975050505050505050565b5f60208284031215610f48575f5ffd5b81516001600160e01b031981168114610545575f5ffd5b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f90610f9890830184610ead565b979650505050505050565b604081525f610fb56040830185610e73565b8281036020840152610fc78185610e73565b95945050505050565b5f60208284031215610fe0575f5ffd5b815161054581610da3565b63ffffffff818116838216019081111561041f5761041f610e01565b60805160a05160c0516145dc6110545f395f81816120110152818161203a01526121d001525f81816107f7015261228501525f81816104c201528181612ab00152612b1101526145dc5ff3fe6080604052600436106102f7575f3560e01c80635c622a0e11610191578063a22cb465116100dc578063d3bf89b111610087578063e985e9c511610062578063e985e9c514610978578063f242432a146109bf578063f41a143d146109de575f5ffd5b8063d3bf89b11461091b578063dfa70d8b1461093a578063e4ae7d7714610959575f5ffd5b8063bd242bcb116100b7578063bd242bcb146108be578063cd6dc687146108dd578063ce156e82146108fc575f5ffd5b8063a22cb46514610838578063ad3cb1cc14610857578063bc7b6d621461089f575f5ffd5b80637c3005861161013c57806391b3c0371161011757806391b3c037146107c75780639dbba19d146107e6578063a02b161e14610819575f5ffd5b80637c3005861461076757806380f760211461078657806385f3e643146107a8575f5ffd5b80636f3ff7261161016c5780636f3ff726146106d35780636f537c72146106f2578063781ef8db14610711575f5ffd5b80635c622a0e146106695780636352211e1461069557806363560a8e146106b4575f5ffd5b8063319c22bb116102515780634e1273f4116101fc5780635357263f116101d75780635357263f1461060c5780635569f33d1461062b5780635adf47241461064a575f5ffd5b80634e1273f4146105b95780634f1ef286146105e557806352d1902d146105f8575f5ffd5b80633634f9111161022c5780633634f9111461053a57806344c9af281461056e57806348688f951461059a575f5ffd5b8063319c22bb146104b1578063341ec559146104fc57806335af62161461051b575f5ffd5b806313c72608116102b15780631e8fca2d1161028c5780631e8fca2d146104525780632eb2c2d6146104715780632f27fa2414610492575f5ffd5b806313c72608146103c657806314ff5ea3146104205780631c3fc3eb1461043f575f5ffd5b8063072d5d77116102e1578063072d5d771461035c5780630e89341c1461037b57806311b8e00a146103a7575f5ffd5b8062fdd58e146102fb57806301ffc9a71461032d575b5f5ffd5b348015610306575f5ffd5b5061031a61031536600461393b565b6109fe565b6040519081526020015b60405180910390f35b348015610338575f5ffd5b5061034c61034736600461397a565b610a35565b6040519015158152602001610324565b348015610367575f5ffd5b5061034c610376366004613995565b610aa6565b348015610386575f5ffd5b5061039a6103953660046139c3565b610ad1565b6040516103249190613a08565b3480156103b2575f5ffd5b5061034c6103c1366004613a1a565b610c01565b3480156103d1575f5ffd5b506104076103e03660046139c3565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610324565b34801561042b575f5ffd5b5061031a61043a3660046139c3565b610c1b565b34801561044a575f5ffd5b5061031a5f81565b34801561045d575f5ffd5b5061031a61046c3660046139c3565b610c42565b34801561047c575f5ffd5b5061049061048b366004613b82565b610c69565b005b34801561049d575f5ffd5b5061031a6104ac3660046139c3565b610d06565b3480156104bc575f5ffd5b506104e47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610324565b348015610507575f5ffd5b50610490610516366004613995565b610d24565b348015610526575f5ffd5b506104e4610535366004613c73565b610dbd565b348015610545575f5ffd5b50610559610554366004613a1a565b610e53565b60408051928352602083019190915201610324565b348015610579575f5ffd5b5061058d6105883660046139c3565b610e73565b6040516103249190613ce6565b3480156105a5575f5ffd5b506104906105b4366004613d39565b610f45565b3480156105c4575f5ffd5b506105d86105d3366004613d8c565b610fe7565b6040516103249190613e8b565b6104906105f3366004613e9d565b6110b2565b348015610603575f5ffd5b5061031a6110d1565b348015610617575f5ffd5b50610490610626366004613e9d565b6110ff565b348015610636575f5ffd5b50610490610645366004613ef7565b61119d565b348015610655575f5ffd5b5061031a610664366004613995565b61133a565b348015610674575f5ffd5b506106886106833660046139c3565b61136c565b6040516103249190613f21565b3480156106a0575f5ffd5b506104e46106af3660046139c3565b6113c2565b3480156106bf575f5ffd5b506104e46106ce366004613c73565b61142c565b3480156106de575f5ffd5b5061034c6106ed366004613f2f565b61143a565b3480156106fd575f5ffd5b5061040761070c366004613c73565b61148b565b34801561071c575f5ffd5b5061034c61072b366004613995565b6001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b348015610772575f5ffd5b5061034c610781366004613f4a565b6114cd565b348015610791575f5ffd5b5061079a6114e1565b604051610324929190613f75565b3480156107b3575f5ffd5b5061031a6107c2366004613f96565b61158c565b3480156107d2575f5ffd5b5061031a6107e1366004613c73565b6115a8565b3480156107f1575f5ffd5b506104e47f000000000000000000000000000000000000000000000000000000000000000081565b348015610824575f5ffd5b506104906108333660046139c3565b6115ea565b348015610843575f5ffd5b5061049061085236600461401f565b6116f7565b348015610862575f5ffd5b5061039a6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b3480156108aa575f5ffd5b506104906108b9366004613995565b611709565b3480156108c9575f5ffd5b506104e46108d83660046139c3565b6117a7565b3480156108e8575f5ffd5b506104906108f736600461393b565b6117c3565b348015610907575f5ffd5b5061034c610916366004613995565b61194c565b348015610926575f5ffd5b5061034c610935366004613f4a565b61196e565b348015610945575f5ffd5b5061034c610954366004613f4a565b6119cd565b348015610964575f5ffd5b506104e4610973366004613c73565b6119e1565b348015610983575f5ffd5b5061034c61099236600461404f565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b3480156109ca575f5ffd5b506104906109d936600461407b565b611a57565b3480156109e9575f5ffd5b5061034c6109f8366004613f2f565b50600190565b5f826001600160a01b0316610a12836113c2565b6001600160a01b031614610a26575f610a29565b60015b60ff1690505b92915050565b5f6001600160e01b031982167fb0f3d367000000000000000000000000000000000000000000000000000000001480610a9757506001600160e01b031982167ff41a143d00000000000000000000000000000000000000000000000000000000145b80610a2f5750610a2f82611ae7565b5f5f83610abb8282610ab6611c5c565b611c6a565b610ac85f86866001611cb8565b95945050505050565b610107546060906001600160a01b0316610b74576101068054610af3906140d3565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1f906140d3565b8015610b6a5780601f10610b4157610100808354040283529160200191610b6a565b820191905f5260205f20905b815481529060010190602001808311610b4d57829003601f168201915b5050505050610a2f565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610bda573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a2f919081019061410b565b5f610c14610c0e84610c42565b83611de1565b9392505050565b5f610a2f82610c3d8463ffffffff8116185f9081526101086020526040902090565b611df8565b5f610a2f82610c648463ffffffff8116185f9081526101086020526040902090565b611e16565b5f610c72611c5c565b9050806001600160a01b0316866001600160a01b031614158015610cbb57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b15610cf15760405163711bec9160e11b81526001600160a01b038083166004830152871660248201526044015b60405180910390fd5b610cfe8686868686611e70565b505050505050565b5f610a2f610d1383610c42565b5f9081526003602052604090205490565b5f5f610d338462100000611ed7565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b038716021781559092509050610d77611c5c565b6001600160a01b0316836001600160a01b0316837fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a450505050565b5f5f610e19610e0085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f4292505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610e49578054600160401b90046001600160a01b0316610e4b565b5f5b949350505050565b5f5f610e67610e6185610c42565b84611f4d565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610ed18584611df8565b606085018190529050610ee48584611e16565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610f128382611f70565b85906002811115610f2557610f25613cb2565b90816002811115610f3857610f38613cb2565b8152505050505050919050565b641000000000610f5d5f82610f58611c5c565b611fa7565b610106610f6b8486836141c4565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416179055610f9d611c5c565b6001600160a01b03167fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd5858585604051610fd99392919061427e565b60405180910390a250505050565b606081518351146110185781518351604051635b05999160e01b815260048101929092526024820152604401610ce8565b5f835167ffffffffffffffff81111561103357611033613a3a565b60405190808252806020026020018201604052801561105c578160200160208202803683370190505b5090505f5b84518110156110aa57602080820286010151611085906020808402870101516109fe565b828281518110611097576110976142be565b6020908102919091010152600101611061565b509392505050565b6110ba612006565b6110c3826120bf565b6110cd82826120dd565b5050565b5f6110da6121c5565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b61010061110f5f82610f58611c5c565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03851617905561010561114583826142d2565b5061114e611c5c565b6001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff4846040516111909190613a08565b60405180910390a3505050565b63ffffffff821682185f90815261010860205260408120906111bf8483611df8565b90505f6111ca611c5c565b600184015490915067ffffffffffffffff164281116112615767ffffffffffffffff8116158061123b575061123962010000836001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b155b1561125c5760405163311388dd60e21b815260048101849052602401610ce8565b611278565b61127861126e8786611e16565b6201000084611fa7565b8067ffffffffffffffff168567ffffffffffffffff1610156112da576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015286166024820152604401610ce8565b60018401805467ffffffffffffffff191667ffffffffffffffff87169081179091556040516001600160a01b038416919085907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a4505050505050565b5f610c1461134784610c42565b5f9081526002602090815260408083206001600160a01b038716845290915290205490565b63ffffffff811681185f908152610108602052604081206001810154610c149067ffffffffffffffff166113bd6113a38685611df8565b5f908152602081905260409020546001600160a01b031690565b611f70565b63ffffffff811681185f908152610108602052604081206113e38382611df8565b831415806113ff5750600181015467ffffffffffffffff164210155b611424575f838152602081905260409020546001600160a01b0316610c14565b610c14565b5f9392505050565b5f610c146106af84846115a8565b6001600160a01b0381165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b60205260408120546f0100000000000000000000000000000090811614610a2f565b5f610c146103e084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f4292505050565b5f610e4b6114da85610c42565b848461220e565b6101045461010580545f926060926001600160a01b03909116918190611506906140d3565b80601f0160208091040260200160405190810160405280929190818152602001828054611532906140d3565b801561157d5780601f106115545761010080835404028352916020019161157d565b820191905f5260205f20905b81548152906001019060200180831161156057829003601f168201915b50505050509050915091509091565b5f61159d8787878787876001612253565b979650505050505050565b5f610c1461043a84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f4292505050565b5f5f6115f883611000611ed7565b91509150611604611c5c565b6001600160a01b0316827f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea860405160405180910390a35f828152602081905260409020546001600160a01b031680156116d457611663818460016127af565b815482905f906116789063ffffffff166143a1565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166116b5906143a1565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b6110cd611702611c5c565b8383612816565b5f5f611719846301000000611ed7565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b038816021790559092509050611761611c5c565b6001600160a01b0316836001600160a01b0316837f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a450505050565b5f818152602081905260408120546001600160a01b0316610a2f565b5f6117cc6128bc565b805490915060ff600160401b820416159067ffffffffffffffff165f811580156117f35750825b90505f8267ffffffffffffffff16600114801561180f5750303b155b90508115801561181d575080155b15611854576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561188357845468ff00000000000000001916600160401b1785555b6001600160a01b0387166118c3576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16118f75f87895f611cb8565b50831561194357845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f5f83611961828261195c611c5c565b6128e4565b610ac85f86866001612945565b5f610e4b61197b85610c42565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f610e4b6119da85610c42565b84846129b1565b5f5f611a24610e0085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f4292505050565b600181015490915067ffffffffffffffff16421015610e49576001810154600160401b90046001600160a01b0316610e4b565b5f611a60611c5c565b9050806001600160a01b0316866001600160a01b031614158015611aa957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b15611ada5760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610ce8565b610cfe86868686866129ec565b5f6001600160e01b031982167fafff3a63000000000000000000000000000000000000000000000000000000001480611b4957506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b80611b7d57506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b80611bb157506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b80611be557506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b80611c1957506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b80611c4d57506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b80610a2f5750610a2f82612a70565b5f611c65612aad565b905090565b5f611c758483612b9e565b90508019831615611cb25760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610ce8565b50505050565b5f835f03611cc757505f610e4b565b611cd084612c64565b6001600160a01b038316611d10576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611dd5575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616611d7088826001612cc4565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a38415611dc957611dc9888785858b612e59565b60019350505050610e4b565b505f9695505050505050565b5f5f611ded8484610e53565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610c14565b5f82611e23575081610a2f565b6001820154610c1490849067ffffffffffffffff16421015611e4c57835463ffffffff16611e5f565b8354611e5f9063ffffffff1660016143c5565b63ffffffff82811690921891161890565b6001600160a01b038416611e9957604051632bfa23e760e11b81525f6004820152602401610ce8565b6001600160a01b038516611ec157604051626a0d4560e21b81525f6004820152602401610ce8565b611ed085858585856001612e62565b5050505050565b63ffffffff821682185f90815261010860205260408120611ef88482611df8565b600182015490925067ffffffffffffffff164210611f2c5760405163311388dd60e21b815260048101839052602401610ce8565b610e6c611f398583611e16565b84610f58611c5c565b805160209091012090565b5f5f611f5883612ec4565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff83164210611f8957505f610a2f565b6001600160a01b038216611f9f57506001610a2f565b506002610a2f565b611fb283838361196e565b612001576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610ce8565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061209f57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120937f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156120bd5760405163703e46dd60e11b815260040160405180910390fd5b565b6f100000000000000000000000000000006110cd5f82610f58611c5c565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612137575060408051601f3d908101601f19168201909252612134918101906143e1565b60015b61215f57604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610ce8565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81146121bb576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ce8565b6120018383612ede565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146120bd5760405163703e46dd60e11b815260040160405180910390fd5b5f838361221e8282610ab6611c5c565b8561223c57604051631850848b60e31b815260040160405180910390fd5b6122498686866001611cb8565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf530969906122ba908b90600401613a08565b5f604051808303815f87803b1580156122d1575f5ffd5b505af11580156122e3573d5f5f3e3d5ffd5b5050895160208b012091505f905061230e8263ffffffff8116185f9081526101086020526040902090565b905061231a8282611df8565b5f818152602081905260408120549194506001600160a01b039091169061233f611c5c565b600184015490915067ffffffffffffffff1642106123ba578515612369576123695f600183611fa7565b6001600160a01b038b1615801561237f57508715155b156123b55760405163d1a3b35560e01b81525f6004820152602481018990526001600160a01b0382166044820152606401610ce8565b61247f565b6001600160a01b038216156123fd578b6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610ce89190613a08565b6001600160a01b038b1661243f578b6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610ce89190613a08565b8515612451576124515f601083611fa7565b8667ffffffffffffffff165f0361247457600183015467ffffffffffffffff1696505b640100000000881797505b6001600160a01b038b16156124a15767ffffffffffffffff87164210156124ae565b67ffffffffffffffff8716155b156124f1576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff88166004820152602401610ce8565b6001600160a01b038216156125895761250c828660016127af565b825483905f906125219063ffffffff166143a1565b91906101000a81548163ffffffff021916908363ffffffff160217905550825f01600481819054906101000a900463ffffffff1661255e906143a1565b91906101000a81548163ffffffff021916908363ffffffff1602179055506125868584611df8565b94505b60018301805484546001600160a01b03808e16600160401b9081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921787558c81169091026001600160e01b031990921667ffffffffffffffff8b1617919091179091558b1661264557806001600160a01b0316845f1b867f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88f8b6040516126389291906143f8565b60405180910390a46126fe565b806001600160a01b0316845f1b867f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8f8f8c60405161268693929190614423565b60405180910390a46126a98b86600160405180602001604052805f815250612f33565b5f6126b48685611e16565b9050806126c3576126c361445e565b604051819087907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a36126fb818a8e5f611cb8565b50505b6001600160a01b038a161561274f57806001600160a01b03168a6001600160a01b0316867fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a45b6001600160a01b038916156127a057806001600160a01b0316896001600160a01b0316867f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a45b50505050979650505050505050565b6001600160a01b0383166127d757604051626a0d4560e21b81525f6004820152602401610ce8565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291611ed09187918590859083612e62565b6001600160a01b038216612858576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610ce8565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611190565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610a2f565b5f6128ef8483612f8f565b90508019831615611cb2576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610ce8565b5f61294f84612c64565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611dd5575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690611d709089908390612cc4565b5f83836129c1828261195c611c5c565b856129df57604051631850848b60e31b815260040160405180910390fd5b6122498686866001612945565b6001600160a01b038416612a1557604051632bfa23e760e11b81525f6004820152602401610ce8565b6001600160a01b038516612a3d57604051626a0d4560e21b81525f6004820152602401610ce8565b6040805160018082526020820186905281830190815260608201859052608082019092529061194387878484875f612e62565b5f6001600160e01b031982167f8f452d62000000000000000000000000000000000000000000000000000000001480610a2f5750610a2f82613046565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612ae157503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015612b5e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b829190614472565b90506001600160a01b038116612b99573391505090565b919050565b5f5f612c1084846001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b905083612c1e579050610a2f565b5f612c436106af86610c3d8163ffffffff8116185f9081526101086020526040902090565b6001600160a01b031603612c5a575f915050610a2f565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612cc1576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610ce8565b50565b5f612cce83612ec4565b90508115612d97575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612d6f576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610ce8565b5f8481526003602052604081208054859290612d8c90849061448d565b90915550611cb29050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612e31576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610ce8565b5f8481526003602052604081208054859290612e4e9084906144a0565b909155505050505050565b611ed085613114565b612e6e868686866131f4565b6001600160a01b03851615610cfe575f612e86611c5c565b90508115612ea157612e9c8188888888886132f2565b611943565b60208581015190850151612eb9838a8a85858a613413565b505050505050505050565b5f612ece82612c64565b50600181901b17600281901b1790565b612ee7826134fa565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115612f2b57612001828261357d565b6110cd6135e6565b6001600160a01b038416612f5c57604051632bfa23e760e11b81525f6004820152602401610ce8565b60408051600180825260208201869052818301908152606082018590526080820190925290610cfe5f8784848784612e62565b5f8215801590612fca57505f612fbf6106af85610c3d8163ffffffff8116185f9081526101086020526040902090565b6001600160a01b0316145b15612fd657505f610a2f565b610c1483836001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b5f6001600160e01b031982167fd9b67a260000000000000000000000000000000000000000000000000000000014806130a857506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b806130dc57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b80610a2f57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610a2f565b8015612cc15763ffffffff811681185f908152610108602052604081209061313c8383611df8565b5f818152602081905260409020549091506001600160a01b0316613162818360016127af565b8254839060049061318090640100000000900463ffffffff166143a1565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6131a98385611df8565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3611ed08282600160405180602001604052805f815250612f33565b6132008484848461361e565b6001600160a01b0383161580159061322057506001600160a01b03841615155b15611cb2575f5b8251811015611ed0575f838281518110613243576132436142be565b6020026020010151905061326c817310000000000000000000000000000000000000008861196e565b6132b4576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610ce8565b5f8383815181106132c7576132c76142be565b602002602001015111156132e9576132e96132e182610c42565b87875f613834565b50600101613227565b6001600160a01b0384163b15610cfe5760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061333690899089908890889088906004016144b3565b6020604051808303815f875af1925050508015613370575060408051601f3d908101601f1916820190925261336d91810190614515565b60015b6133d7573d80801561339d576040519150601f19603f3d011682016040523d82523d5f602084013e6133a2565b606091505b5080515f036133cf57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610ce8565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461194357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610ce8565b6001600160a01b0384163b15610cfe5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906134579089908990889088908890600401614530565b6020604051808303815f875af1925050508015613491575060408051601f3d908101601f1916820190925261348e91810190614515565b60015b6134be573d80801561339d576040519150601f19603f3d011682016040523d82523d5f602084013e6133a2565b6001600160e01b0319811663f23a6e6160e01b1461194357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610ce8565b806001600160a01b03163b5f0361352f57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610ce8565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f5f846001600160a01b031684604051613599919061456c565b5f60405180830381855af49150503d805f81146135d1576040519150601f19603f3d011682016040523d82523d5f602084013e6135d6565b606091505b5091509150610ac8858383613875565b34156120bd576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805182511461364d5781518151604051635b05999160e01b815260048101929092526024820152604401610ce8565b5f613656611c5c565b90505f5b835181101561375657602081810285810182015190850190910151801561374c575f828152602081905260409020546001600160a01b0390811690891681146136d5576040516303dee4c560e01b81526001600160a01b038a1660048201525f60248201526044810183905260648101849052608401610ce8565b6001821115613717576040516303dee4c560e01b81526001600160a01b038a166004820152600160248201526044810183905260648101849052608401610ce8565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389161790555b505060010161365a565b5082516001036137d65760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516137c7929190918252602082015260400190565b60405180910390a45050611ed0565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051613825929190614582565b60405180910390a45050505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015611ed05761386885828685612945565b50610cfe85828585611cb8565b6060826138855761141f826138e5565b815115801561389c57506001600160a01b0384163b155b156138de576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610ce8565b5080610c14565b8051156138f55780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0381168114612cc1575f5ffd5b5f5f6040838503121561394c575f5ffd5b823561395781613927565b946020939093013593505050565b6001600160e01b031981168114612cc1575f5ffd5b5f6020828403121561398a575f5ffd5b8135610c1481613965565b5f5f604083850312156139a6575f5ffd5b8235915060208301356139b881613927565b809150509250929050565b5f602082840312156139d3575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610c1460208301846139da565b5f5f60408385031215613a2b575f5ffd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613a7757613a77613a3a565b604052919050565b5f67ffffffffffffffff821115613a9857613a98613a3a565b5060051b60200190565b5f82601f830112613ab1575f5ffd5b8135613ac4613abf82613a7f565b613a4e565b8082825260208201915060208360051b860101925085831115613ae5575f5ffd5b602085015b83811015613b02578035835260209283019201613aea565b5095945050505050565b5f67ffffffffffffffff821115613b2557613b25613a3a565b50601f01601f191660200190565b5f82601f830112613b42575f5ffd5b8135602083015f613b55613abf84613b0c565b9050828152858383011115613b68575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f5f5f60a08688031215613b96575f5ffd5b8535613ba181613927565b94506020860135613bb181613927565b9350604086013567ffffffffffffffff811115613bcc575f5ffd5b613bd888828901613aa2565b935050606086013567ffffffffffffffff811115613bf4575f5ffd5b613c0088828901613aa2565b925050608086013567ffffffffffffffff811115613c1c575f5ffd5b613c2888828901613b33565b9150509295509295909350565b5f5f83601f840112613c45575f5ffd5b50813567ffffffffffffffff811115613c5c575f5ffd5b602083019150836020828501011115610e6c575f5ffd5b5f5f60208385031215613c84575f5ffd5b823567ffffffffffffffff811115613c9a575f5ffd5b613ca685828601613c35565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b60038110613ce257634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a082019050613cf8828451613cc6565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f5f5f60408486031215613d4b575f5ffd5b833567ffffffffffffffff811115613d61575f5ffd5b613d6d86828701613c35565b9094509250506020840135613d8181613927565b809150509250925092565b5f5f60408385031215613d9d575f5ffd5b823567ffffffffffffffff811115613db3575f5ffd5b8301601f81018513613dc3575f5ffd5b8035613dd1613abf82613a7f565b8082825260208201915060208360051b850101925087831115613df2575f5ffd5b6020840193505b82841015613e1d578335613e0c81613927565b825260209384019390910190613df9565b9450505050602083013567ffffffffffffffff811115613e3b575f5ffd5b613e4785828601613aa2565b9150509250929050565b5f8151808452602084019350602083015f5b82811015613e81578151865260209586019590910190600101613e63565b5093949350505050565b602081525f610c146020830184613e51565b5f5f60408385031215613eae575f5ffd5b8235613eb981613927565b9150602083013567ffffffffffffffff811115613ed4575f5ffd5b613e4785828601613b33565b803567ffffffffffffffff81168114612b99575f5ffd5b5f5f60408385031215613f08575f5ffd5b82359150613f1860208401613ee0565b90509250929050565b60208101610a2f8284613cc6565b5f60208284031215613f3f575f5ffd5b8135610c1481613927565b5f5f5f60608486031215613f5c575f5ffd5b83359250602084013591506040840135613d8181613927565b6001600160a01b0383168152604060208201525f610e4b60408301846139da565b5f5f5f5f5f5f60c08789031215613fab575f5ffd5b863567ffffffffffffffff811115613fc1575f5ffd5b613fcd89828a01613b33565b9650506020870135613fde81613927565b94506040870135613fee81613927565b93506060870135613ffe81613927565b92506080870135915061401360a08801613ee0565b90509295509295509295565b5f5f60408385031215614030575f5ffd5b823561403b81613927565b9150602083013580151581146139b8575f5ffd5b5f5f60408385031215614060575f5ffd5b823561406b81613927565b915060208301356139b881613927565b5f5f5f5f5f60a0868803121561408f575f5ffd5b853561409a81613927565b945060208601356140aa81613927565b93506040860135925060608601359150608086013567ffffffffffffffff811115613c1c575f5ffd5b600181811c908216806140e757607f821691505b60208210810361410557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561411b575f5ffd5b815167ffffffffffffffff811115614131575f5ffd5b8201601f81018413614141575f5ffd5b805161414f613abf82613b0c565b818152856020838501011115614163575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b601f82111561200157805f5260205f20601f840160051c810160208510156141a55750805b601f840160051c820191505b81811015611ed0575f81556001016141b1565b67ffffffffffffffff8311156141dc576141dc613a3a565b6141f0836141ea83546140d3565b83614180565b5f601f841160018114614221575f851561420a5750838201355b5f19600387901b1c1916600186901b178355611ed0565b5f83815260208120601f198716915b828110156142505786850135825560209485019460019092019101614230565b508682101561426c575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff8111156142ec576142ec613a3a565b614300816142fa84546140d3565b84614180565b6020601f821160018114614332575f831561431b5750848201515b5f19600385901b1c1916600184901b178455611ed0565b5f84815260208120601f198516915b828110156143615787850151825560209485019460019092019101614341565b508482101561437e57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff821663ffffffff81036143bc576143bc61438d565b60010192915050565b63ffffffff8181168382160190811115610a2f57610a2f61438d565b5f602082840312156143f1575f5ffd5b5051919050565b604081525f61440a60408301856139da565b905067ffffffffffffffff831660208301529392505050565b606081525f61443560608301866139da565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215614482575f5ffd5b8151610c1481613927565b80820180821115610a2f57610a2f61438d565b81810381811115610a2f57610a2f61438d565b6001600160a01b03861681526001600160a01b038516602082015260a060408201525f6144e360a0830186613e51565b82810360608401526144f58186613e51565b9050828103608084015261450981856139da565b98975050505050505050565b5f60208284031215614525575f5ffd5b8151610c1481613965565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a060808201525f61159d60a08301846139da565b5f82518060208501845e5f920191825250919050565b604081525f6145946040830185613e51565b8281036020840152610ac88185613e5156fea26469706673582212203e7aaed2cf1ef705da86914968a1b001c33aa21e857a37a905b01901f4e601e764736f6c634300081b00338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x6080604052600436106102f7575f3560e01c80635c622a0e11610191578063a22cb465116100dc578063d3bf89b111610087578063e985e9c511610062578063e985e9c514610978578063f242432a146109bf578063f41a143d146109de575f5ffd5b8063d3bf89b11461091b578063dfa70d8b1461093a578063e4ae7d7714610959575f5ffd5b8063bd242bcb116100b7578063bd242bcb146108be578063cd6dc687146108dd578063ce156e82146108fc575f5ffd5b8063a22cb46514610838578063ad3cb1cc14610857578063bc7b6d621461089f575f5ffd5b80637c3005861161013c57806391b3c0371161011757806391b3c037146107c75780639dbba19d146107e6578063a02b161e14610819575f5ffd5b80637c3005861461076757806380f760211461078657806385f3e643146107a8575f5ffd5b80636f3ff7261161016c5780636f3ff726146106d35780636f537c72146106f2578063781ef8db14610711575f5ffd5b80635c622a0e146106695780636352211e1461069557806363560a8e146106b4575f5ffd5b8063319c22bb116102515780634e1273f4116101fc5780635357263f116101d75780635357263f1461060c5780635569f33d1461062b5780635adf47241461064a575f5ffd5b80634e1273f4146105b95780634f1ef286146105e557806352d1902d146105f8575f5ffd5b80633634f9111161022c5780633634f9111461053a57806344c9af281461056e57806348688f951461059a575f5ffd5b8063319c22bb146104b1578063341ec559146104fc57806335af62161461051b575f5ffd5b806313c72608116102b15780631e8fca2d1161028c5780631e8fca2d146104525780632eb2c2d6146104715780632f27fa2414610492575f5ffd5b806313c72608146103c657806314ff5ea3146104205780631c3fc3eb1461043f575f5ffd5b8063072d5d77116102e1578063072d5d771461035c5780630e89341c1461037b57806311b8e00a146103a7575f5ffd5b8062fdd58e146102fb57806301ffc9a71461032d575b5f5ffd5b348015610306575f5ffd5b5061031a61031536600461393b565b6109fe565b6040519081526020015b60405180910390f35b348015610338575f5ffd5b5061034c61034736600461397a565b610a35565b6040519015158152602001610324565b348015610367575f5ffd5b5061034c610376366004613995565b610aa6565b348015610386575f5ffd5b5061039a6103953660046139c3565b610ad1565b6040516103249190613a08565b3480156103b2575f5ffd5b5061034c6103c1366004613a1a565b610c01565b3480156103d1575f5ffd5b506104076103e03660046139c3565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610324565b34801561042b575f5ffd5b5061031a61043a3660046139c3565b610c1b565b34801561044a575f5ffd5b5061031a5f81565b34801561045d575f5ffd5b5061031a61046c3660046139c3565b610c42565b34801561047c575f5ffd5b5061049061048b366004613b82565b610c69565b005b34801561049d575f5ffd5b5061031a6104ac3660046139c3565b610d06565b3480156104bc575f5ffd5b506104e47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610324565b348015610507575f5ffd5b50610490610516366004613995565b610d24565b348015610526575f5ffd5b506104e4610535366004613c73565b610dbd565b348015610545575f5ffd5b50610559610554366004613a1a565b610e53565b60408051928352602083019190915201610324565b348015610579575f5ffd5b5061058d6105883660046139c3565b610e73565b6040516103249190613ce6565b3480156105a5575f5ffd5b506104906105b4366004613d39565b610f45565b3480156105c4575f5ffd5b506105d86105d3366004613d8c565b610fe7565b6040516103249190613e8b565b6104906105f3366004613e9d565b6110b2565b348015610603575f5ffd5b5061031a6110d1565b348015610617575f5ffd5b50610490610626366004613e9d565b6110ff565b348015610636575f5ffd5b50610490610645366004613ef7565b61119d565b348015610655575f5ffd5b5061031a610664366004613995565b61133a565b348015610674575f5ffd5b506106886106833660046139c3565b61136c565b6040516103249190613f21565b3480156106a0575f5ffd5b506104e46106af3660046139c3565b6113c2565b3480156106bf575f5ffd5b506104e46106ce366004613c73565b61142c565b3480156106de575f5ffd5b5061034c6106ed366004613f2f565b61143a565b3480156106fd575f5ffd5b5061040761070c366004613c73565b61148b565b34801561071c575f5ffd5b5061034c61072b366004613995565b6001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b348015610772575f5ffd5b5061034c610781366004613f4a565b6114cd565b348015610791575f5ffd5b5061079a6114e1565b604051610324929190613f75565b3480156107b3575f5ffd5b5061031a6107c2366004613f96565b61158c565b3480156107d2575f5ffd5b5061031a6107e1366004613c73565b6115a8565b3480156107f1575f5ffd5b506104e47f000000000000000000000000000000000000000000000000000000000000000081565b348015610824575f5ffd5b506104906108333660046139c3565b6115ea565b348015610843575f5ffd5b5061049061085236600461401f565b6116f7565b348015610862575f5ffd5b5061039a6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b3480156108aa575f5ffd5b506104906108b9366004613995565b611709565b3480156108c9575f5ffd5b506104e46108d83660046139c3565b6117a7565b3480156108e8575f5ffd5b506104906108f736600461393b565b6117c3565b348015610907575f5ffd5b5061034c610916366004613995565b61194c565b348015610926575f5ffd5b5061034c610935366004613f4a565b61196e565b348015610945575f5ffd5b5061034c610954366004613f4a565b6119cd565b348015610964575f5ffd5b506104e4610973366004613c73565b6119e1565b348015610983575f5ffd5b5061034c61099236600461404f565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b3480156109ca575f5ffd5b506104906109d936600461407b565b611a57565b3480156109e9575f5ffd5b5061034c6109f8366004613f2f565b50600190565b5f826001600160a01b0316610a12836113c2565b6001600160a01b031614610a26575f610a29565b60015b60ff1690505b92915050565b5f6001600160e01b031982167fb0f3d367000000000000000000000000000000000000000000000000000000001480610a9757506001600160e01b031982167ff41a143d00000000000000000000000000000000000000000000000000000000145b80610a2f5750610a2f82611ae7565b5f5f83610abb8282610ab6611c5c565b611c6a565b610ac85f86866001611cb8565b95945050505050565b610107546060906001600160a01b0316610b74576101068054610af3906140d3565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1f906140d3565b8015610b6a5780601f10610b4157610100808354040283529160200191610b6a565b820191905f5260205f20905b815481529060010190602001808311610b4d57829003601f168201915b5050505050610a2f565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610bda573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a2f919081019061410b565b5f610c14610c0e84610c42565b83611de1565b9392505050565b5f610a2f82610c3d8463ffffffff8116185f9081526101086020526040902090565b611df8565b5f610a2f82610c648463ffffffff8116185f9081526101086020526040902090565b611e16565b5f610c72611c5c565b9050806001600160a01b0316866001600160a01b031614158015610cbb57506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b15610cf15760405163711bec9160e11b81526001600160a01b038083166004830152871660248201526044015b60405180910390fd5b610cfe8686868686611e70565b505050505050565b5f610a2f610d1383610c42565b5f9081526003602052604090205490565b5f5f610d338462100000611ed7565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b038716021781559092509050610d77611c5c565b6001600160a01b0316836001600160a01b0316837fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a450505050565b5f5f610e19610e0085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f4292505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610e49578054600160401b90046001600160a01b0316610e4b565b5f5b949350505050565b5f5f610e67610e6185610c42565b84611f4d565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610ed18584611df8565b606085018190529050610ee48584611e16565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610f128382611f70565b85906002811115610f2557610f25613cb2565b90816002811115610f3857610f38613cb2565b8152505050505050919050565b641000000000610f5d5f82610f58611c5c565b611fa7565b610106610f6b8486836141c4565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416179055610f9d611c5c565b6001600160a01b03167fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd5858585604051610fd99392919061427e565b60405180910390a250505050565b606081518351146110185781518351604051635b05999160e01b815260048101929092526024820152604401610ce8565b5f835167ffffffffffffffff81111561103357611033613a3a565b60405190808252806020026020018201604052801561105c578160200160208202803683370190505b5090505f5b84518110156110aa57602080820286010151611085906020808402870101516109fe565b828281518110611097576110976142be565b6020908102919091010152600101611061565b509392505050565b6110ba612006565b6110c3826120bf565b6110cd82826120dd565b5050565b5f6110da6121c5565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b61010061110f5f82610f58611c5c565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03851617905561010561114583826142d2565b5061114e611c5c565b6001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff4846040516111909190613a08565b60405180910390a3505050565b63ffffffff821682185f90815261010860205260408120906111bf8483611df8565b90505f6111ca611c5c565b600184015490915067ffffffffffffffff164281116112615767ffffffffffffffff8116158061123b575061123962010000836001600160a01b03165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602052604090205481161490565b155b1561125c5760405163311388dd60e21b815260048101849052602401610ce8565b611278565b61127861126e8786611e16565b6201000084611fa7565b8067ffffffffffffffff168567ffffffffffffffff1610156112da576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015286166024820152604401610ce8565b60018401805467ffffffffffffffff191667ffffffffffffffff87169081179091556040516001600160a01b038416919085907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a4505050505050565b5f610c1461134784610c42565b5f9081526002602090815260408083206001600160a01b038716845290915290205490565b63ffffffff811681185f908152610108602052604081206001810154610c149067ffffffffffffffff166113bd6113a38685611df8565b5f908152602081905260409020546001600160a01b031690565b611f70565b63ffffffff811681185f908152610108602052604081206113e38382611df8565b831415806113ff5750600181015467ffffffffffffffff164210155b611424575f838152602081905260409020546001600160a01b0316610c14565b610c14565b5f9392505050565b5f610c146106af84846115a8565b6001600160a01b0381165f9081527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b60205260408120546f0100000000000000000000000000000090811614610a2f565b5f610c146103e084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f4292505050565b5f610e4b6114da85610c42565b848461220e565b6101045461010580545f926060926001600160a01b03909116918190611506906140d3565b80601f0160208091040260200160405190810160405280929190818152602001828054611532906140d3565b801561157d5780601f106115545761010080835404028352916020019161157d565b820191905f5260205f20905b81548152906001019060200180831161156057829003601f168201915b50505050509050915091509091565b5f61159d8787878787876001612253565b979650505050505050565b5f610c1461043a84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f4292505050565b5f5f6115f883611000611ed7565b91509150611604611c5c565b6001600160a01b0316827f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea860405160405180910390a35f828152602081905260409020546001600160a01b031680156116d457611663818460016127af565b815482905f906116789063ffffffff166143a1565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166116b5906143a1565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b6110cd611702611c5c565b8383612816565b5f5f611719846301000000611ed7565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b038816021790559092509050611761611c5c565b6001600160a01b0316836001600160a01b0316837f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a450505050565b5f818152602081905260408120546001600160a01b0316610a2f565b5f6117cc6128bc565b805490915060ff600160401b820416159067ffffffffffffffff165f811580156117f35750825b90505f8267ffffffffffffffff16600114801561180f5750303b155b90508115801561181d575080155b15611854576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561188357845468ff00000000000000001916600160401b1785555b6001600160a01b0387166118c3576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16118f75f87895f611cb8565b50831561194357845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f5f83611961828261195c611c5c565b6128e4565b610ac85f86866001612945565b5f610e4b61197b85610c42565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f610e4b6119da85610c42565b84846129b1565b5f5f611a24610e0085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611f4292505050565b600181015490915067ffffffffffffffff16421015610e49576001810154600160401b90046001600160a01b0316610e4b565b5f611a60611c5c565b9050806001600160a01b0316866001600160a01b031614158015611aa957506001600160a01b038087165f9081526001602090815260408083209385168352929052205460ff16155b15611ada5760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610ce8565b610cfe86868686866129ec565b5f6001600160e01b031982167fafff3a63000000000000000000000000000000000000000000000000000000001480611b4957506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b80611b7d57506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b80611bb157506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b80611be557506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b80611c1957506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b80611c4d57506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b80610a2f5750610a2f82612a70565b5f611c65612aad565b905090565b5f611c758483612b9e565b90508019831615611cb25760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610ce8565b50505050565b5f835f03611cc757505f610e4b565b611cd084612c64565b6001600160a01b038316611d10576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611dd5575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616611d7088826001612cc4565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a38415611dc957611dc9888785858b612e59565b60019350505050610e4b565b505f9695505050505050565b5f5f611ded8484610e53565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610c14565b5f82611e23575081610a2f565b6001820154610c1490849067ffffffffffffffff16421015611e4c57835463ffffffff16611e5f565b8354611e5f9063ffffffff1660016143c5565b63ffffffff82811690921891161890565b6001600160a01b038416611e9957604051632bfa23e760e11b81525f6004820152602401610ce8565b6001600160a01b038516611ec157604051626a0d4560e21b81525f6004820152602401610ce8565b611ed085858585856001612e62565b5050505050565b63ffffffff821682185f90815261010860205260408120611ef88482611df8565b600182015490925067ffffffffffffffff164210611f2c5760405163311388dd60e21b815260048101839052602401610ce8565b610e6c611f398583611e16565b84610f58611c5c565b805160209091012090565b5f5f611f5883612ec4565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff83164210611f8957505f610a2f565b6001600160a01b038216611f9f57506001610a2f565b506002610a2f565b611fb283838361196e565b612001576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610ce8565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061209f57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120937f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156120bd5760405163703e46dd60e11b815260040160405180910390fd5b565b6f100000000000000000000000000000006110cd5f82610f58611c5c565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612137575060408051601f3d908101601f19168201909252612134918101906143e1565b60015b61215f57604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610ce8565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81146121bb576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401610ce8565b6120018383612ede565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146120bd5760405163703e46dd60e11b815260040160405180910390fd5b5f838361221e8282610ab6611c5c565b8561223c57604051631850848b60e31b815260040160405180910390fd5b6122498686866001611cb8565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf530969906122ba908b90600401613a08565b5f604051808303815f87803b1580156122d1575f5ffd5b505af11580156122e3573d5f5f3e3d5ffd5b5050895160208b012091505f905061230e8263ffffffff8116185f9081526101086020526040902090565b905061231a8282611df8565b5f818152602081905260408120549194506001600160a01b039091169061233f611c5c565b600184015490915067ffffffffffffffff1642106123ba578515612369576123695f600183611fa7565b6001600160a01b038b1615801561237f57508715155b156123b55760405163d1a3b35560e01b81525f6004820152602481018990526001600160a01b0382166044820152606401610ce8565b61247f565b6001600160a01b038216156123fd578b6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610ce89190613a08565b6001600160a01b038b1661243f578b6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610ce89190613a08565b8515612451576124515f601083611fa7565b8667ffffffffffffffff165f0361247457600183015467ffffffffffffffff1696505b640100000000881797505b6001600160a01b038b16156124a15767ffffffffffffffff87164210156124ae565b67ffffffffffffffff8716155b156124f1576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff88166004820152602401610ce8565b6001600160a01b038216156125895761250c828660016127af565b825483905f906125219063ffffffff166143a1565b91906101000a81548163ffffffff021916908363ffffffff160217905550825f01600481819054906101000a900463ffffffff1661255e906143a1565b91906101000a81548163ffffffff021916908363ffffffff1602179055506125868584611df8565b94505b60018301805484546001600160a01b03808e16600160401b9081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921787558c81169091026001600160e01b031990921667ffffffffffffffff8b1617919091179091558b1661264557806001600160a01b0316845f1b867f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88f8b6040516126389291906143f8565b60405180910390a46126fe565b806001600160a01b0316845f1b867f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8f8f8c60405161268693929190614423565b60405180910390a46126a98b86600160405180602001604052805f815250612f33565b5f6126b48685611e16565b9050806126c3576126c361445e565b604051819087907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a36126fb818a8e5f611cb8565b50505b6001600160a01b038a161561274f57806001600160a01b03168a6001600160a01b0316867fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a45b6001600160a01b038916156127a057806001600160a01b0316896001600160a01b0316867f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a45b50505050979650505050505050565b6001600160a01b0383166127d757604051626a0d4560e21b81525f6004820152602401610ce8565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291611ed09187918590859083612e62565b6001600160a01b038216612858576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610ce8565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611190565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610a2f565b5f6128ef8483612f8f565b90508019831615611cb2576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610ce8565b5f61294f84612c64565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611dd5575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690611d709089908390612cc4565b5f83836129c1828261195c611c5c565b856129df57604051631850848b60e31b815260040160405180910390fd5b6122498686866001612945565b6001600160a01b038416612a1557604051632bfa23e760e11b81525f6004820152602401610ce8565b6001600160a01b038516612a3d57604051626a0d4560e21b81525f6004820152602401610ce8565b6040805160018082526020820186905281830190815260608201859052608082019092529061194387878484875f612e62565b5f6001600160e01b031982167f8f452d62000000000000000000000000000000000000000000000000000000001480610a2f5750610a2f82613046565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612ae157503390565b6040517f442b172c0000000000000000000000000000000000000000000000000000000081523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063442b172c90602401602060405180830381865afa158015612b5e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b829190614472565b90506001600160a01b038116612b99573391505090565b919050565b5f5f612c1084846001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b905083612c1e579050610a2f565b5f612c436106af86610c3d8163ffffffff8116185f9081526101086020526040902090565b6001600160a01b031603612c5a575f915050610a2f565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612cc1576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610ce8565b50565b5f612cce83612ec4565b90508115612d97575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612d6f576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610ce8565b5f8481526003602052604081208054859290612d8c90849061448d565b90915550611cb29050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612e31576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610ce8565b5f8481526003602052604081208054859290612e4e9084906144a0565b909155505050505050565b611ed085613114565b612e6e868686866131f4565b6001600160a01b03851615610cfe575f612e86611c5c565b90508115612ea157612e9c8188888888886132f2565b611943565b60208581015190850151612eb9838a8a85858a613413565b505050505050505050565b5f612ece82612c64565b50600181901b17600281901b1790565b612ee7826134fa565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115612f2b57612001828261357d565b6110cd6135e6565b6001600160a01b038416612f5c57604051632bfa23e760e11b81525f6004820152602401610ce8565b60408051600180825260208201869052818301908152606082018590526080820190925290610cfe5f8784848784612e62565b5f8215801590612fca57505f612fbf6106af85610c3d8163ffffffff8116185f9081526101086020526040902090565b6001600160a01b0316145b15612fd657505f610a2f565b610c1483836001600160a01b03165f8181527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b602090815260408083205494835260028252808320938352929052205417608081901c6fffffffffffffffffffffffffffffffff19919091161790565b5f6001600160e01b031982167fd9b67a260000000000000000000000000000000000000000000000000000000014806130a857506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b806130dc57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b80610a2f57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610a2f565b8015612cc15763ffffffff811681185f908152610108602052604081209061313c8383611df8565b5f818152602081905260409020549091506001600160a01b0316613162818360016127af565b8254839060049061318090640100000000900463ffffffff166143a1565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6131a98385611df8565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3611ed08282600160405180602001604052805f815250612f33565b6132008484848461361e565b6001600160a01b0383161580159061322057506001600160a01b03841615155b15611cb2575f5b8251811015611ed0575f838281518110613243576132436142be565b6020026020010151905061326c817310000000000000000000000000000000000000008861196e565b6132b4576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610ce8565b5f8383815181106132c7576132c76142be565b602002602001015111156132e9576132e96132e182610c42565b87875f613834565b50600101613227565b6001600160a01b0384163b15610cfe5760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061333690899089908890889088906004016144b3565b6020604051808303815f875af1925050508015613370575060408051601f3d908101601f1916820190925261336d91810190614515565b60015b6133d7573d80801561339d576040519150601f19603f3d011682016040523d82523d5f602084013e6133a2565b606091505b5080515f036133cf57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610ce8565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461194357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610ce8565b6001600160a01b0384163b15610cfe5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906134579089908990889088908890600401614530565b6020604051808303815f875af1925050508015613491575060408051601f3d908101601f1916820190925261348e91810190614515565b60015b6134be573d80801561339d576040519150601f19603f3d011682016040523d82523d5f602084013e6133a2565b6001600160e01b0319811663f23a6e6160e01b1461194357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610ce8565b806001600160a01b03163b5f0361352f57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610ce8565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f5f846001600160a01b031684604051613599919061456c565b5f60405180830381855af49150503d805f81146135d1576040519150601f19603f3d011682016040523d82523d5f602084013e6135d6565b606091505b5091509150610ac8858383613875565b34156120bd576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805182511461364d5781518151604051635b05999160e01b815260048101929092526024820152604401610ce8565b5f613656611c5c565b90505f5b835181101561375657602081810285810182015190850190910151801561374c575f828152602081905260409020546001600160a01b0390811690891681146136d5576040516303dee4c560e01b81526001600160a01b038a1660048201525f60248201526044810183905260648101849052608401610ce8565b6001821115613717576040516303dee4c560e01b81526001600160a01b038a166004820152600160248201526044810183905260648101849052608401610ce8565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389161790555b505060010161365a565b5082516001036137d65760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516137c7929190918252602082015260400190565b60405180910390a45050611ed0565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051613825929190614582565b60405180910390a45050505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015611ed05761386885828685612945565b50610cfe85828585611cb8565b6060826138855761141f826138e5565b815115801561389c57506001600160a01b0384163b155b156138de576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610ce8565b5080610c14565b8051156138f55780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0381168114612cc1575f5ffd5b5f5f6040838503121561394c575f5ffd5b823561395781613927565b946020939093013593505050565b6001600160e01b031981168114612cc1575f5ffd5b5f6020828403121561398a575f5ffd5b8135610c1481613965565b5f5f604083850312156139a6575f5ffd5b8235915060208301356139b881613927565b809150509250929050565b5f602082840312156139d3575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610c1460208301846139da565b5f5f60408385031215613a2b575f5ffd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613a7757613a77613a3a565b604052919050565b5f67ffffffffffffffff821115613a9857613a98613a3a565b5060051b60200190565b5f82601f830112613ab1575f5ffd5b8135613ac4613abf82613a7f565b613a4e565b8082825260208201915060208360051b860101925085831115613ae5575f5ffd5b602085015b83811015613b02578035835260209283019201613aea565b5095945050505050565b5f67ffffffffffffffff821115613b2557613b25613a3a565b50601f01601f191660200190565b5f82601f830112613b42575f5ffd5b8135602083015f613b55613abf84613b0c565b9050828152858383011115613b68575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f5f5f60a08688031215613b96575f5ffd5b8535613ba181613927565b94506020860135613bb181613927565b9350604086013567ffffffffffffffff811115613bcc575f5ffd5b613bd888828901613aa2565b935050606086013567ffffffffffffffff811115613bf4575f5ffd5b613c0088828901613aa2565b925050608086013567ffffffffffffffff811115613c1c575f5ffd5b613c2888828901613b33565b9150509295509295909350565b5f5f83601f840112613c45575f5ffd5b50813567ffffffffffffffff811115613c5c575f5ffd5b602083019150836020828501011115610e6c575f5ffd5b5f5f60208385031215613c84575f5ffd5b823567ffffffffffffffff811115613c9a575f5ffd5b613ca685828601613c35565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b60038110613ce257634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a082019050613cf8828451613cc6565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f5f5f60408486031215613d4b575f5ffd5b833567ffffffffffffffff811115613d61575f5ffd5b613d6d86828701613c35565b9094509250506020840135613d8181613927565b809150509250925092565b5f5f60408385031215613d9d575f5ffd5b823567ffffffffffffffff811115613db3575f5ffd5b8301601f81018513613dc3575f5ffd5b8035613dd1613abf82613a7f565b8082825260208201915060208360051b850101925087831115613df2575f5ffd5b6020840193505b82841015613e1d578335613e0c81613927565b825260209384019390910190613df9565b9450505050602083013567ffffffffffffffff811115613e3b575f5ffd5b613e4785828601613aa2565b9150509250929050565b5f8151808452602084019350602083015f5b82811015613e81578151865260209586019590910190600101613e63565b5093949350505050565b602081525f610c146020830184613e51565b5f5f60408385031215613eae575f5ffd5b8235613eb981613927565b9150602083013567ffffffffffffffff811115613ed4575f5ffd5b613e4785828601613b33565b803567ffffffffffffffff81168114612b99575f5ffd5b5f5f60408385031215613f08575f5ffd5b82359150613f1860208401613ee0565b90509250929050565b60208101610a2f8284613cc6565b5f60208284031215613f3f575f5ffd5b8135610c1481613927565b5f5f5f60608486031215613f5c575f5ffd5b83359250602084013591506040840135613d8181613927565b6001600160a01b0383168152604060208201525f610e4b60408301846139da565b5f5f5f5f5f5f60c08789031215613fab575f5ffd5b863567ffffffffffffffff811115613fc1575f5ffd5b613fcd89828a01613b33565b9650506020870135613fde81613927565b94506040870135613fee81613927565b93506060870135613ffe81613927565b92506080870135915061401360a08801613ee0565b90509295509295509295565b5f5f60408385031215614030575f5ffd5b823561403b81613927565b9150602083013580151581146139b8575f5ffd5b5f5f60408385031215614060575f5ffd5b823561406b81613927565b915060208301356139b881613927565b5f5f5f5f5f60a0868803121561408f575f5ffd5b853561409a81613927565b945060208601356140aa81613927565b93506040860135925060608601359150608086013567ffffffffffffffff811115613c1c575f5ffd5b600181811c908216806140e757607f821691505b60208210810361410557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561411b575f5ffd5b815167ffffffffffffffff811115614131575f5ffd5b8201601f81018413614141575f5ffd5b805161414f613abf82613b0c565b818152856020838501011115614163575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b601f82111561200157805f5260205f20601f840160051c810160208510156141a55750805b601f840160051c820191505b81811015611ed0575f81556001016141b1565b67ffffffffffffffff8311156141dc576141dc613a3a565b6141f0836141ea83546140d3565b83614180565b5f601f841160018114614221575f851561420a5750838201355b5f19600387901b1c1916600186901b178355611ed0565b5f83815260208120601f198716915b828110156142505786850135825560209485019460019092019101614230565b508682101561426c575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff8111156142ec576142ec613a3a565b614300816142fa84546140d3565b84614180565b6020601f821160018114614332575f831561431b5750848201515b5f19600385901b1c1916600184901b178455611ed0565b5f84815260208120601f198516915b828110156143615787850151825560209485019460019092019101614341565b508482101561437e57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff821663ffffffff81036143bc576143bc61438d565b60010192915050565b63ffffffff8181168382160190811115610a2f57610a2f61438d565b5f602082840312156143f1575f5ffd5b5051919050565b604081525f61440a60408301856139da565b905067ffffffffffffffff831660208301529392505050565b606081525f61443560608301866139da565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215614482575f5ffd5b8151610c1481613927565b80820180821115610a2f57610a2f61438d565b81810381811115610a2f57610a2f61438d565b6001600160a01b03861681526001600160a01b038516602082015260a060408201525f6144e360a0830186613e51565b82810360608401526144f58186613e51565b9050828103608084015261450981856139da565b98975050505050505050565b5f60208284031215614525575f5ffd5b8151610c1481613965565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a060808201525f61159d60a08301846139da565b5f82518060208501845e5f920191825250919050565b604081525f6145946040830185613e51565b8281036020840152610ac88185613e5156fea26469706673582212203e7aaed2cf1ef705da86914968a1b001c33aa21e857a37a905b01901f4e601e764736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "28949": [ + { + "length": 32, + "start": 8209 + }, + { + "length": 32, + "start": 8250 + }, + { + "length": 32, + "start": 8656 + } + ], + "60111": [ + { + "length": 32, + "start": 1218 + }, + { + "length": 32, + "start": 10928 + }, + { + "length": 32, + "start": 11025 + } + ], + "66658": [ + { + "length": 32, + "start": 2039 + }, + { + "length": 32, + "start": 8837 + } + ] + }, + "inputSourceName": "project/src/registry/UserRegistry.sol", + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "CannotReduceExpiry(uint64,uint64)": [ + { + "details": "Error selector: `0x68c1425a`" + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "details": "Error selector: `0xf1d446c3`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1155InsufficientBalance(address,uint256,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred.", + "tokenId": "Identifier number of a token." + } + } + ], + "ERC1155InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "ERC1155InvalidOperator(address)": [ + { + "details": "Indicates a failure with the `operator` to be approved. Used in approvals.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC1155InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC1155InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC1155MissingApprovalForAll(address,address)": [ + { + "details": "Indicates a failure with the `operator`’s approval. Used in transfers.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner.", + "owner": "Address of the current owner of a token." + } + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "LabelAlreadyRegistered(string)": [ + { + "details": "Error selector: `0xdef545a4`" + } + ], + "LabelAlreadyReserved(string)": [ + { + "details": "Error selector: `0xf60759e0`" + } + ], + "LabelExpired(uint256)": [ + { + "details": "Error selector: `0xc44e2374`" + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "details": "Error selector: `0xe58f6d5a`" + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "ExpiryUpdated(uint256,uint64,address)": { + "params": { + "newExpiry": "The new expiry of the label.", + "sender": "The sender of the call to update the expiry.", + "tokenId": "The token ID of the label." + } + }, + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label registered.", + "labelHash": "The label hash registered.", + "owner": "The owner of the label.", + "sender": "The sender of the call to register.", + "tokenId": "The token ID registered." + } + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label reserved.", + "labelHash": "The label hash reserved.", + "sender": "The sender of the call to reserve.", + "tokenId": "The token ID reserved." + } + }, + "LabelUnregistered(uint256,address)": { + "params": { + "sender": "The sender of the call to unregister.", + "tokenId": "The token ID unregistered." + } + }, + "ParentUpdated(address,string,address)": { + "params": { + "label": "The new label.", + "parent": "The new parent.", + "sender": "The sender of the call to update the parent." + } + }, + "ResolverUpdated(uint256,address,address)": { + "params": { + "resolver": "The new resolver.", + "sender": "The sender of the call to update the resolver.", + "tokenId": "The token ID of the label." + } + }, + "SubregistryUpdated(uint256,address,address)": { + "params": { + "sender": "The sender of the call to update the subregistry.", + "subregistry": "The new subregistry.", + "tokenId": "The token ID of the label." + } + }, + "TokenRegenerated(uint256,uint256)": { + "params": { + "newTokenId": "The new token ID.", + "oldTokenId": "The old token ID." + } + }, + "TokenResource(uint256,uint256)": { + "params": { + "resource": "The EAC resource.", + "tokenId": "The token ID." + } + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + }, + "URIUpdated(string,address,address)": { + "params": { + "renderer": "The new render address.", + "sender": "The sender of the call to update the URI.", + "uri": "The new URI." + } + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "balanceOf(address,uint256)": { + "params": { + "account": "The account to get the balance for.", + "id": "The token ID." + }, + "returns": { + "_0": "balance The balance of the token for the account. This will only ever be 1 or 0." + } + }, + "balanceOfBatch(address[],uint256[])": { + "details": "`accounts` and `ids` must have the same length.", + "params": { + "accounts": "The accounts to get the balances for.", + "ids": "The token IDs." + }, + "returns": { + "_0": "batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0." + } + }, + "canUpgradeFrom(address)": { + "details": "Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call.", + "params": { + "": "{previousImplementation} Ignored." + }, + "returns": { + "allowed": "Always `true` for implementations in this registry family." + } + }, + "constructor": { + "params": { + "hcaFactory": "The HCA factory.", + "labelStore": "The shared label database.", + "namer": "The implementation namer." + } + }, + "findExpiry(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The expiry of the label." + } + }, + "findOwner(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The owner of the label." + } + }, + "findTokenId(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The token ID of the label." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getExpiry(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The expiry of the label, in seconds." + } + }, + "getParent()": { + "returns": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "getResolver(string)": { + "params": { + "label": "The label to fetch a resolver for." + }, + "returns": { + "_0": "resolver The address of a resolver responsible for this label, or `address(0)` if none exists." + } + }, + "getResource(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The resource." + } + }, + "getState(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "state": "The state of the label." + } + }, + "getStatus(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The status of the label." + } + }, + "getSubregistry(string)": { + "params": { + "label": "The label to resolve." + }, + "returns": { + "_0": "The address of the registry for this label, or `address(0)` if none exists." + } + }, + "getTokenId(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token ID." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "initialize(address,uint256)": { + "details": "Grants the supplied role bitmap to `rootAccount` on the root resource. Reverts if the zero address.", + "params": { + "roleBitmap": "The role bitmap granted to `rootAccount`.", + "rootAccount": "Account granted root roles." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "account": "The account to get the approval for.", + "operator": "The operator to get the approval for." + }, + "returns": { + "_0": "approved The approval status." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "latestOwnerOf(uint256)": { + "params": { + "tokenId": "The token ID to query." + }, + "returns": { + "_0": "The latest owner address." + } + }, + "ownerOf(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The owner of the token." + } + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "register(string,address,address,address,uint256,uint64)": { + "params": { + "expiry": "The expiry of the label, in seconds.", + "label": "The label to register.", + "owner": "The address of the owner of the label.", + "registry": "The registry to set as the label.", + "resolver": "The resolver to set for the label.", + "roleBitmap": "The role bitmap to set for the label." + }, + "returns": { + "_0": "The token ID." + } + }, + "renew(uint256,uint64)": { + "details": "If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.", + "params": { + "anyId": "The labelhash, token ID, or resource.", + "newExpiry": "The new expiry, in seconds." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the tokens from.", + "ids": "The token IDs.", + "to": "The address to transfer the tokens to.", + "values": "The amounts of tokens to transfer." + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the token from.", + "id": "The token ID.", + "to": "The address to transfer the token to.", + "value": "The amount of tokens to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "The approval status.", + "operator": "The operator to set the approval for." + } + }, + "setParent(address,string)": { + "details": "Should emit `ParentUpdated`.", + "params": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "setResolver(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "resolver": "The new resolver." + } + }, + "setSubregistry(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "registry": "The new registry." + } + }, + "setURI(string,address)": { + "params": { + "renderer": "The new renderer address.", + "uri_": "The new URI." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "unregister(uint256)": { + "details": "Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.", + "params": { + "anyId": "The labelhash, token ID, or resource." + } + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "uri(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The URI for the token." + } + } + }, + "title": "UserRegistry", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "3576800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "HCA_FACTORY()": "infinite", + "LABEL_STORE()": "infinite", + "ROOT_RESOURCE()": "295", + "UPGRADE_INTERFACE_VERSION()": "infinite", + "balanceOf(address,uint256)": "infinite", + "balanceOfBatch(address[],uint256[])": "infinite", + "canUpgradeFrom(address)": "463", + "findExpiry(string)": "infinite", + "findOwner(string)": "infinite", + "findTokenId(string)": "infinite", + "getAssigneeCount(uint256,uint256)": "7263", + "getExpiry(uint256)": "2537", + "getParent()": "infinite", + "getResolver(string)": "infinite", + "getResource(uint256)": "4812", + "getState(uint256)": "infinite", + "getStatus(uint256)": "infinite", + "getSubregistry(string)": "infinite", + "getTokenId(uint256)": "2663", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "infinite", + "hasRoles(uint256,uint256,address)": "9443", + "hasRootRoles(uint256,address)": "2685", + "initialize(address,uint256)": "infinite", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "2651", + "latestOwnerOf(uint256)": "2575", + "ownerOf(uint256)": "infinite", + "proxiableUUID()": "infinite", + "register(string,address,address,address,uint256,uint64)": "infinite", + "renew(uint256,uint64)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "infinite", + "roles(uint256,address)": "infinite", + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": "infinite", + "safeTransferFrom(address,address,uint256,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "infinite", + "setParent(address,string)": "infinite", + "setResolver(uint256,address)": "infinite", + "setSubregistry(uint256,address)": "infinite", + "setURI(string,address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "unregister(uint256)": "infinite", + "upgradeToAndCall(address,bytes)": "infinite", + "uri(uint256)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"contract ILabelStore\",\"name\":\"labelStore\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"oldExpiry\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"CannotReduceExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"CannotSetPastExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyReserved\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"LabelExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"TransferDisallowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ExpiryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelReserved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelUnregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ParentUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RegistryCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ResolverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SubregistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldTokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newTokenId\",\"type\":\"uint256\"}],\"name\":\"TokenRegenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"TokenResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"renderer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"URIUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LABEL_STORE\",\"outputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"canUpgradeFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getParent\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getResource\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"latestOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"internalType\":\"struct IPermissionedRegistry.State\",\"name\":\"state\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getSubregistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"latestOwnerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setParent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"setSubregistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"},{\"internalType\":\"contract IRegistryURIRenderer\",\"name\":\"renderer\",\"type\":\"address\"}],\"name\":\"setURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"CannotReduceExpiry(uint64,uint64)\":[{\"details\":\"Error selector: `0x68c1425a`\"}],\"CannotSetPastExpiry(uint64)\":[{\"details\":\"Error selector: `0xf1d446c3`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1155InsufficientBalance(address,uint256,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\",\"tokenId\":\"Identifier number of a token.\"}}],\"ERC1155InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"ERC1155InvalidOperator(address)\":[{\"details\":\"Indicates a failure with the `operator` to be approved. Used in approvals.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC1155InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC1155InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC1155MissingApprovalForAll(address,address)\":[{\"details\":\"Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\",\"owner\":\"Address of the current owner of a token.\"}}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"LabelAlreadyRegistered(string)\":[{\"details\":\"Error selector: `0xdef545a4`\"}],\"LabelAlreadyReserved(string)\":[{\"details\":\"Error selector: `0xf60759e0`\"}],\"LabelExpired(uint256)\":[{\"details\":\"Error selector: `0xc44e2374`\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"TransferDisallowed(uint256,address)\":[{\"details\":\"Error selector: `0xe58f6d5a`\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"ExpiryUpdated(uint256,uint64,address)\":{\"params\":{\"newExpiry\":\"The new expiry of the label.\",\"sender\":\"The sender of the call to update the expiry.\",\"tokenId\":\"The token ID of the label.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label registered.\",\"labelHash\":\"The label hash registered.\",\"owner\":\"The owner of the label.\",\"sender\":\"The sender of the call to register.\",\"tokenId\":\"The token ID registered.\"}},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label reserved.\",\"labelHash\":\"The label hash reserved.\",\"sender\":\"The sender of the call to reserve.\",\"tokenId\":\"The token ID reserved.\"}},\"LabelUnregistered(uint256,address)\":{\"params\":{\"sender\":\"The sender of the call to unregister.\",\"tokenId\":\"The token ID unregistered.\"}},\"ParentUpdated(address,string,address)\":{\"params\":{\"label\":\"The new label.\",\"parent\":\"The new parent.\",\"sender\":\"The sender of the call to update the parent.\"}},\"ResolverUpdated(uint256,address,address)\":{\"params\":{\"resolver\":\"The new resolver.\",\"sender\":\"The sender of the call to update the resolver.\",\"tokenId\":\"The token ID of the label.\"}},\"SubregistryUpdated(uint256,address,address)\":{\"params\":{\"sender\":\"The sender of the call to update the subregistry.\",\"subregistry\":\"The new subregistry.\",\"tokenId\":\"The token ID of the label.\"}},\"TokenRegenerated(uint256,uint256)\":{\"params\":{\"newTokenId\":\"The new token ID.\",\"oldTokenId\":\"The old token ID.\"}},\"TokenResource(uint256,uint256)\":{\"params\":{\"resource\":\"The EAC resource.\",\"tokenId\":\"The token ID.\"}},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"},\"URIUpdated(string,address,address)\":{\"params\":{\"renderer\":\"The new render address.\",\"sender\":\"The sender of the call to update the URI.\",\"uri\":\"The new URI.\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"params\":{\"account\":\"The account to get the balance for.\",\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"balance The balance of the token for the account. This will only ever be 1 or 0.\"}},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"`accounts` and `ids` must have the same length.\",\"params\":{\"accounts\":\"The accounts to get the balances for.\",\"ids\":\"The token IDs.\"},\"returns\":{\"_0\":\"batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\"}},\"canUpgradeFrom(address)\":{\"details\":\"Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call.\",\"params\":{\"\":\"{previousImplementation} Ignored.\"},\"returns\":{\"allowed\":\"Always `true` for implementations in this registry family.\"}},\"constructor\":{\"params\":{\"hcaFactory\":\"The HCA factory.\",\"labelStore\":\"The shared label database.\",\"namer\":\"The implementation namer.\"}},\"findExpiry(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The expiry of the label.\"}},\"findOwner(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The owner of the label.\"}},\"findTokenId(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The token ID of the label.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getExpiry(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The expiry of the label, in seconds.\"}},\"getParent()\":{\"returns\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"getResolver(string)\":{\"params\":{\"label\":\"The label to fetch a resolver for.\"},\"returns\":{\"_0\":\"resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\"}},\"getResource(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The resource.\"}},\"getState(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"state\":\"The state of the label.\"}},\"getStatus(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The status of the label.\"}},\"getSubregistry(string)\":{\"params\":{\"label\":\"The label to resolve.\"},\"returns\":{\"_0\":\"The address of the registry for this label, or `address(0)` if none exists.\"}},\"getTokenId(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"initialize(address,uint256)\":{\"details\":\"Grants the supplied role bitmap to `rootAccount` on the root resource. Reverts if the zero address.\",\"params\":{\"roleBitmap\":\"The role bitmap granted to `rootAccount`.\",\"rootAccount\":\"Account granted root roles.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"account\":\"The account to get the approval for.\",\"operator\":\"The operator to get the approval for.\"},\"returns\":{\"_0\":\"approved The approval status.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"latestOwnerOf(uint256)\":{\"params\":{\"tokenId\":\"The token ID to query.\"},\"returns\":{\"_0\":\"The latest owner address.\"}},\"ownerOf(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The owner of the token.\"}},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"register(string,address,address,address,uint256,uint64)\":{\"params\":{\"expiry\":\"The expiry of the label, in seconds.\",\"label\":\"The label to register.\",\"owner\":\"The address of the owner of the label.\",\"registry\":\"The registry to set as the label.\",\"resolver\":\"The resolver to set for the label.\",\"roleBitmap\":\"The role bitmap to set for the label.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"renew(uint256,uint64)\":{\"details\":\"If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"newExpiry\":\"The new expiry, in seconds.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the tokens from.\",\"ids\":\"The token IDs.\",\"to\":\"The address to transfer the tokens to.\",\"values\":\"The amounts of tokens to transfer.\"}},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the token from.\",\"id\":\"The token ID.\",\"to\":\"The address to transfer the token to.\",\"value\":\"The amount of tokens to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"The approval status.\",\"operator\":\"The operator to set the approval for.\"}},\"setParent(address,string)\":{\"details\":\"Should emit `ParentUpdated`.\",\"params\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"setResolver(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"resolver\":\"The new resolver.\"}},\"setSubregistry(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"registry\":\"The new registry.\"}},\"setURI(string,address)\":{\"params\":{\"renderer\":\"The new renderer address.\",\"uri_\":\"The new URI.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"unregister(uint256)\":{\"details\":\"Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"}},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"uri(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The URI for the token.\"}}},\"title\":\"UserRegistry\",\"version\":1},\"userdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"notice\":\"Label expiry cannot be reduced.\"}],\"CannotSetPastExpiry(uint64)\":[{\"notice\":\"Label expiry cannot be before now.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"LabelAlreadyRegistered(string)\":[{\"notice\":\"Label is already registered.\"}],\"LabelAlreadyReserved(string)\":[{\"notice\":\"Label cannot be reserved again.\"}],\"LabelExpired(uint256)\":[{\"notice\":\"Label is expired/unregistered.\"}],\"TransferDisallowed(uint256,address)\":[{\"notice\":\"Transfer is not allowed due to missing transfer admin role.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"ExpiryUpdated(uint256,uint64,address)\":{\"notice\":\"Expiry of label was changed.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"notice\":\"A label was registered.\"},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"notice\":\"A label was reserved.\"},\"LabelUnregistered(uint256,address)\":{\"notice\":\"A label was unregistered.\"},\"ParentUpdated(address,string,address)\":{\"notice\":\"Parent was changed.\"},\"RegistryCreated()\":{\"notice\":\"A registry was created/initialized.\"},\"ResolverUpdated(uint256,address,address)\":{\"notice\":\"Resolver of label was changed.\"},\"SubregistryUpdated(uint256,address,address)\":{\"notice\":\"Subregistry of label was changed.\"},\"TokenRegenerated(uint256,uint256)\":{\"notice\":\"Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance.\"},\"TokenResource(uint256,uint256)\":{\"notice\":\"Associate a token with an EAC resource.\"},\"URIUpdated(string,address,address)\":{\"notice\":\"URI was changed.\"}},\"kind\":\"user\",\"methods\":{\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"LABEL_STORE()\":{\"notice\":\"The shared label database.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"balanceOf(address,uint256)\":{\"notice\":\"Returns the balance of a token for an account.\"},\"balanceOfBatch(address[],uint256[])\":{\"notice\":\"Returns the balances of a batch of tokens for an account.\"},\"canUpgradeFrom(address)\":{\"notice\":\"Declares this implementation as an eligible verifiable proxy upgrade target.\"},\"findExpiry(string)\":{\"notice\":\"Fetches the label expiry.\"},\"findOwner(string)\":{\"notice\":\"Fetches the label owner.\"},\"findTokenId(string)\":{\"notice\":\"Fetches the token ID for a label.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getExpiry(uint256)\":{\"notice\":\"Get expiry of label.\"},\"getParent()\":{\"notice\":\"Get canonical \\\"location\\\" of this registry.\"},\"getResolver(string)\":{\"notice\":\"Fetches the resolver responsible for the specified label.\"},\"getResource(uint256)\":{\"notice\":\"Get `resource` from `anyId`.\"},\"getState(uint256)\":{\"notice\":\"Get the state of a label.\"},\"getStatus(uint256)\":{\"notice\":\"Get `Status` from `anyId`.\"},\"getSubregistry(string)\":{\"notice\":\"Fetches the registry for a label.\"},\"getTokenId(uint256)\":{\"notice\":\"Get `tokenId` from `anyId`.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"initialize(address,uint256)\":{\"notice\":\"Initializes a proxy instance of `UserRegistry`.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Returns the approval for all operator.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"latestOwnerOf(uint256)\":{\"notice\":\"Get the latest owner of a token. If the token was burned, returns null.\"},\"ownerOf(uint256)\":{\"notice\":\"Returns the owner of a token.\"},\"register(string,address,address,address,uint256,uint64)\":{\"notice\":\"Registers a new label.\"},\"renew(uint256,uint64)\":{\"notice\":\"Renew a label.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Transfers multiple tokens from one address to another.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"notice\":\"Transfers a single token from one address to another.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Sets the approval for all operator.\"},\"setParent(address,string)\":{\"notice\":\"Change canonical \\\"location\\\".\"},\"setResolver(uint256,address)\":{\"notice\":\"Change resolver of label.\"},\"setSubregistry(uint256,address)\":{\"notice\":\"Change registry of label.\"},\"setURI(string,address)\":{\"notice\":\"Set the URI for the registry.\"},\"unregister(uint256)\":{\"notice\":\"Delete a label.\"},\"uri(uint256)\":{\"notice\":\"Returns the URI for a token.\"}},\"notice\":\"UUPS-upgradeable `PermissionedRegistry` designed to be deployed as a proxy via `VerifiableFactory` for user-owned subdomain registries. The constructor disables initializers on the implementation contract; proxies call `initialize()` to set up the admin and initial roles. Upgrade authorization requires the upgrade role in the root resource.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/UserRegistry.sol\":\"UserRegistry\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\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 * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\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 Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\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 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\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 _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\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 // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\\n *\\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\\n */\\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\\n return INITIALIZABLE_STORAGE;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n bytes32 slot = _initializableStorageSlot();\\n assembly {\\n $.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IERC1822Proxiable} from \\\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\\\";\\nimport {Initializable} from \\\"./Initializable.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 */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\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 _checkNotDelegated();\\n _;\\n }\\n\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\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 * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {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 onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: 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\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\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 ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\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 ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.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 the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\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 ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\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 * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, bytes memory returndata) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n _revert(returndata);\\n }\\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 or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) 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 assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155} from \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x35d120c427299af1525aaf07955314d9e36a62f14408eb93dec71a2e001f74d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/utils/ERC1155Utils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\nimport {IERC1155Errors} from \\\"../../../interfaces/draft-IERC6093.sol\\\";\\n\\n/**\\n * @dev Library that provide common ERC-1155 utility functions.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].\\n *\\n * _Available since v5.1._\\n */\\nlibrary ERC1155Utils {\\n /**\\n * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155Received(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver.onERC1155Received.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155BatchReceived(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x22f099c02c252dd1f6ddc464916ce683294a63b23b3c6ee3d290b77398e2474b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)\\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\\n\\npragma solidity ^0.8.20;\\n\\nimport {Comparators} from \\\"./Comparators.sol\\\";\\nimport {SlotDerivation} from \\\"./SlotDerivation.sol\\\";\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\nimport {Math} from \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to array types.\\n */\\nlibrary Arrays {\\n using SlotDerivation for bytes32;\\n using StorageSlot for bytes32;\\n\\n /**\\n * @dev Sort an array of uint256 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n uint256[] memory array,\\n function(uint256, uint256) pure returns (bool) comp\\n ) internal pure returns (uint256[] memory) {\\n _quickSort(_begin(array), _end(array), comp);\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\\n */\\n function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\\n sort(array, Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of address (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n address[] memory array,\\n function(address, address) pure returns (bool) comp\\n ) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of address in increasing order.\\n */\\n function sort(address[] memory array) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n bytes32[] memory array,\\n function(bytes32, bytes32) pure returns (bool) comp\\n ) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\\n */\\n function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\\n * at end (exclusive). Sorting follows the `comp` comparator.\\n *\\n * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\\n *\\n * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\\n * be used only if the limits are within a memory array.\\n */\\n function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\\n unchecked {\\n if (end - begin < 0x40) return;\\n\\n // Use first element as pivot\\n uint256 pivot = _mload(begin);\\n // Position where the pivot should be at the end of the loop\\n uint256 pos = begin;\\n\\n for (uint256 it = begin + 0x20; it < end; it += 0x20) {\\n if (comp(_mload(it), pivot)) {\\n // If the value stored at the iterator's position comes before the pivot, we increment the\\n // position of the pivot and move the value there.\\n pos += 0x20;\\n _swap(pos, it);\\n }\\n }\\n\\n _swap(begin, pos); // Swap pivot into place\\n _quickSort(begin, pos, comp); // Sort the left side of the pivot\\n _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first element of `array`.\\n */\\n function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\\n assembly (\\\"memory-safe\\\") {\\n ptr := add(array, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\\n * that comes just after the last element of the array.\\n */\\n function _end(uint256[] memory array) private pure returns (uint256 ptr) {\\n unchecked {\\n return _begin(array) + array.length * 0x20;\\n }\\n }\\n\\n /**\\n * @dev Load memory word (as a uint256) at location `ptr`.\\n */\\n function _mload(uint256 ptr) private pure returns (uint256 value) {\\n assembly {\\n value := mload(ptr)\\n }\\n }\\n\\n /**\\n * @dev Swaps the elements memory location `ptr1` and `ptr2`.\\n */\\n function _swap(uint256 ptr1, uint256 ptr2) private pure {\\n assembly {\\n let value1 := mload(ptr1)\\n let value2 := mload(ptr2)\\n mstore(ptr1, value2)\\n mstore(ptr2, value1)\\n }\\n }\\n\\n /// @dev Helper: low level cast address memory array to uint256 memory array\\n function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\\n function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast address comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(address, address) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(bytes32, bytes32) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /**\\n * @dev Searches a sorted `array` and returns the first index that contains\\n * a value greater or equal to `element`. If no such index exists (i.e. all\\n * values in the array are strictly less than `element`), the array length is\\n * returned. Time complexity O(log n).\\n *\\n * NOTE: The `array` is expected to be sorted in ascending order, and to\\n * contain no repeated elements.\\n *\\n * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\\n * support for repeated elements in the array. The {lowerBound} function should\\n * be used instead.\\n */\\n function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n low = mid + 1;\\n }\\n }\\n\\n // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\\n if (low > 0 && unsafeAccess(array, low - 1).value == element) {\\n return low - 1;\\n } else {\\n return low;\\n }\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value greater or equal than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\\n */\\n function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value strictly greater than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\\n */\\n function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {lowerBound}, but with an array in memory.\\n */\\n function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {upperBound}, but with an array in memory.\\n */\\n function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getAddressSlot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getBytes32Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getUint256Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(address[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(uint256[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55a4fdb408e3db950b48f4a6131e538980be8c5f48ee59829d92d66477140cd6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides a set of functions to compare values.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Comparators {\\n function lt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a < b;\\n }\\n\\n function gt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a > b;\\n }\\n}\\n\",\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\\n * the solidity language / compiler.\\n *\\n * 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.].\\n *\\n * Example usage:\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using StorageSlot for bytes32;\\n * using SlotDerivation for bytes32;\\n *\\n * // Declare a namespace\\n * string private constant _NAMESPACE = \\\"\\\"; // eg. OpenZeppelin.Slot\\n *\\n * function setValueInNamespace(uint256 key, address newValue) internal {\\n * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\\n * }\\n *\\n * function getValueInNamespace(uint256 key) internal view returns (address) {\\n * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {StorageSlot}.\\n *\\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\\n * upgrade safety will ignore the slots accessed through this library.\\n *\\n * _Available since v5.1._\\n */\\nlibrary SlotDerivation {\\n /**\\n * @dev Derive an ERC-7201 slot from a string (namespace).\\n */\\n function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\\n slot := and(keccak256(0x00, 0x20), not(0xff))\\n }\\n }\\n\\n /**\\n * @dev Add an offset to a slot to get the n-th element of a structure or an array.\\n */\\n function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\\n unchecked {\\n return bytes32(uint256(slot) + pos);\\n }\\n }\\n\\n /**\\n * @dev Derive the location of the first element in an array from the slot where the length is stored.\\n */\\n function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, slot)\\n result := keccak256(0x00, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, and(key, shr(96, not(0))))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, iszero(iszero(key)))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x67672e4ca1dafdcc661d4eba8475cfac631fa0933309258e3af7644b92e1fb26\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IProxyAuthorization {\\n function canUpgradeFrom(address previousImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, _msgSender());\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, _msgSender());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _roles[ROOT_RESOURCE][account] & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return\\n (_roles[ROOT_RESOURCE][account] | _roles[resource][account]) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (_hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (_hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n uint256 roleBitmap =\\n (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) >> 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function _hasZeroNybbles(uint256 value) private pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 hasZeroNybbles;\\n unchecked {\\n hasZeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return hasZeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xdf8918a909b0ab3bf17bc3a560fbdff6ca6e9502cbee54eb0923f1fae04d2fb1\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x9f29748b40665df976c08cdaf434b469dc73ef50e938c36be6773dc7b6a6f014\",\"license\":\"MIT\"},\"project/src/erc1155/ERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {\\n IERC1155MetadataURI\\n} from \\\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\\\";\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport {ERC1155Utils} from \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol\\\";\\nimport {Arrays} from \\\"@openzeppelin/contracts/utils/Arrays.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {HCAContext} from \\\"../hca/HCAContext.sol\\\";\\n\\nimport {IERC1155Singleton} from \\\"./interfaces/IERC1155Singleton.sol\\\";\\n\\n/// @notice ERC1155 variant enforcing exactly one owner per token ID.\\n///\\n/// Instead of the standard nested balance mapping (`id \\u2192 address \\u2192 balance`), uses a flat\\n/// `id \\u2192 address` ownership mapping. `balanceOf` returns 1 if the account is the owner,\\n/// 0 otherwise. Transferring value > 1 reverts.\\n///\\n/// Used by `PermissionedRegistry` to represent domain name ownership as non-divisible tokens.\\n/// The registry overrides `ownerOf` to add expiry and version validation on top of raw ownership.\\n///\\n/// Inherits `HCAContext` so that `_msgSender()` resolves HCA proxy accounts to their real\\n/// owners for approval checks and operator tracking.\\n///\\n/// @author OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC1155/ERC1155.sol)\\n/// @dev This contract has been modified from the implementation at the above link.\\nabstract contract ERC1155Singleton is\\n HCAContext,\\n ERC165,\\n IERC1155Singleton,\\n IERC1155Errors,\\n IERC1155MetadataURI\\n{\\n using Arrays for uint256[];\\n\\n using Arrays for address[];\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Maps each token ID to its single owner address.\\n mapping(uint256 id => address account) private _owners;\\n\\n /// @dev Standard ERC1155 operator approval mapping.\\n mapping(address account => mapping(address operator => bool)) private _operatorApprovals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155Singleton).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Sets the approval for all operator.\\n /// @param operator The operator to set the approval for.\\n /// @param approved The approval status.\\n function setApprovalForAll(address operator, bool approved) public virtual {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /// @notice Transfers a single token from one address to another.\\n /// @param from The address to transfer the token from.\\n /// @param to The address to transfer the token to.\\n /// @param id The token ID.\\n /// @param value The amount of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `to` cannot be the zero address.\\n /// @dev If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.\\n /// @dev `from` must have a balance of tokens of type `id` of at least `value` amount.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the\\n /// acceptance magic value.\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data)\\n public\\n virtual\\n {\\n address sender = _msgSender();\\n if (from != sender && !isApprovedForAll(from, sender)) {\\n revert ERC1155MissingApprovalForAll(sender, from);\\n }\\n _safeTransferFrom(from, to, id, value, data);\\n }\\n\\n /// @notice Transfers multiple tokens from one address to another.\\n /// @param from The address to transfer the tokens from.\\n /// @param to The address to transfer the tokens to.\\n /// @param ids The token IDs.\\n /// @param values The amounts of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `ids` and `values` must have the same length.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the\\n /// acceptance magic value.\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n public\\n virtual\\n {\\n address sender = _msgSender();\\n if (from != sender && !isApprovedForAll(from, sender)) {\\n revert ERC1155MissingApprovalForAll(sender, from);\\n }\\n _safeBatchTransferFrom(from, to, ids, values, data);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 id) public view virtual returns (address owner) {\\n return _owners[id];\\n }\\n\\n /// @notice Returns the URI for a token.\\n /// @param id The token ID.\\n /// @return uri The URI for the token.\\n function uri(uint256 id) public view virtual returns (string memory uri);\\n\\n /// @notice Returns the balance of a token for an account.\\n /// @param account The account to get the balance for.\\n /// @param id The token ID.\\n /// @return balance The balance of the token for the account. This will only ever be 1 or 0.\\n function balanceOf(address account, uint256 id) public view virtual returns (uint256) {\\n return ownerOf(id) == account ? 1 : 0;\\n }\\n\\n /// @notice Returns the balances of a batch of tokens for an account.\\n /// @param accounts The accounts to get the balances for.\\n /// @param ids The token IDs.\\n /// @return batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\\n /// @dev `accounts` and `ids` must have the same length.\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n returns (uint256[] memory)\\n {\\n if (accounts.length != ids.length) {\\n revert ERC1155InvalidArrayLength(ids.length, accounts.length);\\n }\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));\\n }\\n\\n return batchBalances;\\n }\\n\\n /// @notice Returns the approval for all operator.\\n /// @param account The account to get the approval for.\\n /// @param operator The operator to get the approval for.\\n /// @return approved The approval status.\\n function isApprovedForAll(address account, address operator) public view virtual returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Apply token updates for each pair in `ids` and `values`.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not the current owner or `value > 1`.\\n /// @dev This function does not perform ERC-1155 receiver acceptance checks.\\n /// @dev Emits `TransferSingle` when one token ID is updated, otherwise emits `TransferBatch`.\\n function _update(address from, address to, uint256[] memory ids, uint256[] memory values)\\n internal\\n virtual\\n {\\n if (ids.length != values.length) {\\n revert ERC1155InvalidArrayLength(ids.length, values.length);\\n }\\n\\n address operator = _msgSender();\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids.unsafeMemoryAccess(i);\\n uint256 value = values.unsafeMemoryAccess(i);\\n\\n if (value > 0) {\\n address owner = _owners[id];\\n if (owner != from) {\\n revert ERC1155InsufficientBalance(from, 0, value, id);\\n } else if (value > 1) {\\n revert ERC1155InsufficientBalance(from, 1, value, id);\\n }\\n _owners[id] = to;\\n }\\n }\\n\\n if (ids.length == 1) {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n emit TransferSingle(operator, from, to, id, value);\\n } else {\\n emit TransferBatch(operator, from, to, ids, values);\\n }\\n }\\n\\n /// @notice Apply token updates and run ERC-1155 receiver acceptance checks.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @param batch `true` if a batch operation.\\n /// @dev Calls `_update` before external receiver callbacks.\\n /// @dev If `to` is a contract, this calls `onERC1155Received` or `onERC1155BatchReceived`.\\n /// @dev Overriding is discouraged because post-callback state writes can introduce reentrancy bugs.\\n function _updateWithAcceptanceCheck(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data,\\n bool batch\\n )\\n internal\\n virtual\\n {\\n _update(from, to, ids, values);\\n if (to != address(0)) {\\n address operator = _msgSender();\\n if (batch) {\\n ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data);\\n } else {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data);\\n }\\n }\\n }\\n\\n /// @notice Safely transfer `value` tokens of token ID `id` from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param id Token ID to transfer.\\n /// @param value Amount to transfer.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, to, ids, values, data, false);\\n }\\n\\n /// @notice Safely transfer multiple token IDs from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param ids Token IDs to transfer.\\n /// @param values Amounts to transfer for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferBatch`.\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n _updateWithAcceptanceCheck(from, to, ids, values, data, true);\\n }\\n\\n /// @notice Mint `value` tokens of token ID `id` to `to`.\\n /// @param to Address receiving the minted token.\\n /// @param id Token ID to mint.\\n /// @param value Amount to mint.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(address(0), to, ids, values, data, false);\\n }\\n\\n /// @notice Burn `value` tokens of token ID `id` from `from`.\\n /// @param from Address to burn from.\\n /// @param id Token ID to burn.\\n /// @param value Amount to burn.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not current owner or `value > 1`.\\n /// @dev Emits `TransferSingle`.\\n function _burn(address from, uint256 id, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, address(0), ids, values, \\\"\\\", false);\\n }\\n\\n /// @notice Set or clear approval for `operator` to manage all tokens owned by `owner`.\\n /// @param owner Token owner granting or revoking approval.\\n /// @param operator Operator receiving approval.\\n /// @param approved Approval status to set.\\n /// @dev Reverts with `ERC1155InvalidOperator` if `operator` is the zero address.\\n /// @dev Emits `ApprovalForAll`.\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n if (operator == address(0)) {\\n revert ERC1155InvalidOperator(address(0));\\n }\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Gas-optimized assembly helper that creates two length-1 memory arrays without Solidity's\\n /// default zero-initialization overhead. Used to adapt single-token operations (`_mint`,\\n /// `_burn`, `_safeTransferFrom`) to the array-based `_update` function.\\n function _asSingletonArrays(uint256 element1, uint256 element2)\\n private\\n pure\\n returns (uint256[] memory array1, uint256[] memory array2)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Load the free memory pointer\\n array1 := mload(0x40)\\n // Set array length to 1\\n mstore(array1, 1)\\n // Store the single element at the next word after the length (where content starts)\\n mstore(add(array1, 0x20), element1)\\n\\n // Repeat for next array locating it right after the first array\\n array2 := add(array1, 0x40)\\n mstore(array2, 1)\\n mstore(add(array2, 0x20), element2)\\n\\n // Update the free memory pointer by pointing after the second array\\n mstore(0x40, add(array2, 0x40))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9af9852c17f9d19765bd2b21fe2076d96845f0c0f7e9b0faa1d905793d3b677d\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/hca/HCAContext.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {Context} from \\\"@openzeppelin/contracts/utils/Context.sol\\\";\\n\\nimport {HCAEquivalence} from \\\"./HCAEquivalence.sol\\\";\\n\\n/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with\\n/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()`\\n/// calls in the contract (including inherited modifiers and access control) automatically\\n/// resolve HCA proxy accounts to their owners. The HCA factory records deterministic HCA accounts\\n/// before those HCAs resolve to their owner.\\n///\\nabstract contract HCAContext is Context, HCAEquivalence {\\n /// @dev Returns either the account owner of an HCA or the original sender\\n function _msgSender() internal view virtual override returns (address) {\\n return _msgSenderWithHcaEquivalence();\\n }\\n}\\n\",\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\"},\"project/src/hca/HCAEquivalence.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IHCAFactoryBasic} from \\\"./interfaces/IHCAFactoryBasic.sol\\\";\\n\\n/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a\\n/// contract-based account whose actions should be attributed to its registered owner rather\\n/// than to the contract address itself.\\n///\\n/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory address is\\n/// zero, `msg.sender` is returned unchanged. The HCA factory returns zero for non-HCA callers and\\n/// HCAs that are not recorded for their owner, which makes them use the original-sender fallback.\\n///\\n/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()`\\n/// automatically attribute actions to the account owner regardless of whether the caller is\\n/// an EOA or an HCA proxy.\\n///\\nabstract contract HCAEquivalence {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The HCA factory contract\\n IHCAFactoryBasic public immutable HCA_FACTORY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory contract.\\n constructor(IHCAFactoryBasic hcaFactory) {\\n HCA_FACTORY = hcaFactory;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`.\\n /// Reverts if the HCA factory rejects lookup for the caller.\\n function _msgSenderWithHcaEquivalence() internal view returns (address) {\\n if (address(HCA_FACTORY) == address(0)) {\\n return msg.sender;\\n }\\n address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender);\\n if (accountOwner == address(0)) {\\n return msg.sender;\\n }\\n return accountOwner;\\n }\\n}\\n\",\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\"},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\n/// @notice Basic interface for Hidden Contract Account ownership lookup.\\n/// @dev Interface selector: `0x442b172c`\\ninterface IHCAFactoryBasic {\\n /// @notice Returns the account owner of the given HCA.\\n /// @dev Returns zero when the queried address is not a recorded HCA.\\n /// @param hca The HCA to get the account owner of.\\n /// @return The account owner of the given HCA.\\n function getAccountOwner(address hca) external view returns (address);\\n}\\n\",\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\"},\"project/src/registry/PermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IEnhancedAccessControl} from \\\"../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {ERC1155Singleton} from \\\"../erc1155/ERC1155Singleton.sol\\\";\\nimport {IERC1155Singleton} from \\\"../erc1155/interfaces/IERC1155Singleton.sol\\\";\\nimport {HCAEquivalence} from \\\"../hca/HCAEquivalence.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {ILabelStore} from \\\"../utils/interfaces/ILabelStore.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./interfaces/IOwnedRegistry.sol\\\";\\nimport {IPermissionedRegistry} from \\\"./interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"./interfaces/IRegistry.sol\\\";\\nimport {IRegistryURIRenderer} from \\\"./interfaces/IRegistryURIRenderer.sol\\\";\\nimport {IStandardRegistry} from \\\"./interfaces/IStandardRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./interfaces/ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./interfaces/ITokenizedRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"./libraries/RegistryRolesLib.sol\\\";\\n\\n/// @notice A tokenized (ERC1155) registry with resource-scoped access control for subdomain management.\\n///\\n/// Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource\\n/// interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`)\\n/// to resolve any of these to the canonical storage slot for the name.\\n///\\n/// The registry maintains two independent version counters per name:\\n/// - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form\\n/// the EAC resource ID. This means a re-registered name gets a fresh permission scope.\\n/// - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint)\\n/// due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring\\n/// changes to roles create new tokens and prevent frontrunning a transfer with a role revocation.\\n///\\n/// Names are treated as `AVAILABLE` once `block.timestamp >= expiry`.\\n///\\n/// URI renderer address is embedded into URI data as `abi.encodePacked(uint8(1), address)`.\\n///\\n/// State diagram:\\n///\\n/// register()\\n/// +ROLE_REGISTRAR\\n/// +------------------->----------------------+\\n/// | |\\n/// | renew() | renew()\\n/// | +ROLE_RENEW | +ROLE_RENEW\\n/// | +------+ | +------+\\n/// | | | | | |\\n/// \\u028c \\u028c v v v |\\n/// AVAILABLE --------> RESERVED -------------> REGISTERED >--+\\n/// \\u028c register() v register() v\\n/// | w/owner=0 | +ROLE_REGISTER_RESERVED |\\n/// | +ROLE_REGISTRAR | |\\n/// | | |\\n/// +--------<---------+------------<------------+\\n/// unregister()\\n/// +ROLE_UNREGISTER\\n///\\ncontract PermissionedRegistry is ERC1155Singleton, EnhancedAccessControl, IPermissionedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n struct Entry {\\n /// @dev Incremented on unregister; combined with labelhash to form the EAC resource ID.\\n uint32 eacVersionId;\\n /// @dev Incremented on unregister and on token regeneration; combined with labelhash to form the ERC1155 token ID.\\n uint32 tokenVersionId;\\n /// @dev Child registry for this name.\\n IRegistry subregistry;\\n /// @dev Timestamp at or after which the name is considered expired/available.\\n uint64 expiry;\\n /// @dev Resolver address for this name.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The shared label database.\\n ILabelStore public immutable LABEL_STORE;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The parent registry of this registry.\\n IRegistry internal _parentRegistry;\\n\\n /// @dev The child label of this registry.\\n string internal _childLabel;\\n\\n /// @dev The metadata URI.\\n string internal _uri;\\n\\n /// @dev The metadata renderer.\\n IRegistryURIRenderer internal _uriRenderer;\\n\\n /// @dev The entries of this registry.\\n mapping(uint256 storageId => Entry entry) internal _entries;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory to use.\\n /// @param labelStore The shared label database.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n constructor(\\n IHCAFactoryBasic hcaFactory,\\n ILabelStore labelStore,\\n address rootAccount,\\n uint256 roleBitmap\\n )\\n HCAEquivalence(hcaFactory)\\n {\\n emit RegistryCreated();\\n LABEL_STORE = labelStore;\\n _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false);\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(IERC165, ERC1155Singleton, EnhancedAccessControl)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IPermissionedRegistry).interfaceId ||\\n interfaceId == type(IStandardRegistry).interfaceId ||\\n interfaceId == type(ITokenizedRegistry).interfaceId ||\\n interfaceId == type(ITemporalRegistry).interfaceId ||\\n interfaceId == type(IOwnedRegistry).interfaceId ||\\n interfaceId == type(IRegistry).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IStandardRegistry\\n function setSubregistry(uint256 anyId, IRegistry registry) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_SUBREGISTRY);\\n entry.subregistry = registry;\\n emit SubregistryUpdated(tokenId, registry, _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setResolver(uint256 anyId, address resolver) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_RESOLVER);\\n entry.resolver = resolver;\\n emit ResolverUpdated(tokenId, resolver, _msgSender());\\n }\\n\\n /// @notice Set the URI for the registry.\\n /// @param uri_ The new URI.\\n /// @param renderer The new renderer address.\\n function setURI(string calldata uri_, IRegistryURIRenderer renderer)\\n public\\n virtual\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_URI)\\n {\\n _uri = uri_;\\n _uriRenderer = renderer;\\n emit URIUpdated(uri_, address(renderer), _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setParent(IRegistry parent, string memory label)\\n public\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_PARENT)\\n {\\n _parentRegistry = parent;\\n _childLabel = label;\\n emit ParentUpdated(parent, label, _msgSender());\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n public\\n virtual\\n returns (uint256)\\n {\\n return _register(label, owner, registry, resolver, roleBitmap, expiry, true);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\\n function unregister(uint256 anyId) public {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_UNREGISTER);\\n emit LabelUnregistered(tokenId, _msgSender());\\n address owner = super.ownerOf(tokenId);\\n if (owner != address(0)) {\\n _burn(owner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n }\\n entry.expiry = uint64(block.timestamp);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev If `REGISTERED | RESERVED`, requires `ROLE_RENEW`.\\n /// If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\\n function renew(uint256 anyId, uint64 newExpiry) public override {\\n Entry storage entry = _entry(anyId);\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n address sender = _msgSender();\\n uint64 expiry = entry.expiry;\\n if (_isExpired(expiry)) {\\n if (expiry == 0 || !hasRootRoles(RegistryRolesLib.ROLE_RENEW, sender)) {\\n revert LabelExpired(tokenId); // never registered OR cannot revive\\n }\\n } else {\\n _checkRoles(_constructResource(anyId, entry), RegistryRolesLib.ROLE_RENEW, sender);\\n }\\n if (newExpiry < expiry) {\\n revert CannotReduceExpiry(expiry, newExpiry);\\n }\\n entry.expiry = newExpiry;\\n emit ExpiryUpdated(tokenId, newExpiry, sender);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function grantRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.grantRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function revokeRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.revokeRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IRegistry\\n function getSubregistry(string calldata label) public view virtual returns (IRegistry) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return\\n _isExpired(entry.expiry)\\n ? IRegistry(address(0))\\n : entry.subregistry;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getResolver(string calldata label) public view virtual returns (address) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? address(0) : entry.resolver;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getParent() public view returns (IRegistry parent, string memory label) {\\n return (_parentRegistry, _childLabel);\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) public view returns (bool) {\\n return hasRootRoles(RegistryRolesLib.ROLE_CAN_NAME, namer);\\n }\\n\\n /// @inheritdoc ITemporalRegistry\\n function findExpiry(string calldata label) public view returns (uint64) {\\n return getExpiry(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc IOwnedRegistry\\n function findOwner(string calldata label) public view returns (address) {\\n return ownerOf(findTokenId(label));\\n }\\n\\n /// @inheritdoc ITokenizedRegistry\\n function findTokenId(string calldata label) public view returns (uint256) {\\n return getTokenId(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ERC1155Singleton\\n function uri(uint256 tokenId) public view override returns (string memory) {\\n return\\n address(_uriRenderer) != address(0)\\n ? _uriRenderer.renderURI(this, tokenId)\\n : _uri;\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function getExpiry(uint256 anyId) public view returns (uint64) {\\n return _entry(anyId).expiry;\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getResource(uint256 anyId) public view returns (uint256) {\\n return _constructResource(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getTokenId(uint256 anyId) public view returns (uint256) {\\n return _constructTokenId(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getStatus(uint256 anyId) public view returns (Status) {\\n Entry storage entry = _entry(anyId);\\n return _constructStatus(entry.expiry, super.ownerOf(_constructTokenId(anyId, entry)));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getState(uint256 anyId) public view returns (State memory state) {\\n Entry storage entry = _entry(anyId);\\n uint64 expiry = entry.expiry;\\n state.expiry = expiry;\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n state.tokenId = tokenId;\\n state.resource = _constructResource(anyId, entry);\\n address owner = super.ownerOf(tokenId);\\n state.latestOwner = owner;\\n state.status = _constructStatus(expiry, owner);\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function latestOwnerOf(uint256 tokenId) public view returns (address) {\\n return super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 tokenId)\\n public\\n view\\n override(ERC1155Singleton, IERC1155Singleton)\\n returns (address)\\n {\\n Entry storage entry = _entry(tokenId);\\n return\\n tokenId != _constructTokenId(tokenId, entry) || _isExpired(entry.expiry)\\n ? address(0)\\n : super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 anyId, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roles(getResource(anyId), account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 anyId)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roleCount(getResource(anyId));\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasAssignees(getResource(anyId), roleBitmap);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256 counts, uint256 mask)\\n {\\n return super.getAssigneeCount(getResource(anyId), roleBitmap);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev If `AVAILABLE`, requires `ROLE_REGISTRAR` on root and status becomes `REGISTERED`.\\n /// * If `owner` is null (`roleBitmap` must be 0), status becomes `RESERVED`.\\n /// If `RESERVED`, requires `ROLE_REGISTER_RESERVED` on root and status becomes `REGISTERED`.\\n /// * If `expiry` is 0, uses current expiry.\\n function _register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry,\\n bool checkRoles\\n )\\n internal\\n returns (uint256 tokenId)\\n {\\n LABEL_STORE.setLabel(label);\\n uint256 labelId = LibLabel.id(label);\\n Entry storage entry = _entry(labelId);\\n tokenId = _constructTokenId(labelId, entry);\\n address prevOwner = super.ownerOf(tokenId);\\n address sender = _msgSender(); // the registrar, not the registrant\\n if (_isExpired(entry.expiry)) {\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTRAR, sender);\\n }\\n if (owner == address(0) && roleBitmap != 0) {\\n revert EACCannotGrantRoles(ROOT_RESOURCE, roleBitmap, sender); // strict\\n }\\n } else {\\n if (prevOwner != address(0)) {\\n revert LabelAlreadyRegistered(label); // cannot overwrite REGISTERED\\n } else if (owner == address(0)) {\\n revert LabelAlreadyReserved(label); // cannot overwrite RESERVED\\n }\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTER_RESERVED, sender);\\n }\\n if (expiry == 0) {\\n expiry = entry.expiry; // use RESERVED expiry\\n }\\n roleBitmap |= RegistryRolesLib.ROLE_WAS_RESERVED; // remember\\n }\\n if (owner == address(0) ? expiry == 0 : _isExpired(expiry)) {\\n revert CannotSetPastExpiry(expiry);\\n }\\n if (prevOwner != address(0)) {\\n _burn(prevOwner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n tokenId = _constructTokenId(tokenId, entry);\\n }\\n entry.expiry = expiry;\\n entry.subregistry = registry;\\n entry.resolver = resolver;\\n if (owner == address(0)) {\\n emit LabelReserved(tokenId, bytes32(labelId), label, expiry, sender);\\n } else {\\n emit LabelRegistered(tokenId, bytes32(labelId), label, owner, expiry, sender);\\n _mint(owner, tokenId, 1, \\\"\\\");\\n uint256 resource = _constructResource(tokenId, entry);\\n assert(resource != ROOT_RESOURCE);\\n emit TokenResource(tokenId, resource);\\n _grantRoles(resource, roleBitmap, owner, false);\\n }\\n if (address(registry) != address(0)) {\\n emit SubregistryUpdated(tokenId, registry, sender);\\n }\\n if (address(resolver) != address(0)) {\\n emit ResolverUpdated(tokenId, resolver, sender);\\n }\\n }\\n\\n /// @dev Override `ERC1155Singleton._update()` to transfer the roles to the new owner if the token is transferred.\\n function _update(address from, address to, uint256[] memory tokenIds, uint256[] memory amounts)\\n internal\\n override\\n {\\n super._update(from, to, tokenIds, amounts); // ensures amounts[i] is 0 or 1\\n if (to != address(0) && from != address(0)) {\\n // only transfers (skip mint and burn)\\n for (uint256 i; i < tokenIds.length; ++i) {\\n uint256 tokenId = tokenIds[i];\\n // only check ROLE_CAN_TRANSFER_ADMIN on original owner (from)\\n // ROLE_CAN_TRANSFER_ADMIN is technically a property of the token\\n if (!hasRoles(tokenId, RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, from)) {\\n revert TransferDisallowed(tokenId, from);\\n } else if (amounts[i] > 0) {\\n _transferRoles(getResource(tokenId), from, to, false);\\n }\\n }\\n }\\n }\\n\\n /// @dev Override the base registry _onRolesGranted function to regenerate the token when the roles are granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Override the base registry _onRolesRevoked function to regenerate the token when the roles are revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Bump `tokenVersionId` via burn+mint if token is not expired.\\n function _regenerate(uint256 resource) internal {\\n if (resource != ROOT_RESOURCE) {\\n Entry storage entry = _entry(resource);\\n uint256 tokenId = _constructTokenId(resource, entry);\\n address owner = super.ownerOf(tokenId); // grant/revoke only on registered\\n _burn(owner, tokenId, 1);\\n ++entry.tokenVersionId;\\n uint256 newTokenId = _constructTokenId(tokenId, entry);\\n emit TokenRegenerated(tokenId, newTokenId); // resource is unchanged\\n _mint(owner, newTokenId, 1, \\\"\\\");\\n }\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token non-admin roles can only be granted to registered tokens.\\n ///\\n /// Token admin roles are only assigned during name registration to maintain\\n /// controlled permission management. This ensures that role delegation\\n /// follows the intended security model where admin privileges are granted at\\n /// registration time and cannot be arbitrarily granted afterward.\\n ///\\n /// Root admin roles are unaffected.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles (regular roles only, not admin roles).\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n override\\n returns (uint256)\\n {\\n uint256 roleBitmap = super._getSettableRoles(resource, account);\\n if (resource == ROOT_RESOURCE) {\\n return roleBitmap;\\n } else if (ownerOf(_constructTokenId(resource, _entry(resource))) == address(0)) {\\n return 0; // available or reserved\\n }\\n return roleBitmap >> 128; // remove admin\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token roles can only be revoked from registered tokens.\\n ///\\n /// Root roles are unaffected.\\n ///\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n override\\n returns (uint256)\\n {\\n if (\\n resource != ROOT_RESOURCE &&\\n ownerOf(_constructTokenId(resource, _entry(resource))) == address(0)\\n ) {\\n return 0; // available or reserved\\n }\\n return super._getRevokableRoles(resource, account);\\n }\\n\\n /// @dev Zeroes version bits in `anyId` to return the canonical storage entry for the name.\\n function _entry(uint256 anyId) internal view returns (Entry storage) {\\n return _entries[LibLabel.withVersion(anyId, 0)];\\n }\\n\\n /// @dev Assert token is not expired and caller has necessary roles.\\n function _checkExpiryAndTokenRoles(uint256 anyId, uint256 roleBitmap)\\n internal\\n view\\n returns (uint256 tokenId, Entry storage entry)\\n {\\n entry = _entry(anyId);\\n tokenId = _constructTokenId(anyId, entry);\\n if (_isExpired(entry.expiry)) {\\n revert LabelExpired(tokenId);\\n }\\n _checkRoles(_constructResource(anyId, entry), roleBitmap, _msgSender());\\n }\\n\\n /// @dev Internal logic for expired status.\\n function _isExpired(uint64 expiry) internal view returns (bool) {\\n return block.timestamp >= expiry;\\n }\\n\\n /// @dev Create `resource` from parts.\\n /// Does nothing if `ROOT_RESOURCE`.\\n /// Returns next resource if expired.\\n function _constructResource(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n if (anyId == ROOT_RESOURCE) {\\n return anyId;\\n }\\n return\\n LibLabel.withVersion(\\n anyId,\\n _isExpired(entry.expiry)\\n ? entry.eacVersionId + 1\\n : entry.eacVersionId\\n );\\n }\\n\\n /// @dev Create `tokenId` from parts.\\n function _constructTokenId(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n return LibLabel.withVersion(anyId, entry.tokenVersionId);\\n }\\n\\n /// @dev Create `Status` from parts.\\n function _constructStatus(uint64 expiry, address owner) internal view returns (Status) {\\n if (_isExpired(expiry)) {\\n return Status.AVAILABLE;\\n } else if (owner == address(0)) {\\n return Status.RESERVED;\\n } else {\\n return Status.REGISTERED;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3d065298bcd998d8a638d5e52ff7ed15b8eff4ef43666eb8219a5858ace5a5e7\",\"license\":\"MIT\"},\"project/src/registry/UserRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IProxyAuthorization} from \\\"@ensdomains/verifiable-factory/IProxyAuthorization.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {IHCAFactoryBasic} from \\\"../hca/interfaces/IHCAFactoryBasic.sol\\\";\\nimport {ILabelStore} from \\\"../utils/interfaces/ILabelStore.sol\\\";\\n\\nimport {RegistryRolesLib} from \\\"./libraries/RegistryRolesLib.sol\\\";\\nimport {PermissionedRegistry} from \\\"./PermissionedRegistry.sol\\\";\\n\\n/// @title UserRegistry\\n/// @notice UUPS-upgradeable `PermissionedRegistry` designed to be deployed as a proxy via\\n/// `VerifiableFactory` for user-owned subdomain registries. The constructor disables\\n/// initializers on the implementation contract; proxies call `initialize()` to set up the\\n/// admin and initial roles. Upgrade authorization requires the upgrade role in the root resource.\\ncontract UserRegistry is Initializable, PermissionedRegistry, UUPSUpgradeable, IProxyAuthorization {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param hcaFactory The HCA factory.\\n /// @param labelStore The shared label database.\\n /// @param namer The implementation namer.\\n constructor(IHCAFactoryBasic hcaFactory, ILabelStore labelStore, address namer)\\n PermissionedRegistry(\\n hcaFactory,\\n labelStore,\\n namer,\\n RegistryRolesLib.ROLE_CAN_NAME | RegistryRolesLib.ROLE_CAN_NAME_ADMIN\\n )\\n {\\n // This disables initialization for the implementation contract\\n _disableInitializers();\\n }\\n\\n /// @notice Initializes a proxy instance of `UserRegistry`.\\n /// @dev Grants the supplied role bitmap to `rootAccount` on the root resource.\\n /// Reverts if the zero address.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n function initialize(address rootAccount, uint256 roleBitmap) public initializer {\\n if (rootAccount == address(0)) {\\n revert InvalidOwner();\\n }\\n emit RegistryCreated();\\n _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false);\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(UUPSUpgradeable).interfaceId ||\\n interfaceId == type(IProxyAuthorization).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Declares this implementation as an eligible verifiable proxy upgrade target.\\n /// @dev Upgrade authorization is still enforced by the current implementation during the UUPS\\n /// upgrade call.\\n /// @param {previousImplementation} Ignored.\\n /// @return allowed Always `true` for implementations in this registry family.\\n function canUpgradeFrom(\\n address /* previousImplementation */\\n )\\n external\\n pure\\n virtual\\n override\\n returns (bool allowed)\\n {\\n return true;\\n }\\n\\n /// @dev Restricts UUPS upgrades to accounts holding the upgrade role on the root resource.\\n /// @param newImplementation The address of the new implementation contract.\\n function _authorizeUpgrade(address newImplementation)\\n internal\\n override\\n onlyRootRoles(RegistryRolesLib.ROLE_UPGRADE)\\n {}\\n}\\n\",\"keccak256\":\"0x8b8318ffe692d6b76bd8c04bfb2ceef0c9e429fb362462e0926566948bf0f1c7\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0xafff3a63`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n}\\n\",\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryURIRenderer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6c55e19b`\\ninterface IRegistryURIRenderer {\\n /// @notice Generate URI for `tokenId` from `registry`.\\n /// @param registry The registry.\\n /// @param tokenId The token ID in the registry.\\n /// @return The generated URI.\\n function renderURI(IRegistry registry, uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa6ea64ff73d10fa58118ae9c0d0c2caa72f2f3488776227a22bd0cd9cd6586f6\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 7: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x6bd37001025ec90ffe9b852fcfdf68be81a9f70f8777d80136bea1c04da30041\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/interfaces/ILabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @notice Interface for a shared label database.\\n/// @dev Interface selector: `0x0d48fe93`\\ninterface ILabelStore {\\n /// @notice A label was recorded.\\n /// @param labelHash The hash of `label`.\\n /// @param label The recorded label.\\n event Label(bytes32 indexed labelHash, string label);\\n\\n /// @notice Ensure `label` can be inverted from `anyId`.\\n /// @param label The label.\\n function setLabel(string calldata label) external;\\n\\n /// @notice Invert `anyId` to the corresponding label.\\n /// @param anyId The truncated labelhash.\\n /// @return The label or null if unknown.\\n function getLabel(uint256 anyId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 59110, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_owners", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 59117, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 55601, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_roles", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 55606, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_roleCount", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 55611, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "__gap", + "offset": 0, + "slot": "4", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 66662, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_parentRegistry", + "offset": 0, + "slot": "260", + "type": "t_contract(IRegistry)68656" + }, + { + "astId": 66665, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_childLabel", + "offset": 0, + "slot": "261", + "type": "t_string_storage" + }, + { + "astId": 66668, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_uri", + "offset": 0, + "slot": "262", + "type": "t_string_storage" + }, + { + "astId": 66672, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_uriRenderer", + "offset": 0, + "slot": "263", + "type": "t_contract(IRegistryURIRenderer)68771" + }, + { + "astId": 66678, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_entries", + "offset": 0, + "slot": "264", + "type": "t_mapping(t_uint256,t_struct(Entry)66654_storage)" + }, + { + "astId": 66683, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "__gap", + "offset": 0, + "slot": "265", + "type": "t_array(t_uint256)256_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRegistry)68656": { + "encoding": "inplace", + "label": "contract IRegistry", + "numberOfBytes": "20" + }, + "t_contract(IRegistryURIRenderer)68771": { + "encoding": "inplace", + "label": "contract IRegistryURIRenderer", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "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_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_struct(Entry)66654_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct PermissionedRegistry.Entry)", + "numberOfBytes": "32", + "value": "t_struct(Entry)66654_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Entry)66654_storage": { + "encoding": "inplace", + "label": "struct PermissionedRegistry.Entry", + "members": [ + { + "astId": 66640, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "eacVersionId", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 66643, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "tokenVersionId", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 66647, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "subregistry", + "offset": 8, + "slot": "0", + "type": "t_contract(IRegistry)68656" + }, + { + "astId": 66650, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "expiry", + "offset": 0, + "slot": "1", + "type": "t_uint64" + }, + { + "astId": 66653, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "resolver", + "offset": 8, + "slot": "1", + "type": "t_address" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "notice": "Label expiry cannot be reduced." + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "notice": "Label expiry cannot be before now." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "LabelAlreadyRegistered(string)": [ + { + "notice": "Label is already registered." + } + ], + "LabelAlreadyReserved(string)": [ + { + "notice": "Label cannot be reserved again." + } + ], + "LabelExpired(uint256)": [ + { + "notice": "Label is expired/unregistered." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "notice": "Transfer is not allowed due to missing transfer admin role." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "ExpiryUpdated(uint256,uint64,address)": { + "notice": "Expiry of label was changed." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "notice": "A label was registered." + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "notice": "A label was reserved." + }, + "LabelUnregistered(uint256,address)": { + "notice": "A label was unregistered." + }, + "ParentUpdated(address,string,address)": { + "notice": "Parent was changed." + }, + "RegistryCreated()": { + "notice": "A registry was created/initialized." + }, + "ResolverUpdated(uint256,address,address)": { + "notice": "Resolver of label was changed." + }, + "SubregistryUpdated(uint256,address,address)": { + "notice": "Subregistry of label was changed." + }, + "TokenRegenerated(uint256,uint256)": { + "notice": "Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance." + }, + "TokenResource(uint256,uint256)": { + "notice": "Associate a token with an EAC resource." + }, + "URIUpdated(string,address,address)": { + "notice": "URI was changed." + } + }, + "kind": "user", + "methods": { + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "LABEL_STORE()": { + "notice": "The shared label database." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "balanceOf(address,uint256)": { + "notice": "Returns the balance of a token for an account." + }, + "balanceOfBatch(address[],uint256[])": { + "notice": "Returns the balances of a batch of tokens for an account." + }, + "canUpgradeFrom(address)": { + "notice": "Declares this implementation as an eligible verifiable proxy upgrade target." + }, + "findExpiry(string)": { + "notice": "Fetches the label expiry." + }, + "findOwner(string)": { + "notice": "Fetches the label owner." + }, + "findTokenId(string)": { + "notice": "Fetches the token ID for a label." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getExpiry(uint256)": { + "notice": "Get expiry of label." + }, + "getParent()": { + "notice": "Get canonical \"location\" of this registry." + }, + "getResolver(string)": { + "notice": "Fetches the resolver responsible for the specified label." + }, + "getResource(uint256)": { + "notice": "Get `resource` from `anyId`." + }, + "getState(uint256)": { + "notice": "Get the state of a label." + }, + "getStatus(uint256)": { + "notice": "Get `Status` from `anyId`." + }, + "getSubregistry(string)": { + "notice": "Fetches the registry for a label." + }, + "getTokenId(uint256)": { + "notice": "Get `tokenId` from `anyId`." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "initialize(address,uint256)": { + "notice": "Initializes a proxy instance of `UserRegistry`." + }, + "isApprovedForAll(address,address)": { + "notice": "Returns the approval for all operator." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "latestOwnerOf(uint256)": { + "notice": "Get the latest owner of a token. If the token was burned, returns null." + }, + "ownerOf(uint256)": { + "notice": "Returns the owner of a token." + }, + "register(string,address,address,address,uint256,uint64)": { + "notice": "Registers a new label." + }, + "renew(uint256,uint64)": { + "notice": "Renew a label." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "notice": "Transfers multiple tokens from one address to another." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "notice": "Transfers a single token from one address to another." + }, + "setApprovalForAll(address,bool)": { + "notice": "Sets the approval for all operator." + }, + "setParent(address,string)": { + "notice": "Change canonical \"location\"." + }, + "setResolver(uint256,address)": { + "notice": "Change resolver of label." + }, + "setSubregistry(uint256,address)": { + "notice": "Change registry of label." + }, + "setURI(string,address)": { + "notice": "Set the URI for the registry." + }, + "unregister(uint256)": { + "notice": "Delete a label." + }, + "uri(uint256)": { + "notice": "Returns the URI for a token." + } + }, + "notice": "UUPS-upgradeable `PermissionedRegistry` designed to be deployed as a proxy via `VerifiableFactory` for user-owned subdomain registries. The constructor disables initializers on the implementation contract; proxies call `initialize()` to set up the admin and initial roles. Upgrade authorization requires the upgrade role in the root resource.", + "version": 1 + }, + "argsData": "0x000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf94300000000000000000000000023ea712da760c4e09fc9be108f1f1da6d5d6d053000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80", + "transaction": { + "hash": "0x37a5c60f54f2c41fa2566cb1e65ad9377ca7e0835dc75a6f6d902c62e76e12ea", + "nonce": "0x1e91", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x304a86727994da2f2dbd07eeaaa798c71181ecef275267b88bd93f5c67041375", + "blockNumber": "0xa6a806", + "transactionIndex": "0x3a" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/VerifiableFactory.json b/contracts/deployments/sepolia-official-v1-20260525-r2/VerifiableFactory.json new file mode 100644 index 000000000..3c41148e2 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/VerifiableFactory.json @@ -0,0 +1,191 @@ +{ + "address": "0xd2a632d8a8b67c2c4398c255cbd7af8dd7236198", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "proxyAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "salt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ProxyDeployed", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "uint256", + "name": "salt", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "deployProxy", + "outputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxyLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "expectedImplementation", + "type": "address" + } + ], + "name": "verifyContract", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "VerifiableFactory", + "sourceName": "lib/verifiable-factory/src/VerifiableFactory.sol", + "bytecode": "0x60a0604052348015600e575f5ffd5b506040516019906042565b604051809103905ff0801580156031573d5f5f3e3d5ffd5b506001600160a01b0316608052604f565b610523806105e583390190565b60805161057861006d5f395f81816078015261028201526105785ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80635d84121a14610043578063813845bc14610073578063debf7e871461009a575b5f5ffd5b6100566100513660046103d5565b6100bd565b6040516001600160a01b0390911681526020015b60405180910390f35b6100567f000000000000000000000000000000000000000000000000000000000000000081565b6100ad6100a83660046104a3565b6101d0565b604051901515815260200161006a565b604080513360208201529081018390525f9081906060016040516020818303038152906040528051906020012090505f6100f68261027b565b9050818151602083015ff592508261010c575f5ffd5b6040517fd1f578940000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063d1f578949061015390899088906004016104da565b5f604051808303815f87803b15801561016a575f5ffd5b505af115801561017c573d5f5f3e3d5ffd5b5050604080518881526001600160a01b038a81166020830152871693503392507f0a2c575ff341b41da136c9ccae74ec230a927a024d18f0dccf46d123f28f5f54910160405180910390a350509392505050565b5f823b6101de57505f610275565b826001600160a01b03166395c5c9736040518163ffffffff1660e01b81526004016040805180830381865afa925050508015610237575060408051601f3d908101601f191682019092526102349181019061051f565b60015b1561027257836001600160a01b0316816001600160a01b03161461025f575f92505050610275565b61026985836102a7565b92505050610275565b505f5b92915050565b60606102757f0000000000000000000000000000000000000000000000000000000000000000836102e0565b5f5f6102b28361027b565b90505f6102c78483805190602001203061035f565b6001600160a01b03908116908616149250505092915050565b6040805160578082526080820190925260609160208201818036833750507f3d604d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000060208301525060609390931b6034840152507f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006048830152605782015290565b5f604051836040820152846020820152828152600b8101905060ff8153605590206001600160a01b0316949350505050565b6001600160a01b03811681146103a5575f5ffd5b50565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f5f606084860312156103e7575f5ffd5b83356103f281610391565b925060208401359150604084013567ffffffffffffffff811115610414575f5ffd5b8401601f81018613610424575f5ffd5b803567ffffffffffffffff81111561043e5761043e6103a8565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561046d5761046d6103a8565b604052818152828201602001881015610484575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f5f604083850312156104b4575f5ffd5b82356104bf81610391565b915060208301356104cf81610391565b809150509250929050565b6001600160a01b0383168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b5f5f60408385031215610530575f5ffd5b8251915060208301516104cf8161039156fea26469706673582212205bf825de1356712df20e83899b09ea0dbec42f8014023ccdc67f0356a6108ebd64736f6c634300081b003360a0604052348015600e575f5ffd5b50336080526080516104f961002a5f395f609601526104f95ff3fe60806040526004361061003e575f3560e01c80634f1ef2861461007257806385369dd71461008557806395c5c973146100d5578063d1f5789414610106575b6100706100697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001610119565b005b610070610080366004610412565b610172565b348015610090575f5ffd5b506100b87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100e0575f5ffd5b506100e96102ff565b604080519283526001600160a01b039091166020830152016100cc565b610070610114366004610412565b610334565b365f5f375f5f365f855af4811561015f577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54831461015f5763784cf7005f526004601cfd5b3d5f5f3e80801561016e573d5ff35b3d5ffd5b6001600160a01b0383166101b2576040517f0760838f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6101db7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b90506001600160a01b03811661021d576040517f40dde93500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff41a143d0000000000000000000000000000000000000000000000000000000081526001600160a01b03828116600483015285919082169063f41a143d90602401602060405180830381865afa15801561027d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a1919061049d565b6102ee576040517fca3316870000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301528616602482015260440160405180910390fd5b6102f8825f610119565b5050505050565b5f5f602080303b035f303c50505f517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc549091565b8261034657630760838f5f526004601cfd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541561037a57630dc149f05f526004601cfd5b823b61039157634c9c8ce35f52826020526024601cfd5b827f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55827fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f5fa2808080156103ff5781845f375f5f835f885af4806103f9573d5f5f3e3d5ffd5b506102f8565b34156102f85763b398979f5f526004601cfd5b5f5f5f60408486031215610424575f5ffd5b83356001600160a01b038116811461043a575f5ffd5b9250602084013567ffffffffffffffff811115610455575f5ffd5b8401601f81018613610465575f5ffd5b803567ffffffffffffffff81111561047b575f5ffd5b86602082840101111561048c575f5ffd5b939660209190910195509293505050565b5f602082840312156104ad575f5ffd5b815180151581146104bc575f5ffd5b939250505056fea264697066735822122009f90c622d9dee6285a966a65ee891401113b95120f5d740f403e832666f061964736f6c634300081b0033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80635d84121a14610043578063813845bc14610073578063debf7e871461009a575b5f5ffd5b6100566100513660046103d5565b6100bd565b6040516001600160a01b0390911681526020015b60405180910390f35b6100567f000000000000000000000000000000000000000000000000000000000000000081565b6100ad6100a83660046104a3565b6101d0565b604051901515815260200161006a565b604080513360208201529081018390525f9081906060016040516020818303038152906040528051906020012090505f6100f68261027b565b9050818151602083015ff592508261010c575f5ffd5b6040517fd1f578940000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063d1f578949061015390899088906004016104da565b5f604051808303815f87803b15801561016a575f5ffd5b505af115801561017c573d5f5f3e3d5ffd5b5050604080518881526001600160a01b038a81166020830152871693503392507f0a2c575ff341b41da136c9ccae74ec230a927a024d18f0dccf46d123f28f5f54910160405180910390a350509392505050565b5f823b6101de57505f610275565b826001600160a01b03166395c5c9736040518163ffffffff1660e01b81526004016040805180830381865afa925050508015610237575060408051601f3d908101601f191682019092526102349181019061051f565b60015b1561027257836001600160a01b0316816001600160a01b03161461025f575f92505050610275565b61026985836102a7565b92505050610275565b505f5b92915050565b60606102757f0000000000000000000000000000000000000000000000000000000000000000836102e0565b5f5f6102b28361027b565b90505f6102c78483805190602001203061035f565b6001600160a01b03908116908616149250505092915050565b6040805160578082526080820190925260609160208201818036833750507f3d604d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000060208301525060609390931b6034840152507f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006048830152605782015290565b5f604051836040820152846020820152828152600b8101905060ff8153605590206001600160a01b0316949350505050565b6001600160a01b03811681146103a5575f5ffd5b50565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f5f606084860312156103e7575f5ffd5b83356103f281610391565b925060208401359150604084013567ffffffffffffffff811115610414575f5ffd5b8401601f81018613610424575f5ffd5b803567ffffffffffffffff81111561043e5761043e6103a8565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561046d5761046d6103a8565b604052818152828201602001881015610484575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f5f604083850312156104b4575f5ffd5b82356104bf81610391565b915060208301356104cf81610391565b809150509250929050565b6001600160a01b0383168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f8301168401019150509392505050565b5f5f60408385031215610530575f5ffd5b8251915060208301516104cf8161039156fea26469706673582212205bf825de1356712df20e83899b09ea0dbec42f8014023ccdc67f0356a6108ebd64736f6c634300081b0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "55138": [ + { + "length": 32, + "start": 120 + }, + { + "length": 32, + "start": 642 + } + ] + }, + "inputSourceName": "project/lib/verifiable-factory/src/VerifiableFactory.sol", + "devdoc": { + "kind": "dev", + "methods": { + "deployProxy(address,uint256,bytes)": { + "details": "Deploys a new verifiable proxy clone at a deterministic address. The deployed proxy is an EIP-1167-style clone that delegates proxy mechanics to the factory's `proxyLogic` contract. The clone runtime also appends the derived salt so the factory can later verify the proxy's CREATE2 address. The CREATE2 salt is `keccak256(abi.encode(msg.sender, salt))`, so two callers can reuse the same user salt without colliding.", + "params": { + "implementation": "The address of the contract implementation the proxy will delegate calls to.", + "salt": "A value provided by the caller to ensure uniqueness of the proxy address." + }, + "returns": { + "proxy": "The address of the deployed proxy clone." + } + }, + "verifyContract(address,address)": { + "details": "Initiates verification of a proxy contract. This function attempts to validate a proxy contract by retrieving its salt and reconstructing the address to ensure it was correctly deployed by the current factory.", + "params": { + "proxy": "The address of the proxy contract being verified." + }, + "returns": { + "_0": "A boolean indicating whether the verification succeeded." + } + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "280000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "deployProxy(address,uint256,bytes)": "infinite", + "proxyLogic()": "infinite", + "verifyContract(address,address)": "infinite" + }, + "internal": { + "_proxyCreationCode(bytes32)": "infinite", + "_verifyContract(address,bytes32)": "infinite", + "isContract(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxyAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"salt\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ProxyDeployed\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"salt\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"deployProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxyLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"expectedImplementation\",\"type\":\"address\"}],\"name\":\"verifyContract\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"deployProxy(address,uint256,bytes)\":{\"details\":\"Deploys a new verifiable proxy clone at a deterministic address. The deployed proxy is an EIP-1167-style clone that delegates proxy mechanics to the factory's `proxyLogic` contract. The clone runtime also appends the derived salt so the factory can later verify the proxy's CREATE2 address. The CREATE2 salt is `keccak256(abi.encode(msg.sender, salt))`, so two callers can reuse the same user salt without colliding.\",\"params\":{\"implementation\":\"The address of the contract implementation the proxy will delegate calls to.\",\"salt\":\"A value provided by the caller to ensure uniqueness of the proxy address.\"},\"returns\":{\"proxy\":\"The address of the deployed proxy clone.\"}},\"verifyContract(address,address)\":{\"details\":\"Initiates verification of a proxy contract. This function attempts to validate a proxy contract by retrieving its salt and reconstructing the address to ensure it was correctly deployed by the current factory.\",\"params\":{\"proxy\":\"The address of the proxy contract being verified.\"},\"returns\":{\"_0\":\"A boolean indicating whether the verification succeeded.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/lib/verifiable-factory/src/VerifiableFactory.sol\":\"VerifiableFactory\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:solady/=project/lib/solady/src/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\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 There's no code to deploy.\\n */\\n error Create2EmptyBytecode();\\n\\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(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n if (bytecode.length == 0) {\\n revert Create2EmptyBytecode();\\n }\\n assembly (\\\"memory-safe\\\") {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n // if no address was created, and returndata is not empty, bubble revert\\n if and(iszero(addr), not(iszero(returndatasize()))) {\\n let p := mload(0x40)\\n returndatacopy(p, 0, returndatasize())\\n revert(p, returndatasize())\\n }\\n }\\n if (addr == address(0)) {\\n revert Errors.FailedDeployment();\\n }\\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(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {\\n assembly (\\\"memory-safe\\\") {\\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 := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xbb7e8401583d26268ea9103013bcdcd90866a7718bd91105ebd21c9bf11f4f06\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/CloneProxyBytecode.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nlibrary CloneProxyBytecode {\\n // EIP-1167 minimal proxy creation/runtime code:\\n // https://eips.ethereum.org/EIPS/eip-1167\\n //\\n // Standard runtime is 45 bytes:\\n // 363d3d373d3d3d363d73<20-byte implementation>5af43d82803e903d91602b57fd5bf3\\n //\\n // We append a 32-byte salt to the runtime and make the creation stub return 77 bytes\\n // instead of the standard 45. The proxy still executes the same minimal-proxy logic;\\n // UUPSProxyLogic reads the appended salt with extcodecopy().\\n uint256 internal constant CREATION_CODE_LENGTH = 0x57;\\n\\n function creationCode(address logic, bytes32 salt) internal pure returns (bytes memory code) {\\n code = new bytes(CREATION_CODE_LENGTH);\\n\\n assembly (\\\"memory-safe\\\") {\\n let ptr := add(code, 0x20)\\n\\n // Creation stub plus runtime prefix. The creation stub returns 77 bytes:\\n // 45 bytes of EIP-1167 runtime plus our appended 32-byte salt.\\n mstore(ptr, 0x3d604d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n // Fill the EIP-1167 PUSH20 slot with the shared proxy logic address.\\n mstore(add(ptr, 0x14), shl(0x60, logic))\\n // Runtime suffix: delegatecall to `logic`, copy returndata, then return or revert.\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n // Append salt after the executable minimal-proxy runtime for extcodecopy().\\n mstore(add(ptr, 0x37), salt)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2973c5070195e3c2806b59f1dc7a9da5aa1efa4a30867d9715def848bd51780f\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IProxyAuthorization {\\n function canUpgradeFrom(address previousImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IUUPSProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IUUPSProxy {\\n error ImplementationCannotBeZeroAddress();\\n\\n error AlreadyInitialized();\\n\\n error ImplementationNotSet();\\n\\n error InvalidUpgradeTarget(address currentImplementation, address newImplementation);\\n\\n error UpgradeNotAllowedInContext();\\n\\n function initialize(address implementation, bytes calldata data) external payable;\\n\\n function getVerifiableProxyData() external view returns (bytes32 salt, address implementation);\\n\\n function verifiableProxyFactory() external view returns (address);\\n}\\n\",\"keccak256\":\"0xf0b7151951532e69f98ded4b36a6994921a9636e70e369ef9714d38ce8264060\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IVerifiableFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IVerifiableFactory {\\n event ProxyDeployed(address indexed sender, address indexed proxyAddress, uint256 salt, address implementation);\\n\\n function deployProxy(address implementation, uint256 salt, bytes memory data) external returns (address);\\n\\n function verifyContract(address proxy, address expectedImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x00499139966665152ce90dddf24ae3047c6fb07d3e045b1e4d77ec9e86dc4eef\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/UUPSProxyLogic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport {IProxyAuthorization} from \\\"./IProxyAuthorization.sol\\\";\\nimport {IUUPSProxy} from \\\"./IUUPSProxy.sol\\\";\\n\\ncontract UUPSProxyLogic is IUUPSProxy {\\n /// @dev `keccak256(bytes(\\\"eip1967.proxy.implementation\\\")) - 1`.\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ImplementationCannotBeZeroAddress()\\\")))`.\\n uint256 internal constant _IMPLEMENTATION_CANNOT_BE_ZERO_ADDRESS_ERROR_SELECTOR = 0x0760838f;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"AlreadyInitialized()\\\")))`.\\n uint256 internal constant _ALREADY_INITIALIZED_ERROR_SELECTOR = 0x0dc149f0;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"UpgradeNotAllowedInContext()\\\")))`.\\n uint256 internal constant _UPGRADE_NOT_ALLOWED_IN_CONTEXT_ERROR_SELECTOR = 0x784cf700;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ERC1967InvalidImplementation(address)\\\")))`.\\n uint256 internal constant _ERC1967_INVALID_IMPLEMENTATION_ERROR_SELECTOR = 0x4c9c8ce3;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ERC1967NonPayable()\\\")))`.\\n uint256 internal constant _ERC1967_NON_PAYABLE_ERROR_SELECTOR = 0xb398979f;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"Upgraded(address)\\\")))`.\\n uint256 internal constant _UPGRADED_EVENT_SELECTOR =\\n 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;\\n\\n address public immutable verifiableProxyFactory;\\n\\n constructor() {\\n verifiableProxyFactory = msg.sender;\\n }\\n\\n function initialize(address implementation, bytes calldata data) external payable {\\n assembly {\\n if eq(implementation, 0) {\\n mstore(0, _IMPLEMENTATION_CANNOT_BE_ZERO_ADDRESS_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n if iszero(eq(sload(_IMPLEMENTATION_SLOT), 0)) {\\n mstore(0, _ALREADY_INITIALIZED_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n if iszero(extcodesize(implementation)) {\\n mstore(0, _ERC1967_INVALID_IMPLEMENTATION_ERROR_SELECTOR)\\n mstore(0x20, implementation)\\n revert(0x1c, 0x24)\\n }\\n sstore(_IMPLEMENTATION_SLOT, implementation)\\n log2(0, 0, _UPGRADED_EVENT_SELECTOR, implementation)\\n\\n let dlength := data.length\\n switch dlength\\n case 0 {\\n if callvalue() {\\n mstore(0, _ERC1967_NON_PAYABLE_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n }\\n default {\\n calldatacopy(0, data.offset, dlength)\\n let result := delegatecall(gas(), implementation, 0, dlength, 0, 0)\\n if iszero(result) {\\n returndatacopy(0, 0, returndatasize())\\n revert(0, returndatasize())\\n }\\n }\\n }\\n }\\n\\n function getVerifiableProxyData() public view returns (bytes32 salt, address implementation) {\\n assembly {\\n extcodecopy(address(), 0, sub(extcodesize(address()), 0x20), 0x20)\\n salt := mload(0)\\n implementation := sload(_IMPLEMENTATION_SLOT)\\n }\\n }\\n\\n function upgradeToAndCall(address newImplementation, bytes calldata) external payable {\\n if (newImplementation == address(0)) revert ImplementationCannotBeZeroAddress();\\n\\n address implementation = _implementation();\\n if (implementation == address(0)) revert ImplementationNotSet();\\n\\n IProxyAuthorization newImpl = IProxyAuthorization(newImplementation);\\n if (!newImpl.canUpgradeFrom(implementation)) {\\n revert InvalidUpgradeTarget(implementation, newImplementation);\\n }\\n\\n _delegate(implementation, false);\\n }\\n\\n function _implementation() internal view returns (address impl) {\\n assembly {\\n impl := sload(_IMPLEMENTATION_SLOT)\\n }\\n }\\n\\n function _delegate(address implementation, bool checkImplementation) internal {\\n assembly {\\n calldatacopy(0, 0, calldatasize())\\n\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n if checkImplementation {\\n if iszero(eq(implementation, sload(_IMPLEMENTATION_SLOT))) {\\n mstore(0, _UPGRADE_NOT_ALLOWED_IN_CONTEXT_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n }\\n\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n fallback() external payable {\\n _delegate(_implementation(), true);\\n }\\n}\\n\",\"keccak256\":\"0x3633e240557a6ee77fb29b913f6cc5aa6a8b546cc6a9e927458e93fa0622c07f\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/VerifiableFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport {Create2} from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\nimport {CloneProxyBytecode} from \\\"./CloneProxyBytecode.sol\\\";\\nimport {UUPSProxyLogic} from \\\"./UUPSProxyLogic.sol\\\";\\nimport {IUUPSProxy} from \\\"./IUUPSProxy.sol\\\";\\nimport {IVerifiableFactory} from \\\"./IVerifiableFactory.sol\\\";\\n\\ncontract VerifiableFactory is IVerifiableFactory {\\n address public immutable proxyLogic;\\n\\n constructor() {\\n proxyLogic = address(new UUPSProxyLogic());\\n }\\n\\n /**\\n * @dev Deploys a new verifiable proxy clone at a deterministic address.\\n *\\n * The deployed proxy is an EIP-1167-style clone that delegates proxy mechanics to the\\n * factory's `proxyLogic` contract. The clone runtime also appends the derived salt so the\\n * factory can later verify the proxy's CREATE2 address.\\n *\\n * The CREATE2 salt is `keccak256(abi.encode(msg.sender, salt))`, so two callers can reuse\\n * the same user salt without colliding.\\n *\\n * @param implementation The address of the contract implementation the proxy will delegate calls to.\\n * @param salt A value provided by the caller to ensure uniqueness of the proxy address.\\n * @return proxy The address of the deployed proxy clone.\\n */\\n function deployProxy(address implementation, uint256 salt, bytes memory data) external returns (address proxy) {\\n bytes32 outerSalt = keccak256(abi.encode(msg.sender, salt));\\n bytes memory executableBytecode = _proxyCreationCode(outerSalt);\\n\\n assembly {\\n proxy := create2(0, add(executableBytecode, 0x20), mload(executableBytecode), outerSalt)\\n if iszero(proxy) {\\n revert(0, 0)\\n }\\n }\\n\\n IUUPSProxy(proxy).initialize(implementation, data);\\n\\n emit ProxyDeployed(msg.sender, proxy, salt, implementation);\\n }\\n\\n /**\\n * @dev Initiates verification of a proxy contract.\\n *\\n * This function attempts to validate a proxy contract by retrieving its salt\\n * and reconstructing the address to ensure it was correctly deployed by the\\n * current factory.\\n *\\n * @param proxy The address of the proxy contract being verified.\\n * @return A boolean indicating whether the verification succeeded.\\n */\\n function verifyContract(address proxy, address expectedImplementation) public view returns (bool) {\\n if (!isContract(proxy)) return false;\\n\\n try IUUPSProxy(proxy).getVerifiableProxyData() returns (bytes32 salt, address actualImplementation) {\\n if (actualImplementation != expectedImplementation) return false;\\n return _verifyContract(proxy, salt);\\n } catch {}\\n return false;\\n }\\n\\n function _verifyContract(address proxy, bytes32 salt) private view returns (bool) {\\n bytes memory proxyBytecode = _proxyCreationCode(salt);\\n\\n address expectedProxyAddress = Create2.computeAddress(salt, keccak256(proxyBytecode), address(this));\\n\\n return expectedProxyAddress == proxy;\\n }\\n\\n function _proxyCreationCode(bytes32 salt) private view returns (bytes memory creationCode) {\\n creationCode = CloneProxyBytecode.creationCode(proxyLogic, salt);\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n}\\n\",\"keccak256\":\"0xb59ebead19f6c9f00645c1290acd3c627b40389b14c959347fe08b89e1ce074e\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "argsData": "0x", + "transaction": { + "hash": "0x8a27bf67c91c4771374815b4b229672a5611e5fd3b6fccb67b7166485e863d16", + "nonce": "0x1e52", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x6d6fffd8eedaa1b66fcf4766c7ab8079bdbb9e7116fb0c4a490dbbe27d1be06d", + "blockNumber": "0xa6a7c5", + "transactionIndex": "0x45" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia-official-v1-20260525-r2/WrapperRegistryImpl.json b/contracts/deployments/sepolia-official-v1-20260525-r2/WrapperRegistryImpl.json new file mode 100644 index 000000000..b41969091 --- /dev/null +++ b/contracts/deployments/sepolia-official-v1-20260525-r2/WrapperRegistryImpl.json @@ -0,0 +1,3701 @@ +{ + "address": "0x9d9d230d9b894d3cc14fc7801031f45cd5007f18", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "address", + "name": "graveyard", + "type": "address" + }, + { + "internalType": "contract IVerifiableFactory", + "name": "verifiableFactory", + "type": "address" + }, + { + "internalType": "address", + "name": "ensV1Resolver", + "type": "address" + }, + { + "internalType": "contract IHCAFactoryBasic", + "name": "hcaFactory", + "type": "address" + }, + { + "internalType": "contract ApprovedUpgradeGate", + "name": "upgradeGate", + "type": "address" + }, + { + "internalType": "contract ILabelStore", + "name": "labelStore", + "type": "address" + }, + { + "internalType": "contract IAddressSet", + "name": "publicResolverSet", + "type": "address" + }, + { + "internalType": "address", + "name": "publicResolver", + "type": "address" + }, + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "oldExpiry", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "CannotReduceExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "CannotSetPastExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "FrozenTokenApproval", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "LabelExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameDataMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameNotLocked", + "type": "error" + }, + { + "inputs": [], + "name": "NameRequiresMigration", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "TransferDisallowed", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "UpgradeTargetNotApproved", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExpiryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ParentUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RegistryCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ResolverUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SubregistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTokenId", + "type": "uint256" + } + ], + "name": "TokenRegenerated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "TokenResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "renderer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "URIUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "GRAVEYARD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HCA_FACTORY", + "outputs": [ + { + "internalType": "contract IHCAFactoryBasic", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LABEL_STORE", + "outputs": [ + { + "internalType": "contract ILabelStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_RESOLVER_SET", + "outputs": [ + { + "internalType": "contract IAddressSet", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_GATE", + "outputs": [ + { + "internalType": "contract ApprovedUpgradeGate", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "V1_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERIFIABLE_FACTORY", + "outputs": [ + { + "internalType": "contract IVerifiableFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WRAPPER_REGISTRY_IMPL", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "canUpgradeFrom", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[]", + "name": "mds", + "type": "tuple[]" + } + ], + "name": "finishERC1155Migration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParent", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getResource", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "internalType": "address", + "name": "latestOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "internalType": "struct IPermissionedRegistry.State", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getStatus", + "outputs": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getSubregistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedName", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNode", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "contract IRegistry", + "name": "parentRegistry", + "type": "address" + }, + { + "internalType": "string", + "name": "childLabel", + "type": "string" + }, + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "latestOwnerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setParent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "setSubregistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + }, + { + "internalType": "contract IRegistryURIRenderer", + "name": "renderer", + "type": "address" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "WrapperRegistry", + "sourceName": "src/registry/WrapperRegistry.sol", + "bytecode": "0x610200604052306101a052348015610015575f80fd5b50604051616b1b380380616b1b83398101604081905261003491610e79565b6001600160a01b0386166080526040518a908a908a90309087908790869086908e908d908b907f0100000000000000000000000000000001000000000000000000000000000000907fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16001600160a01b03831660a0526100ba5f828482610185565b505050506001600160a01b0383811660c081905290831660e05260408051633f15457f60e01b81529051919250633f15457f9160048083019260209291908290030181865afa15801561010f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101339190610f4c565b6001600160a01b0390811661010052958616610120525050918316610140528216610160528116610180528981166101c05287166101e052506101769050610297565b50505050505050505050611158565b5f835f0361019457505f61028f565b61019d84610334565b6001600160a01b0383166101c45760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214610289575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166102248882600161037d565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561027d5761027d888785858b6104ad565b6001935050505061028f565b5f925050505b949350505050565b5f6102a06104bd565b805490915068010000000000000000900460ff16156102d25760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146103315780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561033157604051630153d96960e51b8152600481018290526024015b60405180910390fd5b5f610387836104e7565b9050811561041d575f848152600360205260409020546103cd9082161980195f80516020616afb83398151915291909101165f80516020616adb83398151915216151590565b156103f557604051631f22ca6960e31b81526004810185905260248101849052604401610374565b5f8481526003602052604081208054859290610412908490610f7b565b909155506104a79050565b5f8481526003602052604090205461045c901982161980195f80516020616afb83398151915291909101165f80516020616adb83398151915216151590565b1561048457604051631f80c19b60e01b81526004810185905260248101849052604401610374565b5f84815260036020526040812080548592906104a1908490610f8e565b90915550505b50505050565b6104b685610501565b5050505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b5f6104f182610334565b50600181901b17600281901b1790565b80156103315763ffffffff811681185f908152610108602052604081209061052983836105ed565b5f818152602081905260409020549091506001600160a01b031661054f8183600161060e565b8254839060049061056d90640100000000900463ffffffff16610fa1565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f61059c83856105ed60201b60201c565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a36104b68282600160405180602001604052805f81525061067560201b60201c565b80545f9063ffffffff808516851864010000000090920416185b9392505050565b6001600160a01b03831661063657604051626a0d4560e21b81525f6004820152602401610374565b604080516001808252602082018590528183019081526060820184905260a082019092525f608082018181529192916104b691879185908590836106ea565b6001600160a01b03841661069e57604051632bfa23e760e11b81525f6004820152602401610374565b604080516001808252602082018690528183019081526060820185905260808201909252906106d15f87848487846106ea565b505050505050565b63ffffffff82811690921891161890565b6106f68686868661074d565b6001600160a01b038516156106d1575f61070e610828565b9050811561072957610724818888888888610836565b610744565b60208581015190850151610741838a8a85858a610957565b50505b50505050505050565b61075984848484610a3e565b6001600160a01b0383161580159061077957506001600160a01b03841615155b156104a7575f5b82518110156104b6575f83828151811061079c5761079c610fc3565b602002602001015190506107bb816001609c1b88610c4760201b60201c565b6107ea576040516372c7b6ad60e11b8152600481018290526001600160a01b0387166024820152604401610374565b5f8383815181106107fd576107fd610fc3565b6020026020010151111561081f5761081f61081782610ca6565b87875f610ccd565b50600101610780565b5f610831610d0e565b905090565b6001600160a01b0384163b156106d15760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061087a908990899088908890889060040161103f565b6020604051808303815f875af19250505080156108b4575060408051601f3d908101601f191682019092526108b19181019061109c565b60015b61091b573d8080156108e1576040519150601f19603f3d011682016040523d82523d5f602084013e6108e6565b606091505b5080515f0361091357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610374565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461074457604051632bfa23e760e11b81526001600160a01b0386166004820152602401610374565b6001600160a01b0384163b156106d15760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e619061099b90899089908890889088906004016110c3565b6020604051808303815f875af19250505080156109d5575060408051601f3d908101601f191682019092526109d29181019061109c565b60015b610a02573d8080156108e1576040519150601f19603f3d011682016040523d82523d5f602084013e6108e6565b6001600160e01b0319811663f23a6e6160e01b1461074457604051632bfa23e760e11b81526001600160a01b0386166004820152602401610374565b8051825114610a6d5781518151604051635b05999160e01b815260048101929092526024820152604401610374565b5f610a76610828565b90505f5b8351811015610b69576020818102858101820151908501909101518015610b5f575f828152602081905260409020546001600160a01b039081169089168114610af5576040516303dee4c560e01b81526001600160a01b038a1660048201525f60248201526044810183905260648101849052608401610374565b6001821115610b37576040516303dee4c560e01b81526001600160a01b038a166004820152600160248201526044810183905260648101849052608401610374565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0389161790555b5050600101610a7a565b508251600103610be95760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051610bda929190918252602082015260400190565b60405180910390a450506104b6565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8686604051610c38929190611107565b60405180910390a45050505050565b5f61028f610c5485610ca6565b5f9081526002602090815260408083206001600160a01b03871684528252808320547fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b90925290912054178416841490565b5f6104e182610cc88163ffffffff8116185f9081526101086020526040902090565b610dab565b5f8481526002602090815260408083206001600160a01b038716845290915290205480156104b657610d0185828685610df9565b506106d185828585610185565b6080515f906001600160a01b0316610d2557503390565b60805160405163110ac5cb60e21b81523360048201525f916001600160a01b03169063442b172c90602401602060405180830381865afa158015610d6b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d8f9190610f4c565b90506001600160a01b038116610da6573391505090565b919050565b5f82610db85750816104e1565b60018201546106079084906001600160401b0316421015610de657835463ffffffff82811690921891161890565b83546106d99063ffffffff166001611134565b5f610e0384610334565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214610289575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690610224908990839061037d565b6001600160a01b0381168114610331575f80fd5b5f805f805f805f805f806101408b8d031215610e93575f80fd5b8a51610e9e81610e65565b60208c0151909a50610eaf81610e65565b60408c0151909950610ec081610e65565b60608c0151909850610ed181610e65565b60808c0151909750610ee281610e65565b60a08c0151909650610ef381610e65565b60c08c0151909550610f0481610e65565b60e08c0151909450610f1581610e65565b6101008c0151909350610f2781610e65565b6101208c0151909250610f3981610e65565b809150509295989b9194979a5092959850565b5f60208284031215610f5c575f80fd5b815161060781610e65565b634e487b7160e01b5f52601160045260245ffd5b808201808211156104e1576104e1610f67565b818103818111156104e1576104e1610f67565b5f63ffffffff808316818103610fb957610fb9610f67565b6001019392505050565b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b8381101561100657815187529582019590820190600101610fea565b509495945050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0386811682528516602082015260a0604082018190525f9061106a90830186610fd7565b828103606084015261107c8186610fd7565b905082810360808401526110908185611011565b98975050505050505050565b5f602082840312156110ac575f80fd5b81516001600160e01b031981168114610607575f80fd5b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f906110fc90830184611011565b979650505050505050565b604081525f6111196040830185610fd7565b828103602084015261112b8185610fd7565b95945050505050565b63ffffffff81811683821601908082111561115157611151610f67565b5092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e0516158586112835f395f8181610619015261233701525f818161064c0152611c2301525f81816122730152818161229c015261248801525f8181610b85015261289e01525f8181610b52015261282301525f81816106f101526129a901525f8181610444015261297a01525f81816127980152612d6f01525f8181610762015281816128dd0152612b7601525f81816104840152818161193201528181611c81015281816125ae01528181612662015281816127190152818161292001528181612aca01528181612b4301528181612cc80152612e0101525f8181610923015261360c01525f81816105290152818161323b015261328501526158585ff3fe60806040526004361061030e575f3560e01c80635d05f04911610197578063a22cb465116100df578063dfa70d8b1161008e578063dfa70d8b14610a86578063e4ae7d7714610aa5578063e985e9c514610ac4578063f23a6e6114610ae3578063f242432a14610b02578063f41a143d14610b21578063f923b68514610b41578063ffeb4a3014610b74575f80fd5b8063a22cb46514610983578063ad3cb1cc146109a2578063bc197c81146109d2578063bc7b6d6214610a0a578063bd242bcb14610a29578063ce156e8214610a48578063d3bf89b114610a67575f80fd5b80637c300586116101465780637c3005861461087f57806380f760211461089e57806385f3e643146108c057806391b3c037146108df5780639b224b1d146108fe5780639dbba19d146109125780639e77193214610945578063a02b161e14610964575f80fd5b80635d05f049146107b05780636352211e146107cf57806363560a8e146107ee5780636e7a21161461080d5780636f3ff726146108225780636f537c7214610841578063781ef8db14610860575f80fd5b806335af62161161025a5780634f1ef286116102095780634f1ef2861461069a57806352d1902d146106ad5780635357263f146106c1578063547c9d2d146106e05780635569f33d146107135780635adf4724146107325780635c1a6b68146107515780635c622a0e14610784575f80fd5b806335af62161461056a5780633634f9111461058957806344c9af28146105bd57806348688f95146105e95780634b2dc431146106085780634b30228c1461063b5780634e1273f41461066e575f80fd5b806318ad9b71116102c157806318ad9b7114610433578063192cf07d146104735780631c3fc3eb146104a65780631e8fca2d146104b95780632eb2c2d6146104d85780632f27fa24146104f9578063319c22bb14610518578063341ec5591461054b575f80fd5b8062fdd58e1461031257806301ffc9a714610344578063072d5d77146103735780630e89341c1461039257806311b8e00a146103be57806313c72608146103dd57806314ff5ea314610414575b5f80fd5b34801561031d575f80fd5b5061033161032c3660046144fe565b610ba7565b6040519081526020015b60405180910390f35b34801561034f575f80fd5b5061036361035e36600461453d565b610bde565b604051901515815260200161033b565b34801561037e575f80fd5b5061036361038d366004614558565b610c38565b34801561039d575f80fd5b506103b16103ac366004614586565b610c63565b60405161033b91906145cb565b3480156103c9575f80fd5b506103636103d83660046145dd565b610d7a565b3480156103e8575f80fd5b506103fc6103f7366004614586565b610d94565b6040516001600160401b03909116815260200161033b565b34801561041f575f80fd5b5061033161042e366004614586565b610db1565b34801561043e575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b60405161033b91906145fd565b34801561047e575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b3480156104b1575f80fd5b506103315f81565b3480156104c4575f80fd5b506103316104d3366004614586565b610dc4565b3480156104e3575f80fd5b506104f76104f2366004614756565b610dd7565b005b348015610504575f80fd5b50610331610513366004614586565b610e56565b348015610523575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610556575f80fd5b506104f7610565366004614558565b610e74565b348015610575575f80fd5b50610466610584366004614839565b610ef8565b348015610594575f80fd5b506105a86105a33660046145dd565b610f79565b6040805192835260208301919091520161033b565b3480156105c8575f80fd5b506105dc6105d7366004614586565b610f99565b60405161033b91906148ab565b3480156105f4575f80fd5b506104f76106033660046148fc565b61105f565b348015610613575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610646575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610679575f80fd5b5061068d61068836600461494e565b6110f4565b60405161033b9190614a43565b6104f76106a8366004614a55565b6111be565b3480156106b8575f80fd5b506103316111dd565b3480156106cc575f80fd5b506104f76106db366004614a55565b6111f8565b3480156106eb575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b34801561071e575f80fd5b506104f761072d366004614aab565b611289565b34801561073d575f80fd5b5061033161074c366004614558565b6113c5565b34801561075c575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b34801561078f575f80fd5b506107a361079e366004614586565b6113f7565b60405161033b9190614ace565b3480156107bb575f80fd5b506104f76107ca366004614b1c565b61142e565b3480156107da575f80fd5b506104666107e9366004614586565b61148c565b3480156107f9575f80fd5b50610466610808366004614839565b6114d8565b348015610818575f80fd5b5061020954610331565b34801561082d575f80fd5b5061036361083c366004614b82565b6114e6565b34801561084c575f80fd5b506103fc61085b366004614839565b6114f5565b34801561086b575f80fd5b5061036361087a366004614558565b611537565b34801561088a575f80fd5b50610363610899366004614b9d565b611560565b3480156108a9575f80fd5b506108b2611574565b60405161033b929190614bc8565b3480156108cb575f80fd5b506103316108da366004614beb565b61161f565b3480156108ea575f80fd5b506103316108f9366004614839565b611660565b348015610909575f80fd5b506103b16116a2565b34801561091d575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610950575f80fd5b506104f761095f366004614c77565b6116b1565b34801561096f575f80fd5b506104f761097e366004614586565b61180a565b34801561098e575f80fd5b506104f761099d366004614cfa565b611914565b3480156109ad575f80fd5b506103b1604051806040016040528060058152602001640352e302e360dc1b81525081565b3480156109dd575f80fd5b506109f16109ec366004614d26565b611926565b6040516001600160e01b0319909116815260200161033b565b348015610a15575f80fd5b506104f7610a24366004614558565b611abe565b348015610a34575f80fd5b50610466610a43366004614586565b611b47565b348015610a53575f80fd5b50610363610a62366004614558565b611b51565b348015610a72575f80fd5b50610363610a81366004614b9d565b611b73565b348015610a91575f80fd5b50610363610aa0366004614b9d565b611bbf565b348015610ab0575f80fd5b50610466610abf366004614839565b611bd3565b348015610acf575f80fd5b50610363610ade366004614ddc565b611c48565b348015610aee575f80fd5b506109f1610afd366004614e08565b611c75565b348015610b0d575f80fd5b506104f7610b1c366004614e7e565b611e65565b348015610b2c575f80fd5b50610363610b3b366004614b82565b50600190565b348015610b4c575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610b7f575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b5f826001600160a01b0316610bbb8361148c565b6001600160a01b031614610bcf575f610bd2565b60015b60ff1690505b92915050565b5f636b2f733960e01b6001600160e01b031983161480610c0e575063b0f3d36760e01b6001600160e01b03198316145b80610c29575063f41a143d60e01b6001600160e01b03198316145b80610bd85750610bd882611ed7565b5f8083610c4d8282610c48611efb565b611f04565b610c5a5f86866001611f39565b95945050505050565b610107546060906001600160a01b0316610d06576101068054610c8590614ee1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb190614ee1565b8015610cfc5780601f10610cd357610100808354040283529160200191610cfc565b820191905f5260205f20905b815481529060010190602001808311610cdf57829003601f168201915b5050505050610bd8565b61010754604051636c55e19b60e01b8152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610d53573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bd89190810190614f4f565b5f610d8d610d8784610dc4565b83612049565b9392505050565b5f610d9e82612060565b600101546001600160401b031692915050565b5f610bd882610dbf84612060565b612079565b5f610bd882610dd284612060565b612097565b5f610de0611efb565b9050806001600160a01b0316866001600160a01b031614158015610e0b5750610e098682611c48565b155b15610e415760405163711bec9160e11b81526001600160a01b038083166004830152871660248201526044015b60405180910390fd5b610e4e86868686866120f0565b505050505050565b5f610bd8610e6383610dc4565b5f9081526003602052604090205490565b5f80610e838462100000612157565b8054600160401b600160e01b031916600160401b6001600160a01b038716021781559092509050610eb2611efb565b6001600160a01b0316836001600160a01b0316837fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a450505050565b5f80610f40610f3b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506121b792505050565b612060565b60018101549091506001600160401b0316421015610f6f578054600160401b90046001600160a01b0316610f71565b5f5b949350505050565b5f80610f8d610f8785610dc4565b846121c2565b915091505b9250929050565b6040805160a0810182525f80825260208201819052918101829052606081018290526080810182905290610fcc83612060565b60018101546001600160401b0316602084018190529091505f610fef8584612079565b6060850181905290506110028584612097565b60808501525f611011826121e5565b6001600160a01b0381166040870152905061102c83826121ff565b8590600281111561103f5761103f614877565b9081600281111561105257611052614877565b8152505050505050919050565b6410000000006110775f82611072611efb565b612235565b610106611085848683614feb565b5061010780546001600160a01b0319166001600160a01b0384161790556110aa611efb565b6001600160a01b03167fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd58585856040516110e69392919061509f565b60405180910390a250505050565b606081518351146111255781518351604051635b05999160e01b815260048101929092526024820152604401610e38565b5f83516001600160401b0381111561113f5761113f614611565b604051908082528060200260200182016040528015611168578160200160208202803683370190505b5090505f5b84518110156111b65760208082028601015161119190602080840287010151610ba7565b8282815181106111a3576111a36150df565b602090810291909101015260010161116d565b509392505050565b6111c6612268565b6111cf8261230e565b6111d982826123ca565b5050565b5f6111e661247d565b505f805160206157e383398151915290565b6101006112085f82611072611efb565b61010480546001600160a01b0319166001600160a01b03851617905561010561123183826150f3565b5061123a611efb565b6001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff48460405161127c91906145cb565b60405180910390a3505050565b5f61129383612060565b90505f6112a08483612079565b90505f6112ab611efb565b60018401549091506001600160401b0316428111611309576001600160401b03811615806112e357506112e16201000083611537565b155b156113045760405163311388dd60e21b815260048101849052602401610e38565b611320565b6113206113168786612097565b6201000084612235565b806001600160401b0316856001600160401b0316101561136657604051633460a12d60e11b81526001600160401b03808316600483015286166024820152604401610e38565b60018401805467ffffffffffffffff19166001600160401b0387169081179091556040516001600160a01b038416919085907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a4505050505050565b5f610d8d6113d284610dc4565b5f9081526002602090815260408083206001600160a01b038716845290915290205490565b5f8061140283612060565b6001810154909150610d8d906001600160401b03166114296114248685612079565b6121e5565b6121ff565b333014611450573360405163d86ad9cf60e01b8152600401610e3891906145fd565b82811461147a57604051635b05999160e01b81526004810184905260248101829052604401610e38565b611486848484846124c6565b50505050565b5f8061149783612060565b90506114a38382612079565b831415806114be575060018101546001600160401b03164210155b6114d0576114cb836121e5565b610d8d565b5f9392505050565b5f610d8d6107e98484611660565b5f610bd8600160781b83611537565b5f610d8d6103f784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506121b792505050565b6001600160a01b03165f9081525f80516020615803833981519152602052604090205481161490565b5f610f7161156d85610dc4565b8484612c2d565b6101045461010580545f926060926001600160a01b0390911691819061159990614ee1565b80601f01602080910402602001604051908101604052809291908181526020018280546115c590614ee1565b80156116105780601f106115e757610100808354040283529160200191611610565b820191905f5260205f20905b8154815290600101906020018083116115f357829003601f168201915b50505050509050915091509091565b5f61162987612c72565b1561164757604051630811f43760e31b815260040160405180910390fd5b611655878787878787612dec565b979650505050505050565b5f610d8d61042e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506121b792505050565b60606116ac612dfd565b905090565b5f6116ba612e97565b805490915060ff600160401b82041615906001600160401b03165f811580156116e05750825b90505f826001600160401b031660011480156116fb5750303b155b905081158015611709575080155b156117275760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561175157845460ff60401b1916600160401b1785555b6102098b905561010480546001600160a01b0319166001600160a01b038c16179055610105611781898b83614feb565b506040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16117b65f87895f611f39565b5083156117fd57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b5f8061181883611000612157565b91509150611824611efb565b6001600160a01b0316827f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea860405160405180910390a35f611864836121e5565b90506001600160a01b038116156118f25761188181846001612ebf565b815482905f906118969063ffffffff166151bd565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166118d3906151bd565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff1916426001600160401b03161790555050565b6111d961191f611efb565b8383612f13565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146119aa576119aa63d86ad9cf60e01b3360405160240161197391906145fd565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612f9f565b82826119b760e0896151df565b6119c29060406151f6565b808210156119fc576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b1790526119fc90612f9f565b5f611a09868801886152a4565b604051635d05f04960e01b81529091503090635d05f04990611a33908e908e9086906004016153db565b5f604051808303815f87803b158015611a4a575f80fd5b505af1925050508015611a5b575060015b611a9d573d808015611a88576040519150601f19603f3d011682016040523d82523d5f602084013e611a8d565b606091505b50611a9781612f9f565b50611aad565b5063bc197c8160e01b9350611aaf565b505b50505098975050505050505050565b5f80611ace846301000000612157565b600181018054600160401b600160e01b031916600160401b6001600160a01b038816021790559092509050611b01611efb565b6001600160a01b0316836001600160a01b0316837f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a450505050565b5f610bd8826121e5565b5f8083611b668282611b61611efb565b612fb2565b610c5a5f86866001612fe7565b5f610f71611b8085610dc4565b5f9081526002602090815260408083206001600160a01b03871684528252808320545f8051602061580383398151915290925290912054178416841490565b5f610f71611bcc85610dc4565b8484613053565b5f611c1283838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612c7292505050565b611c20576114cb838361308e565b507f000000000000000000000000000000000000000000000000000000000000000092915050565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611cc257611cc263d86ad9cf60e01b3360405160240161197391906145fd565b828260e080821015611d00576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b179052611d0090612f9f565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f19909201910181611d3857905050905089825f81518110611d8057611d806150df565b6020908102919091010152611d978789018961541f565b815f81518110611da957611da96150df565b6020908102919091010152604051635d05f04960e01b81523090635d05f04990611dd99085908590600401615450565b5f604051808303815f87803b158015611df0575f80fd5b505af1925050508015611e01575060015b611e43573d808015611e2e576040519150601f19603f3d011682016040523d82523d5f602084013e611e33565b606091505b50611e3d81612f9f565b50611e55565b5063f23a6e6160e01b9450611e589050565b50505b5050509695505050505050565b5f611e6e611efb565b9050806001600160a01b0316866001600160a01b031614158015611e995750611e978682611c48565b155b15611eca5760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610e38565b610e4e8686868686613103565b5f6001600160e01b03198216630271189760e51b1480610bd85750610bd882613172565b5f6116ac613238565b5f611f0f8483613315565b905080198316156114865783838360405163d1a3b35560e01b8152600401610e3893929190615474565b5f835f03611f4857505f610f71565b611f5184613361565b6001600160a01b038316611f785760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461203d575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616611fd8888260016133a8565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561203157612031888785858b61348f565b60019350505050610f71565b505f9695505050505050565b5f806120558484610f79565b501515949350505050565b63ffffffff8116185f9081526101086020526040902090565b80545f9063ffffffff80851685186401000000009092041618610d8d565b5f826120a4575081610bd8565b6001820154610d8d9084906001600160401b03164210156120cc57835463ffffffff166120df565b83546120df9063ffffffff166001615493565b63ffffffff82811690921891161890565b6001600160a01b038416612119575f604051632bfa23e760e11b8152600401610e3891906145fd565b6001600160a01b038516612141575f604051626a0d4560e21b8152600401610e3891906145fd565b61215085858585856001613498565b5050505050565b5f8061216284612060565b905061216e8482612079565b60018201549092506001600160401b031642106121a15760405163311388dd60e21b815260048101839052602401610e38565b610f926121ae8583612097565b84611072611efb565b805160209091012090565b5f806121cd836134fa565b5f948552600360205260409094205484169492505050565b5f908152602081905260409020546001600160a01b031690565b5f6001600160401b038316421061221757505f610bd8565b6001600160a01b03821661222d57506001610bd8565b506002610bd8565b612240838383611b73565b61226357828282604051634b27a13360e01b8152600401610e3893929190615474565b505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806122ee57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166122e25f805160206157e3833981519152546001600160a01b031690565b6001600160a01b031614155b1561230c5760405163703e46dd60e11b815260040160405180910390fd5b565b6001607c1b6123205f82611072611efb565b604051634b5bc65f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906396b78cbe9061236c9085906004016145fd565b602060405180830381865afa158015612387573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123ab91906154b7565b6111d95781604051630f74d7dd60e41b8152600401610e3891906145fd565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612424575060408051601f3d908101601f19168201909252612421918101906154d2565b60015b6124435781604051634c9c8ce360e01b8152600401610e3891906145fd565b5f805160206157e3833981519152811461247357604051632a87526960e21b815260048101829052602401610e38565b6122638383613514565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461230c5760405163703e46dd60e11b815260040160405180910390fd5b6102095430905f5b85811015612c24575f8585838181106124e9576124e96150df565b90506020028101906124fb91906154e9565b61250490615507565b60208101519091506001600160a01b0316612532576040516349e27cff60e01b815260040160405180910390fd5b5f888884818110612545576125456150df565b8451805160209182012091029290920135925061256d905085825f9182526020526040902090565b821461258f5760405163edec356960e01b815260048101839052602401610e38565b6060830151604051630178fe3f60e01b8152600481018490525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156125fb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261f9190615512565b925092505061263082600116151590565b15612aa45760408216158015906126d7575060405163020604bf60e21b8152600481018690525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063081812fc90602401602060405180830381865afa1580156126a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126cb9190615559565b6001600160a01b031614155b156126f85760405163a4f0771360e01b815260048101869052602401610e38565b600882165f0361278257604051630c4b7b8560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631896f70a906127509088905f90600401615574565b5f604051808303815f87803b158015612767575f80fd5b505af1158015612779573d5f803e3d5ffd5b505050506128c0565b604051630178b8bf60e01b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178b8bf90602401602060405180830381865afa1580156127e5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128099190615559565b604051630d76f7ed60e11b81529093506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631aedefda906128589086906004016145fd565b602060405180830381865afa158015612873573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061289791906154b7565b156128c0577f000000000000000000000000000000000000000000000000000000000000000092505b604051637921219560e11b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526001606483015260a060848301525f60a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c4015f604051808303815f87803b158015612961575f80fd5b505af1158015612973573d5f803e3d5ffd5b505050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d84121a7f0000000000000000000000000000000000000000000000000000000000000000885f1c898e8c5f01518d602001516129df8b613569565b6040516024016129f395949392919061558b565b60408051601f198184030181529181526020820180516001600160e01b0316634f3b8c9960e11b179052516001600160e01b031960e086901b168152612a3e939291906004016155c5565b6020604051808303815f875af1158015612a5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a7e9190615559565b9050612a9d875f015188602001518387612a97886135a0565b876135e7565b5050612c13565b6201000062030000831603612bf757604051630c4b7b8560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631896f70a90612b019088905f90600401615574565b5f604051808303815f87803b158015612b18575f80fd5b505af1158015612b2a573d5f803e3d5ffd5b5050604051636c64c90d60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063d8c9921a9150612b9e908b9088907f000000000000000000000000000000000000000000000000000000000000000090600401615474565b5f604051808303815f87803b158015612bb5575f80fd5b505af1158015612bc7573d5f803e3d5ffd5b50508751602089015160408a0151612bf194509192509086630110000061011160941b01866135e7565b50612c13565b604051630dff478560e11b815260048101869052602401610e38565b5050505050508060010190506124ce565b50505050505050565b5f8383612c3d8282610c48611efb565b85612c5b57604051631850848b60e31b815260040160405180910390fd5b612c688686866001611f39565b9695505050505050565b805160208201205f905f612c8582610d94565b6001600160401b03161115612c9c57505f92915050565b610209545f908152602082905260408120604051630178fe3f60e01b8152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015612d15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d399190615512565b5091505062010000620300008216148015610c5a57506040516302571be360e01b8152600481018390525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015612db4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dd89190615559565b6001600160a01b0316141595945050505050565b5f61165587878787878760016135f3565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166320c38e2b612e386102095490565b6040518263ffffffff1660e01b8152600401612e5691815260200190565b5f60405180830381865afa158015612e70573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526116ac9190810190614f4f565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610bd8565b6001600160a01b038316612ee7575f604051626a0d4560e21b8152600401610e3891906145fd565b5f80612ef38484613a9b565b91509150612150855f848460405180602001604052805f8152505f613498565b6001600160a01b038216612f3b575f60405162ced3e160e81b8152600401610e3891906145fd565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910161127c565b612fa881613ac3565b9050805160208201fd5b5f612fbd8483613b7d565b90508019831615611486578383836040516314c09c6360e31b8152600401610e3893929190615474565b5f612ff184613361565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461203d575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690611fd890899083906133a8565b5f83836130638282611b61611efb565b8561308157604051631850848b60e31b815260040160405180910390fd5b612c688686866001612fe7565b5f806130d1610f3b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506121b792505050565b60018101549091506001600160401b0316421015610f6f576001810154600160401b90046001600160a01b0316610f71565b6001600160a01b03841661312c575f604051632bfa23e760e11b8152600401610e3891906145fd565b6001600160a01b038516613154575f604051626a0d4560e21b8152600401610e3891906145fd565b5f806131608585613a9b565b91509150612c2487878484875f613498565b5f6001600160e01b0319821663afff3a6360e01b14806131a257506001600160e01b03198216632e112adb60e21b145b806131bd57506001600160e01b031982166391b3c03760e01b145b806131d857506001600160e01b031982166337a9be3960e11b145b806131f357506001600160e01b031982166331ab054760e11b145b8061320e57506001600160e01b03198216630147d9fd60e61b145b8061322957506001600160e01b0319821663379ffb9360e11b145b80610bd85750610bd882613bba565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661326c57503390565b60405163110ac5cb60e21b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063442b172c906132ba9033906004016145fd565b602060405180830381865afa1580156132d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132f99190615559565b90506001600160a01b038116613310573391505090565b919050565b5f806133218484613bde565b90508361332f579050610bd8565b5f6133406107e986610dbf81612060565b6001600160a01b031603613357575f915050610bd8565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156133a557604051630153d96960e51b815260048101829052602401610e38565b50565b5f6133b2836134fa565b90508115613424575f848152600360205260409020546133d490821619613c2d565b156133fc57604051631f22ca6960e31b81526004810185905260248101849052604401610e38565b5f84815260036020526040812080548592906134199084906151f6565b909155506114869050565b5f8481526003602052604090205461343f9019821619613c2d565b1561346757604051631f80c19b60e01b81526004810185905260248101849052604401610e38565b5f84815260036020526040812080548592906134849084906155eb565b909155505050505050565b61215085613c7c565b6134a486868686613d45565b6001600160a01b03851615610e4e575f6134bc611efb565b905081156134d7576134d2818888888888613e0c565b612c24565b602085810151908501516134ef838a8a85858a613f1b565b505050505050505050565b5f61350482613361565b50600181901b17600281901b1790565b61351d82613ff9565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115613561576122638282614053565b6111d96140bc565b5f602082168103613578576001175b6002821661358757608081901b175b62010000630100001160781b01601160f81b0117919050565b5f620400008216156135b25762010000175b600882165f036135c3576301000000175b600282166135d257608081901b175b600482165f03613310576001609c1b17919050565b5f6116558787878787875f5b60405163bf53096960e01b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990613641908b906004016145cb565b5f604051808303815f87803b158015613658575f80fd5b505af115801561366a573d5f803e3d5ffd5b5050895160208b012091505f905061368182612060565b905061368d8282612079565b92505f613699846121e5565b90505f6136a4611efb565b60018401549091506001600160401b0316421061370c5785156136cd576136cd5f600183612235565b6001600160a01b038b161580156136e357508715155b15613707575f888260405163d1a3b35560e01b8152600401610e3893929190615474565b61379d565b6001600160a01b03821615613736578b6040516337bd516960e21b8152600401610e3891906145cb565b6001600160a01b038b1661375f578b6040516307b03acf60e51b8152600401610e3891906145cb565b8515613771576137715f601083612235565b866001600160401b03165f036137925760018301546001600160401b031696505b640100000000881797505b6001600160a01b038b16156137be576001600160401b0387164210156137ca565b6001600160401b038716155b156137f35760405163f1d446c360e01b81526001600160401b0388166004820152602401610e38565b6001600160a01b0382161561388b5761380e82866001612ebf565b825483905f906138239063ffffffff166151bd565b91906101000a81548163ffffffff021916908363ffffffff160217905550825f01600481819054906101000a900463ffffffff16613860906151bd565b91906101000a81548163ffffffff021916908363ffffffff1602179055506138888584612079565b94505b60018301805484546001600160a01b03808e16600160401b908102600160401b600160e01b03199093169290921787558c81169091026001600160e01b03199092166001600160401b038b1617919091179091558b1661393157806001600160a01b0316845f1b867f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88f8b6040516139249291906155fe565b60405180910390a46139ea565b806001600160a01b0316845f1b867f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8f8f8c60405161397293929190615628565b60405180910390a46139958b86600160405180602001604052805f8152506140db565b5f6139a08685612097565b9050806139af576139af615663565b604051819087907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a36139e7818a8e5f611f39565b50505b6001600160a01b038a1615613a3b57806001600160a01b03168a6001600160a01b0316867fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a45b6001600160a01b03891615613a8c57806001600160a01b0316896001600160a01b0316867f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a45b50505050979650505050505050565b6040805160018082526020820194909452808201938452606081019290925260808201905291565b60605f8251118015613aed575062461bcd60e51b613ae083615677565b6001600160e01b03191614155b15613b795762461bcd60e51b6f0aee4c2e0e0cac88ae4e4dee4747460f60831b613b1684614122565b604051602001613b279291906156c1565b60408051601f1981840301815290829052613b44916024016145cb565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b5f8215801590613ba457505f613b996107e985610dbf81612060565b6001600160a01b0316145b15613bb057505f610bd8565b610d8d8383613bde565b5f6001600160e01b031982166347a296b160e11b1480610bd85750610bd88261418a565b6001600160a01b03165f8181525f80516020615803833981519152602090815260408083205494835260028252808320938352929052205417608081901c6001600160801b0319919091161790565b80197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef91909101167f888888888888888888888888888888888888888888888888888888888888888816151590565b80156133a5575f613c8c82612060565b90505f613c998383612079565b90505f613ca5826121e5565b9050613cb381836001612ebf565b82548390600490613cd190640100000000900463ffffffff166151bd565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f613cfa8385612079565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a36121508282600160405180602001604052805f8152506140db565b613d51848484846141f4565b6001600160a01b03831615801590613d7157506001600160a01b03841615155b15611486575f5b8251811015612150575f838281518110613d9457613d946150df565b60200260200101519050613dad816001609c1b88611b73565b613dce5780866040516372c7b6ad60e11b8152600401610e38929190615574565b5f838381518110613de157613de16150df565b60200260200101511115613e0357613e03613dfb82610dc4565b87875f6143cf565b50600101613d78565b6001600160a01b0384163b15610e4e5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613e5090899089908890889088906004016156dc565b6020604051808303815f875af1925050508015613e8a575060408051601f3d908101601f19168201909252613e8791810190615739565b60015b613ee8573d808015613eb7576040519150601f19603f3d011682016040523d82523d5f602084013e613ebc565b606091505b5080515f03613ee05784604051632bfa23e760e11b8152600401610e3891906145fd565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b14612c245784604051632bfa23e760e11b8152600401610e3891906145fd565b6001600160a01b0384163b15610e4e5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613f5f9089908990889088908890600401615754565b6020604051808303815f875af1925050508015613f99575060408051601f3d908101601f19168201909252613f9691810190615739565b60015b613fc6573d808015613eb7576040519150601f19603f3d011682016040523d82523d5f602084013e613ebc565b6001600160e01b0319811663f23a6e6160e01b14612c245784604051632bfa23e760e11b8152600401610e3891906145fd565b806001600160a01b03163b5f036140255780604051634c9c8ce360e01b8152600401610e3891906145fd565b5f805160206157e383398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161406f919061578d565b5f60405180830381855af49150503d805f81146140a7576040519150601f19603f3d011682016040523d82523d5f602084013e6140ac565b606091505b5091509150610c5a858383614410565b341561230c5760405163b398979f60e01b815260040160405180910390fd5b6001600160a01b038416614104575f604051632bfa23e760e11b8152600401610e3891906145fd565b5f806141108585613a9b565b91509150610e4e5f878484875f613498565b805160609060011b806001600160401b0381111561414257614142614611565b6040519080825280601f01601f19166020018201604052801561416c576020820181803683370190505b509150602083810190830161418282828561445e565b505050919050565b5f6001600160e01b03198216636cdb3d1360e11b14806141ba57506001600160e01b031982166331a9108f60e11b145b806141d557506001600160e01b031982166303a24d0760e21b145b80610bd857506301ffc9a760e01b6001600160e01b0319831614610bd8565b80518251146142235781518151604051635b05999160e01b815260048101929092526024820152604401610e38565b5f61422c611efb565b90505f5b83518110156142f15760208181028581018201519085019091015180156142e7575f828152602081905260409020546001600160a01b03908116908916811461429457885f83856040516303dee4c560e01b8152600401610e389493929190615798565b60018211156142bf5788600183856040516303dee4c560e01b8152600401610e389493929190615798565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0389161790555b5050600101614230565b5082516001036143715760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051614362929190918252602082015260400190565b60405180910390a45050612150565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516143c09291906157be565b60405180910390a45050505050565b5f8481526002602090815260408083206001600160a01b038716845290915290205480156121505761440385828685612fe7565b50610e4e85828585611f39565b606082614420576114cb826144c1565b815115801561443757506001600160a01b0384163b155b156144575783604051639996b31560e01b8152600401610e3891906145fd565b5080610d8d565b8181015b808310156114865783516101005b828510801561447e57505f81115b156144b45760031901600f82821c16600a811061449e57806057016144a3565b806030015b905080865350600190940193614470565b5050602084019350614462565b8051156144d15780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b6001600160a01b03811681146133a5575f80fd5b5f806040838503121561450f575f80fd5b823561451a816144ea565b946020939093013593505050565b6001600160e01b0319811681146133a5575f80fd5b5f6020828403121561454d575f80fd5b8135610d8d81614528565b5f8060408385031215614569575f80fd5b82359150602083013561457b816144ea565b809150509250929050565b5f60208284031215614596575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610d8d602083018461459d565b5f80604083850312156145ee575f80fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561464d5761464d614611565b604052919050565b5f6001600160401b0382111561466d5761466d614611565b5060051b60200190565b5f82601f830112614686575f80fd5b8135602061469b61469683614655565b614625565b8083825260208201915060208460051b8701019350868411156146bc575f80fd5b602086015b848110156146d857803583529183019183016146c1565b509695505050505050565b5f6001600160401b038211156146fb576146fb614611565b50601f01601f191660200190565b5f82601f830112614718575f80fd5b8135614726614696826146e3565b81815284602083860101111561473a575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a0868803121561476a575f80fd5b8535614775816144ea565b94506020860135614785816144ea565b935060408601356001600160401b03808211156147a0575f80fd5b6147ac89838a01614677565b945060608801359150808211156147c1575f80fd5b6147cd89838a01614677565b935060808801359150808211156147e2575f80fd5b506147ef88828901614709565b9150509295509295909350565b5f8083601f84011261480c575f80fd5b5081356001600160401b03811115614822575f80fd5b602083019150836020828501011115610f92575f80fd5b5f806020838503121561484a575f80fd5b82356001600160401b0381111561485f575f80fd5b61486b858286016147fc565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600381106148a757634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506148bd82845161488b565b6001600160401b03602084015116602083015260018060a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f6040848603121561490e575f80fd5b83356001600160401b03811115614923575f80fd5b61492f868287016147fc565b9094509250506020840135614943816144ea565b809150509250925092565b5f806040838503121561495f575f80fd5b82356001600160401b0380821115614975575f80fd5b818501915085601f830112614988575f80fd5b8135602061499861469683614655565b82815260059290921b840181019181810190898411156149b6575f80fd5b948201945b838610156149dd5785356149ce816144ea565b825294820194908201906149bb565b965050860135925050808211156149f2575f80fd5b506149ff85828601614677565b9150509250929050565b5f815180845260208085019450602084015f5b83811015614a3857815187529582019590820190600101614a1c565b509495945050505050565b602081525f610d8d6020830184614a09565b5f8060408385031215614a66575f80fd5b8235614a71816144ea565b915060208301356001600160401b03811115614a8b575f80fd5b6149ff85828601614709565b6001600160401b03811681146133a5575f80fd5b5f8060408385031215614abc575f80fd5b82359150602083013561457b81614a97565b60208101610bd8828461488b565b5f8083601f840112614aec575f80fd5b5081356001600160401b03811115614b02575f80fd5b6020830191508360208260051b8501011115610f92575f80fd5b5f805f8060408587031215614b2f575f80fd5b84356001600160401b0380821115614b45575f80fd5b614b5188838901614adc565b90965094506020870135915080821115614b69575f80fd5b50614b7687828801614adc565b95989497509550505050565b5f60208284031215614b92575f80fd5b8135610d8d816144ea565b5f805f60608486031215614baf575f80fd5b83359250602084013591506040840135614943816144ea565b6001600160a01b03831681526040602082018190525f90610f719083018461459d565b5f805f805f8060c08789031215614c00575f80fd5b86356001600160401b03811115614c15575f80fd5b614c2189828a01614709565b9650506020870135614c32816144ea565b94506040870135614c42816144ea565b93506060870135614c52816144ea565b92506080870135915060a0870135614c6981614a97565b809150509295509295509295565b5f805f805f8060a08789031215614c8c575f80fd5b863595506020870135614c9e816144ea565b945060408701356001600160401b03811115614cb8575f80fd5b614cc489828a016147fc565b9095509350506060870135614cd8816144ea565b80925050608087013590509295509295509295565b80151581146133a5575f80fd5b5f8060408385031215614d0b575f80fd5b8235614d16816144ea565b9150602083013561457b81614ced565b5f805f805f805f8060a0898b031215614d3d575f80fd5b8835614d48816144ea565b97506020890135614d58816144ea565b965060408901356001600160401b0380821115614d73575f80fd5b614d7f8c838d01614adc565b909850965060608b0135915080821115614d97575f80fd5b614da38c838d01614adc565b909650945060808b0135915080821115614dbb575f80fd5b50614dc88b828c016147fc565b999c989b5096995094979396929594505050565b5f8060408385031215614ded575f80fd5b8235614df8816144ea565b9150602083013561457b816144ea565b5f805f805f8060a08789031215614e1d575f80fd5b8635614e28816144ea565b95506020870135614e38816144ea565b9450604087013593506060870135925060808701356001600160401b03811115614e60575f80fd5b614e6c89828a016147fc565b979a9699509497509295939492505050565b5f805f805f60a08688031215614e92575f80fd5b8535614e9d816144ea565b94506020860135614ead816144ea565b9350604086013592506060860135915060808601356001600160401b03811115614ed5575f80fd5b6147ef88828901614709565b600181811c90821680614ef557607f821691505b602082108103614f1357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f614f26614696846146e3565b9050828152838383011115614f39575f80fd5b8282602083015e5f602084830101529392505050565b5f60208284031215614f5f575f80fd5b81516001600160401b03811115614f74575f80fd5b8201601f81018413614f84575f80fd5b610f7184825160208401614f19565b601f82111561226357805f5260205f20601f840160051c81016020851015614fb85750805b601f840160051c820191505b81811015612150575f8155600101614fc4565b5f19600383901b1c191660019190911b1790565b6001600160401b0383111561500257615002614611565b615016836150108354614ee1565b83614f93565b5f601f841160018114615042575f85156150305750838201355b61503a8682614fd7565b845550612150565b5f83815260208120601f198716915b828110156150715786850135825560209485019460019092019101615051565b508682101561508d575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f60608483018101919091526001600160a01b03929092166020820152601f909201601f191690910101919050565b634e487b7160e01b5f52603260045260245ffd5b81516001600160401b0381111561510c5761510c614611565b6151208161511a8454614ee1565b84614f93565b602080601f83116001811461514e575f841561513c5750858301515b6151468582614fd7565b865550610e4e565b5f85815260208120601f198616915b8281101561517c5788860151825594840194600190910190840161515d565b508582101561519957878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036151d5576151d56151a9565b6001019392505050565b8082028115828204841417610bd857610bd86151a9565b80820180821115610bd857610bd86151a9565b5f60808284031215615219575f80fd5b604051608081016001600160401b03828210818311171561523c5761523c614611565b816040528293508435915080821115615253575f80fd5b5061526085828601614709565b8252506020830135615271816144ea565b60208201526040830135615284816144ea565b60408201526060830135615297816144ea565b6060919091015292915050565b5f60208083850312156152b5575f80fd5b82356001600160401b03808211156152cb575f80fd5b818501915085601f8301126152de575f80fd5b81356152ec61469682614655565b81815260059190911b8301840190848101908883111561530a575f80fd5b8585015b8381101561534057803585811115615324575f80fd5b6153328b89838a0101615209565b84525091860191860161530e565b5098975050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b848110156153ce57601f1986840301895281516080815181865261538e8287018261459d565b838801516001600160a01b03908116888a015260408086015182169089015260609485015116939096019290925250509783019790830190600101615368565b5090979650505050505050565b604080825281018390525f6001600160fb1b038411156153f9575f80fd5b8360051b80866060850137820182810360609081016020850152612c689082018561534d565b5f6020828403121561542f575f80fd5b81356001600160401b03811115615444575f80fd5b610f7184828501615209565b604081525f6154626040830185614a09565b8281036020840152610c5a818561534d565b92835260208301919091526001600160a01b0316604082015260600190565b63ffffffff8181168382160190808211156154b0576154b06151a9565b5092915050565b5f602082840312156154c7575f80fd5b8151610d8d81614ced565b5f602082840312156154e2575f80fd5b5051919050565b5f8235607e198336030181126154fd575f80fd5b9190910192915050565b5f610bd83683615209565b5f805f60608486031215615524575f80fd5b835161552f816144ea565b602085015190935063ffffffff81168114615548575f80fd5b604085015190925061494381614a97565b5f60208284031215615569575f80fd5b8151610d8d816144ea565b9182526001600160a01b0316602082015260400190565b8581525f60018060a01b03808716602084015260a060408401526155b260a084018761459d565b9416606083015250608001529392505050565b60018060a01b0384168152826020820152606060408201525f610c5a606083018461459d565b81810381811115610bd857610bd86151a9565b604081525f615610604083018561459d565b90506001600160401b03831660208301529392505050565b606081525f61563a606083018661459d565b6001600160a01b03949094166020830152506001600160401b0391909116604090910152919050565b634e487b7160e01b5f52600160045260245ffd5b805160208201516001600160e01b031980821692919060048310156141825760049290920360031b82901b161692915050565b5f81518060208401855e5f93019283525090919050565b6001600160801b0319831681525f610f7160108301846156aa565b6001600160a01b0386811682528516602082015260a0604082018190525f9061570790830186614a09565b82810360608401526157198186614a09565b9050828103608084015261572d818561459d565b98975050505050505050565b5f60208284031215615749575f80fd5b8151610d8d81614528565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f906116559083018461459d565b5f610d8d82846156aa565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b604081525f6157d06040830185614a09565b8281036020840152610c5a8185614a0956fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077ba26469706673582212209f360a233e4137d7091a8d1c16ce8080e42a47f5e96ed14890bf221701b0511f64736f6c634300081900338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x60806040526004361061030e575f3560e01c80635d05f04911610197578063a22cb465116100df578063dfa70d8b1161008e578063dfa70d8b14610a86578063e4ae7d7714610aa5578063e985e9c514610ac4578063f23a6e6114610ae3578063f242432a14610b02578063f41a143d14610b21578063f923b68514610b41578063ffeb4a3014610b74575f80fd5b8063a22cb46514610983578063ad3cb1cc146109a2578063bc197c81146109d2578063bc7b6d6214610a0a578063bd242bcb14610a29578063ce156e8214610a48578063d3bf89b114610a67575f80fd5b80637c300586116101465780637c3005861461087f57806380f760211461089e57806385f3e643146108c057806391b3c037146108df5780639b224b1d146108fe5780639dbba19d146109125780639e77193214610945578063a02b161e14610964575f80fd5b80635d05f049146107b05780636352211e146107cf57806363560a8e146107ee5780636e7a21161461080d5780636f3ff726146108225780636f537c7214610841578063781ef8db14610860575f80fd5b806335af62161161025a5780634f1ef286116102095780634f1ef2861461069a57806352d1902d146106ad5780635357263f146106c1578063547c9d2d146106e05780635569f33d146107135780635adf4724146107325780635c1a6b68146107515780635c622a0e14610784575f80fd5b806335af62161461056a5780633634f9111461058957806344c9af28146105bd57806348688f95146105e95780634b2dc431146106085780634b30228c1461063b5780634e1273f41461066e575f80fd5b806318ad9b71116102c157806318ad9b7114610433578063192cf07d146104735780631c3fc3eb146104a65780631e8fca2d146104b95780632eb2c2d6146104d85780632f27fa24146104f9578063319c22bb14610518578063341ec5591461054b575f80fd5b8062fdd58e1461031257806301ffc9a714610344578063072d5d77146103735780630e89341c1461039257806311b8e00a146103be57806313c72608146103dd57806314ff5ea314610414575b5f80fd5b34801561031d575f80fd5b5061033161032c3660046144fe565b610ba7565b6040519081526020015b60405180910390f35b34801561034f575f80fd5b5061036361035e36600461453d565b610bde565b604051901515815260200161033b565b34801561037e575f80fd5b5061036361038d366004614558565b610c38565b34801561039d575f80fd5b506103b16103ac366004614586565b610c63565b60405161033b91906145cb565b3480156103c9575f80fd5b506103636103d83660046145dd565b610d7a565b3480156103e8575f80fd5b506103fc6103f7366004614586565b610d94565b6040516001600160401b03909116815260200161033b565b34801561041f575f80fd5b5061033161042e366004614586565b610db1565b34801561043e575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b60405161033b91906145fd565b34801561047e575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b3480156104b1575f80fd5b506103315f81565b3480156104c4575f80fd5b506103316104d3366004614586565b610dc4565b3480156104e3575f80fd5b506104f76104f2366004614756565b610dd7565b005b348015610504575f80fd5b50610331610513366004614586565b610e56565b348015610523575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610556575f80fd5b506104f7610565366004614558565b610e74565b348015610575575f80fd5b50610466610584366004614839565b610ef8565b348015610594575f80fd5b506105a86105a33660046145dd565b610f79565b6040805192835260208301919091520161033b565b3480156105c8575f80fd5b506105dc6105d7366004614586565b610f99565b60405161033b91906148ab565b3480156105f4575f80fd5b506104f76106033660046148fc565b61105f565b348015610613575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610646575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610679575f80fd5b5061068d61068836600461494e565b6110f4565b60405161033b9190614a43565b6104f76106a8366004614a55565b6111be565b3480156106b8575f80fd5b506103316111dd565b3480156106cc575f80fd5b506104f76106db366004614a55565b6111f8565b3480156106eb575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b34801561071e575f80fd5b506104f761072d366004614aab565b611289565b34801561073d575f80fd5b5061033161074c366004614558565b6113c5565b34801561075c575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b34801561078f575f80fd5b506107a361079e366004614586565b6113f7565b60405161033b9190614ace565b3480156107bb575f80fd5b506104f76107ca366004614b1c565b61142e565b3480156107da575f80fd5b506104666107e9366004614586565b61148c565b3480156107f9575f80fd5b50610466610808366004614839565b6114d8565b348015610818575f80fd5b5061020954610331565b34801561082d575f80fd5b5061036361083c366004614b82565b6114e6565b34801561084c575f80fd5b506103fc61085b366004614839565b6114f5565b34801561086b575f80fd5b5061036361087a366004614558565b611537565b34801561088a575f80fd5b50610363610899366004614b9d565b611560565b3480156108a9575f80fd5b506108b2611574565b60405161033b929190614bc8565b3480156108cb575f80fd5b506103316108da366004614beb565b61161f565b3480156108ea575f80fd5b506103316108f9366004614839565b611660565b348015610909575f80fd5b506103b16116a2565b34801561091d575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610950575f80fd5b506104f761095f366004614c77565b6116b1565b34801561096f575f80fd5b506104f761097e366004614586565b61180a565b34801561098e575f80fd5b506104f761099d366004614cfa565b611914565b3480156109ad575f80fd5b506103b1604051806040016040528060058152602001640352e302e360dc1b81525081565b3480156109dd575f80fd5b506109f16109ec366004614d26565b611926565b6040516001600160e01b0319909116815260200161033b565b348015610a15575f80fd5b506104f7610a24366004614558565b611abe565b348015610a34575f80fd5b50610466610a43366004614586565b611b47565b348015610a53575f80fd5b50610363610a62366004614558565b611b51565b348015610a72575f80fd5b50610363610a81366004614b9d565b611b73565b348015610a91575f80fd5b50610363610aa0366004614b9d565b611bbf565b348015610ab0575f80fd5b50610466610abf366004614839565b611bd3565b348015610acf575f80fd5b50610363610ade366004614ddc565b611c48565b348015610aee575f80fd5b506109f1610afd366004614e08565b611c75565b348015610b0d575f80fd5b506104f7610b1c366004614e7e565b611e65565b348015610b2c575f80fd5b50610363610b3b366004614b82565b50600190565b348015610b4c575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b348015610b7f575f80fd5b506104667f000000000000000000000000000000000000000000000000000000000000000081565b5f826001600160a01b0316610bbb8361148c565b6001600160a01b031614610bcf575f610bd2565b60015b60ff1690505b92915050565b5f636b2f733960e01b6001600160e01b031983161480610c0e575063b0f3d36760e01b6001600160e01b03198316145b80610c29575063f41a143d60e01b6001600160e01b03198316145b80610bd85750610bd882611ed7565b5f8083610c4d8282610c48611efb565b611f04565b610c5a5f86866001611f39565b95945050505050565b610107546060906001600160a01b0316610d06576101068054610c8590614ee1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cb190614ee1565b8015610cfc5780601f10610cd357610100808354040283529160200191610cfc565b820191905f5260205f20905b815481529060010190602001808311610cdf57829003601f168201915b5050505050610bd8565b61010754604051636c55e19b60e01b8152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610d53573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bd89190810190614f4f565b5f610d8d610d8784610dc4565b83612049565b9392505050565b5f610d9e82612060565b600101546001600160401b031692915050565b5f610bd882610dbf84612060565b612079565b5f610bd882610dd284612060565b612097565b5f610de0611efb565b9050806001600160a01b0316866001600160a01b031614158015610e0b5750610e098682611c48565b155b15610e415760405163711bec9160e11b81526001600160a01b038083166004830152871660248201526044015b60405180910390fd5b610e4e86868686866120f0565b505050505050565b5f610bd8610e6383610dc4565b5f9081526003602052604090205490565b5f80610e838462100000612157565b8054600160401b600160e01b031916600160401b6001600160a01b038716021781559092509050610eb2611efb565b6001600160a01b0316836001600160a01b0316837fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a450505050565b5f80610f40610f3b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506121b792505050565b612060565b60018101549091506001600160401b0316421015610f6f578054600160401b90046001600160a01b0316610f71565b5f5b949350505050565b5f80610f8d610f8785610dc4565b846121c2565b915091505b9250929050565b6040805160a0810182525f80825260208201819052918101829052606081018290526080810182905290610fcc83612060565b60018101546001600160401b0316602084018190529091505f610fef8584612079565b6060850181905290506110028584612097565b60808501525f611011826121e5565b6001600160a01b0381166040870152905061102c83826121ff565b8590600281111561103f5761103f614877565b9081600281111561105257611052614877565b8152505050505050919050565b6410000000006110775f82611072611efb565b612235565b610106611085848683614feb565b5061010780546001600160a01b0319166001600160a01b0384161790556110aa611efb565b6001600160a01b03167fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd58585856040516110e69392919061509f565b60405180910390a250505050565b606081518351146111255781518351604051635b05999160e01b815260048101929092526024820152604401610e38565b5f83516001600160401b0381111561113f5761113f614611565b604051908082528060200260200182016040528015611168578160200160208202803683370190505b5090505f5b84518110156111b65760208082028601015161119190602080840287010151610ba7565b8282815181106111a3576111a36150df565b602090810291909101015260010161116d565b509392505050565b6111c6612268565b6111cf8261230e565b6111d982826123ca565b5050565b5f6111e661247d565b505f805160206157e383398151915290565b6101006112085f82611072611efb565b61010480546001600160a01b0319166001600160a01b03851617905561010561123183826150f3565b5061123a611efb565b6001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff48460405161127c91906145cb565b60405180910390a3505050565b5f61129383612060565b90505f6112a08483612079565b90505f6112ab611efb565b60018401549091506001600160401b0316428111611309576001600160401b03811615806112e357506112e16201000083611537565b155b156113045760405163311388dd60e21b815260048101849052602401610e38565b611320565b6113206113168786612097565b6201000084612235565b806001600160401b0316856001600160401b0316101561136657604051633460a12d60e11b81526001600160401b03808316600483015286166024820152604401610e38565b60018401805467ffffffffffffffff19166001600160401b0387169081179091556040516001600160a01b038416919085907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a4505050505050565b5f610d8d6113d284610dc4565b5f9081526002602090815260408083206001600160a01b038716845290915290205490565b5f8061140283612060565b6001810154909150610d8d906001600160401b03166114296114248685612079565b6121e5565b6121ff565b333014611450573360405163d86ad9cf60e01b8152600401610e3891906145fd565b82811461147a57604051635b05999160e01b81526004810184905260248101829052604401610e38565b611486848484846124c6565b50505050565b5f8061149783612060565b90506114a38382612079565b831415806114be575060018101546001600160401b03164210155b6114d0576114cb836121e5565b610d8d565b5f9392505050565b5f610d8d6107e98484611660565b5f610bd8600160781b83611537565b5f610d8d6103f784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506121b792505050565b6001600160a01b03165f9081525f80516020615803833981519152602052604090205481161490565b5f610f7161156d85610dc4565b8484612c2d565b6101045461010580545f926060926001600160a01b0390911691819061159990614ee1565b80601f01602080910402602001604051908101604052809291908181526020018280546115c590614ee1565b80156116105780601f106115e757610100808354040283529160200191611610565b820191905f5260205f20905b8154815290600101906020018083116115f357829003601f168201915b50505050509050915091509091565b5f61162987612c72565b1561164757604051630811f43760e31b815260040160405180910390fd5b611655878787878787612dec565b979650505050505050565b5f610d8d61042e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506121b792505050565b60606116ac612dfd565b905090565b5f6116ba612e97565b805490915060ff600160401b82041615906001600160401b03165f811580156116e05750825b90505f826001600160401b031660011480156116fb5750303b155b905081158015611709575080155b156117275760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561175157845460ff60401b1916600160401b1785555b6102098b905561010480546001600160a01b0319166001600160a01b038c16179055610105611781898b83614feb565b506040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16117b65f87895f611f39565b5083156117fd57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050505050565b5f8061181883611000612157565b91509150611824611efb565b6001600160a01b0316827f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea860405160405180910390a35f611864836121e5565b90506001600160a01b038116156118f25761188181846001612ebf565b815482905f906118969063ffffffff166151bd565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166118d3906151bd565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff1916426001600160401b03161790555050565b6111d961191f611efb565b8383612f13565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146119aa576119aa63d86ad9cf60e01b3360405160240161197391906145fd565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612f9f565b82826119b760e0896151df565b6119c29060406151f6565b808210156119fc576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b1790526119fc90612f9f565b5f611a09868801886152a4565b604051635d05f04960e01b81529091503090635d05f04990611a33908e908e9086906004016153db565b5f604051808303815f87803b158015611a4a575f80fd5b505af1925050508015611a5b575060015b611a9d573d808015611a88576040519150601f19603f3d011682016040523d82523d5f602084013e611a8d565b606091505b50611a9781612f9f565b50611aad565b5063bc197c8160e01b9350611aaf565b505b50505098975050505050505050565b5f80611ace846301000000612157565b600181018054600160401b600160e01b031916600160401b6001600160a01b038816021790559092509050611b01611efb565b6001600160a01b0316836001600160a01b0316837f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a450505050565b5f610bd8826121e5565b5f8083611b668282611b61611efb565b612fb2565b610c5a5f86866001612fe7565b5f610f71611b8085610dc4565b5f9081526002602090815260408083206001600160a01b03871684528252808320545f8051602061580383398151915290925290912054178416841490565b5f610f71611bcc85610dc4565b8484613053565b5f611c1283838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612c7292505050565b611c20576114cb838361308e565b507f000000000000000000000000000000000000000000000000000000000000000092915050565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611cc257611cc263d86ad9cf60e01b3360405160240161197391906145fd565b828260e080821015611d00576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b179052611d0090612f9f565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f19909201910181611d3857905050905089825f81518110611d8057611d806150df565b6020908102919091010152611d978789018961541f565b815f81518110611da957611da96150df565b6020908102919091010152604051635d05f04960e01b81523090635d05f04990611dd99085908590600401615450565b5f604051808303815f87803b158015611df0575f80fd5b505af1925050508015611e01575060015b611e43573d808015611e2e576040519150601f19603f3d011682016040523d82523d5f602084013e611e33565b606091505b50611e3d81612f9f565b50611e55565b5063f23a6e6160e01b9450611e589050565b50505b5050509695505050505050565b5f611e6e611efb565b9050806001600160a01b0316866001600160a01b031614158015611e995750611e978682611c48565b155b15611eca5760405163711bec9160e11b81526001600160a01b03808316600483015287166024820152604401610e38565b610e4e8686868686613103565b5f6001600160e01b03198216630271189760e51b1480610bd85750610bd882613172565b5f6116ac613238565b5f611f0f8483613315565b905080198316156114865783838360405163d1a3b35560e01b8152600401610e3893929190615474565b5f835f03611f4857505f610f71565b611f5184613361565b6001600160a01b038316611f785760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461203d575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616611fd8888260016133a8565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561203157612031888785858b61348f565b60019350505050610f71565b505f9695505050505050565b5f806120558484610f79565b501515949350505050565b63ffffffff8116185f9081526101086020526040902090565b80545f9063ffffffff80851685186401000000009092041618610d8d565b5f826120a4575081610bd8565b6001820154610d8d9084906001600160401b03164210156120cc57835463ffffffff166120df565b83546120df9063ffffffff166001615493565b63ffffffff82811690921891161890565b6001600160a01b038416612119575f604051632bfa23e760e11b8152600401610e3891906145fd565b6001600160a01b038516612141575f604051626a0d4560e21b8152600401610e3891906145fd565b61215085858585856001613498565b5050505050565b5f8061216284612060565b905061216e8482612079565b60018201549092506001600160401b031642106121a15760405163311388dd60e21b815260048101839052602401610e38565b610f926121ae8583612097565b84611072611efb565b805160209091012090565b5f806121cd836134fa565b5f948552600360205260409094205484169492505050565b5f908152602081905260409020546001600160a01b031690565b5f6001600160401b038316421061221757505f610bd8565b6001600160a01b03821661222d57506001610bd8565b506002610bd8565b612240838383611b73565b61226357828282604051634b27a13360e01b8152600401610e3893929190615474565b505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806122ee57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166122e25f805160206157e3833981519152546001600160a01b031690565b6001600160a01b031614155b1561230c5760405163703e46dd60e11b815260040160405180910390fd5b565b6001607c1b6123205f82611072611efb565b604051634b5bc65f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906396b78cbe9061236c9085906004016145fd565b602060405180830381865afa158015612387573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123ab91906154b7565b6111d95781604051630f74d7dd60e41b8152600401610e3891906145fd565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612424575060408051601f3d908101601f19168201909252612421918101906154d2565b60015b6124435781604051634c9c8ce360e01b8152600401610e3891906145fd565b5f805160206157e3833981519152811461247357604051632a87526960e21b815260048101829052602401610e38565b6122638383613514565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461230c5760405163703e46dd60e11b815260040160405180910390fd5b6102095430905f5b85811015612c24575f8585838181106124e9576124e96150df565b90506020028101906124fb91906154e9565b61250490615507565b60208101519091506001600160a01b0316612532576040516349e27cff60e01b815260040160405180910390fd5b5f888884818110612545576125456150df565b8451805160209182012091029290920135925061256d905085825f9182526020526040902090565b821461258f5760405163edec356960e01b815260048101839052602401610e38565b6060830151604051630178fe3f60e01b8152600481018490525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156125fb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261f9190615512565b925092505061263082600116151590565b15612aa45760408216158015906126d7575060405163020604bf60e21b8152600481018690525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063081812fc90602401602060405180830381865afa1580156126a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126cb9190615559565b6001600160a01b031614155b156126f85760405163a4f0771360e01b815260048101869052602401610e38565b600882165f0361278257604051630c4b7b8560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631896f70a906127509088905f90600401615574565b5f604051808303815f87803b158015612767575f80fd5b505af1158015612779573d5f803e3d5ffd5b505050506128c0565b604051630178b8bf60e01b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178b8bf90602401602060405180830381865afa1580156127e5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128099190615559565b604051630d76f7ed60e11b81529093506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631aedefda906128589086906004016145fd565b602060405180830381865afa158015612873573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061289791906154b7565b156128c0577f000000000000000000000000000000000000000000000000000000000000000092505b604051637921219560e11b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526001606483015260a060848301525f60a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c4015f604051808303815f87803b158015612961575f80fd5b505af1158015612973573d5f803e3d5ffd5b505050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d84121a7f0000000000000000000000000000000000000000000000000000000000000000885f1c898e8c5f01518d602001516129df8b613569565b6040516024016129f395949392919061558b565b60408051601f198184030181529181526020820180516001600160e01b0316634f3b8c9960e11b179052516001600160e01b031960e086901b168152612a3e939291906004016155c5565b6020604051808303815f875af1158015612a5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a7e9190615559565b9050612a9d875f015188602001518387612a97886135a0565b876135e7565b5050612c13565b6201000062030000831603612bf757604051630c4b7b8560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631896f70a90612b019088905f90600401615574565b5f604051808303815f87803b158015612b18575f80fd5b505af1158015612b2a573d5f803e3d5ffd5b5050604051636c64c90d60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063d8c9921a9150612b9e908b9088907f000000000000000000000000000000000000000000000000000000000000000090600401615474565b5f604051808303815f87803b158015612bb5575f80fd5b505af1158015612bc7573d5f803e3d5ffd5b50508751602089015160408a0151612bf194509192509086630110000061011160941b01866135e7565b50612c13565b604051630dff478560e11b815260048101869052602401610e38565b5050505050508060010190506124ce565b50505050505050565b5f8383612c3d8282610c48611efb565b85612c5b57604051631850848b60e31b815260040160405180910390fd5b612c688686866001611f39565b9695505050505050565b805160208201205f905f612c8582610d94565b6001600160401b03161115612c9c57505f92915050565b610209545f908152602082905260408120604051630178fe3f60e01b8152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015612d15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d399190615512565b5091505062010000620300008216148015610c5a57506040516302571be360e01b8152600481018390525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015612db4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dd89190615559565b6001600160a01b0316141595945050505050565b5f61165587878787878760016135f3565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166320c38e2b612e386102095490565b6040518263ffffffff1660e01b8152600401612e5691815260200190565b5f60405180830381865afa158015612e70573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526116ac9190810190614f4f565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610bd8565b6001600160a01b038316612ee7575f604051626a0d4560e21b8152600401610e3891906145fd565b5f80612ef38484613a9b565b91509150612150855f848460405180602001604052805f8152505f613498565b6001600160a01b038216612f3b575f60405162ced3e160e81b8152600401610e3891906145fd565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910161127c565b612fa881613ac3565b9050805160208201fd5b5f612fbd8483613b7d565b90508019831615611486578383836040516314c09c6360e31b8152600401610e3893929190615474565b5f612ff184613361565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461203d575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690611fd890899083906133a8565b5f83836130638282611b61611efb565b8561308157604051631850848b60e31b815260040160405180910390fd5b612c688686866001612fe7565b5f806130d1610f3b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506121b792505050565b60018101549091506001600160401b0316421015610f6f576001810154600160401b90046001600160a01b0316610f71565b6001600160a01b03841661312c575f604051632bfa23e760e11b8152600401610e3891906145fd565b6001600160a01b038516613154575f604051626a0d4560e21b8152600401610e3891906145fd565b5f806131608585613a9b565b91509150612c2487878484875f613498565b5f6001600160e01b0319821663afff3a6360e01b14806131a257506001600160e01b03198216632e112adb60e21b145b806131bd57506001600160e01b031982166391b3c03760e01b145b806131d857506001600160e01b031982166337a9be3960e11b145b806131f357506001600160e01b031982166331ab054760e11b145b8061320e57506001600160e01b03198216630147d9fd60e61b145b8061322957506001600160e01b0319821663379ffb9360e11b145b80610bd85750610bd882613bba565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661326c57503390565b60405163110ac5cb60e21b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063442b172c906132ba9033906004016145fd565b602060405180830381865afa1580156132d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132f99190615559565b90506001600160a01b038116613310573391505090565b919050565b5f806133218484613bde565b90508361332f579050610bd8565b5f6133406107e986610dbf81612060565b6001600160a01b031603613357575f915050610bd8565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156133a557604051630153d96960e51b815260048101829052602401610e38565b50565b5f6133b2836134fa565b90508115613424575f848152600360205260409020546133d490821619613c2d565b156133fc57604051631f22ca6960e31b81526004810185905260248101849052604401610e38565b5f84815260036020526040812080548592906134199084906151f6565b909155506114869050565b5f8481526003602052604090205461343f9019821619613c2d565b1561346757604051631f80c19b60e01b81526004810185905260248101849052604401610e38565b5f84815260036020526040812080548592906134849084906155eb565b909155505050505050565b61215085613c7c565b6134a486868686613d45565b6001600160a01b03851615610e4e575f6134bc611efb565b905081156134d7576134d2818888888888613e0c565b612c24565b602085810151908501516134ef838a8a85858a613f1b565b505050505050505050565b5f61350482613361565b50600181901b17600281901b1790565b61351d82613ff9565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115613561576122638282614053565b6111d96140bc565b5f602082168103613578576001175b6002821661358757608081901b175b62010000630100001160781b01601160f81b0117919050565b5f620400008216156135b25762010000175b600882165f036135c3576301000000175b600282166135d257608081901b175b600482165f03613310576001609c1b17919050565b5f6116558787878787875f5b60405163bf53096960e01b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990613641908b906004016145cb565b5f604051808303815f87803b158015613658575f80fd5b505af115801561366a573d5f803e3d5ffd5b5050895160208b012091505f905061368182612060565b905061368d8282612079565b92505f613699846121e5565b90505f6136a4611efb565b60018401549091506001600160401b0316421061370c5785156136cd576136cd5f600183612235565b6001600160a01b038b161580156136e357508715155b15613707575f888260405163d1a3b35560e01b8152600401610e3893929190615474565b61379d565b6001600160a01b03821615613736578b6040516337bd516960e21b8152600401610e3891906145cb565b6001600160a01b038b1661375f578b6040516307b03acf60e51b8152600401610e3891906145cb565b8515613771576137715f601083612235565b866001600160401b03165f036137925760018301546001600160401b031696505b640100000000881797505b6001600160a01b038b16156137be576001600160401b0387164210156137ca565b6001600160401b038716155b156137f35760405163f1d446c360e01b81526001600160401b0388166004820152602401610e38565b6001600160a01b0382161561388b5761380e82866001612ebf565b825483905f906138239063ffffffff166151bd565b91906101000a81548163ffffffff021916908363ffffffff160217905550825f01600481819054906101000a900463ffffffff16613860906151bd565b91906101000a81548163ffffffff021916908363ffffffff1602179055506138888584612079565b94505b60018301805484546001600160a01b03808e16600160401b908102600160401b600160e01b03199093169290921787558c81169091026001600160e01b03199092166001600160401b038b1617919091179091558b1661393157806001600160a01b0316845f1b867f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88f8b6040516139249291906155fe565b60405180910390a46139ea565b806001600160a01b0316845f1b867f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8f8f8c60405161397293929190615628565b60405180910390a46139958b86600160405180602001604052805f8152506140db565b5f6139a08685612097565b9050806139af576139af615663565b604051819087907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a36139e7818a8e5f611f39565b50505b6001600160a01b038a1615613a3b57806001600160a01b03168a6001600160a01b0316867fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a1054060405160405180910390a45b6001600160a01b03891615613a8c57806001600160a01b0316896001600160a01b0316867f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d560405160405180910390a45b50505050979650505050505050565b6040805160018082526020820194909452808201938452606081019290925260808201905291565b60605f8251118015613aed575062461bcd60e51b613ae083615677565b6001600160e01b03191614155b15613b795762461bcd60e51b6f0aee4c2e0e0cac88ae4e4dee4747460f60831b613b1684614122565b604051602001613b279291906156c1565b60408051601f1981840301815290829052613b44916024016145cb565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b5f8215801590613ba457505f613b996107e985610dbf81612060565b6001600160a01b0316145b15613bb057505f610bd8565b610d8d8383613bde565b5f6001600160e01b031982166347a296b160e11b1480610bd85750610bd88261418a565b6001600160a01b03165f8181525f80516020615803833981519152602090815260408083205494835260028252808320938352929052205417608081901c6001600160801b0319919091161790565b80197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef91909101167f888888888888888888888888888888888888888888888888888888888888888816151590565b80156133a5575f613c8c82612060565b90505f613c998383612079565b90505f613ca5826121e5565b9050613cb381836001612ebf565b82548390600490613cd190640100000000900463ffffffff166151bd565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f613cfa8385612079565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a36121508282600160405180602001604052805f8152506140db565b613d51848484846141f4565b6001600160a01b03831615801590613d7157506001600160a01b03841615155b15611486575f5b8251811015612150575f838281518110613d9457613d946150df565b60200260200101519050613dad816001609c1b88611b73565b613dce5780866040516372c7b6ad60e11b8152600401610e38929190615574565b5f838381518110613de157613de16150df565b60200260200101511115613e0357613e03613dfb82610dc4565b87875f6143cf565b50600101613d78565b6001600160a01b0384163b15610e4e5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613e5090899089908890889088906004016156dc565b6020604051808303815f875af1925050508015613e8a575060408051601f3d908101601f19168201909252613e8791810190615739565b60015b613ee8573d808015613eb7576040519150601f19603f3d011682016040523d82523d5f602084013e613ebc565b606091505b5080515f03613ee05784604051632bfa23e760e11b8152600401610e3891906145fd565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b14612c245784604051632bfa23e760e11b8152600401610e3891906145fd565b6001600160a01b0384163b15610e4e5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613f5f9089908990889088908890600401615754565b6020604051808303815f875af1925050508015613f99575060408051601f3d908101601f19168201909252613f9691810190615739565b60015b613fc6573d808015613eb7576040519150601f19603f3d011682016040523d82523d5f602084013e613ebc565b6001600160e01b0319811663f23a6e6160e01b14612c245784604051632bfa23e760e11b8152600401610e3891906145fd565b806001600160a01b03163b5f036140255780604051634c9c8ce360e01b8152600401610e3891906145fd565b5f805160206157e383398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161406f919061578d565b5f60405180830381855af49150503d805f81146140a7576040519150601f19603f3d011682016040523d82523d5f602084013e6140ac565b606091505b5091509150610c5a858383614410565b341561230c5760405163b398979f60e01b815260040160405180910390fd5b6001600160a01b038416614104575f604051632bfa23e760e11b8152600401610e3891906145fd565b5f806141108585613a9b565b91509150610e4e5f878484875f613498565b805160609060011b806001600160401b0381111561414257614142614611565b6040519080825280601f01601f19166020018201604052801561416c576020820181803683370190505b509150602083810190830161418282828561445e565b505050919050565b5f6001600160e01b03198216636cdb3d1360e11b14806141ba57506001600160e01b031982166331a9108f60e11b145b806141d557506001600160e01b031982166303a24d0760e21b145b80610bd857506301ffc9a760e01b6001600160e01b0319831614610bd8565b80518251146142235781518151604051635b05999160e01b815260048101929092526024820152604401610e38565b5f61422c611efb565b90505f5b83518110156142f15760208181028581018201519085019091015180156142e7575f828152602081905260409020546001600160a01b03908116908916811461429457885f83856040516303dee4c560e01b8152600401610e389493929190615798565b60018211156142bf5788600183856040516303dee4c560e01b8152600401610e389493929190615798565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0389161790555b5050600101614230565b5082516001036143715760208301515f906020840151909150856001600160a01b0316876001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628585604051614362929190918252602082015260400190565b60405180910390a45050612150565b836001600160a01b0316856001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb86866040516143c09291906157be565b60405180910390a45050505050565b5f8481526002602090815260408083206001600160a01b038716845290915290205480156121505761440385828685612fe7565b50610e4e85828585611f39565b606082614420576114cb826144c1565b815115801561443757506001600160a01b0384163b155b156144575783604051639996b31560e01b8152600401610e3891906145fd565b5080610d8d565b8181015b808310156114865783516101005b828510801561447e57505f81115b156144b45760031901600f82821c16600a811061449e57806057016144a3565b806030015b905080865350600190940193614470565b5050602084019350614462565b8051156144d15780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b6001600160a01b03811681146133a5575f80fd5b5f806040838503121561450f575f80fd5b823561451a816144ea565b946020939093013593505050565b6001600160e01b0319811681146133a5575f80fd5b5f6020828403121561454d575f80fd5b8135610d8d81614528565b5f8060408385031215614569575f80fd5b82359150602083013561457b816144ea565b809150509250929050565b5f60208284031215614596575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610d8d602083018461459d565b5f80604083850312156145ee575f80fd5b50508035926020909101359150565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561464d5761464d614611565b604052919050565b5f6001600160401b0382111561466d5761466d614611565b5060051b60200190565b5f82601f830112614686575f80fd5b8135602061469b61469683614655565b614625565b8083825260208201915060208460051b8701019350868411156146bc575f80fd5b602086015b848110156146d857803583529183019183016146c1565b509695505050505050565b5f6001600160401b038211156146fb576146fb614611565b50601f01601f191660200190565b5f82601f830112614718575f80fd5b8135614726614696826146e3565b81815284602083860101111561473a575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a0868803121561476a575f80fd5b8535614775816144ea565b94506020860135614785816144ea565b935060408601356001600160401b03808211156147a0575f80fd5b6147ac89838a01614677565b945060608801359150808211156147c1575f80fd5b6147cd89838a01614677565b935060808801359150808211156147e2575f80fd5b506147ef88828901614709565b9150509295509295909350565b5f8083601f84011261480c575f80fd5b5081356001600160401b03811115614822575f80fd5b602083019150836020828501011115610f92575f80fd5b5f806020838503121561484a575f80fd5b82356001600160401b0381111561485f575f80fd5b61486b858286016147fc565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600381106148a757634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506148bd82845161488b565b6001600160401b03602084015116602083015260018060a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f6040848603121561490e575f80fd5b83356001600160401b03811115614923575f80fd5b61492f868287016147fc565b9094509250506020840135614943816144ea565b809150509250925092565b5f806040838503121561495f575f80fd5b82356001600160401b0380821115614975575f80fd5b818501915085601f830112614988575f80fd5b8135602061499861469683614655565b82815260059290921b840181019181810190898411156149b6575f80fd5b948201945b838610156149dd5785356149ce816144ea565b825294820194908201906149bb565b965050860135925050808211156149f2575f80fd5b506149ff85828601614677565b9150509250929050565b5f815180845260208085019450602084015f5b83811015614a3857815187529582019590820190600101614a1c565b509495945050505050565b602081525f610d8d6020830184614a09565b5f8060408385031215614a66575f80fd5b8235614a71816144ea565b915060208301356001600160401b03811115614a8b575f80fd5b6149ff85828601614709565b6001600160401b03811681146133a5575f80fd5b5f8060408385031215614abc575f80fd5b82359150602083013561457b81614a97565b60208101610bd8828461488b565b5f8083601f840112614aec575f80fd5b5081356001600160401b03811115614b02575f80fd5b6020830191508360208260051b8501011115610f92575f80fd5b5f805f8060408587031215614b2f575f80fd5b84356001600160401b0380821115614b45575f80fd5b614b5188838901614adc565b90965094506020870135915080821115614b69575f80fd5b50614b7687828801614adc565b95989497509550505050565b5f60208284031215614b92575f80fd5b8135610d8d816144ea565b5f805f60608486031215614baf575f80fd5b83359250602084013591506040840135614943816144ea565b6001600160a01b03831681526040602082018190525f90610f719083018461459d565b5f805f805f8060c08789031215614c00575f80fd5b86356001600160401b03811115614c15575f80fd5b614c2189828a01614709565b9650506020870135614c32816144ea565b94506040870135614c42816144ea565b93506060870135614c52816144ea565b92506080870135915060a0870135614c6981614a97565b809150509295509295509295565b5f805f805f8060a08789031215614c8c575f80fd5b863595506020870135614c9e816144ea565b945060408701356001600160401b03811115614cb8575f80fd5b614cc489828a016147fc565b9095509350506060870135614cd8816144ea565b80925050608087013590509295509295509295565b80151581146133a5575f80fd5b5f8060408385031215614d0b575f80fd5b8235614d16816144ea565b9150602083013561457b81614ced565b5f805f805f805f8060a0898b031215614d3d575f80fd5b8835614d48816144ea565b97506020890135614d58816144ea565b965060408901356001600160401b0380821115614d73575f80fd5b614d7f8c838d01614adc565b909850965060608b0135915080821115614d97575f80fd5b614da38c838d01614adc565b909650945060808b0135915080821115614dbb575f80fd5b50614dc88b828c016147fc565b999c989b5096995094979396929594505050565b5f8060408385031215614ded575f80fd5b8235614df8816144ea565b9150602083013561457b816144ea565b5f805f805f8060a08789031215614e1d575f80fd5b8635614e28816144ea565b95506020870135614e38816144ea565b9450604087013593506060870135925060808701356001600160401b03811115614e60575f80fd5b614e6c89828a016147fc565b979a9699509497509295939492505050565b5f805f805f60a08688031215614e92575f80fd5b8535614e9d816144ea565b94506020860135614ead816144ea565b9350604086013592506060860135915060808601356001600160401b03811115614ed5575f80fd5b6147ef88828901614709565b600181811c90821680614ef557607f821691505b602082108103614f1357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f614f26614696846146e3565b9050828152838383011115614f39575f80fd5b8282602083015e5f602084830101529392505050565b5f60208284031215614f5f575f80fd5b81516001600160401b03811115614f74575f80fd5b8201601f81018413614f84575f80fd5b610f7184825160208401614f19565b601f82111561226357805f5260205f20601f840160051c81016020851015614fb85750805b601f840160051c820191505b81811015612150575f8155600101614fc4565b5f19600383901b1c191660019190911b1790565b6001600160401b0383111561500257615002614611565b615016836150108354614ee1565b83614f93565b5f601f841160018114615042575f85156150305750838201355b61503a8682614fd7565b845550612150565b5f83815260208120601f198716915b828110156150715786850135825560209485019460019092019101615051565b508682101561508d575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f60608483018101919091526001600160a01b03929092166020820152601f909201601f191690910101919050565b634e487b7160e01b5f52603260045260245ffd5b81516001600160401b0381111561510c5761510c614611565b6151208161511a8454614ee1565b84614f93565b602080601f83116001811461514e575f841561513c5750858301515b6151468582614fd7565b865550610e4e565b5f85815260208120601f198616915b8281101561517c5788860151825594840194600190910190840161515d565b508582101561519957878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036151d5576151d56151a9565b6001019392505050565b8082028115828204841417610bd857610bd86151a9565b80820180821115610bd857610bd86151a9565b5f60808284031215615219575f80fd5b604051608081016001600160401b03828210818311171561523c5761523c614611565b816040528293508435915080821115615253575f80fd5b5061526085828601614709565b8252506020830135615271816144ea565b60208201526040830135615284816144ea565b60408201526060830135615297816144ea565b6060919091015292915050565b5f60208083850312156152b5575f80fd5b82356001600160401b03808211156152cb575f80fd5b818501915085601f8301126152de575f80fd5b81356152ec61469682614655565b81815260059190911b8301840190848101908883111561530a575f80fd5b8585015b8381101561534057803585811115615324575f80fd5b6153328b89838a0101615209565b84525091860191860161530e565b5098975050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b848110156153ce57601f1986840301895281516080815181865261538e8287018261459d565b838801516001600160a01b03908116888a015260408086015182169089015260609485015116939096019290925250509783019790830190600101615368565b5090979650505050505050565b604080825281018390525f6001600160fb1b038411156153f9575f80fd5b8360051b80866060850137820182810360609081016020850152612c689082018561534d565b5f6020828403121561542f575f80fd5b81356001600160401b03811115615444575f80fd5b610f7184828501615209565b604081525f6154626040830185614a09565b8281036020840152610c5a818561534d565b92835260208301919091526001600160a01b0316604082015260600190565b63ffffffff8181168382160190808211156154b0576154b06151a9565b5092915050565b5f602082840312156154c7575f80fd5b8151610d8d81614ced565b5f602082840312156154e2575f80fd5b5051919050565b5f8235607e198336030181126154fd575f80fd5b9190910192915050565b5f610bd83683615209565b5f805f60608486031215615524575f80fd5b835161552f816144ea565b602085015190935063ffffffff81168114615548575f80fd5b604085015190925061494381614a97565b5f60208284031215615569575f80fd5b8151610d8d816144ea565b9182526001600160a01b0316602082015260400190565b8581525f60018060a01b03808716602084015260a060408401526155b260a084018761459d565b9416606083015250608001529392505050565b60018060a01b0384168152826020820152606060408201525f610c5a606083018461459d565b81810381811115610bd857610bd86151a9565b604081525f615610604083018561459d565b90506001600160401b03831660208301529392505050565b606081525f61563a606083018661459d565b6001600160a01b03949094166020830152506001600160401b0391909116604090910152919050565b634e487b7160e01b5f52600160045260245ffd5b805160208201516001600160e01b031980821692919060048310156141825760049290920360031b82901b161692915050565b5f81518060208401855e5f93019283525090919050565b6001600160801b0319831681525f610f7160108301846156aa565b6001600160a01b0386811682528516602082015260a0604082018190525f9061570790830186614a09565b82810360608401526157198186614a09565b9050828103608084015261572d818561459d565b98975050505050505050565b5f60208284031215615749575f80fd5b8151610d8d81614528565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f906116559083018461459d565b5f610d8d82846156aa565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b604081525f6157d06040830185614a09565b8281036020840152610c5a8185614a0956fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077ba26469706673582212209f360a233e4137d7091a8d1c16ce8080e42a47f5e96ed14890bf221701b0511f64736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "2865": [ + { + "length": 32, + "start": 8819 + }, + { + "length": 32, + "start": 8860 + }, + { + "length": 32, + "start": 9352 + } + ], + "11973": [ + { + "length": 32, + "start": 1321 + }, + { + "length": 32, + "start": 12859 + }, + { + "length": 32, + "start": 12933 + } + ], + "12068": [ + { + "length": 32, + "start": 1156 + }, + { + "length": 32, + "start": 6450 + }, + { + "length": 32, + "start": 7297 + }, + { + "length": 32, + "start": 9646 + }, + { + "length": 32, + "start": 9826 + }, + { + "length": 32, + "start": 10009 + }, + { + "length": 32, + "start": 10528 + }, + { + "length": 32, + "start": 10954 + }, + { + "length": 32, + "start": 11075 + }, + { + "length": 32, + "start": 11464 + }, + { + "length": 32, + "start": 11777 + } + ], + "12071": [ + { + "length": 32, + "start": 1890 + }, + { + "length": 32, + "start": 10461 + }, + { + "length": 32, + "start": 11126 + } + ], + "12075": [ + { + "length": 32, + "start": 10136 + }, + { + "length": 32, + "start": 11631 + } + ], + "12428": [ + { + "length": 32, + "start": 1092 + }, + { + "length": 32, + "start": 10618 + } + ], + "12431": [ + { + "length": 32, + "start": 1777 + }, + { + "length": 32, + "start": 10665 + } + ], + "12435": [ + { + "length": 32, + "start": 2898 + }, + { + "length": 32, + "start": 10275 + } + ], + "12438": [ + { + "length": 32, + "start": 2949 + }, + { + "length": 32, + "start": 10398 + } + ], + "14420": [ + { + "length": 32, + "start": 2339 + }, + { + "length": 32, + "start": 13836 + } + ], + "16197": [ + { + "length": 32, + "start": 1612 + }, + { + "length": 32, + "start": 7203 + } + ], + "16201": [ + { + "length": 32, + "start": 1561 + }, + { + "length": 32, + "start": 9015 + } + ] + }, + "inputSourceName": "project/src/registry/WrapperRegistry.sol", + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "CannotReduceExpiry(uint64,uint64)": [ + { + "details": "Error selector: `0x68c1425a`" + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "details": "Error selector: `0xf1d446c3`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1155InsufficientBalance(address,uint256,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred.", + "tokenId": "Identifier number of a token." + } + } + ], + "ERC1155InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "ERC1155InvalidOperator(address)": [ + { + "details": "Indicates a failure with the `operator` to be approved. Used in approvals.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC1155InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC1155InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC1155MissingApprovalForAll(address,address)": [ + { + "details": "Indicates a failure with the `operator`’s approval. Used in transfers.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner.", + "owner": "Address of the current owner of a token." + } + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "FrozenTokenApproval(uint256)": [ + { + "details": "Error selector: `0xa4f07713`" + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "LabelAlreadyRegistered(string)": [ + { + "details": "Error selector: `0xdef545a4`" + } + ], + "LabelAlreadyReserved(string)": [ + { + "details": "Error selector: `0xf60759e0`" + } + ], + "LabelExpired(uint256)": [ + { + "details": "Error selector: `0xc44e2374`" + } + ], + "NameDataMismatch(uint256)": [ + { + "details": "Error selector: `0xedec3569`" + } + ], + "NameNotLocked(uint256)": [ + { + "details": "Error selector: `0x1bfe8f0a`" + } + ], + "NameRequiresMigration()": [ + { + "details": "Error selector: `0x408fa1b8`" + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "details": "Error selector: `0xe58f6d5a`" + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ], + "UnauthorizedCaller(address)": [ + { + "details": "Error selector: `0xd86ad9cf`", + "params": { + "caller": "The address that attempted the unauthorized operation" + } + } + ], + "UpgradeTargetNotApproved(address)": [ + { + "details": "Error selector: `0xf74d7dd0`", + "params": { + "implementation": "The disallowed implementation address." + } + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "ExpiryUpdated(uint256,uint64,address)": { + "params": { + "newExpiry": "The new expiry of the label.", + "sender": "The sender of the call to update the expiry.", + "tokenId": "The token ID of the label." + } + }, + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label registered.", + "labelHash": "The label hash registered.", + "owner": "The owner of the label.", + "sender": "The sender of the call to register.", + "tokenId": "The token ID registered." + } + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label reserved.", + "labelHash": "The label hash reserved.", + "sender": "The sender of the call to reserve.", + "tokenId": "The token ID reserved." + } + }, + "LabelUnregistered(uint256,address)": { + "params": { + "sender": "The sender of the call to unregister.", + "tokenId": "The token ID unregistered." + } + }, + "ParentUpdated(address,string,address)": { + "params": { + "label": "The new label.", + "parent": "The new parent.", + "sender": "The sender of the call to update the parent." + } + }, + "ResolverUpdated(uint256,address,address)": { + "params": { + "resolver": "The new resolver.", + "sender": "The sender of the call to update the resolver.", + "tokenId": "The token ID of the label." + } + }, + "SubregistryUpdated(uint256,address,address)": { + "params": { + "sender": "The sender of the call to update the subregistry.", + "subregistry": "The new subregistry.", + "tokenId": "The token ID of the label." + } + }, + "TokenRegenerated(uint256,uint256)": { + "params": { + "newTokenId": "The new token ID.", + "oldTokenId": "The old token ID." + } + }, + "TokenResource(uint256,uint256)": { + "params": { + "resource": "The EAC resource.", + "tokenId": "The token ID." + } + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + }, + "URIUpdated(string,address,address)": { + "params": { + "renderer": "The new render address.", + "sender": "The sender of the call to update the URI.", + "uri": "The new URI." + } + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "balanceOf(address,uint256)": { + "params": { + "account": "The account to get the balance for.", + "id": "The token ID." + }, + "returns": { + "_0": "balance The balance of the token for the account. This will only ever be 1 or 0." + } + }, + "balanceOfBatch(address[],uint256[])": { + "details": "`accounts` and `ids` must have the same length.", + "params": { + "accounts": "The accounts to get the balances for.", + "ids": "The token IDs." + }, + "returns": { + "_0": "batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0." + } + }, + "canUpgradeFrom(address)": { + "details": "Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call, including the wrapper upgrade target allowlist.", + "params": { + "": "{previousImplementation} Ignored." + }, + "returns": { + "allowed": "Always `true` for implementations in this wrapper registry family." + } + }, + "constructor": { + "params": { + "ensV1Resolver": "The ENSv1 resolver.", + "graveyard": "The ENSv1 `BaseRegistrar` token graveyard.", + "hcaFactory": "The HCA factory.", + "labelStore": "The shared label database.", + "nameWrapper": "The ENSv1 NameWrapper.", + "namer": "The implementation namer.", + "publicResolver": "The replacement `PublicResolver`.", + "publicResolverSet": "The approved list of `PublicResolver` contracts.", + "upgradeGate": "The upgrade target allowlist.", + "verifiableFactory": "The VerifiableFactory." + } + }, + "findExpiry(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The expiry of the label." + } + }, + "findOwner(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The owner of the label." + } + }, + "findTokenId(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The token ID of the label." + } + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "details": "Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts", + "params": { + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated.", + "mds": "The migration parameters for each name, indexed in parallel with `ids`." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getExpiry(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The expiry of the label, in seconds." + } + }, + "getParent()": { + "returns": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "getResolver(string)": { + "details": "Return `V1_RESOLVER` upon visiting migratable children.", + "params": { + "label": "The label to fetch a resolver for." + }, + "returns": { + "_0": "resolver The address of a resolver responsible for this label, or `address(0)` if none exists." + } + }, + "getResource(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The resource." + } + }, + "getState(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "state": "The state of the label." + } + }, + "getStatus(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The status of the label." + } + }, + "getSubregistry(string)": { + "params": { + "label": "The label to resolve." + }, + "returns": { + "_0": "The address of the registry for this label, or `address(0)` if none exists." + } + }, + "getTokenId(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token ID." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "initialize(bytes32,address,string,address,uint256)": { + "params": { + "childLabel": "The subdomain for this registry.", + "node": "Namehash of this registry.", + "parentRegistry": "The parent of this registry.", + "roleBitmap": "The role bitmap granted to `rootAccount`.", + "rootAccount": "Account granted root roles." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "account": "The account to get the approval for.", + "operator": "The operator to get the approval for." + }, + "returns": { + "_0": "approved The approval status." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "latestOwnerOf(uint256)": { + "params": { + "tokenId": "The token ID to query." + }, + "returns": { + "_0": "The latest owner address." + } + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.", + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed" + } + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data` struct containing migration parameters.", + "id": "The NameWrapper token ID (namehash) of the name being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed" + } + }, + "ownerOf(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The owner of the token." + } + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "register(string,address,address,address,uint256,uint64)": { + "details": "Blocks registration of emancipated children.", + "params": { + "expiry": "The expiry of the label, in seconds.", + "label": "The label to register.", + "owner": "The address of the owner of the label.", + "registry": "The registry to set as the label.", + "resolver": "The resolver to set for the label.", + "roleBitmap": "The role bitmap to set for the label." + }, + "returns": { + "tokenId": "The token ID." + } + }, + "renew(uint256,uint64)": { + "details": "If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.", + "params": { + "anyId": "The labelhash, token ID, or resource.", + "newExpiry": "The new expiry, in seconds." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the tokens from.", + "ids": "The token IDs.", + "to": "The address to transfer the tokens to.", + "values": "The amounts of tokens to transfer." + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the token from.", + "id": "The token ID.", + "to": "The address to transfer the token to.", + "value": "The amount of tokens to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "The approval status.", + "operator": "The operator to set the approval for." + } + }, + "setParent(address,string)": { + "details": "Should emit `ParentUpdated`.", + "params": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "setResolver(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "resolver": "The new resolver." + } + }, + "setSubregistry(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "registry": "The new registry." + } + }, + "setURI(string,address)": { + "params": { + "renderer": "The new renderer address.", + "uri_": "The new URI." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "unregister(uint256)": { + "details": "Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.", + "params": { + "anyId": "The labelhash, token ID, or resource." + } + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "uri(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The URI for the token." + } + } + }, + "stateVariables": { + "_node": { + "details": "The namehash of this registry." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "4523200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "GRAVEYARD()": "infinite", + "HCA_FACTORY()": "infinite", + "LABEL_STORE()": "infinite", + "NAME_WRAPPER()": "infinite", + "PUBLIC_RESOLVER()": "infinite", + "PUBLIC_RESOLVER_SET()": "infinite", + "ROOT_RESOURCE()": "272", + "UPGRADE_GATE()": "infinite", + "UPGRADE_INTERFACE_VERSION()": "infinite", + "V1_RESOLVER()": "infinite", + "VERIFIABLE_FACTORY()": "infinite", + "WRAPPER_REGISTRY_IMPL()": "infinite", + "balanceOf(address,uint256)": "infinite", + "balanceOfBatch(address[],uint256[])": "infinite", + "canUpgradeFrom(address)": "507", + "findExpiry(string)": "infinite", + "findOwner(string)": "infinite", + "findTokenId(string)": "infinite", + "finishERC1155Migration(uint256[],(string,address,address,address)[])": "infinite", + "getAssigneeCount(uint256,uint256)": "7374", + "getExpiry(uint256)": "2700", + "getParent()": "infinite", + "getResolver(string)": "infinite", + "getResource(uint256)": "4964", + "getState(uint256)": "infinite", + "getStatus(uint256)": "infinite", + "getSubregistry(string)": "infinite", + "getTokenId(uint256)": "2763", + "getWrappedName()": "infinite", + "getWrappedNode()": "2392", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "infinite", + "hasRoles(uint256,uint256,address)": "infinite", + "hasRootRoles(uint256,address)": "infinite", + "initialize(bytes32,address,string,address,uint256)": "infinite", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "infinite", + "latestOwnerOf(uint256)": "2685", + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": "infinite", + "onERC1155Received(address,address,uint256,uint256,bytes)": "infinite", + "ownerOf(uint256)": "infinite", + "proxiableUUID()": "infinite", + "register(string,address,address,address,uint256,uint64)": "infinite", + "renew(uint256,uint64)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "infinite", + "roles(uint256,address)": "infinite", + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": "infinite", + "safeTransferFrom(address,address,uint256,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "infinite", + "setParent(address,string)": "infinite", + "setResolver(uint256,address)": "infinite", + "setSubregistry(uint256,address)": "infinite", + "setURI(string,address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "unregister(uint256)": "infinite", + "upgradeToAndCall(address,bytes)": "infinite", + "uri(uint256)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite", + "_getRegistry()": "infinite", + "_inject(string memory,address,contract IRegistry,address,uint256,uint64)": "infinite", + "_isMigratableChild(string memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"graveyard\",\"type\":\"address\"},{\"internalType\":\"contract IVerifiableFactory\",\"name\":\"verifiableFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ensV1Resolver\",\"type\":\"address\"},{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"hcaFactory\",\"type\":\"address\"},{\"internalType\":\"contract ApprovedUpgradeGate\",\"name\":\"upgradeGate\",\"type\":\"address\"},{\"internalType\":\"contract ILabelStore\",\"name\":\"labelStore\",\"type\":\"address\"},{\"internalType\":\"contract IAddressSet\",\"name\":\"publicResolverSet\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"publicResolver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"oldExpiry\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"CannotReduceExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"CannotSetPastExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"FrozenTokenApproval\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyReserved\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"LabelExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameNotLocked\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NameRequiresMigration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"TransferDisallowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"UpgradeTargetNotApproved\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ExpiryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelReserved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelUnregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ParentUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RegistryCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ResolverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SubregistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldTokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newTokenId\",\"type\":\"uint256\"}],\"name\":\"TokenRegenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"TokenResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"renderer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"URIUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"GRAVEYARD\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"HCA_FACTORY\",\"outputs\":[{\"internalType\":\"contract IHCAFactoryBasic\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LABEL_STORE\",\"outputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PUBLIC_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PUBLIC_RESOLVER_SET\",\"outputs\":[{\"internalType\":\"contract IAddressSet\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADE_GATE\",\"outputs\":[{\"internalType\":\"contract ApprovedUpgradeGate\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"V1_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERIFIABLE_FACTORY\",\"outputs\":[{\"internalType\":\"contract IVerifiableFactory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WRAPPER_REGISTRY_IMPL\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"canUpgradeFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[]\",\"name\":\"mds\",\"type\":\"tuple[]\"}],\"name\":\"finishERC1155Migration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getParent\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getResource\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"latestOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"internalType\":\"struct IPermissionedRegistry.State\",\"name\":\"state\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getSubregistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedName\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNode\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"contract IRegistry\",\"name\":\"parentRegistry\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"childLabel\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"latestOwnerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setParent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"setSubregistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"},{\"internalType\":\"contract IRegistryURIRenderer\",\"name\":\"renderer\",\"type\":\"address\"}],\"name\":\"setURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"CannotReduceExpiry(uint64,uint64)\":[{\"details\":\"Error selector: `0x68c1425a`\"}],\"CannotSetPastExpiry(uint64)\":[{\"details\":\"Error selector: `0xf1d446c3`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1155InsufficientBalance(address,uint256,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\",\"tokenId\":\"Identifier number of a token.\"}}],\"ERC1155InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"ERC1155InvalidOperator(address)\":[{\"details\":\"Indicates a failure with the `operator` to be approved. Used in approvals.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC1155InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC1155InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC1155MissingApprovalForAll(address,address)\":[{\"details\":\"Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\",\"owner\":\"Address of the current owner of a token.\"}}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"FrozenTokenApproval(uint256)\":[{\"details\":\"Error selector: `0xa4f07713`\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"LabelAlreadyRegistered(string)\":[{\"details\":\"Error selector: `0xdef545a4`\"}],\"LabelAlreadyReserved(string)\":[{\"details\":\"Error selector: `0xf60759e0`\"}],\"LabelExpired(uint256)\":[{\"details\":\"Error selector: `0xc44e2374`\"}],\"NameDataMismatch(uint256)\":[{\"details\":\"Error selector: `0xedec3569`\"}],\"NameNotLocked(uint256)\":[{\"details\":\"Error selector: `0x1bfe8f0a`\"}],\"NameRequiresMigration()\":[{\"details\":\"Error selector: `0x408fa1b8`\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"TransferDisallowed(uint256,address)\":[{\"details\":\"Error selector: `0xe58f6d5a`\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}],\"UnauthorizedCaller(address)\":[{\"details\":\"Error selector: `0xd86ad9cf`\",\"params\":{\"caller\":\"The address that attempted the unauthorized operation\"}}],\"UpgradeTargetNotApproved(address)\":[{\"details\":\"Error selector: `0xf74d7dd0`\",\"params\":{\"implementation\":\"The disallowed implementation address.\"}}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"ExpiryUpdated(uint256,uint64,address)\":{\"params\":{\"newExpiry\":\"The new expiry of the label.\",\"sender\":\"The sender of the call to update the expiry.\",\"tokenId\":\"The token ID of the label.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label registered.\",\"labelHash\":\"The label hash registered.\",\"owner\":\"The owner of the label.\",\"sender\":\"The sender of the call to register.\",\"tokenId\":\"The token ID registered.\"}},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label reserved.\",\"labelHash\":\"The label hash reserved.\",\"sender\":\"The sender of the call to reserve.\",\"tokenId\":\"The token ID reserved.\"}},\"LabelUnregistered(uint256,address)\":{\"params\":{\"sender\":\"The sender of the call to unregister.\",\"tokenId\":\"The token ID unregistered.\"}},\"ParentUpdated(address,string,address)\":{\"params\":{\"label\":\"The new label.\",\"parent\":\"The new parent.\",\"sender\":\"The sender of the call to update the parent.\"}},\"ResolverUpdated(uint256,address,address)\":{\"params\":{\"resolver\":\"The new resolver.\",\"sender\":\"The sender of the call to update the resolver.\",\"tokenId\":\"The token ID of the label.\"}},\"SubregistryUpdated(uint256,address,address)\":{\"params\":{\"sender\":\"The sender of the call to update the subregistry.\",\"subregistry\":\"The new subregistry.\",\"tokenId\":\"The token ID of the label.\"}},\"TokenRegenerated(uint256,uint256)\":{\"params\":{\"newTokenId\":\"The new token ID.\",\"oldTokenId\":\"The old token ID.\"}},\"TokenResource(uint256,uint256)\":{\"params\":{\"resource\":\"The EAC resource.\",\"tokenId\":\"The token ID.\"}},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"},\"URIUpdated(string,address,address)\":{\"params\":{\"renderer\":\"The new render address.\",\"sender\":\"The sender of the call to update the URI.\",\"uri\":\"The new URI.\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"params\":{\"account\":\"The account to get the balance for.\",\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"balance The balance of the token for the account. This will only ever be 1 or 0.\"}},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"`accounts` and `ids` must have the same length.\",\"params\":{\"accounts\":\"The accounts to get the balances for.\",\"ids\":\"The token IDs.\"},\"returns\":{\"_0\":\"batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\"}},\"canUpgradeFrom(address)\":{\"details\":\"Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call, including the wrapper upgrade target allowlist.\",\"params\":{\"\":\"{previousImplementation} Ignored.\"},\"returns\":{\"allowed\":\"Always `true` for implementations in this wrapper registry family.\"}},\"constructor\":{\"params\":{\"ensV1Resolver\":\"The ENSv1 resolver.\",\"graveyard\":\"The ENSv1 `BaseRegistrar` token graveyard.\",\"hcaFactory\":\"The HCA factory.\",\"labelStore\":\"The shared label database.\",\"nameWrapper\":\"The ENSv1 NameWrapper.\",\"namer\":\"The implementation namer.\",\"publicResolver\":\"The replacement `PublicResolver`.\",\"publicResolverSet\":\"The approved list of `PublicResolver` contracts.\",\"upgradeGate\":\"The upgrade target allowlist.\",\"verifiableFactory\":\"The VerifiableFactory.\"}},\"findExpiry(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The expiry of the label.\"}},\"findOwner(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The owner of the label.\"}},\"findTokenId(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The token ID of the label.\"}},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"details\":\"Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts\",\"params\":{\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\",\"mds\":\"The migration parameters for each name, indexed in parallel with `ids`.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getExpiry(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The expiry of the label, in seconds.\"}},\"getParent()\":{\"returns\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"getResolver(string)\":{\"details\":\"Return `V1_RESOLVER` upon visiting migratable children.\",\"params\":{\"label\":\"The label to fetch a resolver for.\"},\"returns\":{\"_0\":\"resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\"}},\"getResource(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The resource.\"}},\"getState(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"state\":\"The state of the label.\"}},\"getStatus(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The status of the label.\"}},\"getSubregistry(string)\":{\"params\":{\"label\":\"The label to resolve.\"},\"returns\":{\"_0\":\"The address of the registry for this label, or `address(0)` if none exists.\"}},\"getTokenId(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"initialize(bytes32,address,string,address,uint256)\":{\"params\":{\"childLabel\":\"The subdomain for this registry.\",\"node\":\"Namehash of this registry.\",\"parentRegistry\":\"The parent of this registry.\",\"roleBitmap\":\"The role bitmap granted to `rootAccount`.\",\"rootAccount\":\"Account granted root roles.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"account\":\"The account to get the approval for.\",\"operator\":\"The operator to get the approval for.\"},\"returns\":{\"_0\":\"approved The approval status.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"latestOwnerOf(uint256)\":{\"params\":{\"tokenId\":\"The token ID to query.\"},\"returns\":{\"_0\":\"The latest owner address.\"}},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\",\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\"}},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data` struct containing migration parameters.\",\"id\":\"The NameWrapper token ID (namehash) of the name being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\"}},\"ownerOf(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The owner of the token.\"}},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"register(string,address,address,address,uint256,uint64)\":{\"details\":\"Blocks registration of emancipated children.\",\"params\":{\"expiry\":\"The expiry of the label, in seconds.\",\"label\":\"The label to register.\",\"owner\":\"The address of the owner of the label.\",\"registry\":\"The registry to set as the label.\",\"resolver\":\"The resolver to set for the label.\",\"roleBitmap\":\"The role bitmap to set for the label.\"},\"returns\":{\"tokenId\":\"The token ID.\"}},\"renew(uint256,uint64)\":{\"details\":\"If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"newExpiry\":\"The new expiry, in seconds.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the tokens from.\",\"ids\":\"The token IDs.\",\"to\":\"The address to transfer the tokens to.\",\"values\":\"The amounts of tokens to transfer.\"}},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the token from.\",\"id\":\"The token ID.\",\"to\":\"The address to transfer the token to.\",\"value\":\"The amount of tokens to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"The approval status.\",\"operator\":\"The operator to set the approval for.\"}},\"setParent(address,string)\":{\"details\":\"Should emit `ParentUpdated`.\",\"params\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"setResolver(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"resolver\":\"The new resolver.\"}},\"setSubregistry(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"registry\":\"The new registry.\"}},\"setURI(string,address)\":{\"params\":{\"renderer\":\"The new renderer address.\",\"uri_\":\"The new URI.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"unregister(uint256)\":{\"details\":\"Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"}},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"uri(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The URI for the token.\"}}},\"stateVariables\":{\"_node\":{\"details\":\"The namehash of this registry.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"notice\":\"Label expiry cannot be reduced.\"}],\"CannotSetPastExpiry(uint64)\":[{\"notice\":\"Label expiry cannot be before now.\"}],\"FrozenTokenApproval(uint256)\":[{\"notice\":\"NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"LabelAlreadyRegistered(string)\":[{\"notice\":\"Label is already registered.\"}],\"LabelAlreadyReserved(string)\":[{\"notice\":\"Label cannot be reserved again.\"}],\"LabelExpired(uint256)\":[{\"notice\":\"Label is expired/unregistered.\"}],\"NameDataMismatch(uint256)\":[{\"notice\":\"NameWrapper or BaseRegistrar token does not match supplied data.\"}],\"NameNotLocked(uint256)\":[{\"notice\":\"NameWrapper token is unlocked.\"}],\"NameRequiresMigration()\":[{\"notice\":\"Name cannot be registered because unmigrated NameWrapper token exists.\"}],\"TransferDisallowed(uint256,address)\":[{\"notice\":\"Transfer is not allowed due to missing transfer admin role.\"}],\"UnauthorizedCaller(address)\":[{\"notice\":\"Thrown when a caller is not authorized to perform the requested operation\"}],\"UpgradeTargetNotApproved(address)\":[{\"notice\":\"Upgrade target is not approved for `WrapperRegistry` proxies.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"ExpiryUpdated(uint256,uint64,address)\":{\"notice\":\"Expiry of label was changed.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"notice\":\"A label was registered.\"},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"notice\":\"A label was reserved.\"},\"LabelUnregistered(uint256,address)\":{\"notice\":\"A label was unregistered.\"},\"ParentUpdated(address,string,address)\":{\"notice\":\"Parent was changed.\"},\"RegistryCreated()\":{\"notice\":\"A registry was created/initialized.\"},\"ResolverUpdated(uint256,address,address)\":{\"notice\":\"Resolver of label was changed.\"},\"SubregistryUpdated(uint256,address,address)\":{\"notice\":\"Subregistry of label was changed.\"},\"TokenRegenerated(uint256,uint256)\":{\"notice\":\"Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance.\"},\"TokenResource(uint256,uint256)\":{\"notice\":\"Associate a token with an EAC resource.\"},\"URIUpdated(string,address,address)\":{\"notice\":\"URI was changed.\"}},\"kind\":\"user\",\"methods\":{\"GRAVEYARD()\":{\"notice\":\"The ENSv1 `BaseRegistrar` token graveyard.\"},\"HCA_FACTORY()\":{\"notice\":\"The HCA factory contract\"},\"LABEL_STORE()\":{\"notice\":\"The shared label database.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\"},\"PUBLIC_RESOLVER()\":{\"notice\":\"The replacement `PublicResolver`.\"},\"PUBLIC_RESOLVER_SET()\":{\"notice\":\"The list of `PublicResolver` contracts that require replacement.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"UPGRADE_GATE()\":{\"notice\":\"Gate for approved implementation upgrade targets.\"},\"V1_RESOLVER()\":{\"notice\":\"Fallback resolver for ENSv1 resolution.\"},\"VERIFIABLE_FACTORY()\":{\"notice\":\"The shared factory for verifiable deployments.\"},\"WRAPPER_REGISTRY_IMPL()\":{\"notice\":\"The `WrapperRegistry` implementation contract.\"},\"balanceOf(address,uint256)\":{\"notice\":\"Returns the balance of a token for an account.\"},\"balanceOfBatch(address[],uint256[])\":{\"notice\":\"Returns the balances of a batch of tokens for an account.\"},\"canUpgradeFrom(address)\":{\"notice\":\"Declares this implementation as an eligible verifiable proxy upgrade target.\"},\"findExpiry(string)\":{\"notice\":\"Fetches the label expiry.\"},\"findOwner(string)\":{\"notice\":\"Fetches the label owner.\"},\"findTokenId(string)\":{\"notice\":\"Fetches the token ID for a label.\"},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"notice\":\"Convert NameWrapper tokens to their equivalent ENSv2 form.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getExpiry(uint256)\":{\"notice\":\"Get expiry of label.\"},\"getParent()\":{\"notice\":\"Get canonical \\\"location\\\" of this registry.\"},\"getResolver(string)\":{\"notice\":\"Fetches the resolver responsible for the specified label.\"},\"getResource(uint256)\":{\"notice\":\"Get `resource` from `anyId`.\"},\"getState(uint256)\":{\"notice\":\"Get the state of a label.\"},\"getStatus(uint256)\":{\"notice\":\"Get `Status` from `anyId`.\"},\"getSubregistry(string)\":{\"notice\":\"Fetches the registry for a label.\"},\"getTokenId(uint256)\":{\"notice\":\"Get `tokenId` from `anyId`.\"},\"getWrappedName()\":{\"notice\":\"Returns the DNS-encoded name for this registry.\"},\"getWrappedNode()\":{\"notice\":\"Returns the NameWrapper node (namehash).\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"initialize(bytes32,address,string,address,uint256)\":{\"notice\":\"Initializes WrapperRegistry.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Returns the approval for all operator.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"latestOwnerOf(uint256)\":{\"notice\":\"Get the latest owner of a token. If the token was burned, returns null.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"notice\":\"Migrate one NameWrapper token via `safeTransferFrom()`.\"},\"ownerOf(uint256)\":{\"notice\":\"Returns the owner of a token.\"},\"register(string,address,address,address,uint256,uint64)\":{\"notice\":\"Registers a new label.\"},\"renew(uint256,uint64)\":{\"notice\":\"Renew a label.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Transfers multiple tokens from one address to another.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"notice\":\"Transfers a single token from one address to another.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Sets the approval for all operator.\"},\"setParent(address,string)\":{\"notice\":\"Change canonical \\\"location\\\".\"},\"setResolver(uint256,address)\":{\"notice\":\"Change resolver of label.\"},\"setSubregistry(uint256,address)\":{\"notice\":\"Change registry of label.\"},\"setURI(string,address)\":{\"notice\":\"Set the URI for the registry.\"},\"unregister(uint256)\":{\"notice\":\"Delete a label.\"},\"uri(uint256)\":{\"notice\":\"Returns the URI for a token.\"}},\"notice\":\"UUPS-upgradeable registry that wraps an ENSv1 NameWrapper, supporting migration of wrapped names into the namechain registry system.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/WrapperRegistry.sol\":\"WrapperRegistry\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://10dc5a91b042cc3b5de7c06163532355e9d616ee2182dc28910dddf7dc4c6197\",\"dweb:/ipfs/QmQTuQRA96EFZxGaMnenrz33keRD2GMVnNygLFu4fkywYv\"]},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fcf03e1a9386d80ff6b8e31870063424454f69d2626c0efb2c8cf55e69151489\",\"dweb:/ipfs/QmVYgfMSc1ve5JWePqiAGSXEfD76emw3oLsCM1krstmJq5\"]},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://603aabc890496db91c17f8b946bfee9e33d2192275e59fc172d1fb4fba9e4f0d\",\"dweb:/ipfs/QmZZuSHAGWWhgQdQKYU3KzNHssyW1L5EGbVFaQZADs4AGe\"]},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8042fdeb4d5e58dd33105c1b903ce3bece8c894e7493b7aa888a03cf09aff793\",\"dweb:/ipfs/QmW9YsQaERFrYoxoZooReX9m7eteK6JPo2RbaUhm9NcNe8\"]},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://561155e2b3dce64c470feb854544ca2474e0a8e2e31a92f6304ad1955631c619\",\"dweb:/ipfs/QmPDfTbsiQGHcdvq7piJvXDgD465f7qdr7FDai3dtvBgfX\"]},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3e7594410b4f3efd266274e25bed905e4d1d1bbb071d0de35b6824003fcb4409\",\"dweb:/ipfs/QmNNtwjjf1xdSmFVj19V9uBkzp1uA27aAgPHAgRMCMrug2\"]},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://71aa1053dd87829c5eb25d32840d7b0d33cd9d54d22e905a01436bf97cc32b8c\",\"dweb:/ipfs/QmeMNnGKqf3oZyYwDQzEuQhti58UCCMRCMAD2EBx5T8dSH\"]},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a85d9e2d6b235900131129386047fae5fb77438806b681ac566119868be5a502\",\"dweb:/ipfs/Qmd9ys5jeRx77TDVeRqWUme7a5LUDT4k7wQ91wVSayDpTR\"]},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5afeadfdf2232a2333afb5345b65a25f7199b62ed6fde403273b762c91f5e9af\",\"dweb:/ipfs/QmWKhi3FuqX2KgRrBdh65gB3pmiwA2QMYPeiDbsMKv6a88\"]},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f1bc47de2e6e12b3680e47a4dd5b6e3c1e85b65851378aa1d617309edbc1200d\",\"dweb:/ipfs/QmSPcJ9HmkmsSDvMS4KZijnxoGMAEn8HbQuY4fe8DroZEE\"]},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ebd19cec65d3998dad25dc9beecd33055b1900f26c3f61377c78926ca0637c9a\",\"dweb:/ipfs/QmUda1jFjWf2ptQrahTgU6953SZY7ZWksRaTo2dKGX4BMK\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6917f8a323e7811f041aecd4d9fd6e92455a6fba38a797ac6f6e208c7912b79d\",\"dweb:/ipfs/QmShuYv55wYHGi4EFkDB8QfF7ZCHoKk2efyz3AWY1ExSq7\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"keccak256\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d3b36282ab029b46bd082619a308a2ea11c309967b9425b7b7a6eb0b0c1c3196\",\"dweb:/ipfs/QmP2YVfDB2FoREax3vJu7QhDnyYRMw52WPrCD4vdT2kuDA\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://271f914261a19d87117a777e0924ada545c16191ef9b00cc40b0134fc14ebc70\",\"dweb:/ipfs/QmdvVNWHGHQrGGPonZJs5NuzTevTjZRM2zayKrDJf7WBA2\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5aa4f07e65444784c29cd7bfcc2341b34381e4e5b5da9f0c5bd00d7f430e66fa\",\"dweb:/ipfs/QmWRMh4Q9DpaU9GvsiXmDdoNYMyyece9if7hnfLz7uqzWM\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cb2f27cd3952aa667e198fba0d9b7bcec52fbb12c16f013c25fe6fb52b29cc0e\",\"dweb:/ipfs/QmeuohBFoeyDPZA9JNCTEDz3VBfBD4EABWuWXVhHAuEpKR\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ba1d02f4847670a1b83dec9f7d37f0b0418d6043447b69f3a29a5f9efc547fcf\",\"dweb:/ipfs/QmQ7iH2keLNUKgq2xSWcRmuBE5eZ3F5whYAkAGzCNNoEWB\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://919c7ea27c77275c3c341da0c4a26a66a20ed27605fbe8becf11f58ec3bc65bf\",\"dweb:/ipfs/QmRLKyVE2n7e2Jo4bLNn8eLgqqhNGYnVQyjJPWdr8poskf\"]},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7e66dfde185df46104c11bc89d08fa0760737aa59a2b8546a656473d810a8ea4\",\"dweb:/ipfs/QmXvyqtXPaPss2PD7eqPoSao5Szm2n6UMoiG8TZZDjmChR\"]},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da62d6be1f5c6edf577f0cb45666a8aa9c2086a4bac87d95d65f02e2f4c36a4b\",\"dweb:/ipfs/QmNkpvBpoCMvX8JwAFNSc5XxJ2q5BXJpL5L1txb4QkqVFF\"]},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11fea9f8bc98949ac6709f0c1699db7430d2948137aa94d5a9e95a91f61a710a\",\"dweb:/ipfs/QmQdfRXxQjwP6yn3DVo1GHPpriKNcFghSPi94Z1oKEFUNS\"]},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a2608291cb038b388d80b79a06b6118a42f7894ff67b7da10ec0dbbf5b2973ba\",\"dweb:/ipfs/QmWohqcBLbcxmA4eGPhZDXe5RYMMEEpFq22nfkaUMvTfw1\"]},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://399594cd8bb0143bc9e55e0f1d071d0d8c850a394fb7a319d50edd55d9ed822b\",\"dweb:/ipfs/QmbPZzgtT6LEm9CMqWfagQFwETbV1ztpECBB1DtQHrKiRz\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://687e2ec572d0e63827bb0025b91f2246be4c938f830ef4b4c288ee2e3727d5ca\",\"dweb:/ipfs/QmZXWSAQ9ftVrqNEa5ZTpN4wxvzCgsSW12cgiSRkrLTpQ8\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"keccak256\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d8cbb06152d82ebdd5ba1d33454e5759492040f309a82637c7e99c948a04fa20\",\"dweb:/ipfs/QmQQuLr6WSfLu97pMEh6XLefk99TSj9k5Qu1zXGPepwGiK\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"keccak256\":\"0x35d120c427299af1525aaf07955314d9e36a62f14408eb93dec71a2e001f74d3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://743e38acf441eece428c008be399c40a3ca5b2d595d58faf656cbdbac1a45374\",\"dweb:/ipfs/QmcWDuWkndox3dxa5P7ZgpKy3iuQKkxBq1cR9hPV1ZzAfa\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol\":{\"keccak256\":\"0x22f099c02c252dd1f6ddc464916ce683294a63b23b3c6ee3d290b77398e2474b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://82d2ba4b77ecc4f70211e0de1a920e3ea29eb86c3e16ef8f2a7d746c72a97f1e\",\"dweb:/ipfs/QmYBqATARQEnxd33jW6iYCuEPaL6KdYyYSoQrjFXZka3of\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8150ceb4ac947e8a442b2a9c017e01e880b2be2dd958f1fa9bc405f4c5a86508\",\"dweb:/ipfs/QmbcBmFX66AY6Kbhnd5gx7zpkgqnUafo43XnmayAM7zVdB\"]},\"project/lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0x55a4fdb408e3db950b48f4a6131e538980be8c5f48ee59829d92d66477140cd6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3e1ad251e692822ce1494135a4ecb5b97c19b90aa82418fd2959ce32017953fd\",\"dweb:/ipfs/QmT6N7mf6heZYhY2BAQ5kwZp9o3SXzGVdkMqUszx67WRDN\"]},\"project/lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"project/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x67672e4ca1dafdcc661d4eba8475cfac631fa0933309258e3af7644b92e1fb26\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://30192451f05ea5ddb0c18bd0f9003f098505836ba19c08a9c365adf829454da2\",\"dweb:/ipfs/QmfCuZSCTyCdFoSKn7MSaN6hZksnQn9ZhrZDAdRTCbwGu2\"]},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8084aa71a4cc7d2980972412a88fe4f114869faea3fefa5436431644eb5c0287\",\"dweb:/ipfs/Qmbqfs5dRdPvHVKY8kTaeyc65NdqXRQwRK7h9s5UJEhD1p\"]},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621\",\"dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL\"]},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40f30fe28a969241e3dcfc38561ccb8e0104828a09ea27ec242acf4cf17813b3\",\"dweb:/ipfs/QmZakqRvVvZaoePUKMsUJ6F5iEuGKCcDBb9z4WxB9wvXak\"]},\"project/lib/verifiable-factory/src/IVerifiableFactory.sol\":{\"keccak256\":\"0x00499139966665152ce90dddf24ae3047c6fb07d3e045b1e4d77ec9e86dc4eef\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2e97399cd7f8f9983fe0be67bc3d528b2c509eee5aaa1a7379f9b84029619c65\",\"dweb:/ipfs/QmVPFAMdX9Jd8Du3aKQdThDjG8Q1ajYMxec52kyQAY3Xho\"]},\"project/src/CommonErrors.sol\":{\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://294480f5f2584f2eb48760131c1974384180f90021fc6c0a8ad652636797099c\",\"dweb:/ipfs/QmX5LKhT7nSU88ERQARjyhtEB7ePDmFkF3nE5aYhzWTjvU\"]},\"project/src/access-control/EnhancedAccessControl.sol\":{\"keccak256\":\"0xdf8918a909b0ab3bf17bc3a560fbdff6ca6e9502cbee54eb0923f1fae04d2fb1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f18d3014143b6c07594ce9a7387b6bf5d2f8a19a30beb486b228d9be0a164eb1\",\"dweb:/ipfs/QmSEfyEXGAZwg2JG8BP5WSwQu8p9uTVLbJoyAatGoVtBbR\"]},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://72fa6513382456e23d04f041fafcc86973593ea04690a46256593b3d6b7f690a\",\"dweb:/ipfs/QmUHZ6d5VhQd38AejUARFDNYSagMYfRk7zywNdMniko9os\"]},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"keccak256\":\"0x9f29748b40665df976c08cdaf434b469dc73ef50e938c36be6773dc7b6a6f014\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ab27667845d02734949f30c6c751f3522fa758e3d2ce398bbd3802acd793c3bd\",\"dweb:/ipfs/QmPdRSzs3mcpZMMZmq8SAcqqpw32f4unKVnDD5a3WQVyof\"]},\"project/src/erc1155/ERC1155Singleton.sol\":{\"keccak256\":\"0x9af9852c17f9d19765bd2b21fe2076d96845f0c0f7e9b0faa1d905793d3b677d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://020442007ea540cd4f86bab5dc4fa46d20881dd9ff43b65a95c74b2b4ea948bc\",\"dweb:/ipfs/QmQgyqGwsAodDwzamNaxmGQko5WrbawhuY82ZHmAf54X1F\"]},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0a6e8c9d901d39d587f24337783a8b91cbbb95683b746481754071693790bfe5\",\"dweb:/ipfs/QmZy1bPciKVPF5W5DDekDquHBfwk1cM7XNBqhzoC8RP5ES\"]},\"project/src/hca/HCAContext.sol\":{\"keccak256\":\"0x6c845b6261e529771155d3537b7990120ac0126174f7e63d3167ddff1b8f3cc1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a741c711c64cb3215e7aab9d23a9977f5b42a1a8dc10e558caf56d515361b0b2\",\"dweb:/ipfs/Qmdhb9K4h5wqAWxJtKEwfQAEMycuikXahpW9UvKqgnkryq\"]},\"project/src/hca/HCAEquivalence.sol\":{\"keccak256\":\"0x3e78401b98154ef7df629f19ff5a8b156d847f7b71c0889b4767d5ad81d3cf78\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40de8d64a7e4fc633d3e1d1b56cf579084983ed0a56275bba63e85de3431219c\",\"dweb:/ipfs/QmPgzp7YxnPS3UbuHGsoaERCLUJAMLYE14rznMktQtXbqJ\"]},\"project/src/hca/interfaces/IHCAFactoryBasic.sol\":{\"keccak256\":\"0xf298e05861b1072dd368683794cae5670e5170a414ed1151336663378f5a63ed\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5750cefb33368019d1f857e11102df501fee4d72ef2c242746e78e3dd046b1b4\",\"dweb:/ipfs/QmVNNq7s5SgHhdGtt7idXiSFaajT1xiP8wSA2CVV1Sq5c1\"]},\"project/src/migration/AbstractWrapperReceiver.sol\":{\"keccak256\":\"0x0c15f9f657ba58bf5081cbff88c385c9e673ba87aed2032397ec2c5448d7fe1a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fd118194db53d6d1cf7ebc891cc673cc356cd2a3363f75f4646c0cf1c52cced3\",\"dweb:/ipfs/QmSepYZ5w8bf9rYwaEEyCJe7U1Jpy8wP2LxUyd2YBX2Nkp\"]},\"project/src/migration/LockedWrapperReceiver.sol\":{\"keccak256\":\"0xfdd9a054e4bb46a6908503af4af181db9ccc1dbdd7625f488fc9a8d4811b3b35\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://58cadc7a0877e1de8d20a3af33a193e57f56b5cced288d94bb400e01461cbc6a\",\"dweb:/ipfs/QmUg5jXXM5wEuQKQPmEjRbrL5v14jGfPswNLG6pruHpZ7Y\"]},\"project/src/migration/libraries/LibMigration.sol\":{\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c0751f78faa3a3d37b4bbd9c28ebab22af6d47bd33c97fcaee433b90dbe03c61\",\"dweb:/ipfs/QmcGVP9FskRV1qTbicgVMMVWJnFd5tk9LBWb1ckKwkKC2c\"]},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"keccak256\":\"0xb1cf6d7413558f8d257bdf8f734aaa57d4323e27854ae3ce79b7f017ff133510\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8d3a5798cf82a25225a2d528b13e1368e6fa49e9c1aaa280c9bab973fc6dfdfc\",\"dweb:/ipfs/QmQ8Rg5fAu9mir6NVUr2fngXMjkizcPLUMUfrYtuqC58X9\"]},\"project/src/registrar/ETHRegistrar.sol\":{\"keccak256\":\"0x98448c1cb629eec852d9e6ba65ab8b1d46b68f813c2687b0c84d115fbc84b91c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bf81ba81e5834f4ca5b1c0d2a691977465c4d648adbf473b91647fd66a4c3a1b\",\"dweb:/ipfs/QmeamGecojzmA9NczAJ9n5wrw2uGy1paju2uE3VUXXhc76\"]},\"project/src/registrar/interfaces/IETHRegistrar.sol\":{\"keccak256\":\"0x7e824c5019f8eb7d7a283451700234716353e01d649c811b5ced5cf58b476289\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a8d5f251631a78e681db6dc3680f4dbdd67eaee6ecf4491260d2347a640dfe69\",\"dweb:/ipfs/QmZDUmKJpEUJoHJ8wAkWCN8jgUut4xkHgjw94RFphk2oqz\"]},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f67fa758790fef15907887f9f93dcfbdc4907d700addce8b593f86c9299d2f73\",\"dweb:/ipfs/QmPN3EXTMVLJucoRNqMWyuiQALNC7SRmKRHX7DbbCnc4NF\"]},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dc0fdf679eddd0a120667b75767a176a4ab3d6da460b902517edbcf08a4ffc6b\",\"dweb:/ipfs/QmVzwpvBLoWyUfeGu1P5H6gvDqUD8B7KF5K7GbfPWGVHPu\"]},\"project/src/registry/ApprovedUpgradeGate.sol\":{\"keccak256\":\"0xecaf823f2344fb8336d18f889905de806299edfa6424796a24ce584eeda1eb2f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dfdc8a8bf29fa23db93e9ab126ba64c8866b31600b568046ba8e2e68d45d06e9\",\"dweb:/ipfs/QmT8WEix9RkyKB7CcAqS8V84Vj3NfGoNRkHh1CMQHMTqMZ\"]},\"project/src/registry/PermissionedRegistry.sol\":{\"keccak256\":\"0x3d065298bcd998d8a638d5e52ff7ed15b8eff4ef43666eb8219a5858ace5a5e7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://18d3415ae9ba3c1afb7c52ae0d0f51843705614c902772ade97cfdb28092c48d\",\"dweb:/ipfs/QmVMBXB3pG13h2oMjwBYAF3w6dK4KH92ZjQHEj1eAYNS6c\"]},\"project/src/registry/WrapperRegistry.sol\":{\"keccak256\":\"0x6307ebe0589ac35d62063d982f10da4a5904cf9bffe9f9a42f62e082ac51ff91\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e1f2a4701bbe07e750faac38759304188199f7cb3b70c5f265b950f7722a2b4f\",\"dweb:/ipfs/QmbeQwRZsLobDwD1BT9HLRtzN5ifGnFAw6UFFgMZeYYnGv\"]},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c9f7beea3328330b481de31e0d8dd2da1c416540ec41339d674bf2e13f2d8254\",\"dweb:/ipfs/Qmbftc1CSyFCAxRfwaXpyRMwRn1Rryxb7KLfwB5FM5Siio\"]},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"keccak256\":\"0x3cb8ee0cd5eeab9a218873d448515e2c2d4ef8fca788e446b311f53582e907be\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://30e4f3dcc28303aea7880788da1f2daea6eaf0979a02ba9ce364777607093b88\",\"dweb:/ipfs/QmdcnMmTB2CDz8MoiLoK2Zcqgp9ix45ZP1hfSosXbvP3vE\"]},\"project/src/registry/interfaces/IRegistry.sol\":{\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dce497e971fcd006e10a3de52335eaf137d8f864641592270bc2e1a682e286fa\",\"dweb:/ipfs/QmbBXJCyQYjGgmFVWc33T9wu4qn1kgQ1TSEvwGkCfH6keK\"]},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8755e9aa5e8541d05aa0470a189804d19c3305269e39bc1a5f1b096b90b446b8\",\"dweb:/ipfs/QmehAS72QYkDiEyD3kC29efwJGJHjzGboD1DcosNcHvpeh\"]},\"project/src/registry/interfaces/IRegistryURIRenderer.sol\":{\"keccak256\":\"0xa6ea64ff73d10fa58118ae9c0d0c2caa72f2f3488776227a22bd0cd9cd6586f6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fad26d2e735225585dc459ffd90467e9cecd407215120d02ef848ad8856eb718\",\"dweb:/ipfs/QmXNtf6FdxnFH7pGU6UNhWdGs46CUm8scJBV1zRpMTUXSe\"]},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://67ae762c75c392a1ccd9cd5d97dd8d5f737e3a7661799a688805110b0af5190f\",\"dweb:/ipfs/Qmc6Rug6vgZCkCWKHXfroav73ryKnL8jicWd9jnYZ5YKYq\"]},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35dc26d4e8040334099ea2d86c1821d8c14c5dc1d47ffd5dbaaf5679f863775d\",\"dweb:/ipfs/QmXV5gJpSKEqBndXx3RuTpncBkty3XHd5FEdFP3NrL5yVk\"]},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://18708b341e61090e3dc9c0efc7ed54d1f79bd5f2658fc3cb0ce1b57962630363\",\"dweb:/ipfs/QmXKYpjoCj2GDtMDqNRApijEmKMLvk1xQRXepztRJaEFrg\"]},\"project/src/registry/interfaces/IWrapperRegistry.sol\":{\"keccak256\":\"0xfc002c3302da346dbe758ecdcf33ef4fbdcefd2e693971a85c31f2c4c86676cd\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://492459b2b5063bd5c62035d7b38ba3394c90edfba0452ce9fb24cc48f6173146\",\"dweb:/ipfs/QmVHKSyAJQXQFFr5YNTUqAWJrnoejjYMhs2Ya1QrbZcEgN\"]},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"keccak256\":\"0x6bd37001025ec90ffe9b852fcfdf68be81a9f70f8777d80136bea1c04da30041\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0dd151524e438b5a2f8511ae4fb9984a499e9f3012f911f431ddaecb53cde0a0\",\"dweb:/ipfs/QmcCqVCxrSMonGnzrpW5TWFjeWnXtkYxdYxkhuojm3WhmC\"]},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1b852474bf93262c0d27b220a6ab014a612a80f0a3d9bafda8eb5393b22ea22e\",\"dweb:/ipfs/QmTtJ69KTVTdHtwYVpyFBnPBJJX8cB3QU8SHMwyY2XbrN6\"]},\"project/src/utils/LibLabel.sol\":{\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ae17071bb62753a811050a33f8280256d6ffa43107f1b6409c60c2f3cb207662\",\"dweb:/ipfs/QmU6fQikpmCa7EebwLbtDbEmsfSgiQDUqXMbyyombnFAts\"]},\"project/src/utils/WrappedErrorLib.sol\":{\"keccak256\":\"0xf92862b6509cf553bd542925617318a2509bfdc6457e8b5d102c8e9658c610e4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e2d2a9fc03c7c18699d435477489167a1c9f97ac7558931c28a59f37a09c2b7f\",\"dweb:/ipfs/QmUYYjDXhoFHYSu2zzWSHzqwakY2gozQz3i5YGrE8S5ihb\"]},\"project/src/utils/interfaces/IAddressSet.sol\":{\"keccak256\":\"0xcb4f9c6364c1cf8a737591088f488ede7a7c6bc9d7d87f2dbdac731b492bd862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://68ad6de4f0bbef675c58894dc19356d7e724fe8c19d5626d8450284b5f370fe5\",\"dweb:/ipfs/QmTNQ6LpeuAwC4X76nEKezwwixrAfQjmiXvcpvJ9KQGN1x\"]},\"project/src/utils/interfaces/ILabelStore.sol\":{\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://553cf61818e8737861d4b0acc58603e877db221b0779eccf01f0ccceeaf14915\",\"dweb:/ipfs/QmNzjoJrE7cAjPmZWKS8DKTJbEgGEfNZRqkUJ64BwfKGYf\"]}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 11144, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_owners", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 11151, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 10019, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_roles", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 10024, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_roleCount", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 10029, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "__gap", + "offset": 0, + "slot": "4", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 14424, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_parentRegistry", + "offset": 0, + "slot": "260", + "type": "t_contract(IRegistry)16719" + }, + { + "astId": 14427, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_childLabel", + "offset": 0, + "slot": "261", + "type": "t_string_storage" + }, + { + "astId": 14430, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_uri", + "offset": 0, + "slot": "262", + "type": "t_string_storage" + }, + { + "astId": 14434, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_uriRenderer", + "offset": 0, + "slot": "263", + "type": "t_contract(IRegistryURIRenderer)16834" + }, + { + "astId": 14440, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_entries", + "offset": 0, + "slot": "264", + "type": "t_mapping(t_uint256,t_struct(Entry)14416_storage)" + }, + { + "astId": 14445, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "__gap", + "offset": 0, + "slot": "265", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 16204, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_node", + "offset": 0, + "slot": "521", + "type": "t_bytes32" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRegistry)16719": { + "encoding": "inplace", + "label": "contract IRegistry", + "numberOfBytes": "20" + }, + "t_contract(IRegistryURIRenderer)16834": { + "encoding": "inplace", + "label": "contract IRegistryURIRenderer", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "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_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_struct(Entry)14416_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct PermissionedRegistry.Entry)", + "numberOfBytes": "32", + "value": "t_struct(Entry)14416_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Entry)14416_storage": { + "encoding": "inplace", + "label": "struct PermissionedRegistry.Entry", + "members": [ + { + "astId": 14402, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "eacVersionId", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 14405, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "tokenVersionId", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 14409, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "subregistry", + "offset": 8, + "slot": "0", + "type": "t_contract(IRegistry)16719" + }, + { + "astId": 14412, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "expiry", + "offset": 0, + "slot": "1", + "type": "t_uint64" + }, + { + "astId": 14415, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "resolver", + "offset": 8, + "slot": "1", + "type": "t_address" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "notice": "Label expiry cannot be reduced." + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "notice": "Label expiry cannot be before now." + } + ], + "FrozenTokenApproval(uint256)": [ + { + "notice": "NameWrapper token has existing approval and burned `CANNOT_APPROVE`." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "LabelAlreadyRegistered(string)": [ + { + "notice": "Label is already registered." + } + ], + "LabelAlreadyReserved(string)": [ + { + "notice": "Label cannot be reserved again." + } + ], + "LabelExpired(uint256)": [ + { + "notice": "Label is expired/unregistered." + } + ], + "NameDataMismatch(uint256)": [ + { + "notice": "NameWrapper or BaseRegistrar token does not match supplied data." + } + ], + "NameNotLocked(uint256)": [ + { + "notice": "NameWrapper token is unlocked." + } + ], + "NameRequiresMigration()": [ + { + "notice": "Name cannot be registered because unmigrated NameWrapper token exists." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "notice": "Transfer is not allowed due to missing transfer admin role." + } + ], + "UnauthorizedCaller(address)": [ + { + "notice": "Thrown when a caller is not authorized to perform the requested operation" + } + ], + "UpgradeTargetNotApproved(address)": [ + { + "notice": "Upgrade target is not approved for `WrapperRegistry` proxies." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "ExpiryUpdated(uint256,uint64,address)": { + "notice": "Expiry of label was changed." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "notice": "A label was registered." + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "notice": "A label was reserved." + }, + "LabelUnregistered(uint256,address)": { + "notice": "A label was unregistered." + }, + "ParentUpdated(address,string,address)": { + "notice": "Parent was changed." + }, + "RegistryCreated()": { + "notice": "A registry was created/initialized." + }, + "ResolverUpdated(uint256,address,address)": { + "notice": "Resolver of label was changed." + }, + "SubregistryUpdated(uint256,address,address)": { + "notice": "Subregistry of label was changed." + }, + "TokenRegenerated(uint256,uint256)": { + "notice": "Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance." + }, + "TokenResource(uint256,uint256)": { + "notice": "Associate a token with an EAC resource." + }, + "URIUpdated(string,address,address)": { + "notice": "URI was changed." + } + }, + "kind": "user", + "methods": { + "GRAVEYARD()": { + "notice": "The ENSv1 `BaseRegistrar` token graveyard." + }, + "HCA_FACTORY()": { + "notice": "The HCA factory contract" + }, + "LABEL_STORE()": { + "notice": "The shared label database." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens." + }, + "PUBLIC_RESOLVER()": { + "notice": "The replacement `PublicResolver`." + }, + "PUBLIC_RESOLVER_SET()": { + "notice": "The list of `PublicResolver` contracts that require replacement." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "UPGRADE_GATE()": { + "notice": "Gate for approved implementation upgrade targets." + }, + "V1_RESOLVER()": { + "notice": "Fallback resolver for ENSv1 resolution." + }, + "VERIFIABLE_FACTORY()": { + "notice": "The shared factory for verifiable deployments." + }, + "WRAPPER_REGISTRY_IMPL()": { + "notice": "The `WrapperRegistry` implementation contract." + }, + "balanceOf(address,uint256)": { + "notice": "Returns the balance of a token for an account." + }, + "balanceOfBatch(address[],uint256[])": { + "notice": "Returns the balances of a batch of tokens for an account." + }, + "canUpgradeFrom(address)": { + "notice": "Declares this implementation as an eligible verifiable proxy upgrade target." + }, + "findExpiry(string)": { + "notice": "Fetches the label expiry." + }, + "findOwner(string)": { + "notice": "Fetches the label owner." + }, + "findTokenId(string)": { + "notice": "Fetches the token ID for a label." + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "notice": "Convert NameWrapper tokens to their equivalent ENSv2 form." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getExpiry(uint256)": { + "notice": "Get expiry of label." + }, + "getParent()": { + "notice": "Get canonical \"location\" of this registry." + }, + "getResolver(string)": { + "notice": "Fetches the resolver responsible for the specified label." + }, + "getResource(uint256)": { + "notice": "Get `resource` from `anyId`." + }, + "getState(uint256)": { + "notice": "Get the state of a label." + }, + "getStatus(uint256)": { + "notice": "Get `Status` from `anyId`." + }, + "getSubregistry(string)": { + "notice": "Fetches the registry for a label." + }, + "getTokenId(uint256)": { + "notice": "Get `tokenId` from `anyId`." + }, + "getWrappedName()": { + "notice": "Returns the DNS-encoded name for this registry." + }, + "getWrappedNode()": { + "notice": "Returns the NameWrapper node (namehash)." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "initialize(bytes32,address,string,address,uint256)": { + "notice": "Initializes WrapperRegistry." + }, + "isApprovedForAll(address,address)": { + "notice": "Returns the approval for all operator." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "latestOwnerOf(uint256)": { + "notice": "Get the latest owner of a token. If the token was burned, returns null." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "notice": "Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "notice": "Migrate one NameWrapper token via `safeTransferFrom()`." + }, + "ownerOf(uint256)": { + "notice": "Returns the owner of a token." + }, + "register(string,address,address,address,uint256,uint64)": { + "notice": "Registers a new label." + }, + "renew(uint256,uint64)": { + "notice": "Renew a label." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "notice": "Transfers multiple tokens from one address to another." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "notice": "Transfers a single token from one address to another." + }, + "setApprovalForAll(address,bool)": { + "notice": "Sets the approval for all operator." + }, + "setParent(address,string)": { + "notice": "Change canonical \"location\"." + }, + "setResolver(uint256,address)": { + "notice": "Change resolver of label." + }, + "setSubregistry(uint256,address)": { + "notice": "Change registry of label." + }, + "setURI(string,address)": { + "notice": "Set the URI for the registry." + }, + "unregister(uint256)": { + "notice": "Delete a label." + }, + "uri(uint256)": { + "notice": "Returns the URI for a token." + } + }, + "notice": "UUPS-upgradeable registry that wraps an ENSv1 NameWrapper, supporting migration of wrapped names into the namechain registry system.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce8000000000000000000000000802453f2f077d5a0c3d0f9a6eb2a36dcfa3c6e0d000000000000000000000000d2a632d8a8b67c2c4398c255cbd7af8dd7236198000000000000000000000000422484c2d51f92830bfb563fa5e172aa2d8b884b000000000000000000000000358680728dedb552adaa9f5eb5d4395b291cf9430000000000000000000000002c83019d86ff3be9cc269687215f4731158a8b6f00000000000000000000000023ea712da760c4e09fc9be108f1f1da6d5d6d053000000000000000000000000fef98bae02b882b00efa02f3d7b379bee6cda86b0000000000000000000000005239a812ec9a62f46dbb5de8f346c8efe7553a9f000000000000000000000000ffffffffff52d316b7bd028358089bc8066b8f80", + "transaction": { + "hash": "0x2a56e9d6c11745652138a531a3ad11b0cb02b30c8aa9790e3e3e5e43c937af26", + "nonce": "0x1e9a", + "origin": "0xffffffffff52d316b7bd028358089bc8066b8f80" + }, + "receipt": { + "blockHash": "0x028d5fe119073083e49f9cea447ee340390de2d89043f7d0cb60f108ae951390", + "blockNumber": "0xa6a80f", + "transactionIndex": "0x4e" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/.chain b/contracts/deployments/sepolia/.chain new file mode 100644 index 000000000..58f80a4ab --- /dev/null +++ b/contracts/deployments/sepolia/.chain @@ -0,0 +1 @@ +{"chainId":"11155111","genesisHash":"0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"} \ No newline at end of file diff --git a/contracts/deployments/sepolia/.deployment.json b/contracts/deployments/sepolia/.deployment.json new file mode 100644 index 000000000..729b1f33f --- /dev/null +++ b/contracts/deployments/sepolia/.deployment.json @@ -0,0 +1,5 @@ +{ + "environment": "sepolia", + "chainId": 11155111, + "deployedAt": "2026-06-29T05:35:12.452Z" +} diff --git a/contracts/deployments/sepolia/.migrations.json b/contracts/deployments/sepolia/.migrations.json new file mode 100644 index 000000000..3a0296b51 --- /dev/null +++ b/contracts/deployments/sepolia/.migrations.json @@ -0,0 +1 @@ +{"universal-resolver:deploy-universal-resolver:v1":1782711300,"universal-resolver:set-universal-resolver-to-v1:v1":1782711300,"universal-resolver:deploy-managed-urp:v1":1782711300,"universal-resolver:deploy-universal-resolver-implementation:v1":1782711312} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ApprovedUpgradeGate.json b/contracts/deployments/sepolia/ApprovedUpgradeGate.json new file mode 100644 index 000000000..72ce2df44 --- /dev/null +++ b/contracts/deployments/sepolia/ApprovedUpgradeGate.json @@ -0,0 +1,285 @@ +{ + "address": "0xc319c9efaae0bd01fec99b7f709fe41510a20595", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "indexed": true, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ImplementationApprovalChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "approvedImplementations", + "outputs": [ + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setImplementationApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "ApprovedUpgradeGate", + "sourceName": "src/registry/ApprovedUpgradeGate.sol", + "bytecode": "0x608060405234801561000f575f80fd5b506040516103fd3803806103fd83398101604081905261002e916100bb565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6100658161006c565b50506100e8565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156100cb575f80fd5b81516001600160a01b03811681146100e1575f80fd5b9392505050565b610308806100f55f395ff3fe608060405234801561000f575f80fd5b5060043610610064575f3560e01c806396b78cbe1161004d57806396b78cbe14610091578063e537b27b146100c3578063f2fde38b146100d6575f80fd5b8063715018a6146100685780638da5cb5b14610072575b5f80fd5b6100706100e9565b005b5f546040516001600160a01b0390911681526020015b60405180910390f35b6100b361009f366004610279565b60016020525f908152604090205460ff1681565b6040519015158152602001610088565b6100706100d1366004610299565b6100fc565b6100706100e4366004610279565b610157565b6100f16101b2565b6100fa5f6101f7565b565b6101046101b2565b6001600160a01b0382165f81815260016020526040808220805460ff191685151590811790915590519092917fdf2de8f46c1295aaa5eaaea8c458190346b99f2dd813bd0a543dff50c0c4106e91a35050565b61015f6101b2565b6001600160a01b0381166101a6576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6101af816101f7565b50565b5f546001600160a01b031633146100fa576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240161019d565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80356001600160a01b0381168114610274575f80fd5b919050565b5f60208284031215610289575f80fd5b6102928261025e565b9392505050565b5f80604083850312156102aa575f80fd5b6102b38361025e565b9150602083013580151581146102c7575f80fd5b80915050925092905056fea2646970667358221220cb539314b8d4c49496bb69b93883fbf520b7405a1c8d09bca64b1913b00c5beb64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610064575f3560e01c806396b78cbe1161004d57806396b78cbe14610091578063e537b27b146100c3578063f2fde38b146100d6575f80fd5b8063715018a6146100685780638da5cb5b14610072575b5f80fd5b6100706100e9565b005b5f546040516001600160a01b0390911681526020015b60405180910390f35b6100b361009f366004610279565b60016020525f908152604090205460ff1681565b6040519015158152602001610088565b6100706100d1366004610299565b6100fc565b6100706100e4366004610279565b610157565b6100f16101b2565b6100fa5f6101f7565b565b6101046101b2565b6001600160a01b0382165f81815260016020526040808220805460ff191685151590811790915590519092917fdf2de8f46c1295aaa5eaaea8c458190346b99f2dd813bd0a543dff50c0c4106e91a35050565b61015f6101b2565b6001600160a01b0381166101a6576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6101af816101f7565b50565b5f546001600160a01b031633146100fa576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240161019d565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80356001600160a01b0381168114610274575f80fd5b919050565b5f60208284031215610289575f80fd5b6102928261025e565b9392505050565b5f80604083850312156102aa575f80fd5b6102b38361025e565b9150602083013580151581146102c7575f80fd5b80915050925092905056fea2646970667358221220cb539314b8d4c49496bb69b93883fbf520b7405a1c8d09bca64b1913b00c5beb64736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/src/registry/ApprovedUpgradeGate.sol", + "devdoc": { + "errors": { + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "events": { + "ImplementationApprovalChanged(address,bool)": { + "params": { + "approved": "Whether upgrades to the implementation are approved.", + "implementation": "The implementation address." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "owner_": "The address that controls implementation approvals." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setImplementationApproval(address,bool)": { + "params": { + "approved": "Whether upgrades to the implementation are approved.", + "implementation": "The implementation address." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "155200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "approvedImplementations(address)": "2528", + "owner()": "2311", + "renounceOwnership()": "infinite", + "setImplementationApproval(address,bool)": "28398", + "transferOwnership(address)": "28358" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ImplementationApprovalChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"approvedImplementations\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setImplementationApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"ImplementationApprovalChanged(address,bool)\":{\"params\":{\"approved\":\"Whether upgrades to the implementation are approved.\",\"implementation\":\"The implementation address.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"owner_\":\"The address that controls implementation approvals.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setImplementationApproval(address,bool)\":{\"params\":{\"approved\":\"Whether upgrades to the implementation are approved.\",\"implementation\":\"The implementation address.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"events\":{\"ImplementationApprovalChanged(address,bool)\":{\"notice\":\"Approval status changed for an implementation.\"}},\"kind\":\"user\",\"methods\":{\"approvedImplementations(address)\":{\"notice\":\"Returns whether an implementation may be used as an upgrade target.\"},\"setImplementationApproval(address,bool)\":{\"notice\":\"Set whether an implementation may be used as an upgrade target.\"}},\"notice\":\"Allowlist for approved implementation upgrade targets.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/ApprovedUpgradeGate.sol\":\"ApprovedUpgradeGate\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/src/registry/ApprovedUpgradeGate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/// @notice Allowlist for approved implementation upgrade targets.\\ncontract ApprovedUpgradeGate is Ownable {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Returns whether an implementation may be used as an upgrade target.\\n mapping(address implementation => bool approved) public approvedImplementations;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Approval status changed for an implementation.\\n /// @param implementation The implementation address.\\n /// @param approved Whether upgrades to the implementation are approved.\\n event ImplementationApprovalChanged(address indexed implementation, bool indexed approved);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ The address that controls implementation approvals.\\n constructor(address owner_) Ownable(owner_) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Set whether an implementation may be used as an upgrade target.\\n /// @param implementation The implementation address.\\n /// @param approved Whether upgrades to the implementation are approved.\\n function setImplementationApproval(address implementation, bool approved) external onlyOwner {\\n approvedImplementations[implementation] = approved;\\n emit ImplementationApprovalChanged(implementation, approved);\\n }\\n}\\n\",\"keccak256\":\"0xecaf823f2344fb8336d18f889905de806299edfa6424796a24ce584eeda1eb2f\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 35256, + "contract": "project/src/registry/ApprovedUpgradeGate.sol:ApprovedUpgradeGate", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 66723, + "contract": "project/src/registry/ApprovedUpgradeGate.sol:ApprovedUpgradeGate", + "label": "approvedImplementations", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + }, + "userdoc": { + "events": { + "ImplementationApprovalChanged(address,bool)": { + "notice": "Approval status changed for an implementation." + } + }, + "kind": "user", + "methods": { + "approvedImplementations(address)": { + "notice": "Returns whether an implementation may be used as an upgrade target." + }, + "setImplementationApproval(address,bool)": { + "notice": "Set whether an implementation may be used as an upgrade target." + } + }, + "notice": "Allowlist for approved implementation upgrade targets.", + "version": 1 + }, + "argsData": "0x00000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d3", + "transaction": { + "hash": "0xc0ce8366832a67a21231176365cb92a1d15dcdb9dbe0280a231d635c4e821bfb", + "nonce": "0x5a", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xd7373161f537406091f749623fec781465c68711a4889b5d4b6e037f47158624", + "blockNumber": "0xaa570e", + "transactionIndex": "0x62" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/BatchRegistrar.json b/contracts/deployments/sepolia/BatchRegistrar.json new file mode 100644 index 000000000..6f25fc2cb --- /dev/null +++ b/contracts/deployments/sepolia/BatchRegistrar.json @@ -0,0 +1,282 @@ +{ + "address": "0xfe2aab6df1cbff84534ce65d9e4a755ba02d6795", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry_", + "type": "address" + }, + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InputLengthMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "string[]", + "name": "labels", + "type": "string[]" + }, + { + "internalType": "uint64[]", + "name": "expires", + "type": "uint64[]" + } + ], + "name": "batchRegister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "BatchRegistrar", + "sourceName": "src/registrar/BatchRegistrar.sol", + "bytecode": "0x60a060405234801561000f575f80fd5b506040516109d63803806109d683398101604081905261002e916100de565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006581610078565b50506001600160a01b0316608052610116565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146100db575f80fd5b50565b5f80604083850312156100ef575f80fd5b82516100fa816100c7565b602084015190925061010b816100c7565b809150509250929050565b6080516108946101425f395f818160820152818161013901528181610240015261038a01526108945ff3fe608060405234801561000f575f80fd5b5060043610610064575f3560e01c8063715018a61161004d578063715018a6146100c05780638da5cb5b146100c8578063f2fde38b146100d8575f80fd5b8063087be49f14610068578063475007081461007d575b5f80fd5b61007b6100763660046105ea565b6100eb565b005b6100a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61007b610469565b5f546001600160a01b03166100a4565b61007b6100e6366004610679565b61047c565b6100f36104d7565b82811461012c576040517faaad13f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b83811015610460575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286101c688888681811061017b5761017b61069b565b905060200281019061018d91906106af565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061051c92505050565b6040518263ffffffff1660e01b81526004016101e491815260200190565b60a060405180830381865afa1580156101ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610722565b90505f81516002811115610239576102396107b4565b03610324577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f3e64387878581811061027f5761027f61069b565b905060200281019061029191906106af565b5f8c8c5f8b8b8b8181106102a7576102a761069b565b90506020020160208101906102bc91906107c8565b6040518863ffffffff1660e01b81526004016102de97969594939291906107e3565b6020604051808303815f875af11580156102fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610847565b50610457565b600181516002811115610339576103396107b4565b1480156103835750806020015167ffffffffffffffff168484848181106103625761036261069b565b905060200201602081019061037791906107c8565b67ffffffffffffffff16115b15610457577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635569f33d82606001518686868181106103ce576103ce61069b565b90506020020160208101906103e391906107c8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925267ffffffffffffffff1660248201526044015f604051808303815f87803b158015610440575f80fd5b505af1158015610452573d5f803e3d5ffd5b505050505b5060010161012e565b50505050505050565b6104716104d7565b61047a5f610527565b565b6104846104d7565b6001600160a01b0381166104cb576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d481610527565b50565b5f546001600160a01b0316331461047a576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104c2565b805160209091012090565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146104d4575f80fd5b5f8083601f8401126105b2575f80fd5b50813567ffffffffffffffff8111156105c9575f80fd5b6020830191508360208260051b85010111156105e3575f80fd5b9250929050565b5f805f805f80608087890312156105ff575f80fd5b863561060a8161058e565b9550602087013561061a8161058e565b9450604087013567ffffffffffffffff80821115610636575f80fd5b6106428a838b016105a2565b9096509450606089013591508082111561065a575f80fd5b5061066789828a016105a2565b979a9699509497509295939492505050565b5f60208284031215610689575f80fd5b81356106948161058e565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e198436030181126106c4575f80fd5b83018035915067ffffffffffffffff8211156106de575f80fd5b6020019150368190038213156105e3575f80fd5b67ffffffffffffffff811681146104d4575f80fd5b8051610712816106f2565b919050565b80516107128161058e565b5f60a08284031215610732575f80fd5b60405160a0810181811067ffffffffffffffff8211171561076157634e487b7160e01b5f52604160045260245ffd5b604052825160038110610772575f80fd5b815261078060208401610707565b602082015261079160408401610717565b604082015260608301516060820152608083015160808201528091505092915050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156107d8575f80fd5b8135610694816106f2565b60c081528660c0820152868860e08301375f60e08883018101919091526001600160a01b0396871660208301529486166040820152929094166060830152608082015267ffffffffffffffff90921660a0830152601f909201601f19160101919050565b5f60208284031215610857575f80fd5b505191905056fea26469706673582212207fe9d472b8dd9a39f4a2db98a90e397b3f465d0364f914c103b5b629722c17d864736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610064575f3560e01c8063715018a61161004d578063715018a6146100c05780638da5cb5b146100c8578063f2fde38b146100d8575f80fd5b8063087be49f14610068578063475007081461007d575b5f80fd5b61007b6100763660046105ea565b6100eb565b005b6100a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61007b610469565b5f546001600160a01b03166100a4565b61007b6100e6366004610679565b61047c565b6100f36104d7565b82811461012c576040517faaad13f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b83811015610460575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286101c688888681811061017b5761017b61069b565b905060200281019061018d91906106af565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061051c92505050565b6040518263ffffffff1660e01b81526004016101e491815260200190565b60a060405180830381865afa1580156101ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610722565b90505f81516002811115610239576102396107b4565b03610324577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f3e64387878581811061027f5761027f61069b565b905060200281019061029191906106af565b5f8c8c5f8b8b8b8181106102a7576102a761069b565b90506020020160208101906102bc91906107c8565b6040518863ffffffff1660e01b81526004016102de97969594939291906107e3565b6020604051808303815f875af11580156102fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610847565b50610457565b600181516002811115610339576103396107b4565b1480156103835750806020015167ffffffffffffffff168484848181106103625761036261069b565b905060200201602081019061037791906107c8565b67ffffffffffffffff16115b15610457577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635569f33d82606001518686868181106103ce576103ce61069b565b90506020020160208101906103e391906107c8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925267ffffffffffffffff1660248201526044015f604051808303815f87803b158015610440575f80fd5b505af1158015610452573d5f803e3d5ffd5b505050505b5060010161012e565b50505050505050565b6104716104d7565b61047a5f610527565b565b6104846104d7565b6001600160a01b0381166104cb576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d481610527565b50565b5f546001600160a01b0316331461047a576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104c2565b805160209091012090565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146104d4575f80fd5b5f8083601f8401126105b2575f80fd5b50813567ffffffffffffffff8111156105c9575f80fd5b6020830191508360208260051b85010111156105e3575f80fd5b9250929050565b5f805f805f80608087890312156105ff575f80fd5b863561060a8161058e565b9550602087013561061a8161058e565b9450604087013567ffffffffffffffff80821115610636575f80fd5b6106428a838b016105a2565b9096509450606089013591508082111561065a575f80fd5b5061066789828a016105a2565b979a9699509497509295939492505050565b5f60208284031215610689575f80fd5b81356106948161058e565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e198436030181126106c4575f80fd5b83018035915067ffffffffffffffff8211156106de575f80fd5b6020019150368190038213156105e3575f80fd5b67ffffffffffffffff811681146104d4575f80fd5b8051610712816106f2565b919050565b80516107128161058e565b5f60a08284031215610732575f80fd5b60405160a0810181811067ffffffffffffffff8211171561076157634e487b7160e01b5f52604160045260245ffd5b604052825160038110610772575f80fd5b815261078060208401610707565b602082015261079160408401610717565b604082015260608301516060820152608083015160808201528091505092915050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156107d8575f80fd5b8135610694816106f2565b60c081528660c0820152868860e08301375f60e08883018101919091526001600160a01b0396871660208301529486166040820152929094166060830152608082015267ffffffffffffffff90921660a0830152601f909201601f19160101919050565b5f60208284031215610857575f80fd5b505191905056fea26469706673582212207fe9d472b8dd9a39f4a2db98a90e397b3f465d0364f914c103b5b629722c17d864736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "27367": [ + { + "length": 32, + "start": 130 + }, + { + "length": 32, + "start": 313 + }, + { + "length": 32, + "start": 576 + }, + { + "length": 32, + "start": 906 + } + ] + }, + "inputSourceName": "project/src/registrar/BatchRegistrar.sol", + "devdoc": { + "errors": { + "InputLengthMismatch()": [ + { + "details": "Error selector: `0xaaad13f7`" + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "kind": "dev", + "methods": { + "batchRegister(address,address,string[],uint64[])": { + "params": { + "expires": "Array of expiry timestamps corresponding to each label", + "labels": "Array of labels to reserve or renew", + "registry": "The registry for all names", + "resolver": "The resolver for all names" + } + }, + "constructor": { + "params": { + "ethRegistry_": "The ETH registry to use for batch registration.", + "owner_": "The owner of the contract." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "title": "BatchRegistrar", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "439200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ETH_REGISTRY()": "infinite", + "batchRegister(address,address,string[],uint64[])": "infinite", + "owner()": "2339", + "renounceOwnership()": "infinite", + "transferOwnership(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InputLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"labels\",\"type\":\"string[]\"},{\"internalType\":\"uint64[]\",\"name\":\"expires\",\"type\":\"uint64[]\"}],\"name\":\"batchRegister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InputLengthMismatch()\":[{\"details\":\"Error selector: `0xaaad13f7`\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"kind\":\"dev\",\"methods\":{\"batchRegister(address,address,string[],uint64[])\":{\"params\":{\"expires\":\"Array of expiry timestamps corresponding to each label\",\"labels\":\"Array of labels to reserve or renew\",\"registry\":\"The registry for all names\",\"resolver\":\"The resolver for all names\"}},\"constructor\":{\"params\":{\"ethRegistry_\":\"The ETH registry to use for batch registration.\",\"owner_\":\"The owner of the contract.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"BatchRegistrar\",\"version\":1},\"userdoc\":{\"errors\":{\"InputLengthMismatch()\":[{\"notice\":\"Thrown when batch registration inputs have different lengths.\"}]},\"kind\":\"user\",\"methods\":{\"ETH_REGISTRY()\":{\"notice\":\"The ETH registry to use for batch registration.\"},\"batchRegister(address,address,string[],uint64[])\":{\"notice\":\"Batch reserve or renew names for pre-migration\"}},\"notice\":\"Simple batch registration contract for pre-migration of ENS names. Only the owner can invoke batch registration.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/BatchRegistrar.sol\":\"BatchRegistrar\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registrar/BatchRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\n/// @title BatchRegistrar\\n/// @notice Simple batch registration contract for pre-migration of ENS names.\\n/// Only the owner can invoke batch registration.\\ncontract BatchRegistrar is Ownable {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ETH registry to use for batch registration.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Thrown when batch registration inputs have different lengths.\\n /// @dev Error selector: `0xaaad13f7`\\n error InputLengthMismatch();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param ethRegistry_ The ETH registry to use for batch registration.\\n /// @param owner_ The owner of the contract.\\n constructor(IPermissionedRegistry ethRegistry_, address owner_) Ownable(owner_) {\\n ETH_REGISTRY = ethRegistry_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Batch reserve or renew names for pre-migration\\n /// @param registry The registry for all names\\n /// @param resolver The resolver for all names\\n /// @param labels Array of labels to reserve or renew\\n /// @param expires Array of expiry timestamps corresponding to each label\\n function batchRegister(\\n IRegistry registry,\\n address resolver,\\n string[] calldata labels,\\n uint64[] calldata expires\\n )\\n external\\n onlyOwner\\n {\\n if (labels.length != expires.length) {\\n revert InputLengthMismatch();\\n }\\n\\n for (uint256 i = 0; i < labels.length; i++) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(labels[i]));\\n\\n if (state.status == IPermissionedRegistry.Status.AVAILABLE) {\\n ETH_REGISTRY.register(labels[i], address(0), registry, resolver, 0, expires[i]);\\n } else if (\\n state.status == IPermissionedRegistry.Status.RESERVED && expires[i] > state.expiry\\n ) {\\n ETH_REGISTRY.renew(state.tokenId, expires[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x500267938ff1c4abbf7fcb0155e65759a672e0d12c16217290e1c38fca25d6fd\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 14920, + "contract": "project/src/registrar/BatchRegistrar.sol:BatchRegistrar", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + }, + "userdoc": { + "errors": { + "InputLengthMismatch()": [ + { + "notice": "Thrown when batch registration inputs have different lengths." + } + ] + }, + "kind": "user", + "methods": { + "ETH_REGISTRY()": { + "notice": "The ETH registry to use for batch registration." + }, + "batchRegister(address,address,string[],uint64[])": { + "notice": "Batch reserve or renew names for pre-migration" + } + }, + "notice": "Simple batch registration contract for pre-migration of ENS names. Only the owner can invoke batch registration.", + "version": 1 + }, + "argsData": "0x00000000000000000000000067b728a792e789a8978b30cf1b3b641f19354b4300000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d3", + "transaction": { + "hash": "0x376fbe3c2612c73eb135061af4697a3397a354e057514e8a2eb29d8442f0f2ef", + "nonce": "0x5f", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xdc9a9bddbdf5808b15c51b980d861311c2ff371bf886d3edc2f73f719e4acabf", + "blockNumber": "0xaa5713", + "transactionIndex": "0xa5" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ContractNamer.json b/contracts/deployments/sepolia/ContractNamer.json new file mode 100644 index 000000000..edf282de1 --- /dev/null +++ b/contracts/deployments/sepolia/ContractNamer.json @@ -0,0 +1,465 @@ +{ + "address": "0x68658a771044873906fc9b6e9f278ac5a0501342", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + } + ], + "contractName": "ContractNamer", + "sourceName": "src/utils/ContractNamer.sol", + "bytecode": "0x60a060405230608052348015610013575f80fd5b5061001c610021565b6100d3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100715760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d05780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b608051610c866100f95f395f81816104de01528181610507015261068a0152610c865ff3fe608060405260043610610093575f3560e01c8063715018a611610066578063ad3cb1cc1161004c578063ad3cb1cc1461017b578063c4d66de8146101d0578063f2fde38b146101ef575f80fd5b8063715018a6146101215780638da5cb5b14610135575f80fd5b806301ffc9a7146100975780634f1ef286146100cb57806352d1902d146100e05780636f3ff72614610102575b5f80fd5b3480156100a2575f80fd5b506100b66100b1366004610a92565b61020e565b60405190151581526020015b60405180910390f35b6100de6100d9366004610b19565b6102a6565b005b3480156100eb575f80fd5b506100f46102c5565b6040519081526020016100c2565b34801561010d575f80fd5b506100b661011c366004610bd5565b6102f3565b34801561012c575f80fd5b506100de61033f565b348015610140575f80fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020016100c2565b348015610186575f80fd5b506101c36040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c29190610bee565b3480156101db575f80fd5b506100de6101ea366004610bd5565b610352565b3480156101fa575f80fd5b506100de610209366004610bd5565b610478565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f6f3ff7260000000000000000000000000000000000000000000000000000000014806102a057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6102ae6104d3565b6102b78261058a565b6102c18282610592565b5050565b5f6102ce61067f565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f816001600160a01b031661032f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161492915050565b6103476106c8565b6103505f61073c565b565b5f61035b6107b9565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156103875750825b90505f8267ffffffffffffffff1660011480156103a35750303b155b9050811580156103b1575080155b156103e8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561041c57845468ff00000000000000001916680100000000000000001785555b610425866107e1565b831561047057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6104806106c8565b6001600160a01b0381166104c7576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d08161073c565b50565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061056c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156103505760405163703e46dd60e11b815260040160405180910390fd5b6104d06106c8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105ec575060408051601f3d908101601f191682019092526105e991810190610c23565b60015b61061457604051634c9c8ce360e01b81526001600160a01b03831660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610670576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016104be565b61067a83836107f2565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103505760405163703e46dd60e11b815260040160405180910390fd5b336106fa7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610350576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104be565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102a0565b6107e9610847565b6104d081610885565b6107fb8261088d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561083f5761067a8282610910565b6102c1610982565b61084f6109ba565b610350576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610480610847565b806001600160a01b03163b5f036108c257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161092c9190610c3a565b5f60405180830381855af49150503d805f8114610964576040519150601f19603f3d011682016040523d82523d5f602084013e610969565b606091505b50915091506109798583836109d8565b95945050505050565b3415610350576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6109c36107b9565b5468010000000000000000900460ff16919050565b6060826109ed576109e882610a50565b610a49565b8151158015610a0457506001600160a01b0384163b155b15610a46576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016104be565b50805b9392505050565b805115610a605780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610aa2575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a49575f80fd5b80356001600160a01b0381168114610ae7575f80fd5b919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8060408385031215610b2a575f80fd5b610b3383610ad1565b9150602083013567ffffffffffffffff80821115610b4f575f80fd5b818501915085601f830112610b62575f80fd5b813581811115610b7457610b74610aec565b604051601f8201601f19908116603f01168101908382118183101715610b9c57610b9c610aec565b81604052828152886020848701011115610bb4575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f60208284031215610be5575f80fd5b610a4982610ad1565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610c33575f80fd5b5051919050565b5f82518060208501845e5f92019182525091905056fea2646970667358221220735b566ee9514b545cc8251908db072b28ccbb5f8a73ed0d9d8d6c8e8872131564736f6c63430008190033", + "deployedBytecode": "0x608060405260043610610093575f3560e01c8063715018a611610066578063ad3cb1cc1161004c578063ad3cb1cc1461017b578063c4d66de8146101d0578063f2fde38b146101ef575f80fd5b8063715018a6146101215780638da5cb5b14610135575f80fd5b806301ffc9a7146100975780634f1ef286146100cb57806352d1902d146100e05780636f3ff72614610102575b5f80fd5b3480156100a2575f80fd5b506100b66100b1366004610a92565b61020e565b60405190151581526020015b60405180910390f35b6100de6100d9366004610b19565b6102a6565b005b3480156100eb575f80fd5b506100f46102c5565b6040519081526020016100c2565b34801561010d575f80fd5b506100b661011c366004610bd5565b6102f3565b34801561012c575f80fd5b506100de61033f565b348015610140575f80fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020016100c2565b348015610186575f80fd5b506101c36040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c29190610bee565b3480156101db575f80fd5b506100de6101ea366004610bd5565b610352565b3480156101fa575f80fd5b506100de610209366004610bd5565b610478565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f6f3ff7260000000000000000000000000000000000000000000000000000000014806102a057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6102ae6104d3565b6102b78261058a565b6102c18282610592565b5050565b5f6102ce61067f565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f816001600160a01b031661032f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161492915050565b6103476106c8565b6103505f61073c565b565b5f61035b6107b9565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156103875750825b90505f8267ffffffffffffffff1660011480156103a35750303b155b9050811580156103b1575080155b156103e8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561041c57845468ff00000000000000001916680100000000000000001785555b610425866107e1565b831561047057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6104806106c8565b6001600160a01b0381166104c7576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d08161073c565b50565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061056c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156103505760405163703e46dd60e11b815260040160405180910390fd5b6104d06106c8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105ec575060408051601f3d908101601f191682019092526105e991810190610c23565b60015b61061457604051634c9c8ce360e01b81526001600160a01b03831660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610670576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016104be565b61067a83836107f2565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103505760405163703e46dd60e11b815260040160405180910390fd5b336106fa7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610350576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104be565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102a0565b6107e9610847565b6104d081610885565b6107fb8261088d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561083f5761067a8282610910565b6102c1610982565b61084f6109ba565b610350576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610480610847565b806001600160a01b03163b5f036108c257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161092c9190610c3a565b5f60405180830381855af49150503d805f8114610964576040519150601f19603f3d011682016040523d82523d5f602084013e610969565b606091505b50915091506109798583836109d8565b95945050505050565b3415610350576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6109c36107b9565b5468010000000000000000900460ff16919050565b6060826109ed576109e882610a50565b610a49565b8151158015610a0457506001600160a01b0384163b155b15610a46576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016104be565b50805b9392505050565b805115610a605780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610aa2575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a49575f80fd5b80356001600160a01b0381168114610ae7575f80fd5b919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8060408385031215610b2a575f80fd5b610b3383610ad1565b9150602083013567ffffffffffffffff80821115610b4f575f80fd5b818501915085601f830112610b62575f80fd5b813581811115610b7457610b74610aec565b604051601f8201601f19908116603f01168101908382118183101715610b9c57610b9c610aec565b81604052828152886020848701011115610bb4575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f60208284031215610be5575f80fd5b610a4982610ad1565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610c33575f80fd5b5051919050565b5f82518060208501845e5f92019182525091905056fea2646970667358221220735b566ee9514b545cc8251908db072b28ccbb5f8a73ed0d9d8d6c8e8872131564736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ] + }, + "events": { + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "initialize(address)": { + "params": { + "owner_": "The contract owner." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "641200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "UPGRADE_INTERFACE_VERSION()": "infinite", + "initialize(address)": "infinite", + "isContractNamer(address)": "2609", + "owner()": "2345", + "proxiableUUID()": "infinite", + "renounceOwnership()": "infinite", + "supportsInterface(bytes4)": "367", + "transferOwnership(address)": "28419", + "upgradeToAndCall(address,bytes)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}]},\"events\":{\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"initialize(address)\":{\"params\":{\"owner_\":\"The contract owner.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(address)\":{\"notice\":\"Initialize the contract.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"}},\"notice\":\"Shared `IContractNamer` instance.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/utils/ContractNamer.sol\":\"ContractNamer\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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 OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\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 * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\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 Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\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 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\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 _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\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 // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\\n *\\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\\n */\\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\\n return INITIALIZABLE_STORAGE;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n bytes32 slot = _initializableStorageSlot();\\n assembly {\\n $.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IERC1822Proxiable} from \\\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\\\";\\nimport {Initializable} from \\\"./Initializable.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 */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\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 _checkNotDelegated();\\n _;\\n }\\n\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\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 * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {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 onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: 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\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\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 ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\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 ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.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 the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\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 ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\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 * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, bytes memory returndata) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n _revert(returndata);\\n }\\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 or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) 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 assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/ContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @notice Shared `IContractNamer` instance.\\ncontract ContractNamer is ERC165, OwnableUpgradeable, UUPSUpgradeable, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /// @notice Initialize the contract.\\n /// @param owner_ The contract owner.\\n function initialize(address owner_) external initializer {\\n __Ownable_init(owner_);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return owner() == namer;\\n }\\n\\n /// @dev Allow owner to upgrade.\\n function _authorizeUpgrade(address) internal override onlyOwner {}\\n}\\n\",\"keccak256\":\"0x69dc17485dba9a662c0c577677eb9a06dcfbe1cdb0bc8471f23ae8fc6fcf856f\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": { + "initialize(address)": { + "notice": "Initialize the contract." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + } + }, + "notice": "Shared `IContractNamer` instance.", + "version": 1 + }, + "solcInput": "{\n \"language\": \"Solidity\",\n \"sources\": {\n \"solc_0.8/openzeppelin/access/Ownable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 (address initialOwner) {\\n _transferOwnership(initialOwner);\\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 _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\"\n },\n \"solc_0.8/openzeppelin/utils/Context.sol\": {\n \"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\"\n },\n \"solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./TransparentUpgradeableProxy.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\n\\n/**\\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\\n */\\ncontract ProxyAdmin is Ownable {\\n\\n constructor (address initialOwner) Ownable(initialOwner) {}\\n\\n /**\\n * @dev Returns the current implementation of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"implementation()\\\")) == 0x5c60da1b\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"5c60da1b\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Returns the current admin of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"admin()\\\")) == 0xf851a440\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"f851a440\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Changes the admin of `proxy` to `newAdmin`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the current admin of `proxy`.\\n */\\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\\n proxy.changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\\n proxy.upgradeTo(implementation);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgradeAndCall(\\n TransparentUpgradeableProxy proxy,\\n address implementation,\\n bytes memory data\\n ) public payable virtual onlyOwner {\\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\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\"\n },\n \"solc_0.8/openzeppelin/proxy/Proxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 overriden 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 internall 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 overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 virtual 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(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\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\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\": {\n \"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\"\n },\n \"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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\"\n },\n \"solc_0.8/openzeppelin/utils/Address.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 functionCall(target, data, \\\"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 require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason 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 // 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\\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}\\n\"\n },\n \"solc_0.8/openzeppelin/utils/StorageSlot.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 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 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 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 assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\"\n },\n \"solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract OptimizedTransparentUpgradeableProxy is ERC1967Proxy {\\n address internal immutable _ADMIN;\\n\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _ADMIN = admin_;\\n\\n // still store it to work with EIP-1967\\n bytes32 slot = _ADMIN_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, admin_)\\n }\\n emit AdminChanged(address(0), admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n\\n function _getAdmin() internal view virtual override returns (address) {\\n return _ADMIN;\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/utils/UUPSUpgradeable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 that the this implementation remains valid after 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\"\n },\n \"solc_0.8/openzeppelin/proxy/utils/Initializable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.0;\\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 * 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 initialize the implementation contract, you can either invoke the\\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() initializer {}\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool 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 Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\\n // contract may have been reentered.\\n require(_initializing ? _isConstructor() : !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} modifier, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n function _isConstructor() private view returns (bool) {\\n return !Address.isContract(address(this));\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/UpgradeableBeacon.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\\n * implementation contract, which is where they will delegate all function calls.\\n *\\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\\n */\\ncontract UpgradeableBeacon is IBeacon, Ownable {\\n address private _implementation;\\n\\n /**\\n * @dev Emitted when the implementation returned by the beacon is changed.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\\n * beacon.\\n */\\n\\n constructor(address implementation_, address initialOwner) Ownable(initialOwner) {\\n _setImplementation(implementation_);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function implementation() public view virtual override returns (address) {\\n return _implementation;\\n }\\n\\n /**\\n * @dev Upgrades the beacon to a new implementation.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * Requirements:\\n *\\n * - msg.sender must be the owner of the contract.\\n * - `newImplementation` must be a contract.\\n */\\n function upgradeTo(address newImplementation) public virtual onlyOwner {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Sets the implementation contract address for this beacon\\n *\\n * Requirements:\\n *\\n * - `newImplementation` must be a contract.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"UpgradeableBeacon: implementation is not a contract\\\");\\n _implementation = newImplementation;\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/BeaconProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"../ERC1967/ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.\\n *\\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\\n * conflict with the storage layout of the implementation behind the proxy.\\n *\\n * _Available since v3.4._\\n */\\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the proxy with `beacon`.\\n *\\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\\n * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity\\n * constructor.\\n *\\n * Requirements:\\n *\\n * - `beacon` must be a contract with the interface {IBeacon}.\\n */\\n constructor(address beacon, bytes memory data) payable {\\n assert(_BEACON_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.beacon\\\")) - 1));\\n _upgradeBeaconToAndCall(beacon, data, false);\\n }\\n\\n /**\\n * @dev Returns the current beacon address.\\n */\\n function _beacon() internal view virtual returns (address) {\\n return _getBeacon();\\n }\\n\\n /**\\n * @dev Returns the current implementation address of the associated beacon.\\n */\\n function _implementation() internal view virtual override returns (address) {\\n return IBeacon(_getBeacon()).implementation();\\n }\\n\\n /**\\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\\n *\\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\\n *\\n * Requirements:\\n *\\n * - `beacon` must be a contract.\\n * - The implementation returned by `beacon` must be a contract.\\n */\\n function _setBeacon(address beacon, bytes memory data) internal virtual {\\n _upgradeBeaconToAndCall(beacon, data, false);\\n }\\n}\\n\"\n }\n },\n \"settings\": {\n \"optimizer\": {\n \"enabled\": true,\n \"runs\": 999999\n },\n \"outputSelection\": {\n \"*\": {\n \"*\": [\n \"abi\",\n \"evm.bytecode\",\n \"evm.deployedBytecode\",\n \"evm.methodIdentifiers\",\n \"metadata\",\n \"devdoc\",\n \"userdoc\",\n \"storageLayout\",\n \"evm.gasEstimates\"\n ],\n \"\": [\n \"ast\"\n ]\n }\n },\n \"metadata\": {\n \"useLiteralContent\": true\n }\n }\n}", + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "argsData": "0x0000000000000000000000001520935e3c23c7d3cf0024537f53bf2bf26c955300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de800000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d300000000000000000000000000000000000000000000000000000000", + "transaction": { + "hash": "0x03b7e559ed4fa05fe7007325d2aaa7ad19198e4f590233e32301b0bd1632e040", + "nonce": "0xb", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x84c17f1ff54fd44334773abb4e7cffccd1a1cb130104767fd16608e953b62cb5", + "blockNumber": "0xaa56b2", + "transactionIndex": "0x67" + }, + "immutableReferences": { + "29968": [ + { + "length": 32, + "start": 1246 + }, + { + "length": 32, + "start": 1287 + }, + { + "length": 32, + "start": 1674 + } + ] + }, + "inputSourceName": "project/src/utils/ContractNamer.sol" +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ContractNamer_Implementation.json b/contracts/deployments/sepolia/ContractNamer_Implementation.json new file mode 100644 index 000000000..78449d478 --- /dev/null +++ b/contracts/deployments/sepolia/ContractNamer_Implementation.json @@ -0,0 +1,436 @@ +{ + "address": "0x1520935e3c23c7d3cf0024537f53bf2bf26c9553", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "contractName": "ContractNamer", + "sourceName": "src/utils/ContractNamer.sol", + "bytecode": "0x60a060405230608052348015610013575f80fd5b5061001c610021565b6100d3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100715760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d05780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b608051610c866100f95f395f81816104de01528181610507015261068a0152610c865ff3fe608060405260043610610093575f3560e01c8063715018a611610066578063ad3cb1cc1161004c578063ad3cb1cc1461017b578063c4d66de8146101d0578063f2fde38b146101ef575f80fd5b8063715018a6146101215780638da5cb5b14610135575f80fd5b806301ffc9a7146100975780634f1ef286146100cb57806352d1902d146100e05780636f3ff72614610102575b5f80fd5b3480156100a2575f80fd5b506100b66100b1366004610a92565b61020e565b60405190151581526020015b60405180910390f35b6100de6100d9366004610b19565b6102a6565b005b3480156100eb575f80fd5b506100f46102c5565b6040519081526020016100c2565b34801561010d575f80fd5b506100b661011c366004610bd5565b6102f3565b34801561012c575f80fd5b506100de61033f565b348015610140575f80fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020016100c2565b348015610186575f80fd5b506101c36040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c29190610bee565b3480156101db575f80fd5b506100de6101ea366004610bd5565b610352565b3480156101fa575f80fd5b506100de610209366004610bd5565b610478565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f6f3ff7260000000000000000000000000000000000000000000000000000000014806102a057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6102ae6104d3565b6102b78261058a565b6102c18282610592565b5050565b5f6102ce61067f565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f816001600160a01b031661032f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161492915050565b6103476106c8565b6103505f61073c565b565b5f61035b6107b9565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156103875750825b90505f8267ffffffffffffffff1660011480156103a35750303b155b9050811580156103b1575080155b156103e8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561041c57845468ff00000000000000001916680100000000000000001785555b610425866107e1565b831561047057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6104806106c8565b6001600160a01b0381166104c7576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d08161073c565b50565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061056c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156103505760405163703e46dd60e11b815260040160405180910390fd5b6104d06106c8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105ec575060408051601f3d908101601f191682019092526105e991810190610c23565b60015b61061457604051634c9c8ce360e01b81526001600160a01b03831660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610670576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016104be565b61067a83836107f2565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103505760405163703e46dd60e11b815260040160405180910390fd5b336106fa7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610350576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104be565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102a0565b6107e9610847565b6104d081610885565b6107fb8261088d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561083f5761067a8282610910565b6102c1610982565b61084f6109ba565b610350576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610480610847565b806001600160a01b03163b5f036108c257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161092c9190610c3a565b5f60405180830381855af49150503d805f8114610964576040519150601f19603f3d011682016040523d82523d5f602084013e610969565b606091505b50915091506109798583836109d8565b95945050505050565b3415610350576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6109c36107b9565b5468010000000000000000900460ff16919050565b6060826109ed576109e882610a50565b610a49565b8151158015610a0457506001600160a01b0384163b155b15610a46576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016104be565b50805b9392505050565b805115610a605780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610aa2575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a49575f80fd5b80356001600160a01b0381168114610ae7575f80fd5b919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8060408385031215610b2a575f80fd5b610b3383610ad1565b9150602083013567ffffffffffffffff80821115610b4f575f80fd5b818501915085601f830112610b62575f80fd5b813581811115610b7457610b74610aec565b604051601f8201601f19908116603f01168101908382118183101715610b9c57610b9c610aec565b81604052828152886020848701011115610bb4575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f60208284031215610be5575f80fd5b610a4982610ad1565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610c33575f80fd5b5051919050565b5f82518060208501845e5f92019182525091905056fea2646970667358221220735b566ee9514b545cc8251908db072b28ccbb5f8a73ed0d9d8d6c8e8872131564736f6c63430008190033", + "deployedBytecode": "0x608060405260043610610093575f3560e01c8063715018a611610066578063ad3cb1cc1161004c578063ad3cb1cc1461017b578063c4d66de8146101d0578063f2fde38b146101ef575f80fd5b8063715018a6146101215780638da5cb5b14610135575f80fd5b806301ffc9a7146100975780634f1ef286146100cb57806352d1902d146100e05780636f3ff72614610102575b5f80fd5b3480156100a2575f80fd5b506100b66100b1366004610a92565b61020e565b60405190151581526020015b60405180910390f35b6100de6100d9366004610b19565b6102a6565b005b3480156100eb575f80fd5b506100f46102c5565b6040519081526020016100c2565b34801561010d575f80fd5b506100b661011c366004610bd5565b6102f3565b34801561012c575f80fd5b506100de61033f565b348015610140575f80fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b0390911681526020016100c2565b348015610186575f80fd5b506101c36040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c29190610bee565b3480156101db575f80fd5b506100de6101ea366004610bd5565b610352565b3480156101fa575f80fd5b506100de610209366004610bd5565b610478565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f6f3ff7260000000000000000000000000000000000000000000000000000000014806102a057507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6102ae6104d3565b6102b78261058a565b6102c18282610592565b5050565b5f6102ce61067f565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f816001600160a01b031661032f7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161492915050565b6103476106c8565b6103505f61073c565b565b5f61035b6107b9565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f811580156103875750825b90505f8267ffffffffffffffff1660011480156103a35750303b155b9050811580156103b1575080155b156103e8576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561041c57845468ff00000000000000001916680100000000000000001785555b610425866107e1565b831561047057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b6104806106c8565b6001600160a01b0381166104c7576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d08161073c565b50565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061056c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105607f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156103505760405163703e46dd60e11b815260040160405180910390fd5b6104d06106c8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156105ec575060408051601f3d908101601f191682019092526105e991810190610c23565b60015b61061457604051634c9c8ce360e01b81526001600160a01b03831660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114610670576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016104be565b61067a83836107f2565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103505760405163703e46dd60e11b815260040160405180910390fd5b336106fa7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610350576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104be565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006102a0565b6107e9610847565b6104d081610885565b6107fb8261088d565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561083f5761067a8282610910565b6102c1610982565b61084f6109ba565b610350576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610480610847565b806001600160a01b03163b5f036108c257604051634c9c8ce360e01b81526001600160a01b03821660048201526024016104be565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161092c9190610c3a565b5f60405180830381855af49150503d805f8114610964576040519150601f19603f3d011682016040523d82523d5f602084013e610969565b606091505b50915091506109798583836109d8565b95945050505050565b3415610350576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6109c36107b9565b5468010000000000000000900460ff16919050565b6060826109ed576109e882610a50565b610a49565b8151158015610a0457506001600160a01b0384163b155b15610a46576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016104be565b50805b9392505050565b805115610a605780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208284031215610aa2575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610a49575f80fd5b80356001600160a01b0381168114610ae7575f80fd5b919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8060408385031215610b2a575f80fd5b610b3383610ad1565b9150602083013567ffffffffffffffff80821115610b4f575f80fd5b818501915085601f830112610b62575f80fd5b813581811115610b7457610b74610aec565b604051601f8201601f19908116603f01168101908382118183101715610b9c57610b9c610aec565b81604052828152886020848701011115610bb4575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f60208284031215610be5575f80fd5b610a4982610ad1565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610c33575f80fd5b5051919050565b5f82518060208501845e5f92019182525091905056fea2646970667358221220735b566ee9514b545cc8251908db072b28ccbb5f8a73ed0d9d8d6c8e8872131564736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "29968": [ + { + "length": 32, + "start": 1246 + }, + { + "length": 32, + "start": 1287 + }, + { + "length": 32, + "start": 1674 + } + ] + }, + "inputSourceName": "project/src/utils/ContractNamer.sol", + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ] + }, + "events": { + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "initialize(address)": { + "params": { + "owner_": "The contract owner." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "641200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "UPGRADE_INTERFACE_VERSION()": "infinite", + "initialize(address)": "infinite", + "isContractNamer(address)": "2609", + "owner()": "2345", + "proxiableUUID()": "infinite", + "renounceOwnership()": "infinite", + "supportsInterface(bytes4)": "367", + "transferOwnership(address)": "28419", + "upgradeToAndCall(address,bytes)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}]},\"events\":{\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"initialize(address)\":{\"params\":{\"owner_\":\"The contract owner.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"initialize(address)\":{\"notice\":\"Initialize the contract.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"}},\"notice\":\"Shared `IContractNamer` instance.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/utils/ContractNamer.sol\":\"ContractNamer\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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 OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\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 * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\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 Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\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 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\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 _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\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 // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\\n *\\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\\n */\\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\\n return INITIALIZABLE_STORAGE;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n bytes32 slot = _initializableStorageSlot();\\n assembly {\\n $.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IERC1822Proxiable} from \\\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\\\";\\nimport {Initializable} from \\\"./Initializable.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 */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\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 _checkNotDelegated();\\n _;\\n }\\n\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\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 * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {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 onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: 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\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\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 ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\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 ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.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 the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\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 ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\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 * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, bytes memory returndata) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n _revert(returndata);\\n }\\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 or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) 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 assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/ContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @notice Shared `IContractNamer` instance.\\ncontract ContractNamer is ERC165, OwnableUpgradeable, UUPSUpgradeable, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n constructor() {\\n _disableInitializers();\\n }\\n\\n /// @notice Initialize the contract.\\n /// @param owner_ The contract owner.\\n function initialize(address owner_) external initializer {\\n __Ownable_init(owner_);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return owner() == namer;\\n }\\n\\n /// @dev Allow owner to upgrade.\\n function _authorizeUpgrade(address) internal override onlyOwner {}\\n}\\n\",\"keccak256\":\"0x69dc17485dba9a662c0c577677eb9a06dcfbe1cdb0bc8471f23ae8fc6fcf856f\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": { + "initialize(address)": { + "notice": "Initialize the contract." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + } + }, + "notice": "Shared `IContractNamer` instance.", + "version": 1 + }, + "argsData": "0x", + "transaction": { + "hash": "0xc9b93aa97e3dce8489a501fa347d9bcfbde41a57e1d096a9ca24f6ae0ee1422c", + "nonce": "0xa", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x84c17f1ff54fd44334773abb4e7cffccd1a1cb130104767fd16608e953b62cb5", + "blockNumber": "0xaa56b2", + "transactionIndex": "0x67" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ContractNamer_Proxy.json b/contracts/deployments/sepolia/ContractNamer_Proxy.json new file mode 100644 index 000000000..269a92d54 --- /dev/null +++ b/contracts/deployments/sepolia/ContractNamer_Proxy.json @@ -0,0 +1,128 @@ +{ + "address": "0x68658a771044873906fc9b6e9f278ac5a0501342", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "contractName": "ERC1967Proxy", + "sourceName": "solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol", + "bytecode": "0x608060405260405161084e38038061084e83398101604081905261002291610349565b61004d60017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd610417565b600080516020610807833981519152146100695761006961043c565b6100758282600061007c565b50506104a1565b610085836100b2565b6000825111806100925750805b156100ad576100ab83836100f260201b6100291760201c565b505b505050565b6100bb8161011e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606101178383604051806060016040528060278152602001610827602791396101de565b9392505050565b610131816102bc60201b6100551760201c565b6101985760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101bd60008051602061080783398151915260001b6102cb60201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161018f565b600080856001600160a01b0316856040516102619190610452565b600060405180830381855af49150503d806000811461029c576040519150601f19603f3d011682016040523d82523d6000602084013e6102a1565b606091505b5090925090506102b28282866102ce565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102dd575081610117565b8251156102ed5782518084602001fd5b8160405162461bcd60e51b815260040161018f919061046e565b634e487b7160e01b600052604160045260246000fd5b60005b83811015610338578181015183820152602001610320565b838111156100ab5750506000910152565b6000806040838503121561035c57600080fd5b82516001600160a01b038116811461037357600080fd5b60208401519092506001600160401b038082111561039057600080fd5b818501915085601f8301126103a457600080fd5b8151818111156103b6576103b6610307565b604051601f8201601f19908116603f011681019083821181831017156103de576103de610307565b816040528281528860208487010111156103f757600080fd5b61040883602083016020880161031d565b80955050505050509250929050565b60008282101561043757634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825161046481846020870161031d565b9190910192915050565b602081526000825180602084015261048d81604085016020870161031d565b601f01601f19169190910160400192915050565b610357806104b06000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201e3c9348ed6dd2f363e89451207bd8df182bc878dc80d47166301a510c8801e964736f6c634300080a0033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "devdoc": { + "details": "This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.", + "kind": "dev", + "methods": { + "constructor": { + "details": "Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "171000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "": "infinite" + }, + "internal": { + "_implementation()": "2144" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an implementation address that can be changed. This address is stored in storage in the location specified by https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the implementation behind the proxy.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Initializes the upgradeable proxy with an initial implementation specified by `_logic`. If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity constructor.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":\"ERC1967Proxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\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\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 virtual 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(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\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\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 overriden 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 internall 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 overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/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\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 functionCall(target, data, \\\"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 require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason 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 // 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\\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}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 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 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 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 assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "solcInput": "{\n \"language\": \"Solidity\",\n \"sources\": {\n \"solc_0.8/openzeppelin/access/Ownable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 (address initialOwner) {\\n _transferOwnership(initialOwner);\\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 _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\"\n },\n \"solc_0.8/openzeppelin/utils/Context.sol\": {\n \"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\"\n },\n \"solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./TransparentUpgradeableProxy.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\n\\n/**\\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\\n */\\ncontract ProxyAdmin is Ownable {\\n\\n constructor (address initialOwner) Ownable(initialOwner) {}\\n\\n /**\\n * @dev Returns the current implementation of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"implementation()\\\")) == 0x5c60da1b\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"5c60da1b\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Returns the current admin of `proxy`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\\n // We need to manually run the static call since the getter cannot be flagged as view\\n // bytes4(keccak256(\\\"admin()\\\")) == 0xf851a440\\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\\\"f851a440\\\");\\n require(success);\\n return abi.decode(returndata, (address));\\n }\\n\\n /**\\n * @dev Changes the admin of `proxy` to `newAdmin`.\\n *\\n * Requirements:\\n *\\n * - This contract must be the current admin of `proxy`.\\n */\\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\\n proxy.changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\\n proxy.upgradeTo(implementation);\\n }\\n\\n /**\\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\\n *\\n * Requirements:\\n *\\n * - This contract must be the admin of `proxy`.\\n */\\n function upgradeAndCall(\\n TransparentUpgradeableProxy proxy,\\n address implementation,\\n bytes memory data\\n ) public payable virtual onlyOwner {\\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\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\"\n },\n \"solc_0.8/openzeppelin/proxy/Proxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 overriden 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 internall 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 overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 virtual 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(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\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\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\": {\n \"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\"\n },\n \"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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\"\n },\n \"solc_0.8/openzeppelin/utils/Address.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 functionCall(target, data, \\\"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 require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(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 require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason 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 // 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\\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}\\n\"\n },\n \"solc_0.8/openzeppelin/utils/StorageSlot.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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 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 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 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 assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\"\n },\n \"solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract OptimizedTransparentUpgradeableProxy is ERC1967Proxy {\\n address internal immutable _ADMIN;\\n\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _ADMIN = admin_;\\n\\n // still store it to work with EIP-1967\\n bytes32 slot = _ADMIN_SLOT;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(slot, admin_)\\n }\\n emit AdminChanged(address(0), admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n\\n function _getAdmin() internal view virtual override returns (address) {\\n return _ADMIN;\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/utils/UUPSUpgradeable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.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 that the this implementation remains valid after 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\"\n },\n \"solc_0.8/openzeppelin/proxy/utils/Initializable.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.0;\\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 * 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 initialize the implementation contract, you can either invoke the\\n * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() initializer {}\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool 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 Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n // If the contract is initializing we ignore whether _initialized is set in order to support multiple\\n // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the\\n // contract may have been reentered.\\n require(_initializing ? _isConstructor() : !_initialized, \\\"Initializable: contract is already initialized\\\");\\n\\n bool isTopLevelCall = !_initializing;\\n if (isTopLevelCall) {\\n _initializing = true;\\n _initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n _initializing = false;\\n }\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} modifier, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n function _isConstructor() private view returns (bool) {\\n return !Address.isContract(address(this));\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/UpgradeableBeacon.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../../access/Ownable.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\\n * implementation contract, which is where they will delegate all function calls.\\n *\\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\\n */\\ncontract UpgradeableBeacon is IBeacon, Ownable {\\n address private _implementation;\\n\\n /**\\n * @dev Emitted when the implementation returned by the beacon is changed.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\\n * beacon.\\n */\\n\\n constructor(address implementation_, address initialOwner) Ownable(initialOwner) {\\n _setImplementation(implementation_);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function implementation() public view virtual override returns (address) {\\n return _implementation;\\n }\\n\\n /**\\n * @dev Upgrades the beacon to a new implementation.\\n *\\n * Emits an {Upgraded} event.\\n *\\n * Requirements:\\n *\\n * - msg.sender must be the owner of the contract.\\n * - `newImplementation` must be a contract.\\n */\\n function upgradeTo(address newImplementation) public virtual onlyOwner {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Sets the implementation contract address for this beacon\\n *\\n * Requirements:\\n *\\n * - `newImplementation` must be a contract.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"UpgradeableBeacon: implementation is not a contract\\\");\\n _implementation = newImplementation;\\n }\\n}\\n\"\n },\n \"solc_0.8/openzeppelin/proxy/beacon/BeaconProxy.sol\": {\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/BeaconProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IBeacon.sol\\\";\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"../ERC1967/ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.\\n *\\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\\n * conflict with the storage layout of the implementation behind the proxy.\\n *\\n * _Available since v3.4._\\n */\\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the proxy with `beacon`.\\n *\\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\\n * will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity\\n * constructor.\\n *\\n * Requirements:\\n *\\n * - `beacon` must be a contract with the interface {IBeacon}.\\n */\\n constructor(address beacon, bytes memory data) payable {\\n assert(_BEACON_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.beacon\\\")) - 1));\\n _upgradeBeaconToAndCall(beacon, data, false);\\n }\\n\\n /**\\n * @dev Returns the current beacon address.\\n */\\n function _beacon() internal view virtual returns (address) {\\n return _getBeacon();\\n }\\n\\n /**\\n * @dev Returns the current implementation address of the associated beacon.\\n */\\n function _implementation() internal view virtual override returns (address) {\\n return IBeacon(_getBeacon()).implementation();\\n }\\n\\n /**\\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\\n *\\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\\n *\\n * Requirements:\\n *\\n * - `beacon` must be a contract.\\n * - The implementation returned by `beacon` must be a contract.\\n */\\n function _setBeacon(address beacon, bytes memory data) internal virtual {\\n _upgradeBeaconToAndCall(beacon, data, false);\\n }\\n}\\n\"\n }\n },\n \"settings\": {\n \"optimizer\": {\n \"enabled\": true,\n \"runs\": 999999\n },\n \"outputSelection\": {\n \"*\": {\n \"*\": [\n \"abi\",\n \"evm.bytecode\",\n \"evm.deployedBytecode\",\n \"evm.methodIdentifiers\",\n \"metadata\",\n \"devdoc\",\n \"userdoc\",\n \"storageLayout\",\n \"evm.gasEstimates\"\n ],\n \"\": [\n \"ast\"\n ]\n }\n },\n \"metadata\": {\n \"useLiteralContent\": true\n }\n }\n}", + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "argsData": "0x0000000000000000000000001520935e3c23c7d3cf0024537f53bf2bf26c955300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de800000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d300000000000000000000000000000000000000000000000000000000", + "transaction": { + "hash": "0x03b7e559ed4fa05fe7007325d2aaa7ad19198e4f590233e32301b0bd1632e040", + "nonce": "0xb", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x807b45694d549501f4dfc415d5c323080fec120c0fc5360ac7924a18329e17d3", + "blockNumber": "0xaa56b3", + "transactionIndex": "0xcf" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/DNSV1MirrorRootBatchRegistrar.json b/contracts/deployments/sepolia/DNSV1MirrorRootBatchRegistrar.json new file mode 100644 index 000000000..60e881bef --- /dev/null +++ b/contracts/deployments/sepolia/DNSV1MirrorRootBatchRegistrar.json @@ -0,0 +1,282 @@ +{ + "address": "0x08c297214c7ea8de81e2d984d66dcc1684054037", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry_", + "type": "address" + }, + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InputLengthMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "string[]", + "name": "labels", + "type": "string[]" + }, + { + "internalType": "uint64[]", + "name": "expires", + "type": "uint64[]" + } + ], + "name": "batchRegister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "BatchRegistrar", + "sourceName": "src/registrar/BatchRegistrar.sol", + "bytecode": "0x60a060405234801561000f575f80fd5b506040516109d63803806109d683398101604081905261002e916100de565b806001600160a01b03811661005c57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006581610078565b50506001600160a01b0316608052610116565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146100db575f80fd5b50565b5f80604083850312156100ef575f80fd5b82516100fa816100c7565b602084015190925061010b816100c7565b809150509250929050565b6080516108946101425f395f818160820152818161013901528181610240015261038a01526108945ff3fe608060405234801561000f575f80fd5b5060043610610064575f3560e01c8063715018a61161004d578063715018a6146100c05780638da5cb5b146100c8578063f2fde38b146100d8575f80fd5b8063087be49f14610068578063475007081461007d575b5f80fd5b61007b6100763660046105ea565b6100eb565b005b6100a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61007b610469565b5f546001600160a01b03166100a4565b61007b6100e6366004610679565b61047c565b6100f36104d7565b82811461012c576040517faaad13f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b83811015610460575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286101c688888681811061017b5761017b61069b565b905060200281019061018d91906106af565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061051c92505050565b6040518263ffffffff1660e01b81526004016101e491815260200190565b60a060405180830381865afa1580156101ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610722565b90505f81516002811115610239576102396107b4565b03610324577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f3e64387878581811061027f5761027f61069b565b905060200281019061029191906106af565b5f8c8c5f8b8b8b8181106102a7576102a761069b565b90506020020160208101906102bc91906107c8565b6040518863ffffffff1660e01b81526004016102de97969594939291906107e3565b6020604051808303815f875af11580156102fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610847565b50610457565b600181516002811115610339576103396107b4565b1480156103835750806020015167ffffffffffffffff168484848181106103625761036261069b565b905060200201602081019061037791906107c8565b67ffffffffffffffff16115b15610457577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635569f33d82606001518686868181106103ce576103ce61069b565b90506020020160208101906103e391906107c8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925267ffffffffffffffff1660248201526044015f604051808303815f87803b158015610440575f80fd5b505af1158015610452573d5f803e3d5ffd5b505050505b5060010161012e565b50505050505050565b6104716104d7565b61047a5f610527565b565b6104846104d7565b6001600160a01b0381166104cb576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d481610527565b50565b5f546001600160a01b0316331461047a576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104c2565b805160209091012090565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146104d4575f80fd5b5f8083601f8401126105b2575f80fd5b50813567ffffffffffffffff8111156105c9575f80fd5b6020830191508360208260051b85010111156105e3575f80fd5b9250929050565b5f805f805f80608087890312156105ff575f80fd5b863561060a8161058e565b9550602087013561061a8161058e565b9450604087013567ffffffffffffffff80821115610636575f80fd5b6106428a838b016105a2565b9096509450606089013591508082111561065a575f80fd5b5061066789828a016105a2565b979a9699509497509295939492505050565b5f60208284031215610689575f80fd5b81356106948161058e565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e198436030181126106c4575f80fd5b83018035915067ffffffffffffffff8211156106de575f80fd5b6020019150368190038213156105e3575f80fd5b67ffffffffffffffff811681146104d4575f80fd5b8051610712816106f2565b919050565b80516107128161058e565b5f60a08284031215610732575f80fd5b60405160a0810181811067ffffffffffffffff8211171561076157634e487b7160e01b5f52604160045260245ffd5b604052825160038110610772575f80fd5b815261078060208401610707565b602082015261079160408401610717565b604082015260608301516060820152608083015160808201528091505092915050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156107d8575f80fd5b8135610694816106f2565b60c081528660c0820152868860e08301375f60e08883018101919091526001600160a01b0396871660208301529486166040820152929094166060830152608082015267ffffffffffffffff90921660a0830152601f909201601f19160101919050565b5f60208284031215610857575f80fd5b505191905056fea26469706673582212207fe9d472b8dd9a39f4a2db98a90e397b3f465d0364f914c103b5b629722c17d864736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610064575f3560e01c8063715018a61161004d578063715018a6146100c05780638da5cb5b146100c8578063f2fde38b146100d8575f80fd5b8063087be49f14610068578063475007081461007d575b5f80fd5b61007b6100763660046105ea565b6100eb565b005b6100a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61007b610469565b5f546001600160a01b03166100a4565b61007b6100e6366004610679565b61047c565b6100f36104d7565b82811461012c576040517faaad13f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b83811015610460575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286101c688888681811061017b5761017b61069b565b905060200281019061018d91906106af565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061051c92505050565b6040518263ffffffff1660e01b81526004016101e491815260200190565b60a060405180830381865afa1580156101ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102239190610722565b90505f81516002811115610239576102396107b4565b03610324577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166385f3e64387878581811061027f5761027f61069b565b905060200281019061029191906106af565b5f8c8c5f8b8b8b8181106102a7576102a761069b565b90506020020160208101906102bc91906107c8565b6040518863ffffffff1660e01b81526004016102de97969594939291906107e3565b6020604051808303815f875af11580156102fa573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031e9190610847565b50610457565b600181516002811115610339576103396107b4565b1480156103835750806020015167ffffffffffffffff168484848181106103625761036261069b565b905060200201602081019061037791906107c8565b67ffffffffffffffff16115b15610457577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635569f33d82606001518686868181106103ce576103ce61069b565b90506020020160208101906103e391906107c8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925267ffffffffffffffff1660248201526044015f604051808303815f87803b158015610440575f80fd5b505af1158015610452573d5f803e3d5ffd5b505050505b5060010161012e565b50505050505050565b6104716104d7565b61047a5f610527565b565b6104846104d7565b6001600160a01b0381166104cb576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b6104d481610527565b50565b5f546001600160a01b0316331461047a576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016104c2565b805160209091012090565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146104d4575f80fd5b5f8083601f8401126105b2575f80fd5b50813567ffffffffffffffff8111156105c9575f80fd5b6020830191508360208260051b85010111156105e3575f80fd5b9250929050565b5f805f805f80608087890312156105ff575f80fd5b863561060a8161058e565b9550602087013561061a8161058e565b9450604087013567ffffffffffffffff80821115610636575f80fd5b6106428a838b016105a2565b9096509450606089013591508082111561065a575f80fd5b5061066789828a016105a2565b979a9699509497509295939492505050565b5f60208284031215610689575f80fd5b81356106948161058e565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e198436030181126106c4575f80fd5b83018035915067ffffffffffffffff8211156106de575f80fd5b6020019150368190038213156105e3575f80fd5b67ffffffffffffffff811681146104d4575f80fd5b8051610712816106f2565b919050565b80516107128161058e565b5f60a08284031215610732575f80fd5b60405160a0810181811067ffffffffffffffff8211171561076157634e487b7160e01b5f52604160045260245ffd5b604052825160038110610772575f80fd5b815261078060208401610707565b602082015261079160408401610717565b604082015260608301516060820152608083015160808201528091505092915050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156107d8575f80fd5b8135610694816106f2565b60c081528660c0820152868860e08301375f60e08883018101919091526001600160a01b0396871660208301529486166040820152929094166060830152608082015267ffffffffffffffff90921660a0830152601f909201601f19160101919050565b5f60208284031215610857575f80fd5b505191905056fea26469706673582212207fe9d472b8dd9a39f4a2db98a90e397b3f465d0364f914c103b5b629722c17d864736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "27367": [ + { + "length": 32, + "start": 130 + }, + { + "length": 32, + "start": 313 + }, + { + "length": 32, + "start": 576 + }, + { + "length": 32, + "start": 906 + } + ] + }, + "inputSourceName": "project/src/registrar/BatchRegistrar.sol", + "devdoc": { + "errors": { + "InputLengthMismatch()": [ + { + "details": "Error selector: `0xaaad13f7`" + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "kind": "dev", + "methods": { + "batchRegister(address,address,string[],uint64[])": { + "params": { + "expires": "Array of expiry timestamps corresponding to each label", + "labels": "Array of labels to reserve or renew", + "registry": "The registry for all names", + "resolver": "The resolver for all names" + } + }, + "constructor": { + "params": { + "ethRegistry_": "The ETH registry to use for batch registration.", + "owner_": "The owner of the contract." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "title": "BatchRegistrar", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "439200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ETH_REGISTRY()": "infinite", + "batchRegister(address,address,string[],uint64[])": "infinite", + "owner()": "2339", + "renounceOwnership()": "infinite", + "transferOwnership(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InputLengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"labels\",\"type\":\"string[]\"},{\"internalType\":\"uint64[]\",\"name\":\"expires\",\"type\":\"uint64[]\"}],\"name\":\"batchRegister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InputLengthMismatch()\":[{\"details\":\"Error selector: `0xaaad13f7`\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"kind\":\"dev\",\"methods\":{\"batchRegister(address,address,string[],uint64[])\":{\"params\":{\"expires\":\"Array of expiry timestamps corresponding to each label\",\"labels\":\"Array of labels to reserve or renew\",\"registry\":\"The registry for all names\",\"resolver\":\"The resolver for all names\"}},\"constructor\":{\"params\":{\"ethRegistry_\":\"The ETH registry to use for batch registration.\",\"owner_\":\"The owner of the contract.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"BatchRegistrar\",\"version\":1},\"userdoc\":{\"errors\":{\"InputLengthMismatch()\":[{\"notice\":\"Thrown when batch registration inputs have different lengths.\"}]},\"kind\":\"user\",\"methods\":{\"ETH_REGISTRY()\":{\"notice\":\"The ETH registry to use for batch registration.\"},\"batchRegister(address,address,string[],uint64[])\":{\"notice\":\"Batch reserve or renew names for pre-migration\"}},\"notice\":\"Simple batch registration contract for pre-migration of ENS names. Only the owner can invoke batch registration.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/BatchRegistrar.sol\":\"BatchRegistrar\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registrar/BatchRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\n/// @title BatchRegistrar\\n/// @notice Simple batch registration contract for pre-migration of ENS names.\\n/// Only the owner can invoke batch registration.\\ncontract BatchRegistrar is Ownable {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ETH registry to use for batch registration.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Thrown when batch registration inputs have different lengths.\\n /// @dev Error selector: `0xaaad13f7`\\n error InputLengthMismatch();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param ethRegistry_ The ETH registry to use for batch registration.\\n /// @param owner_ The owner of the contract.\\n constructor(IPermissionedRegistry ethRegistry_, address owner_) Ownable(owner_) {\\n ETH_REGISTRY = ethRegistry_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Batch reserve or renew names for pre-migration\\n /// @param registry The registry for all names\\n /// @param resolver The resolver for all names\\n /// @param labels Array of labels to reserve or renew\\n /// @param expires Array of expiry timestamps corresponding to each label\\n function batchRegister(\\n IRegistry registry,\\n address resolver,\\n string[] calldata labels,\\n uint64[] calldata expires\\n )\\n external\\n onlyOwner\\n {\\n if (labels.length != expires.length) {\\n revert InputLengthMismatch();\\n }\\n\\n for (uint256 i = 0; i < labels.length; i++) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(labels[i]));\\n\\n if (state.status == IPermissionedRegistry.Status.AVAILABLE) {\\n ETH_REGISTRY.register(labels[i], address(0), registry, resolver, 0, expires[i]);\\n } else if (\\n state.status == IPermissionedRegistry.Status.RESERVED && expires[i] > state.expiry\\n ) {\\n ETH_REGISTRY.renew(state.tokenId, expires[i]);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x500267938ff1c4abbf7fcb0155e65759a672e0d12c16217290e1c38fca25d6fd\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 14920, + "contract": "project/src/registrar/BatchRegistrar.sol:BatchRegistrar", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + }, + "userdoc": { + "errors": { + "InputLengthMismatch()": [ + { + "notice": "Thrown when batch registration inputs have different lengths." + } + ] + }, + "kind": "user", + "methods": { + "ETH_REGISTRY()": { + "notice": "The ETH registry to use for batch registration." + }, + "batchRegister(address,address,string[],uint64[])": { + "notice": "Batch reserve or renew names for pre-migration" + } + }, + "notice": "Simple batch registration contract for pre-migration of ENS names. Only the owner can invoke batch registration.", + "version": 1 + }, + "argsData": "0x00000000000000000000000011b5bfbe9078d826b1edbdd1cfc12f5828d9f50c00000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d3", + "transaction": { + "hash": "0xdef02713ecc47e1857c27d54bf1526ef791d09781d0c6dc10d7d558dfb4c2cfb", + "nonce": "0x14", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x8d7c5845c1e4b225ae138414197f24e7ca7ed2b90aa10b4b2c2c582c14408fc3", + "blockNumber": "0xaa56c1", + "transactionIndex": "0x5c" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/DefaultReverseRegistrarAdapter.json b/contracts/deployments/sepolia/DefaultReverseRegistrarAdapter.json new file mode 100644 index 000000000..954461d01 --- /dev/null +++ b/contracts/deployments/sepolia/DefaultReverseRegistrarAdapter.json @@ -0,0 +1,232 @@ +{ + "address": "0x1f7b9461d17d5cf43553253c6b78d252d9575954", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IDefaultReverseRegistrar", + "name": "defaultReverseRegistrar", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "UnauthorizedNamer", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_REVERSE_REGISTRAR", + "outputs": [ + { + "internalType": "contract IDefaultReverseRegistrar", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "DefaultReverseRegistrarAdapter", + "sourceName": "src/reverse-registrar/DefaultReverseRegistrarAdapter.sol", + "bytecode": "0x60c060405234801561000f575f80fd5b5060405161069538038061069583398101604081905261002e9161005c565b6001600160a01b039081166080521660a052610094565b6001600160a01b0381168114610059575f80fd5b50565b5f806040838503121561006d575f80fd5b825161007881610045565b602084015190925061008981610045565b809150509250929050565b60805160a0516105d46100c15f395f818160fc01526101d701525f818160aa015261026301526105d45ff3fe608060405234801561000f575f80fd5b5060043610610064575f3560e01c806348ee1bcc1161004d57806348ee1bcc146100a55780636f3ff726146100e45780638633886d146100f7575f80fd5b806301ffc9a7146100685780633121db1c14610090575b5f80fd5b61007b610076366004610437565b61011e565b60405190151581526020015b60405180910390f35b6100a361009e36600461048d565b61019d565b005b6100cc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610087565b61007b6100f236600461050b565b610242565b6100cc7f000000000000000000000000000000000000000000000000000000000000000081565b5f7fffffffff00000000000000000000000000000000000000000000000000000000821663379ffb9360e11b148061019757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6101a783336102ce565b6040517fc91199410000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c91199419061021090869086908690600401610526565b5f604051808303815f87803b158015610227575f80fd5b505af1158015610239573d5f803e3d5ffd5b50505050505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa1580156102aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101979190610564565b6102d88282610321565b61031d576040517f0d1b7e4e0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260240160405180910390fd5b5050565b6001600160a01b038281169082161480158161034657505f836001600160a01b03163b115b1561019757826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156103a5575060408051601f3d908101601f191682019092526103a291810190610583565b60015b156103c357826001600160a01b0316816001600160a01b0316149150505b806101975760405163379ffb9360e11b81526001600160a01b038381166004830152841690636f3ff72690602401602060405180830381865afa92505050801561042a575060408051601f3d908101601f1916820190925261042791810190610564565b60015b15610197575b9392505050565b5f60208284031215610447575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610430575f80fd5b6001600160a01b038116811461048a575f80fd5b50565b5f805f6040848603121561049f575f80fd5b83356104aa81610476565b9250602084013567ffffffffffffffff808211156104c6575f80fd5b818601915086601f8301126104d9575f80fd5b8135818111156104e7575f80fd5b8760208285010111156104f8575f80fd5b6020830194508093505050509250925092565b5f6020828403121561051b575f80fd5b813561043081610476565b6001600160a01b038416815260406020820152816040820152818360608301375f818301606090810191909152601f909201601f1916010192915050565b5f60208284031215610574575f80fd5b81518015158114610430575f80fd5b5f60208284031215610593575f80fd5b81516104308161047656fea264697066735822122059856dfccbe7628d0e42ab2fa011c3fcf68fb0efd8681ce887164b01bcaba23564736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610064575f3560e01c806348ee1bcc1161004d57806348ee1bcc146100a55780636f3ff726146100e45780638633886d146100f7575f80fd5b806301ffc9a7146100685780633121db1c14610090575b5f80fd5b61007b610076366004610437565b61011e565b60405190151581526020015b60405180910390f35b6100a361009e36600461048d565b61019d565b005b6100cc7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610087565b61007b6100f236600461050b565b610242565b6100cc7f000000000000000000000000000000000000000000000000000000000000000081565b5f7fffffffff00000000000000000000000000000000000000000000000000000000821663379ffb9360e11b148061019757507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6101a783336102ce565b6040517fc91199410000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c91199419061021090869086908690600401610526565b5f604051808303815f87803b158015610227575f80fd5b505af1158015610239573d5f803e3d5ffd5b50505050505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa1580156102aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101979190610564565b6102d88282610321565b61031d576040517f0d1b7e4e0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260240160405180910390fd5b5050565b6001600160a01b038281169082161480158161034657505f836001600160a01b03163b115b1561019757826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156103a5575060408051601f3d908101601f191682019092526103a291810190610583565b60015b156103c357826001600160a01b0316816001600160a01b0316149150505b806101975760405163379ffb9360e11b81526001600160a01b038381166004830152841690636f3ff72690602401602060405180830381865afa92505050801561042a575060408051601f3d908101601f1916820190925261042791810190610564565b60015b15610197575b9392505050565b5f60208284031215610447575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610430575f80fd5b6001600160a01b038116811461048a575f80fd5b50565b5f805f6040848603121561049f575f80fd5b83356104aa81610476565b9250602084013567ffffffffffffffff808211156104c6575f80fd5b818601915086601f8301126104d9575f80fd5b8135818111156104e7575f80fd5b8760208285010111156104f8575f80fd5b6020830194508093505050509250925092565b5f6020828403121561051b575f80fd5b813561043081610476565b6001600160a01b038416815260406020820152816040820152818360608301375f818301606090810191909152601f909201601f1916010192915050565b5f60208284031215610574575f80fd5b81518015158114610430575f80fd5b5f60208284031215610593575f80fd5b81516104308161047656fea264697066735822122059856dfccbe7628d0e42ab2fa011c3fcf68fb0efd8681ce887164b01bcaba23564736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "72209": [ + { + "length": 32, + "start": 252 + }, + { + "length": 32, + "start": 471 + } + ], + "75299": [ + { + "length": 32, + "start": 170 + }, + { + "length": 32, + "start": 611 + } + ] + }, + "inputSourceName": "project/src/reverse-registrar/DefaultReverseRegistrarAdapter.sol", + "devdoc": { + "details": "The adapter must be configured as a controller on the default reverse registrar.", + "errors": { + "UnauthorizedNamer(address)": [ + { + "details": "Error selector: `0x0d1b7e4e`" + } + ] + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "defaultReverseRegistrar": "The v1 default reverse registrar for `default.reverse`." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "setName(address,string)": { + "params": { + "account": "The contract address.", + "name": "The primary name to store." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "title": "Default Reverse Registrar Adapter", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "298400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "DEFAULT_REVERSE_REGISTRAR()": "infinite", + "isContractNamer(address)": "infinite", + "setName(address,string)": "infinite", + "supportsInterface(bytes4)": "373" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IDefaultReverseRegistrar\",\"name\":\"defaultReverseRegistrar\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"UnauthorizedNamer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_REVERSE_REGISTRAR\",\"outputs\":[{\"internalType\":\"contract IDefaultReverseRegistrar\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"The adapter must be configured as a controller on the default reverse registrar.\",\"errors\":{\"UnauthorizedNamer(address)\":[{\"details\":\"Error selector: `0x0d1b7e4e`\"}]},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"defaultReverseRegistrar\":\"The v1 default reverse registrar for `default.reverse`.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"setName(address,string)\":{\"params\":{\"account\":\"The contract address.\",\"name\":\"The primary name to store.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"title\":\"Default Reverse Registrar Adapter\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"DEFAULT_REVERSE_REGISTRAR()\":{\"notice\":\"The v1 default reverse registrar for `default.reverse`.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"setName(address,string)\":{\"notice\":\"Set account's `default.reverse` primary name.\"}},\"notice\":\"Forwarder for v1 `default.reverse` registrar updates.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/reverse-registrar/DefaultReverseRegistrarAdapter.sol\":\"DefaultReverseRegistrarAdapter\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/reverseRegistrar/IDefaultReverseRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Interface for the Default Reverse Registrar.\\ninterface IDefaultReverseRegistrar {\\n /// @notice Sets the `nameForAddr()` record for the calling account.\\n ///\\n /// @param name The name to set.\\n function setName(string memory name) external;\\n\\n /// @notice Sets the `nameForAddr()` record for the addr provided account using a signature.\\n ///\\n /// @param addr The address to set the name for.\\n /// @param name The name to set.\\n /// @param signatureExpiry Date when the signature expires.\\n /// @param signature The signature from the addr.\\n function setNameForAddrWithSignature(\\n address addr,\\n uint256 signatureExpiry,\\n string memory name,\\n bytes memory signature\\n ) external;\\n\\n function setNameForAddr(address addr, string memory name) external;\\n}\\n\",\"keccak256\":\"0x45187ce3d3f5da57eac0453ae7df24295e820da379eeaf21cfc967a21038fe7e\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/reverse-registrar/DefaultReverseRegistrarAdapter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {\\n IDefaultReverseRegistrar\\n} from \\\"@ens/contracts/reverseRegistrar/IDefaultReverseRegistrar.sol\\\";\\n\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {IContractNamer} from \\\"./interfaces/IContractNamer.sol\\\";\\nimport {AccountNamerLib} from \\\"./libraries/AccountNamerLib.sol\\\";\\n\\n/// @title Default Reverse Registrar Adapter\\n/// @notice Forwarder for v1 `default.reverse` registrar updates.\\n/// @dev The adapter must be configured as a controller on the default reverse registrar.\\ncontract DefaultReverseRegistrarAdapter is DelegatedContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The v1 default reverse registrar for `default.reverse`.\\n IDefaultReverseRegistrar public immutable DEFAULT_REVERSE_REGISTRAR;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param defaultReverseRegistrar The v1 default reverse registrar for `default.reverse`.\\n /// @param contractNamer Delegated contract namer.\\n constructor(IDefaultReverseRegistrar defaultReverseRegistrar, IContractNamer contractNamer)\\n DelegatedContractNamer(contractNamer)\\n {\\n DEFAULT_REVERSE_REGISTRAR = defaultReverseRegistrar;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Set account's `default.reverse` primary name.\\n /// @param account The contract address.\\n /// @param name The primary name to store.\\n function setName(address account, string calldata name) external {\\n AccountNamerLib.requireNamer(account, msg.sender);\\n DEFAULT_REVERSE_REGISTRAR.setNameForAddr(account, name);\\n }\\n}\\n\",\"keccak256\":\"0x6f36574436b9946e9e767112a01ddfbcd67d6521ae7d56b6f121cdbc497e7b69\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/reverse-registrar/libraries/AccountNamerLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {IContractNamer} from \\\"../interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Determine if an address is nameable. \\nlibrary AccountNamerLib {\\n /// @dev Error selector: `0x0d1b7e4e`\\n error UnauthorizedNamer(address namer);\\n\\n /// @dev Check if an address can be named.\\n /// @param account The address to name.\\n /// @param namer The address of the namer.\\n /// @return canName `true` if `namer` can name `addr`.\\n function isNamer(address account, address namer) internal view returns (bool canName) {\\n canName = account == namer;\\n if (!canName && account.code.length > 0) {\\n try Ownable(account).owner() returns (address owner) {\\n canName = owner == namer;\\n } catch {}\\n if (!canName) {\\n try IContractNamer(account).isContractNamer(namer) returns (bool can) {\\n canName = can;\\n } catch {}\\n }\\n }\\n }\\n\\n /// @dev Ensure `namer` can name `account`.\\n /// @param account The address to name.\\n /// @param namer The address of the namer.\\n function requireNamer(address account, address namer) internal view {\\n if (!isNamer(account, namer)) {\\n revert UnauthorizedNamer(namer);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1a2e3cd6439f69053d2de151e240f34b12f6594920f9de0fe888653e01fe0d03\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "DEFAULT_REVERSE_REGISTRAR()": { + "notice": "The v1 default reverse registrar for `default.reverse`." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "setName(address,string)": { + "notice": "Set account's `default.reverse` primary name." + } + }, + "notice": "Forwarder for v1 `default.reverse` registrar updates.", + "version": 1 + }, + "argsData": "0x0000000000000000000000004f382928805ba0e23b30cfb75fc9e848e82dfd4700000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0xeecc6d264f3222e4e14912a1160617eab7a309a12e4fd2df70e475a35f6e152c", + "nonce": "0x52", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xb004481be2e2e1e5ee00ae06eb5e344d97a277690299ced2f852dc35d0fc33e3", + "blockNumber": "0xaa5706", + "transactionIndex": "0x61" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ENSV1Resolver.json b/contracts/deployments/sepolia/ENSV1Resolver.json new file mode 100644 index 000000000..868240fb0 --- /dev/null +++ b/contracts/deployments/sepolia/ENSV1Resolver.json @@ -0,0 +1,738 @@ +{ + "address": "0x5339161a7896ca9841ecc034a49edca40f7b9491", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "batchGatewayProvider", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + }, + { + "internalType": "contract ENS", + "name": "registryV1", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBatchGatewayResponse", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "UnreachableName", + "type": "error" + }, + { + "inputs": [], + "name": "BATCH_GATEWAY_PROVIDER", + "outputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REGISTRY_V1", + "outputs": [ + { + "internalType": "contract ENS", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "hasContext", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "batchGateways", + "type": "string[]" + } + ], + "name": "callResolver", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "name": "ccipBatch", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipBatchCallback", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipReadCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveBatchCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "resolveDirectImmediateCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feature", + "type": "bytes4" + } + ], + "name": "supportsFeature", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "ENSV1Resolver", + "sourceName": "src/resolver/ENSV1Resolver.sol", + "bytecode": "0x610100604052348015610010575f80fd5b50604051612abb380380612abb83398101604081905261002f91610069565b61c3506080526001600160a01b0391821660a05291811660c0521660e0526100b3565b6001600160a01b0381168114610066575f80fd5b50565b5f805f6060848603121561007b575f80fd5b835161008681610052565b602085015190935061009781610052565b60408501519092506100a881610052565b809150509250925092565b60805160a05160c05160e0516129c06100fb5f395f818161023d0152610f3c01525f8181610199015261054201525f8181610116015261042101525f610fe601526129c05ff3fe608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80639061b92311610088578063e370ecbe11610063578063e370ecbe14610238578063eea330f91461025f578063ef46c0b814610291578063f394443a146102a6575f80fd5b80639061b923146101f25780639f28e99d14610205578063b536af7614610225575f80fd5b8063582de3e7116100c3578063582de3e7146101705780636ccb8660146101945780636d6dd540146101bb5780636f3ff726146101df575f80fd5b806301ffc9a7146100e957806348ee1bcc14610111578063491fc4f914610150575b5f80fd5b6100fc6100f73660046119fc565b6102b9565b60405190151581526020015b60405180910390f35b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610108565b61016361015e366004611a55565b610332565b6040516101089190611aea565b6100fc61017e3660046119fc565b6001600160e01b0319166312d6c5b760e31b1490565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101d16101c9366004611a55565b509192909150565b604051610108929190611afc565b6100fc6101ed366004611b4e565b610400565b610163610200366004611a55565b61048c565b610218610213366004611d59565b6105bb565b6040516101089190611f19565b610218610233366004611a55565b61077c565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b61027261026d366004611fe2565b6109cb565b604080516001600160a01b039093168352901515602083015201610108565b6102a461029f366004612021565b6109e4565b005b6101636102b4366004612099565b610a69565b5f639061b92360e01b6001600160e01b03198316148061030257507feea330f9000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b8061031d575063582de3e760e01b6001600160e01b03198316145b8061032c575061032c82610da0565b92915050565b60605f61034185870187611d59565b5190505f806103528587018761215e565b91509150811561038f576103668382610dd4565b6040516020016103769190612195565b60405160208183030381529060405293505050506103f8565b5f835f815181106103a2576103a26121f7565b60209081029190910101516040810151606082015191925090600e16156103cb57805160208201fd5b82156103e857808060200190518101906103e5919061225f565b90505b94506103f89350505050565b5050505b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610468573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032c9190612291565b60606105b261049b8686610f36565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f9201829052506040805160208101825282815281517f093a86d3000000000000000000000000000000000000000000000000000000008152915192955093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063093a86d391600480830192879291908290030181865afa15801561058b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526102b4919081019061233a565b50949350505050565b60408051808201909152606080825260208201525f5b82515181101561076e575f835f015182815181106105f1576105f16121f7565b6020026020010151905060408160600151165f1461060f5750610766565b60608101516030165f036106b9575f61062a825f0151610fa0565b610635576010610638565b60205b9050825b8551518110156106b657825f01516001600160a01b0316865f01518281518110610668576106686121f7565b60200260200101515f01516001600160a01b0316036106ae5781865f01518281518110610697576106976121f7565b602002602001015160600181815117915081815250505b60010161063c565b50505b5f60208260600151165f1490505f806106db8315855f01518660200151610fd2565b91509150811580156107055750630556f18360e41b6106f98261236c565b6001600160e01b031916145b1561071a57606084018051600117905261075a565b606084018051604017905282801561073157508051155b61074657816107465760608401805160021790525b80515f0361075a5760608401805160081790525b60409093019290925250505b6001016105d1565b5061077882611065565b5090565b60408051808201909152606080825260208201525f8061079e8688018861241e565b9150915080518251146107c45760405163252e18f560e11b815260040160405180910390fd5b6107d084860186611d59565b92505f805b8451518110156109a0575f855f015182815181106107f5576107f56121f7565b6020026020010151905060408160600151165f0361099757835183101561098b575f848481518110610829576108296121f7565b60200260200101519050858481518110610845576108456121f7565b602002602001015115610862576060820180516044179052610985565b5f6108708360400151611250565b90505f815f01516001600160a01b0316826060015184846080015160405160240161089c9291906124d0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516108da919061250b565b5f60405180830381855afa9150503d805f8114610912576040519150601f19603f3d011682016040523d82523d5f602084013e610917565b606091505b509350905080806109415750630556f18360e41b6109348461236c565b6001600160e01b03191614155b1561098257606084018051604017905280158061095d57508251155b1561096e5760608401805160021790525b82515f036109825760608401805160081790525b50505b60408201525b6109948361252a565b92505b506001016107d5565b50815181146109c25760405163252e18f560e11b815260040160405180910390fd5b6103f484611065565b5f806109d78484610f36565b5f915091505b9250929050565b5f818060200190518101906109f99190612558565b9050610a64815f01518260200151858460400151604051602401610a1e9291906124d0565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a0860151611294565b505050565b6060866001600160a01b03163b5f03610ab957856040517f5fe9a5df000000000000000000000000000000000000000000000000000000008152600401610ab09190611aea565b60405180910390fd5b5f7fac9650d800000000000000000000000000000000000000000000000000000000610ae48761236c565b6001600160e01b0319161490505f858015610b0b5750610b0b8963477cc53f60e11b611457565b90505f8180610b265750610b268a639061b92360e01b611457565b9050610b398a63582de3e760e01b611457565b8015610bbd5750821580610bbd5750808015610bbd575060405163582de3e760e01b81526312d6c5b760e31b60048201526001600160a01b038b169063582de3e790602401602060405180830381865afa158015610b99573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bbd9190612291565b15610c07578015610be257610bdd8a610bd8848c8c8b6114dd565b61156f565b610c07565b610c078a89636d6dd54060e01b5f60e01b60405180602001604052805f815250611294565b60608315610c4157610c27896004808c51610c229190612627565b611594565b806020019051810190610c3a919061263a565b9050610c8c565b60408051600180825281830190925290816020015b6060815260200190600190039081610c5657905050905088815f81518110610c8057610c806121f7565b60200260200101819052505b8115610ce9575f5b8151811015610ce757610cc2848c848481518110610cb457610cb46121f7565b60200260200101518b6114dd565b828281518110610cd457610cd46121f7565b6020908102919091010152600101610c94565b505b610d923080639f28e99d610cfe8f868c6115f0565b604051602401610d0e9190611f19565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b94909417909352519092507f491fc4f900000000000000000000000000000000000000000000000000000000915f91610d7e918b918a910191151582521515602082015260400190565b604051602081830303815290604052611294565b505050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b148061032c57506301ffc9a760e01b6001600160e01b031983161461032c565b6060825167ffffffffffffffff811115610df057610df0611b69565b604051908082528060200260200182016040528015610e2357816020015b6060815260200190600190039081610e0e5790505b5090505f5b8351811015610f2f575f848281518110610e4457610e446121f7565b60209081029190910101516040810151606082015191925090600e165f03610e88578415610e835780806020019051810190610e80919061225f565b90505b610f07565b805115610f07578051600403601f168015610f0557818167ffffffffffffffff811115610eb757610eb7611b69565b6040519080825280601f01601f191660200182016040528015610ee1576020820181803683370190505b50604051602001610ef39291906126e4565b60405160208183030381529060405291505b505b80848481518110610f1a57610f1a6121f7565b60209081029190910101525050600101610e28565b5092915050565b5f610f967f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250611705915050565b5090949350505050565b5f306001600160a01b03831603610fb957506001919050565b6113885a5f805f808786fa50815a909103109392505050565b5f6060836001600160a01b03168561100a577f000000000000000000000000000000000000000000000000000000000000000061100c565b5a5b8460405161101a919061250b565b5f604051808303818686fa925050503d805f8114611053576040519150601f19603f3d011682016040523d82523d5f602084013e611058565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff81111561108257611082611b69565b6040519080825280602002602001820160405280156110df57816020015b6110cc60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816110a05790505b5090505f805b835151811015611190575f845f01518281518110611105576111056121f7565b6020026020010151905060408160600151165f03611187575f61112b8260400151611250565b90506040518060600160405280825f01516001600160a01b031681526020018260200151815260200182604001518152508585806111689061252a565b96508151811061117a5761117a6121f7565b6020026020010181905250505b506001016110e5565b508015610a6457808252308360200151836040516024016111b191906126f8565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af76000000000000000000000000000000000000000000000000000000009161122591899101611f19565b60408051601f1981840301815290829052630556f18360e41b8252610ab09594939291600401612792565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915261032c61128f836004808651610c229190612627565b611801565b5f806112a96112a288610fa0565b8888610fd2565b91509150811580156112d35750630556f18360e41b6112c78261236c565b6001600160e01b031916145b15611381575f6112e282611250565b9050876001600160a01b0316815f01516001600160a01b03160361137f57308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b03191681526020018981525060405160200161122591906127f5565b505b5f8261138d578461138f565b855b90506001600160e01b031981161561144157306001600160a01b03168183866040516024016113bf9291906124d0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516113fd919061250b565b5f60405180830381855afa9150503d805f8114611435576040519150601f19603f3d011682016040523d82523d5f602084013e61143a565b606091505b5090935091505b821561144f57815160208301f35b815160208301fd5b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f5190508280156114c7575060208210155b80156114d257505f81115b979650505050505050565b6060846115265783836040516024016114f79291906124d0565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b179052611566565b83838360405160240161153b93929190612871565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b1790525b95945050505050565b61159082825f60e01b5f60e01b60405180602001604052805f815250611294565b5050565b60608167ffffffffffffffff8111156115af576115af611b69565b6040519080825280601f01601f1916602001820160405280156115d9576020820181803683370190505b5090506115e98484835f8661186c565b9392505050565b60408051808201909152606080825260208201525f835167ffffffffffffffff81111561161f5761161f611b69565b60405190808252806020026020018201604052801561168257816020015b61166f60405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b81526020019060019003908161163d5790505b5090505f5b84518110156116e8575f8282815181106116a3576116a36121f7565b60209081029190910101516001600160a01b038816815286519091508690839081106116d1576116d16121f7565b602090810291909101810151910152600101611687565b506040805180820190915290815260208101929092525092915050565b5f805f805f61171487876118a9565b909250905081156117f5575f805f61172d8b8b86611705565b92509250925061174682865f9182526020526040902090565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018290529097506001600160a01b038c1690630178b8bf90602401602060405180830381865afa1580156117a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c991906128b3565b97506001600160a01b0388166117e1578287826117e5565b87878a5b97509750975050505050506117f8565b50505b93509350939050565b6040805160a0810182525f8082526060602083018190529282018390528282015260808101919091528180602001905181019061183e91906128ce565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b61187f8561187a8387612977565b6118d6565b61188d8361187a8385612977565b6118a28260208501018560208801018361191e565b5050505050565b5f805f6118b68585611967565b9250905060ff8116156118ce57806021858701012092505b509250929050565b81518111156115905781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610ab0918391600401918252602082015260400190565b5b601f81111561193f578151835260209283019290910190601f190161191f565b8015610a645790518251600160209390930360031b9290921b5f190180199091169116179052565b5f808351831061198c578360405163ba4adc2360e01b8152600401610ab09190611aea565b83838151811061199e5761199e6121f7565b016020015160f81c915050818101600101816119be5783518114156119c4565b83518110155b156109dd578360405163ba4adc2360e01b8152600401610ab09190611aea565b6001600160e01b0319811681146119f9575f80fd5b50565b5f60208284031215611a0c575f80fd5b81356115e9816119e4565b5f8083601f840112611a27575f80fd5b50813567ffffffffffffffff811115611a3e575f80fd5b6020830191508360208285010111156109dd575f80fd5b5f805f8060408587031215611a68575f80fd5b843567ffffffffffffffff80821115611a7f575f80fd5b611a8b88838901611a17565b90965094506020870135915080821115611aa3575f80fd5b50611ab087828801611a17565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6115e96020830184611abc565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b6001600160a01b03811681146119f9575f80fd5b8035611b4981611b2a565b919050565b5f60208284031215611b5e575f80fd5b81356115e981611b2a565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611ba057611ba0611b69565b60405290565b6040516080810167ffffffffffffffff81118282101715611ba057611ba0611b69565b60405160c0810167ffffffffffffffff81118282101715611ba057611ba0611b69565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c1557611c15611b69565b604052919050565b5f67ffffffffffffffff821115611c3657611c36611b69565b5060051b60200190565b5f67ffffffffffffffff821115611c5957611c59611b69565b50601f01601f191660200190565b5f611c79611c7484611c40565b611bec565b9050828152838383011115611c8c575f80fd5b828260208301375f602084830101529392505050565b5f82601f830112611cb1575f80fd5b6115e983833560208501611c67565b5f82601f830112611ccf575f80fd5b81356020611cdf611c7483611c1d565b82815260059290921b84018101918181019086841115611cfd575f80fd5b8286015b84811015611d4e57803567ffffffffffffffff811115611d1f575f80fd5b8701603f81018913611d2f575f80fd5b611d40898683013560408401611c67565b845250918301918301611d01565b509695505050505050565b5f6020808385031215611d6a575f80fd5b823567ffffffffffffffff80821115611d81575f80fd5b9084019060408287031215611d94575f80fd5b611d9c611b7d565b823582811115611daa575f80fd5b8301601f81018813611dba575f80fd5b8035611dc8611c7482611c1d565b81815260059190911b8201860190868101908a831115611de6575f80fd5b8784015b83811015611e8e57803587811115611e00575f80fd5b85016080818e03601f19011215611e15575f80fd5b611e1d611ba6565b8a820135611e2a81611b2a565b8152604082013589811115611e3d575f80fd5b611e4b8f8d83860101611ca2565b8c83015250606082013589811115611e61575f80fd5b611e6f8f8d83860101611ca2565b6040830152506080919091013560608201528352918801918801611dea565b5084525050508284013582811115611ea4575f80fd5b611eb088828601611cc0565b948201949094529695505050505050565b5f8282518085526020808601955060208260051b840101602086015f5b84811015611f0c57601f19868403018952611efa838351611abc565b98840198925090830190600101611ede565b5090979650505050505050565b5f602080835260608084018551604080858801528282518085526080945060808901915060808160051b8a010187850194505f5b82811015611fb757607f198b830301845285516001600160a01b03815116835289810151888b850152611f8289850182611abc565b90508682015184820388860152611f998282611abc565b928b0151948b01949094525095890195938901939150600101611f4d565b50968a0151898803601f190160408b015296611fd38189611ec1565b9b9a5050505050505050505050565b5f8060208385031215611ff3575f80fd5b823567ffffffffffffffff811115612009575f80fd5b61201585828601611a17565b90969095509350505050565b5f8060408385031215612032575f80fd5b823567ffffffffffffffff80821115612049575f80fd5b61205586838701611ca2565b9350602085013591508082111561206a575f80fd5b5061207785828601611ca2565b9150509250929050565b80151581146119f9575f80fd5b8035611b4981612081565b5f805f805f8060c087890312156120ae575f80fd5b6120b787611b3e565b9550602087013567ffffffffffffffff808211156120d3575f80fd5b6120df8a838b01611ca2565b965060408901359150808211156120f4575f80fd5b6121008a838b01611ca2565b955061210e60608a0161208e565b94506080890135915080821115612123575f80fd5b61212f8a838b01611ca2565b935060a0890135915080821115612144575f80fd5b5061215189828a01611cc0565b9150509295509295509295565b5f806040838503121561216f575f80fd5b823561217a81612081565b9150602083013561218a81612081565b809150509250929050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b828110156121ea57603f198886030184526121d8858351611abc565b945092850192908501906001016121bc565b5092979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f612218611c7484611c40565b905082815283838301111561222b575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f830112612250575f80fd5b6115e98383516020850161220b565b5f6020828403121561226f575f80fd5b815167ffffffffffffffff811115612285575f80fd5b6103f884828501612241565b5f602082840312156122a1575f80fd5b81516115e981612081565b5f82601f8301126122bb575f80fd5b815160206122cb611c7483611c1d565b82815260059290921b840181019181810190868411156122e9575f80fd5b8286015b84811015611d4e57805167ffffffffffffffff81111561230b575f80fd5b8701603f8101891361231b575f80fd5b61232c89868301516040840161220b565b8452509183019183016122ed565b5f6020828403121561234a575f80fd5b815167ffffffffffffffff811115612360575f80fd5b6103f8848285016122ac565b5f815160208301516001600160e01b03198082169350600483101561239b5780818460040360031b1b83161693505b505050919050565b5f82601f8301126123b2575f80fd5b813560206123c2611c7483611c1d565b82815260059290921b840181019181810190868411156123e0575f80fd5b8286015b84811015611d4e57803567ffffffffffffffff811115612402575f80fd5b6124108986838b0101611ca2565b8452509183019183016123e4565b5f806040838503121561242f575f80fd5b823567ffffffffffffffff80821115612446575f80fd5b818501915085601f830112612459575f80fd5b81356020612469611c7483611c1d565b82815260059290921b84018101918181019089841115612487575f80fd5b948201945b838610156124ae57853561249f81612081565b8252948201949082019061248c565b965050860135925050808211156124c3575f80fd5b50612077858286016123a3565b604081525f6124e26040830185611abc565b82810360208401526115668185611abc565b5f81518060208401855e5f93019283525090919050565b5f6115e982846124f4565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161253b5761253b612516565b5060010190565b8051611b4981611b2a565b8051611b49816119e4565b5f60208284031215612568575f80fd5b815167ffffffffffffffff8082111561257f575f80fd5b9083019060c08286031215612592575f80fd5b61259a611bc9565b6125a383612542565b81526125b16020840161254d565b60208201526040830151828111156125c7575f80fd5b6125d387828601612241565b6040830152506125e56060840161254d565b60608201526125f66080840161254d565b608082015260a08301518281111561260c575f80fd5b61261887828601612241565b60a08301525095945050505050565b8181038181111561032c5761032c612516565b5f602080838503121561264b575f80fd5b825167ffffffffffffffff80821115612662575f80fd5b818501915085601f830112612675575f80fd5b8151612683611c7482611c1d565b81815260059190911b830184019084810190888311156126a1575f80fd5b8585015b838110156126d7578051858111156126bb575f80fd5b6126c98b89838a0101612241565b8452509186019186016126a5565b5098975050505050505050565b5f6103f86126f283866124f4565b846124f4565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b8381101561278457603f19898403018552815160606001600160a01b03825116855288820151818a87015261275682870182611ec1565b915050878201519150848103888601526127708183611abc565b96890196945050509086019060010161271f565b509098975050505050505050565b6001600160a01b038616815260a060208201525f6127b360a0830187611ec1565b82810360408401526127c58187611abc565b90506001600160e01b03198516606084015282810360808401526127e98185611abc565b98975050505050505050565b602081526001600160a01b0382511660208201525f60208301516001600160e01b031980821660408501526040850151915060c0606085015261283b60e0850183611abc565b91508060608601511660808501528060808601511660a08501525060a0840151601f198483030160c08501526115668282611abc565b606081525f6128836060830186611abc565b82810360208401526128958186611abc565b905082810360408401526128a98185611abc565b9695505050505050565b5f602082840312156128c3575f80fd5b81516115e981611b2a565b5f805f805f60a086880312156128e2575f80fd5b85516128ed81611b2a565b602087015190955067ffffffffffffffff8082111561290a575f80fd5b61291689838a016122ac565b9550604088015191508082111561292b575f80fd5b61293789838a01612241565b945060608801519150612949826119e4565b60808801519193508082111561295d575f80fd5b5061296a88828901612241565b9150509295509295909350565b8082018082111561032c5761032c61251656fea2646970667358221220f7f08fac33be2b0187513eb7551b6c4b2f467349de499d89767e8c8de773540564736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80639061b92311610088578063e370ecbe11610063578063e370ecbe14610238578063eea330f91461025f578063ef46c0b814610291578063f394443a146102a6575f80fd5b80639061b923146101f25780639f28e99d14610205578063b536af7614610225575f80fd5b8063582de3e7116100c3578063582de3e7146101705780636ccb8660146101945780636d6dd540146101bb5780636f3ff726146101df575f80fd5b806301ffc9a7146100e957806348ee1bcc14610111578063491fc4f914610150575b5f80fd5b6100fc6100f73660046119fc565b6102b9565b60405190151581526020015b60405180910390f35b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610108565b61016361015e366004611a55565b610332565b6040516101089190611aea565b6100fc61017e3660046119fc565b6001600160e01b0319166312d6c5b760e31b1490565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101d16101c9366004611a55565b509192909150565b604051610108929190611afc565b6100fc6101ed366004611b4e565b610400565b610163610200366004611a55565b61048c565b610218610213366004611d59565b6105bb565b6040516101089190611f19565b610218610233366004611a55565b61077c565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b61027261026d366004611fe2565b6109cb565b604080516001600160a01b039093168352901515602083015201610108565b6102a461029f366004612021565b6109e4565b005b6101636102b4366004612099565b610a69565b5f639061b92360e01b6001600160e01b03198316148061030257507feea330f9000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b8061031d575063582de3e760e01b6001600160e01b03198316145b8061032c575061032c82610da0565b92915050565b60605f61034185870187611d59565b5190505f806103528587018761215e565b91509150811561038f576103668382610dd4565b6040516020016103769190612195565b60405160208183030381529060405293505050506103f8565b5f835f815181106103a2576103a26121f7565b60209081029190910101516040810151606082015191925090600e16156103cb57805160208201fd5b82156103e857808060200190518101906103e5919061225f565b90505b94506103f89350505050565b5050505b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610468573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032c9190612291565b60606105b261049b8686610f36565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f9201829052506040805160208101825282815281517f093a86d3000000000000000000000000000000000000000000000000000000008152915192955093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063093a86d391600480830192879291908290030181865afa15801561058b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526102b4919081019061233a565b50949350505050565b60408051808201909152606080825260208201525f5b82515181101561076e575f835f015182815181106105f1576105f16121f7565b6020026020010151905060408160600151165f1461060f5750610766565b60608101516030165f036106b9575f61062a825f0151610fa0565b610635576010610638565b60205b9050825b8551518110156106b657825f01516001600160a01b0316865f01518281518110610668576106686121f7565b60200260200101515f01516001600160a01b0316036106ae5781865f01518281518110610697576106976121f7565b602002602001015160600181815117915081815250505b60010161063c565b50505b5f60208260600151165f1490505f806106db8315855f01518660200151610fd2565b91509150811580156107055750630556f18360e41b6106f98261236c565b6001600160e01b031916145b1561071a57606084018051600117905261075a565b606084018051604017905282801561073157508051155b61074657816107465760608401805160021790525b80515f0361075a5760608401805160081790525b60409093019290925250505b6001016105d1565b5061077882611065565b5090565b60408051808201909152606080825260208201525f8061079e8688018861241e565b9150915080518251146107c45760405163252e18f560e11b815260040160405180910390fd5b6107d084860186611d59565b92505f805b8451518110156109a0575f855f015182815181106107f5576107f56121f7565b6020026020010151905060408160600151165f0361099757835183101561098b575f848481518110610829576108296121f7565b60200260200101519050858481518110610845576108456121f7565b602002602001015115610862576060820180516044179052610985565b5f6108708360400151611250565b90505f815f01516001600160a01b0316826060015184846080015160405160240161089c9291906124d0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516108da919061250b565b5f60405180830381855afa9150503d805f8114610912576040519150601f19603f3d011682016040523d82523d5f602084013e610917565b606091505b509350905080806109415750630556f18360e41b6109348461236c565b6001600160e01b03191614155b1561098257606084018051604017905280158061095d57508251155b1561096e5760608401805160021790525b82515f036109825760608401805160081790525b50505b60408201525b6109948361252a565b92505b506001016107d5565b50815181146109c25760405163252e18f560e11b815260040160405180910390fd5b6103f484611065565b5f806109d78484610f36565b5f915091505b9250929050565b5f818060200190518101906109f99190612558565b9050610a64815f01518260200151858460400151604051602401610a1e9291906124d0565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a0860151611294565b505050565b6060866001600160a01b03163b5f03610ab957856040517f5fe9a5df000000000000000000000000000000000000000000000000000000008152600401610ab09190611aea565b60405180910390fd5b5f7fac9650d800000000000000000000000000000000000000000000000000000000610ae48761236c565b6001600160e01b0319161490505f858015610b0b5750610b0b8963477cc53f60e11b611457565b90505f8180610b265750610b268a639061b92360e01b611457565b9050610b398a63582de3e760e01b611457565b8015610bbd5750821580610bbd5750808015610bbd575060405163582de3e760e01b81526312d6c5b760e31b60048201526001600160a01b038b169063582de3e790602401602060405180830381865afa158015610b99573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bbd9190612291565b15610c07578015610be257610bdd8a610bd8848c8c8b6114dd565b61156f565b610c07565b610c078a89636d6dd54060e01b5f60e01b60405180602001604052805f815250611294565b60608315610c4157610c27896004808c51610c229190612627565b611594565b806020019051810190610c3a919061263a565b9050610c8c565b60408051600180825281830190925290816020015b6060815260200190600190039081610c5657905050905088815f81518110610c8057610c806121f7565b60200260200101819052505b8115610ce9575f5b8151811015610ce757610cc2848c848481518110610cb457610cb46121f7565b60200260200101518b6114dd565b828281518110610cd457610cd46121f7565b6020908102919091010152600101610c94565b505b610d923080639f28e99d610cfe8f868c6115f0565b604051602401610d0e9190611f19565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b94909417909352519092507f491fc4f900000000000000000000000000000000000000000000000000000000915f91610d7e918b918a910191151582521515602082015260400190565b604051602081830303815290604052611294565b505050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b148061032c57506301ffc9a760e01b6001600160e01b031983161461032c565b6060825167ffffffffffffffff811115610df057610df0611b69565b604051908082528060200260200182016040528015610e2357816020015b6060815260200190600190039081610e0e5790505b5090505f5b8351811015610f2f575f848281518110610e4457610e446121f7565b60209081029190910101516040810151606082015191925090600e165f03610e88578415610e835780806020019051810190610e80919061225f565b90505b610f07565b805115610f07578051600403601f168015610f0557818167ffffffffffffffff811115610eb757610eb7611b69565b6040519080825280601f01601f191660200182016040528015610ee1576020820181803683370190505b50604051602001610ef39291906126e4565b60405160208183030381529060405291505b505b80848481518110610f1a57610f1a6121f7565b60209081029190910101525050600101610e28565b5092915050565b5f610f967f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250611705915050565b5090949350505050565b5f306001600160a01b03831603610fb957506001919050565b6113885a5f805f808786fa50815a909103109392505050565b5f6060836001600160a01b03168561100a577f000000000000000000000000000000000000000000000000000000000000000061100c565b5a5b8460405161101a919061250b565b5f604051808303818686fa925050503d805f8114611053576040519150601f19603f3d011682016040523d82523d5f602084013e611058565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff81111561108257611082611b69565b6040519080825280602002602001820160405280156110df57816020015b6110cc60405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816110a05790505b5090505f805b835151811015611190575f845f01518281518110611105576111056121f7565b6020026020010151905060408160600151165f03611187575f61112b8260400151611250565b90506040518060600160405280825f01516001600160a01b031681526020018260200151815260200182604001518152508585806111689061252a565b96508151811061117a5761117a6121f7565b6020026020010181905250505b506001016110e5565b508015610a6457808252308360200151836040516024016111b191906126f8565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af76000000000000000000000000000000000000000000000000000000009161122591899101611f19565b60408051601f1981840301815290829052630556f18360e41b8252610ab09594939291600401612792565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915261032c61128f836004808651610c229190612627565b611801565b5f806112a96112a288610fa0565b8888610fd2565b91509150811580156112d35750630556f18360e41b6112c78261236c565b6001600160e01b031916145b15611381575f6112e282611250565b9050876001600160a01b0316815f01516001600160a01b03160361137f57308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b03191681526020018981525060405160200161122591906127f5565b505b5f8261138d578461138f565b855b90506001600160e01b031981161561144157306001600160a01b03168183866040516024016113bf9291906124d0565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516113fd919061250b565b5f60405180830381855afa9150503d805f8114611435576040519150601f19603f3d011682016040523d82523d5f602084013e61143a565b606091505b5090935091505b821561144f57815160208301f35b815160208301fd5b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f5190508280156114c7575060208210155b80156114d257505f81115b979650505050505050565b6060846115265783836040516024016114f79291906124d0565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b179052611566565b83838360405160240161153b93929190612871565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b1790525b95945050505050565b61159082825f60e01b5f60e01b60405180602001604052805f815250611294565b5050565b60608167ffffffffffffffff8111156115af576115af611b69565b6040519080825280601f01601f1916602001820160405280156115d9576020820181803683370190505b5090506115e98484835f8661186c565b9392505050565b60408051808201909152606080825260208201525f835167ffffffffffffffff81111561161f5761161f611b69565b60405190808252806020026020018201604052801561168257816020015b61166f60405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b81526020019060019003908161163d5790505b5090505f5b84518110156116e8575f8282815181106116a3576116a36121f7565b60209081029190910101516001600160a01b038816815286519091508690839081106116d1576116d16121f7565b602090810291909101810151910152600101611687565b506040805180820190915290815260208101929092525092915050565b5f805f805f61171487876118a9565b909250905081156117f5575f805f61172d8b8b86611705565b92509250925061174682865f9182526020526040902090565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018290529097506001600160a01b038c1690630178b8bf90602401602060405180830381865afa1580156117a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c991906128b3565b97506001600160a01b0388166117e1578287826117e5565b87878a5b97509750975050505050506117f8565b50505b93509350939050565b6040805160a0810182525f8082526060602083018190529282018390528282015260808101919091528180602001905181019061183e91906128ce565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b61187f8561187a8387612977565b6118d6565b61188d8361187a8385612977565b6118a28260208501018560208801018361191e565b5050505050565b5f805f6118b68585611967565b9250905060ff8116156118ce57806021858701012092505b509250929050565b81518111156115905781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610ab0918391600401918252602082015260400190565b5b601f81111561193f578151835260209283019290910190601f190161191f565b8015610a645790518251600160209390930360031b9290921b5f190180199091169116179052565b5f808351831061198c578360405163ba4adc2360e01b8152600401610ab09190611aea565b83838151811061199e5761199e6121f7565b016020015160f81c915050818101600101816119be5783518114156119c4565b83518110155b156109dd578360405163ba4adc2360e01b8152600401610ab09190611aea565b6001600160e01b0319811681146119f9575f80fd5b50565b5f60208284031215611a0c575f80fd5b81356115e9816119e4565b5f8083601f840112611a27575f80fd5b50813567ffffffffffffffff811115611a3e575f80fd5b6020830191508360208285010111156109dd575f80fd5b5f805f8060408587031215611a68575f80fd5b843567ffffffffffffffff80821115611a7f575f80fd5b611a8b88838901611a17565b90965094506020870135915080821115611aa3575f80fd5b50611ab087828801611a17565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6115e96020830184611abc565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b6001600160a01b03811681146119f9575f80fd5b8035611b4981611b2a565b919050565b5f60208284031215611b5e575f80fd5b81356115e981611b2a565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611ba057611ba0611b69565b60405290565b6040516080810167ffffffffffffffff81118282101715611ba057611ba0611b69565b60405160c0810167ffffffffffffffff81118282101715611ba057611ba0611b69565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c1557611c15611b69565b604052919050565b5f67ffffffffffffffff821115611c3657611c36611b69565b5060051b60200190565b5f67ffffffffffffffff821115611c5957611c59611b69565b50601f01601f191660200190565b5f611c79611c7484611c40565b611bec565b9050828152838383011115611c8c575f80fd5b828260208301375f602084830101529392505050565b5f82601f830112611cb1575f80fd5b6115e983833560208501611c67565b5f82601f830112611ccf575f80fd5b81356020611cdf611c7483611c1d565b82815260059290921b84018101918181019086841115611cfd575f80fd5b8286015b84811015611d4e57803567ffffffffffffffff811115611d1f575f80fd5b8701603f81018913611d2f575f80fd5b611d40898683013560408401611c67565b845250918301918301611d01565b509695505050505050565b5f6020808385031215611d6a575f80fd5b823567ffffffffffffffff80821115611d81575f80fd5b9084019060408287031215611d94575f80fd5b611d9c611b7d565b823582811115611daa575f80fd5b8301601f81018813611dba575f80fd5b8035611dc8611c7482611c1d565b81815260059190911b8201860190868101908a831115611de6575f80fd5b8784015b83811015611e8e57803587811115611e00575f80fd5b85016080818e03601f19011215611e15575f80fd5b611e1d611ba6565b8a820135611e2a81611b2a565b8152604082013589811115611e3d575f80fd5b611e4b8f8d83860101611ca2565b8c83015250606082013589811115611e61575f80fd5b611e6f8f8d83860101611ca2565b6040830152506080919091013560608201528352918801918801611dea565b5084525050508284013582811115611ea4575f80fd5b611eb088828601611cc0565b948201949094529695505050505050565b5f8282518085526020808601955060208260051b840101602086015f5b84811015611f0c57601f19868403018952611efa838351611abc565b98840198925090830190600101611ede565b5090979650505050505050565b5f602080835260608084018551604080858801528282518085526080945060808901915060808160051b8a010187850194505f5b82811015611fb757607f198b830301845285516001600160a01b03815116835289810151888b850152611f8289850182611abc565b90508682015184820388860152611f998282611abc565b928b0151948b01949094525095890195938901939150600101611f4d565b50968a0151898803601f190160408b015296611fd38189611ec1565b9b9a5050505050505050505050565b5f8060208385031215611ff3575f80fd5b823567ffffffffffffffff811115612009575f80fd5b61201585828601611a17565b90969095509350505050565b5f8060408385031215612032575f80fd5b823567ffffffffffffffff80821115612049575f80fd5b61205586838701611ca2565b9350602085013591508082111561206a575f80fd5b5061207785828601611ca2565b9150509250929050565b80151581146119f9575f80fd5b8035611b4981612081565b5f805f805f8060c087890312156120ae575f80fd5b6120b787611b3e565b9550602087013567ffffffffffffffff808211156120d3575f80fd5b6120df8a838b01611ca2565b965060408901359150808211156120f4575f80fd5b6121008a838b01611ca2565b955061210e60608a0161208e565b94506080890135915080821115612123575f80fd5b61212f8a838b01611ca2565b935060a0890135915080821115612144575f80fd5b5061215189828a01611cc0565b9150509295509295509295565b5f806040838503121561216f575f80fd5b823561217a81612081565b9150602083013561218a81612081565b809150509250929050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b828110156121ea57603f198886030184526121d8858351611abc565b945092850192908501906001016121bc565b5092979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f612218611c7484611c40565b905082815283838301111561222b575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f830112612250575f80fd5b6115e98383516020850161220b565b5f6020828403121561226f575f80fd5b815167ffffffffffffffff811115612285575f80fd5b6103f884828501612241565b5f602082840312156122a1575f80fd5b81516115e981612081565b5f82601f8301126122bb575f80fd5b815160206122cb611c7483611c1d565b82815260059290921b840181019181810190868411156122e9575f80fd5b8286015b84811015611d4e57805167ffffffffffffffff81111561230b575f80fd5b8701603f8101891361231b575f80fd5b61232c89868301516040840161220b565b8452509183019183016122ed565b5f6020828403121561234a575f80fd5b815167ffffffffffffffff811115612360575f80fd5b6103f8848285016122ac565b5f815160208301516001600160e01b03198082169350600483101561239b5780818460040360031b1b83161693505b505050919050565b5f82601f8301126123b2575f80fd5b813560206123c2611c7483611c1d565b82815260059290921b840181019181810190868411156123e0575f80fd5b8286015b84811015611d4e57803567ffffffffffffffff811115612402575f80fd5b6124108986838b0101611ca2565b8452509183019183016123e4565b5f806040838503121561242f575f80fd5b823567ffffffffffffffff80821115612446575f80fd5b818501915085601f830112612459575f80fd5b81356020612469611c7483611c1d565b82815260059290921b84018101918181019089841115612487575f80fd5b948201945b838610156124ae57853561249f81612081565b8252948201949082019061248c565b965050860135925050808211156124c3575f80fd5b50612077858286016123a3565b604081525f6124e26040830185611abc565b82810360208401526115668185611abc565b5f81518060208401855e5f93019283525090919050565b5f6115e982846124f4565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161253b5761253b612516565b5060010190565b8051611b4981611b2a565b8051611b49816119e4565b5f60208284031215612568575f80fd5b815167ffffffffffffffff8082111561257f575f80fd5b9083019060c08286031215612592575f80fd5b61259a611bc9565b6125a383612542565b81526125b16020840161254d565b60208201526040830151828111156125c7575f80fd5b6125d387828601612241565b6040830152506125e56060840161254d565b60608201526125f66080840161254d565b608082015260a08301518281111561260c575f80fd5b61261887828601612241565b60a08301525095945050505050565b8181038181111561032c5761032c612516565b5f602080838503121561264b575f80fd5b825167ffffffffffffffff80821115612662575f80fd5b818501915085601f830112612675575f80fd5b8151612683611c7482611c1d565b81815260059190911b830184019084810190888311156126a1575f80fd5b8585015b838110156126d7578051858111156126bb575f80fd5b6126c98b89838a0101612241565b8452509186019186016126a5565b5098975050505050505050565b5f6103f86126f283866124f4565b846124f4565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b8381101561278457603f19898403018552815160606001600160a01b03825116855288820151818a87015261275682870182611ec1565b915050878201519150848103888601526127708183611abc565b96890196945050509086019060010161271f565b509098975050505050505050565b6001600160a01b038616815260a060208201525f6127b360a0830187611ec1565b82810360408401526127c58187611abc565b90506001600160e01b03198516606084015282810360808401526127e98185611abc565b98975050505050505050565b602081526001600160a01b0382511660208201525f60208301516001600160e01b031980821660408501526040850151915060c0606085015261283b60e0850183611abc565b91508060608601511660808501528060808601511660a08501525060a0840151601f198483030160c08501526115668282611abc565b606081525f6128836060830186611abc565b82810360208401526128958186611abc565b905082810360408401526128a98185611abc565b9695505050505050565b5f602082840312156128c3575f80fd5b81516115e981611b2a565b5f805f805f60a086880312156128e2575f80fd5b85516128ed81611b2a565b602087015190955067ffffffffffffffff8082111561290a575f80fd5b61291689838a016122ac565b9550604088015191508082111561292b575f80fd5b61293789838a01612241565b945060608801519150612949826119e4565b60808801519193508082111561295d575f80fd5b5061296a88828901612241565b9150509295509295909350565b8082018082111561032c5761032c61251656fea2646970667358221220f7f08fac33be2b0187513eb7551b6c4b2f467349de499d89767e8c8de773540564736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "1201": [ + { + "length": 32, + "start": 4070 + } + ], + "69302": [ + { + "length": 32, + "start": 409 + }, + { + "length": 32, + "start": 1346 + } + ], + "69443": [ + { + "length": 32, + "start": 573 + }, + { + "length": 32, + "start": 3900 + } + ], + "75299": [ + { + "length": 32, + "start": 278 + }, + { + "length": 32, + "start": 1057 + } + ] + }, + "inputSourceName": "project/src/resolver/ENSV1Resolver.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "InvalidBatchGatewayResponse()": [ + { + "details": "Error selector: `0x4a5c31ea`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "UnreachableName(bytes)": [ + { + "details": "`name` cannot be resolved. Error selector: `0x5fe9a5df`", + "params": { + "name": "The DNS-encoded ENS name." + } + } + ] + }, + "kind": "dev", + "methods": { + "callResolver(address,bytes,bytes,bool,bytes,string[])": { + "details": "Reverts `UnreachableName` if resolver is not a contract. This function never returns normally. The return type is necessary to define the result of the callback. Call this function externally or with `ccipRead()` to intercept the response.", + "params": { + "batchGateways": "The batch gateway URLs.", + "context": "The context for `IExtendedDNSResolver`.", + "data": "The calldata for the resolution.", + "hasContext": "True if `IExtendedDNSResolver` should be considered.", + "name": "The DNS-encoded ENS name.", + "resolver": "The resolver to call." + } + }, + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": { + "details": "Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`." + }, + "ccipBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \"done\".", + "params": { + "extraData": "The contextual data passed from `ccipBatch()`.", + "response": "The response from the batch gateway." + }, + "returns": { + "batch": "The batch where every lookup is \"done\"." + } + }, + "ccipReadCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.", + "params": { + "extraData": "The contextual data passed from `ccipRead()`.", + "response": "The response from offchain." + } + }, + "constructor": { + "params": { + "batchGatewayProvider": "The batch gateway provider.", + "contractNamer": "Delegated contract namer.", + "registryV1": "The ENSv1 registry." + } + }, + "getResolver(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The underlying resolver address.", + "_1": "`true` if `resolver` is offchain." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "resolveBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `callResolver()` from batch calling a resolver.", + "params": { + "extraData": "The abi-encoded properties of the call.", + "response": "The response data from the batch gateway." + }, + "returns": { + "_0": "result The response from the resolver." + } + }, + "resolveDirectImmediateCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `callResolver()` from direct calling an immediate resolver." + }, + "supportsFeature(bytes4)": { + "params": { + "featureId": "The feature identifier." + }, + "returns": { + "_0": "`true` if the feature is supported by the contract." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "2137600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BATCH_GATEWAY_PROVIDER()": "infinite", + "CONTRACT_NAMER()": "infinite", + "REGISTRY_V1()": "infinite", + "callResolver(address,bytes,bytes,bool,bytes,string[])": "infinite", + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": "infinite", + "ccipBatchCallback(bytes,bytes)": "infinite", + "ccipReadCallback(bytes,bytes)": "infinite", + "getResolver(bytes)": "infinite", + "isContractNamer(address)": "infinite", + "resolve(bytes,bytes)": "infinite", + "resolveBatchCallback(bytes,bytes)": "infinite", + "resolveDirectImmediateCallback(bytes,bytes)": "infinite", + "supportsFeature(bytes4)": "396", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_findResolver(bytes calldata)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"batchGatewayProvider\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"},{\"internalType\":\"contract ENS\",\"name\":\"registryV1\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBatchGatewayResponse\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"UnreachableName\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BATCH_GATEWAY_PROVIDER\",\"outputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REGISTRY_V1\",\"outputs\":[{\"internalType\":\"contract ENS\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"hasContext\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"batchGateways\",\"type\":\"string[]\"}],\"name\":\"callResolver\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"name\":\"ccipBatch\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipBatchCallback\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipReadCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveBatchCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"resolveDirectImmediateCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"feature\",\"type\":\"bytes4\"}],\"name\":\"supportsFeature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"InvalidBatchGatewayResponse()\":[{\"details\":\"Error selector: `0x4a5c31ea`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"UnreachableName(bytes)\":[{\"details\":\"`name` cannot be resolved. Error selector: `0x5fe9a5df`\",\"params\":{\"name\":\"The DNS-encoded ENS name.\"}}]},\"kind\":\"dev\",\"methods\":{\"callResolver(address,bytes,bytes,bool,bytes,string[])\":{\"details\":\"Reverts `UnreachableName` if resolver is not a contract. This function never returns normally. The return type is necessary to define the result of the callback. Call this function externally or with `ccipRead()` to intercept the response.\",\"params\":{\"batchGateways\":\"The batch gateway URLs.\",\"context\":\"The context for `IExtendedDNSResolver`.\",\"data\":\"The calldata for the resolution.\",\"hasContext\":\"True if `IExtendedDNSResolver` should be considered.\",\"name\":\"The DNS-encoded ENS name.\",\"resolver\":\"The resolver to call.\"}},\"ccipBatch(((address,bytes,bytes,uint256)[],string[]))\":{\"details\":\"Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`.\"},\"ccipBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\",\"params\":{\"extraData\":\"The contextual data passed from `ccipBatch()`.\",\"response\":\"The response from the batch gateway.\"},\"returns\":{\"batch\":\"The batch where every lookup is \\\"done\\\".\"}},\"ccipReadCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.\",\"params\":{\"extraData\":\"The contextual data passed from `ccipRead()`.\",\"response\":\"The response from offchain.\"}},\"constructor\":{\"params\":{\"batchGatewayProvider\":\"The batch gateway provider.\",\"contractNamer\":\"Delegated contract namer.\",\"registryV1\":\"The ENSv1 registry.\"}},\"getResolver(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The underlying resolver address.\",\"_1\":\"`true` if `resolver` is offchain.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"resolveBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `callResolver()` from batch calling a resolver.\",\"params\":{\"extraData\":\"The abi-encoded properties of the call.\",\"response\":\"The response data from the batch gateway.\"},\"returns\":{\"_0\":\"result The response from the resolver.\"}},\"resolveDirectImmediateCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `callResolver()` from direct calling an immediate resolver.\"},\"supportsFeature(bytes4)\":{\"params\":{\"featureId\":\"The feature identifier.\"},\"returns\":{\"_0\":\"`true` if the feature is supported by the contract.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBatchGatewayResponse()\":[{\"notice\":\"The batch gateway supplied an incorrect number of responses.\"}]},\"kind\":\"user\",\"methods\":{\"BATCH_GATEWAY_PROVIDER()\":{\"notice\":\"Shared batch gateway provider.\"},\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"REGISTRY_V1()\":{\"notice\":\"The ENSv1 registry used to look up resolvers for names.\"},\"callResolver(address,bytes,bytes,bool,bytes,string[])\":{\"notice\":\"Perform forward resolution. Call this function with `ccipRead()` to intercept the response. Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers. - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features, the call is performed directly without the batch gateway. - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature, the call is performed directly without the batch gateway. - Otherwise, the call is performed with the batch gateway. The batch gateway is only invoked if any call reverts `OffchainLookup`. If the calldata is `multicall()` it is disassembled, called separately, and reassembled.\"},\"getResolver(bytes)\":{\"notice\":\"Fetch the underlying resolver for `name`. Callers should enable EIP-3668. * If `offchain`, additional information is necessary to locate `resolver`. * If `resolver` is null, `offchain` is irrelevant.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"supportsFeature(bytes4)\":{\"notice\":\"Check if a feature is supported.\"}},\"notice\":\"Resolver that performs resolutions using ENSv1.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/resolver/ENSV1Resolver.sol\":\"ENSV1Resolver\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/CCIPBatcher.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {IBatchGateway} from \\\"./IBatchGateway.sol\\\";\\nimport {CCIPReader, EIP3668, OffchainLookup} from \\\"./CCIPReader.sol\\\";\\n\\n/// @dev CCIP-Read batch gateway client implementation.\\n///\\n/// Since requests are read-only, empty responses are considered an error.\\n///\\n/// Usage: `ccipRead(address(this), abi.encodeCall(this.ccipBatch, (createBatch(...))), ...)`\\n///\\nabstract contract CCIPBatcher is CCIPReader {\\n /// @notice The batch gateway supplied an incorrect number of responses.\\n /// @dev Error selector: `0x4a5c31ea`\\n error InvalidBatchGatewayResponse();\\n\\n uint256 constant FLAG_OFFCHAIN = 1 << 0; // the lookup reverted `OffchainLookup`\\n uint256 constant FLAG_CALL_ERROR = 1 << 1; // the initial call or callback reverted\\n uint256 constant FLAG_BATCH_ERROR = 1 << 2; // `OffchainLookup` failed on the batch gateway\\n uint256 constant FLAG_EMPTY_RESPONSE = 1 << 3; // the initial call or callback returned `0x`\\n uint256 constant FLAG_EIP140_BEFORE = 1 << 4; // does not have revert op code\\n uint256 constant FLAG_EIP140_AFTER = 1 << 5; // has revert op code\\n uint256 constant FLAG_DONE = 1 << 6; // the lookup has finished processing (private)\\n\\n uint256 constant FLAGS_ANY_ERROR =\\n FLAG_CALL_ERROR | FLAG_BATCH_ERROR | FLAG_EMPTY_RESPONSE;\\n uint256 constant FLAGS_ANY_EIP140 = FLAG_EIP140_BEFORE | FLAG_EIP140_AFTER;\\n\\n /// @dev An independent `OffchainLookup` session.\\n struct Lookup {\\n address target; // contract to call\\n bytes call; // initial calldata\\n bytes data; // response or error\\n uint256 flags; // see: FLAG_*\\n }\\n\\n /// @dev A batch gateway session.\\n struct Batch {\\n Lookup[] lookups;\\n string[] gateways;\\n }\\n\\n /// @dev Create a batch for a single target with multiple calls.\\n /// @param target The target contract.\\n /// @param calls The list of calldata.\\n /// @param gateways The batch gateway URLs.\\n function createBatch(\\n address target,\\n bytes[] memory calls,\\n string[] memory gateways\\n ) internal pure returns (Batch memory) {\\n Lookup[] memory lookups = new Lookup[](calls.length);\\n for (uint256 i; i < calls.length; ++i) {\\n Lookup memory lu = lookups[i];\\n lu.target = target;\\n lu.call = calls[i];\\n }\\n return Batch(lookups, gateways);\\n }\\n\\n /// @dev Use `ccipRead()` to call this function with a batch.\\n /// The callback response will be `abi.encode(batch)`.\\n function ccipBatch(\\n Batch memory batch\\n ) external view returns (Batch memory) {\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) != 0) {\\n continue; // don't call a lookup that's already done\\n }\\n if ((lu.flags & FLAGS_ANY_EIP140) == 0) {\\n uint256 flags = detectEIP140(lu.target)\\n ? FLAG_EIP140_AFTER\\n : FLAG_EIP140_BEFORE;\\n for (uint256 j = i; j < batch.lookups.length; ++j) {\\n if (batch.lookups[j].target == lu.target) {\\n batch.lookups[j].flags |= flags;\\n }\\n }\\n }\\n bool unsafe = (lu.flags & FLAG_EIP140_AFTER) == 0;\\n (bool ok, bytes memory v) = safeCall(!unsafe, lu.target, lu.call);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n lu.flags |= FLAG_OFFCHAIN;\\n } else {\\n lu.flags |= FLAG_DONE;\\n if (unsafe && v.length == 0) {\\n // unsafe contracts appear the same for throw and unimplemented fallback\\n // decision: interpret like an unimplemented function selector response\\n } else if (!ok) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n lu.data = v;\\n }\\n _revertBatchGateway(batch); // reverts if any offchain\\n return batch;\\n }\\n\\n /// @dev Check if the batch is \\\"done\\\". If not, revert `OffchainLookup` for batch gateway.\\n function _revertBatchGateway(Batch memory batch) internal view {\\n IBatchGateway.Request[] memory requests = new IBatchGateway.Request[](\\n batch.lookups.length\\n );\\n uint256 count;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n requests[count++] = IBatchGateway.Request(\\n p.sender,\\n p.urls,\\n p.callData\\n );\\n }\\n }\\n if (count > 0) {\\n assembly {\\n mstore(requests, count) // truncate to number of offchain requests\\n }\\n revert OffchainLookup(\\n address(this),\\n batch.gateways,\\n abi.encodeCall(IBatchGateway.query, (requests)),\\n this.ccipBatchCallback.selector,\\n abi.encode(batch)\\n );\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipBatch()`.\\n /// Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\\n /// @param response The response from the batch gateway.\\n /// @param extraData The contextual data passed from `ccipBatch()`.\\n /// @return batch The batch where every lookup is \\\"done\\\".\\n function ccipBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (Batch memory batch) {\\n (bool[] memory failures, bytes[] memory responses) = abi.decode(\\n response,\\n (bool[], bytes[])\\n );\\n if (failures.length != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n batch = abi.decode(extraData, (Batch));\\n uint256 expected;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n if (expected < responses.length) {\\n bytes memory v = responses[expected];\\n if (failures[expected]) {\\n lu.flags |= FLAG_DONE | FLAG_BATCH_ERROR;\\n } else {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n bool ok;\\n // assumption: unsafe contracts don't revert OffchainLookup()\\n (ok, v) = p.sender.staticcall(\\n abi.encodeWithSelector(\\n p.callbackFunction,\\n v,\\n p.extraData\\n )\\n );\\n if (ok || bytes4(v) != OffchainLookup.selector) {\\n lu.flags |= FLAG_DONE;\\n // decision: promote empty response from the callback => call error\\n // ie. the initial function was implemented but the callback was not\\n // this can be detected via FLAG_OFFCHAIN\\n if (!ok || v.length == 0) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n }\\n lu.data = v;\\n }\\n ++expected;\\n }\\n }\\n if (expected != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n _revertBatchGateway(batch);\\n }\\n\\n /// @dev Safely collapse `Lookup[]` into `bytes[]`.\\n /// If `FLAGS_ANY_ERROR` and response is non-empty, the response is zero-padded so that `length % 32 == 4`.\\n /// @param lookups Array of completed lookups.\\n /// @param wrapped If `true`, successful responses are unwrapped as `bytes`.\\n /// @return arr Array of call responses.\\n function _toResponseArray(Lookup[] memory lookups, bool wrapped) internal pure returns (bytes[] memory arr) {\\n arr = new bytes[](lookups.length);\\n for (uint256 i; i < lookups.length; ++i) {\\n Lookup memory lu = lookups[i];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) == 0) {\\n if (wrapped) {\\n v = abi.decode(v, (bytes));\\n }\\n } else if (v.length != 0) {\\n // force pad error response to length mod 32 == 4\\n // prevents unverified data from passing as valid response \\n unchecked {\\n uint256 pad = (4 - v.length) & 31;\\n if (pad > 0) {\\n v = abi.encodePacked(v, new bytes(pad)); \\n }\\n }\\n }\\n arr[i] = v;\\n }\\n return arr;\\n }\\n}\",\"keccak256\":\"0xc7fe6929199a1019dd0c3faf9884b5250786fb77d3c3df3e772cfd4ed823d684\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/CCIPReader.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n/// @author Modified from https://github.com/unruggable-labs/CCIPReader.sol/blob/341576fe7ff2b6e0c93fc08f37740cf6439f5873/contracts/CCIPReader.sol\\n\\n/// MIT License\\n/// Portions Copyright (c) 2025 Unruggable\\n/// Portions Copyright (c) 2025 ENS Labs Ltd\\n\\n/// @dev Instructions:\\n/// 1. inherit this contract\\n/// 2. call `ccipRead()` similar to `staticcall()`\\n/// 3. do not put logic after this invocation\\n/// 4. implement all response logic in callback\\n/// 5. ensure that return type of calling function == callback function\\n\\nimport {EIP3668, OffchainLookup} from \\\"./EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\n\\ncontract CCIPReader {\\n /// @dev Default unsafe call gas (sufficient for legacy ENS resolver profiles).\\n uint256 constant DEFAULT_UNSAFE_CALL_GAS = 50000;\\n\\n /// @dev Special-purpose value for identity callback: `f(x) = x`.\\n bytes4 constant IDENTITY_FUNCTION = bytes4(0);\\n\\n /// @dev The gas limit for calling functions on unsafe contracts.\\n uint256 immutable unsafeCallGas;\\n\\n constructor(uint256 _unsafeCallGas) {\\n unsafeCallGas = _unsafeCallGas;\\n }\\n\\n /// @dev A recursive CCIP-Read session.\\n struct Context {\\n address target;\\n bytes4 callbackFunction;\\n bytes extraData;\\n bytes4 successCallbackFunction;\\n bytes4 failureCallbackFunction;\\n bytes myExtraData;\\n }\\n\\n /// @dev Same as `ccipRead()` but the callback function is the identity.\\n function ccipRead(address target, bytes memory call) internal view {\\n ccipRead(target, call, IDENTITY_FUNCTION, IDENTITY_FUNCTION, \\\"\\\");\\n }\\n\\n /// @dev Performs a CCIP-Read and handles internal recursion.\\n /// Reverts `OffchainLookup` if necessary.\\n /// Use `IDENTITY_FUNCTION` as the callback function selector for return/revert behavior.\\n /// @param target The contract address.\\n /// @param call The calldata to `staticcall()` on `target`.\\n /// @param successCallbackFunction The function selector of callback on success.\\n /// @param failureCallbackFunction The function selector of callback on failure.\\n /// @param extraData The contextual data relayed to callback function.\\n function ccipRead(\\n address target,\\n bytes memory call,\\n bytes4 successCallbackFunction,\\n bytes4 failureCallbackFunction,\\n bytes memory extraData\\n ) internal view {\\n // We call the intended function that **could** revert with an `OffchainLookup`\\n // We destructure the response into an execution status bool and our return bytes\\n (bool ok, bytes memory v) = safeCall(\\n detectEIP140(target),\\n target,\\n call\\n );\\n // IF the function reverted with an `OffchainLookup`\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n // We decode the response error into a tuple\\n // tuples allow flexibility noting stack too deep constraints\\n EIP3668.Params memory p = decodeOffchainLookup(v);\\n if (p.sender == target) {\\n // We then wrap the error data in an `OffchainLookup` sent/'owned' by this contract\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n this.ccipReadCallback.selector,\\n abi.encode(\\n Context(\\n target,\\n p.callbackFunction,\\n p.extraData,\\n successCallbackFunction,\\n failureCallbackFunction,\\n extraData\\n )\\n )\\n );\\n }\\n }\\n // IF we have gotten here, the 'real' target does not revert with an `OffchainLookup` error\\n // figure out what callback to call\\n bytes4 callbackFunction = ok\\n ? successCallbackFunction\\n : failureCallbackFunction;\\n if (callbackFunction != IDENTITY_FUNCTION) {\\n // The exit point of this architecture is OUR callback in the 'real'\\n // We pass through the response to that callback\\n (ok, v) = address(this).staticcall(\\n abi.encodeWithSelector(callbackFunction, v, extraData)\\n );\\n }\\n // OR the call to the 'real' target reverts with a different error selector\\n // OR the call to OUR callback reverts with ANY error selector\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipRead()`.\\n /// @param response The response from offchain.\\n /// @param extraData The contextual data passed from `ccipRead()`.\\n /// @dev The return type of this function is polymorphic depending on the caller.\\n function ccipReadCallback(\\n bytes memory response,\\n bytes memory extraData\\n ) external view {\\n Context memory ctx = abi.decode(extraData, (Context));\\n // Since the callback can revert too (but has the same return structure)\\n // We can reuse the calling infrastructure to call the callback\\n ccipRead(\\n ctx.target,\\n abi.encodeWithSelector(\\n ctx.callbackFunction,\\n response,\\n ctx.extraData\\n ),\\n ctx.successCallbackFunction,\\n ctx.failureCallbackFunction,\\n ctx.myExtraData\\n );\\n }\\n\\n /// @dev Decode `OffchainLookup` error data into a struct.\\n /// @param v The error data of the revert.\\n /// @return p The decoded `OffchainLookup` params.\\n function decodeOffchainLookup(\\n bytes memory v\\n ) internal pure returns (EIP3668.Params memory p) {\\n p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n }\\n\\n /// @dev Determine if `target` uses `revert()` instead of `invalid()`.\\n // Assumption: only newer contracts revert `OffchainLookup`.\\n /// @param target The contract to test.\\n /// @return safe True if safe to call.\\n function detectEIP140(address target) internal view returns (bool safe) {\\n if (target == address(this)) return true;\\n // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md\\n assembly {\\n let G := 5000\\n let g := gas()\\n pop(staticcall(G, target, 0, 0, 0, 0))\\n safe := lt(sub(g, gas()), G)\\n }\\n }\\n\\n /// @dev Same as `staticcall()` but prevents OOG when not `safe`.\\n function safeCall(\\n bool safe,\\n address target,\\n bytes memory call\\n ) internal view returns (bool ok, bytes memory v) {\\n (ok, v) = target.staticcall{gas: safe ? gasleft() : unsafeCallGas}(\\n call\\n );\\n }\\n}\\n\",\"keccak256\":\"0xa6f483e89e779385c2b7ea6376d92cd3c05c98f91d1a3c7c43dc7422fe6b014f\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IBatchGateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for Batch Gateway Offchain Lookup Protocol.\\n/// https://docs.ens.domains/ensip/21/\\n/// @dev Interface selector: `0xa780bab6`\\ninterface IBatchGateway {\\n /// @notice An HTTP error occurred.\\n /// @dev Error selector: `0x01800152`\\n error HttpError(uint16 status, string message);\\n\\n /// @dev Information extracted from an `OffchainLookup` revert.\\n struct Request {\\n address sender;\\n string[] urls;\\n bytes data;\\n }\\n\\n /// @notice Perform multiple `OffchainLookup` in parallel.\\n /// Callers should enable EIP-3668.\\n /// @param requests The array of requests to lookup in parallel.\\n /// @return failures The failure status of the corresponding request.\\n /// @return responses The response or error data of the corresponding request.\\n function query(\\n Request[] memory requests\\n ) external view returns (bool[] memory failures, bytes[] memory responses);\\n}\\n\",\"keccak256\":\"0xfd7f0c7bdc29fc732ec54da2ebaea241873e55082e484729901811bc9374d6f6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IGatewayProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for shared gateway URLs.\\n/// @dev Interface selector: `0x093a86d3`\\ninterface IGatewayProvider {\\n /// @notice Get the gateways.\\n /// @return The gateway URLs.\\n function gateways() external view returns (string[] memory);\\n}\\n\",\"keccak256\":\"0x7c169843cfb65657a88fb4d5f7ec44612994d7d87cb7b1a67cbfdb18758823e0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverFeatures.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary ResolverFeatures {\\n /// @notice Implements `resolve(multicall([...]))`.\\n /// @dev Feature: `0x96b62db8`\\n bytes4 constant RESOLVE_MULTICALL =\\n bytes4(keccak256(\\\"eth.ens.resolver.extended.multicall\\\"));\\n\\n /// @notice Returns the same records independent of name or node.\\n /// @dev Feature: `0x86fb8da8`\\n bytes4 constant SINGULAR = bytes4(keccak256(\\\"eth.ens.resolver.singular\\\"));\\n}\\n\",\"keccak256\":\"0x87d131fcbdd7951a17b0a94f7f02470ec3f62c6004cf91c2d2acc54098373be6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ICompositeResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport {IExtendedResolver} from \\\"./IExtendedResolver.sol\\\";\\n\\n/// @notice A resolver that calls other resolvers.\\n/// @dev Interface selector: `0xeea330f9`\\ninterface ICompositeResolver is IExtendedResolver {\\n /// @notice Fetch the underlying resolver for `name`.\\n /// Callers should enable EIP-3668.\\n ///\\n /// * If `offchain`, additional information is necessary to locate `resolver`.\\n /// * If `resolver` is null, `offchain` is irrelevant.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return resolver The underlying resolver address.\\n /// @return offchain `true` if `resolver` is offchain.\\n function getResolver(\\n bytes memory name\\n ) external view returns (address resolver, bool offchain);\\n}\\n\",\"keccak256\":\"0xe267bef9a45073c92129ededa0275acf29394fa3fb30547bab8138dac485e2b2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedDNSResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data,\\n bytes memory context\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x541f8799c34ff9e7035d09f06ae0f0f8a16b6065e9b60a15670b957321630f72\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/RegistryUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {ENS} from \\\"../registry/ENS.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\n\\nlibrary RegistryUtils {\\n /// @notice Find the resolver for `name[offset:]`.\\n /// @dev Reverts `DNSDecodingFailed`.\\n /// @param registry The ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return resolver The resolver, or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(\\n ENS registry,\\n bytes memory name,\\n uint256 offset\\n )\\n internal\\n view\\n returns (address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (\\n address parentResolver,\\n bytes32 parentNode,\\n uint256 parentOffset\\n ) = findResolver(registry, name, next);\\n node = NameCoder.namehash(parentNode, labelHash);\\n resolver = registry.resolver(node);\\n return\\n resolver != address(0)\\n ? (resolver, node, offset)\\n : (parentResolver, node, parentOffset);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x21e7f6027b4fd2aa8c2a3e2225f88d1794faeff9377ba5ebc7a80b97d46cc214\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/ResolverCaller.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {\\n ERC165Checker\\n} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {CCIPBatcher} from \\\"../ccipRead/CCIPBatcher.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\nimport {IERC7996} from \\\"../utils/IERC7996.sol\\\";\\nimport {ResolverFeatures} from \\\"../resolvers/ResolverFeatures.sol\\\";\\n\\n// resolver profiles\\nimport {IExtendedResolver} from \\\"../resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {\\n IExtendedDNSResolver\\n} from \\\"../resolvers/profiles/IExtendedDNSResolver.sol\\\";\\nimport {IMulticallable} from \\\"../resolvers/IMulticallable.sol\\\";\\n\\nabstract contract ResolverCaller is CCIPBatcher {\\n /// @dev `name` cannot be resolved.\\n /// Error selector: `0x5fe9a5df`\\n /// @param name The DNS-encoded ENS name.\\n error UnreachableName(bytes name);\\n\\n /// @notice Perform forward resolution.\\n ///\\n /// Call this function with `ccipRead()` to intercept the response.\\n /// Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers.\\n ///\\n /// - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features,\\n /// the call is performed directly without the batch gateway.\\n /// - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature,\\n /// the call is performed directly without the batch gateway.\\n /// - Otherwise, the call is performed with the batch gateway.\\n /// The batch gateway is only invoked if any call reverts `OffchainLookup`.\\n /// If the calldata is `multicall()` it is disassembled, called separately, and reassembled.\\n ///\\n /// @dev Reverts `UnreachableName` if resolver is not a contract.\\n\\t/// This function never returns normally.\\n\\t/// The return type is necessary to define the result of the callback.\\n\\t/// Call this function externally or with `ccipRead()` to intercept the response.\\n /// @param resolver The resolver to call.\\n /// @param name The DNS-encoded ENS name.\\n /// @param data The calldata for the resolution.\\n /// @param hasContext True if `IExtendedDNSResolver` should be considered.\\n /// @param context The context for `IExtendedDNSResolver`.\\n /// @param batchGateways The batch gateway URLs.\\n function callResolver(\\n address resolver,\\n bytes memory name,\\n bytes memory data,\\n bool hasContext,\\n bytes memory context,\\n string[] memory batchGateways\\n ) public view returns (bytes memory) {\\n if (resolver.code.length == 0) {\\n revert UnreachableName(name);\\n }\\n bool multi = bytes4(data) == IMulticallable.multicall.selector;\\n bool extendedDNS = hasContext &&\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IExtendedDNSResolver).interfaceId\\n );\\n bool extended = extendedDNS ||\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IExtendedResolver).interfaceId\\n );\\n if (\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IERC7996).interfaceId\\n ) &&\\n (!multi ||\\n (extended &&\\n IERC7996(resolver).supportsFeature(\\n ResolverFeatures.RESOLVE_MULTICALL\\n )))\\n ) {\\n if (extended) {\\n // resolve() has the same return signature as callResolver()\\n ccipRead(\\n resolver,\\n _makeExtendedCall(extendedDNS, name, data, context)\\n );\\n } else {\\n ccipRead(\\n resolver,\\n data,\\n this.resolveDirectImmediateCallback.selector, // ==> step 2\\n IDENTITY_FUNCTION,\\n \\\"\\\"\\n );\\n }\\n }\\n bytes[] memory calls;\\n if (multi) {\\n calls = abi.decode(\\n BytesUtils.substring(data, 4, data.length - 4),\\n (bytes[])\\n );\\n } else {\\n calls = new bytes[](1);\\n calls[0] = data;\\n }\\n if (extended) {\\n for (uint256 i; i < calls.length; ++i) {\\n calls[i] = _makeExtendedCall(\\n extendedDNS,\\n name,\\n calls[i],\\n context\\n );\\n }\\n }\\n ccipRead(\\n address(this),\\n abi.encodeCall(\\n this.ccipBatch,\\n (createBatch(resolver, calls, batchGateways))\\n ),\\n this.resolveBatchCallback.selector, // ==> step 2\\n IDENTITY_FUNCTION,\\n abi.encode(multi, extended)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `callResolver()` from direct calling an immediate resolver.\\n function resolveDirectImmediateCallback(\\n bytes calldata response,\\n bytes calldata\\n ) external pure returns (bytes calldata) {\\n return response; // the calldata was direct, so wrap it\\n }\\n\\n /// @dev CCIP-Read callback for `callResolver()` from batch calling a resolver.\\n /// @param response The response data from the batch gateway.\\n /// @param extraData The abi-encoded properties of the call.\\n /// @return result The response from the resolver.\\n function resolveBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external pure returns (bytes memory) {\\n Lookup[] memory lookups = abi.decode(response, (Batch)).lookups;\\n (bool multi, bool extended) = abi.decode(extraData, (bool, bool));\\n if (multi) {\\n return abi.encode(_toResponseArray(lookups, extended));\\n } else {\\n Lookup memory lu = lookups[0];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) != 0) {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n if (extended) {\\n v = abi.decode(v, (bytes)); // unwrap resolve()\\n }\\n return v;\\n }\\n }\\n\\n /// @dev Create extended resolver calldata.\\n function _makeExtendedCall(\\n bool extendedDNS,\\n bytes memory name,\\n bytes memory call,\\n bytes memory context\\n ) internal pure returns (bytes memory) {\\n return\\n extendedDNS\\n ? abi.encodeCall(\\n IExtendedDNSResolver.resolve,\\n (name, call, context)\\n )\\n : abi.encodeCall(IExtendedResolver.resolve, (name, call));\\n }\\n}\\n\",\"keccak256\":\"0xf639a50d41e390b0c156667b59960b0422e738027a87a111464a196fb71638d7\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/IERC7996.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for expressing contract features not visible from the ABI.\\n/// @dev Interface selector: `0x582de3e7`\\ninterface IERC7996 {\\n /// @notice Check if a feature is supported.\\n /// @param featureId The feature identifier.\\n /// @return `true` if the feature is supported by the contract.\\n function supportsFeature(bytes4 featureId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf499a48e4e879ec7775f375d2cb5af047720ab6ae4b6f89a40a578c4e0f51631\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x5a08ad61f4e82b8a3323562661a86fb10b10190848073fdc13d4ac43710ffba5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/resolver/AbstractMirrorResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {CCIPReader} from \\\"@ens/contracts/ccipRead/CCIPReader.sol\\\";\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {ICompositeResolver} from \\\"@ens/contracts/resolvers/profiles/ICompositeResolver.sol\\\";\\nimport {IExtendedResolver} from \\\"@ens/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {ResolverFeatures} from \\\"@ens/contracts/resolvers/ResolverFeatures.sol\\\";\\nimport {ResolverCaller} from \\\"@ens/contracts/universalResolver/ResolverCaller.sol\\\";\\nimport {IERC7996} from \\\"@ens/contracts/utils/IERC7996.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\n/// @dev Resolver that mirrors resolution of the same name to a different registry.\\nabstract contract AbstractMirrorResolver is\\n ICompositeResolver,\\n IERC7996,\\n ResolverCaller,\\n DelegatedContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Shared batch gateway provider.\\n IGatewayProvider public immutable BATCH_GATEWAY_PROVIDER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n constructor(IGatewayProvider batchGatewayProvider, IContractNamer contractNamer)\\n CCIPReader(DEFAULT_UNSAFE_CALL_GAS)\\n DelegatedContractNamer(contractNamer)\\n {\\n BATCH_GATEWAY_PROVIDER = batchGatewayProvider;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(DelegatedContractNamer)\\n returns (bool)\\n {\\n return\\n type(IExtendedResolver).interfaceId == interfaceId ||\\n type(ICompositeResolver).interfaceId == interfaceId ||\\n type(IERC7996).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /// @inheritdoc IERC7996\\n function supportsFeature(bytes4 feature) external pure returns (bool) {\\n return ResolverFeatures.RESOLVE_MULTICALL == feature;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IExtendedResolver\\n function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory) {\\n callResolver(_findResolver(name), name, data, false, \\\"\\\", BATCH_GATEWAY_PROVIDER.gateways());\\n }\\n\\n /// @inheritdoc ICompositeResolver\\n function getResolver(bytes calldata name) external view returns (address, bool) {\\n return (_findResolver(name), false);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Determine the resolver for `name`.\\n function _findResolver(bytes calldata name) internal view virtual returns (address);\\n}\\n\",\"keccak256\":\"0x4297a896783bb27602ce3891ec9839fff69e81621c12bbdcce9f1ac73c14ed57\",\"license\":\"MIT\"},\"project/src/resolver/ENSV1Resolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {RegistryUtils} from \\\"@ens/contracts/universalResolver/RegistryUtils.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {AbstractMirrorResolver} from \\\"./AbstractMirrorResolver.sol\\\";\\n\\n/// @notice Resolver that performs resolutions using ENSv1.\\ncontract ENSV1Resolver is AbstractMirrorResolver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 registry used to look up resolvers for names.\\n ENS public immutable REGISTRY_V1;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n /// @param registryV1 The ENSv1 registry.\\n constructor(IGatewayProvider batchGatewayProvider, IContractNamer contractNamer, ENS registryV1)\\n AbstractMirrorResolver(batchGatewayProvider, contractNamer)\\n {\\n REGISTRY_V1 = registryV1;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc AbstractMirrorResolver\\n function _findResolver(bytes calldata name) internal view override returns (address resolver) {\\n (resolver, , ) = RegistryUtils.findResolver(REGISTRY_V1, name, 0);\\n }\\n}\\n\",\"keccak256\":\"0xed764abc8297b680aacf12d0feb6a3e33c006db01b371c9af2b96689cb6d32c4\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "InvalidBatchGatewayResponse()": [ + { + "notice": "The batch gateway supplied an incorrect number of responses." + } + ] + }, + "kind": "user", + "methods": { + "BATCH_GATEWAY_PROVIDER()": { + "notice": "Shared batch gateway provider." + }, + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "REGISTRY_V1()": { + "notice": "The ENSv1 registry used to look up resolvers for names." + }, + "callResolver(address,bytes,bytes,bool,bytes,string[])": { + "notice": "Perform forward resolution. Call this function with `ccipRead()` to intercept the response. Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers. - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features, the call is performed directly without the batch gateway. - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature, the call is performed directly without the batch gateway. - Otherwise, the call is performed with the batch gateway. The batch gateway is only invoked if any call reverts `OffchainLookup`. If the calldata is `multicall()` it is disassembled, called separately, and reassembled." + }, + "getResolver(bytes)": { + "notice": "Fetch the underlying resolver for `name`. Callers should enable EIP-3668. * If `offchain`, additional information is necessary to locate `resolver`. * If `resolver` is null, `offchain` is irrelevant." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "supportsFeature(bytes4)": { + "notice": "Check if a feature is supported." + } + }, + "notice": "Resolver that performs resolutions using ENSv1.", + "version": 1 + }, + "argsData": "0x000000000000000000000000e4e7245716d12d0f6aea01dfe0e635c43d7d083c00000000000000000000000068658a771044873906fc9b6e9f278ac5a050134200000000000000000000000000000000000c2e074ec69a0dfb2997ba6c7d2e1e", + "transaction": { + "hash": "0x447c60f1e969325c11182eb02515968c167baa8b1753c615dcb9b2ba87488e8e", + "nonce": "0xc", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xf11734a9175da49a93631b86b262d0cad042ec5cb69a28a8c434b0648b3e7b30", + "blockNumber": "0xaa56b4", + "transactionIndex": "0x73" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ENSV2Resolver.json b/contracts/deployments/sepolia/ENSV2Resolver.json new file mode 100644 index 000000000..384d46d78 --- /dev/null +++ b/contracts/deployments/sepolia/ENSV2Resolver.json @@ -0,0 +1,775 @@ +{ + "address": "0x6f988f299926ce361450db390d66dd604dcd8b21", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "batchGatewayProvider", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "rootRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "ethResolver", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBatchGatewayResponse", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "UnreachableName", + "type": "error" + }, + { + "inputs": [], + "name": "BATCH_GATEWAY_PROVIDER", + "outputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "hasContext", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "batchGateways", + "type": "string[]" + } + ], + "name": "callResolver", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "name": "ccipBatch", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipBatchCallback", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipReadCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveBatchCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "resolveDirectImmediateCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feature", + "type": "bytes4" + } + ], + "name": "supportsFeature", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "ENSV2Resolver", + "sourceName": "src/resolver/ENSV2Resolver.sol", + "bytecode": "0x610120604052348015610010575f80fd5b50604051612ca6380380612ca683398101604081905261002f9161006f565b61c3506080526001600160a01b0392831660a05292821660c052811660e05216610100526100cb565b6001600160a01b038116811461006c575f80fd5b50565b5f805f8060808587031215610082575f80fd5b845161008d81610058565b602086015190945061009e81610058565b60408601519093506100af81610058565b60608601519092506100c081610058565b939692955090935050565b60805160a05160c05160e05161010051612b7b61012b5f395f818161026f01528181610ffc015261102f01525f81816102480152610f6f01525f81816101a4015261057401525f8181610121015261045301525f61109b0152612b7b5ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c80639061b92311610093578063d8b55d2711610063578063d8b55d271461026a578063eea330f914610291578063ef46c0b8146102c3578063f394443a146102d8575f80fd5b80639061b923146101fd5780639f28e99d14610210578063b536af7614610230578063c92cc49a14610243575f80fd5b8063582de3e7116100ce578063582de3e71461017b5780636ccb86601461019f5780636d6dd540146101c65780636f3ff726146101ea575f80fd5b806301ffc9a7146100f457806348ee1bcc1461011c578063491fc4f91461015b575b5f80fd5b610107610102366004611bb7565b6102eb565b60405190151581526020015b60405180910390f35b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610113565b61016e610169366004611c10565b610364565b6040516101139190611ca5565b610107610189366004611bb7565b6001600160e01b0319166312d6c5b760e31b1490565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101dc6101d4366004611c10565b509192909150565b604051610113929190611cb7565b6101076101f8366004611d09565b610432565b61016e61020b366004611c10565b6104be565b61022361021e366004611f14565b6105ed565b60405161011391906120d4565b61022361023e366004611c10565b6107ae565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6102a461029f36600461219d565b6109fd565b604080516001600160a01b039093168352901515602083015201610113565b6102d66102d13660046121dc565b610a16565b005b61016e6102e6366004612254565b610a9b565b5f639061b92360e01b6001600160e01b03198316148061033457507feea330f9000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b8061034f575063582de3e760e01b6001600160e01b03198316145b8061035e575061035e82610dd2565b92915050565b60605f61037385870187611f14565b5190505f8061038485870187612319565b9150915081156103c1576103988382610e06565b6040516020016103a89190612350565b604051602081830303815290604052935050505061042a565b5f835f815181106103d4576103d46123b2565b60209081029190910101516040810151606082015191925090600e16156103fd57805160208201fd5b821561041a5780806020019051810190610417919061241a565b90505b945061042a9350505050565b5050505b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561049a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061035e919061244c565b60606105e46104cd8686610f68565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f9201829052506040805160208101825282815281517f093a86d3000000000000000000000000000000000000000000000000000000008152915192955093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063093a86d391600480830192879291908290030181865afa1580156105bd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526102e691908101906124f5565b50949350505050565b60408051808201909152606080825260208201525f5b8251518110156107a0575f835f01518281518110610623576106236123b2565b6020026020010151905060408160600151165f146106415750610798565b60608101516030165f036106eb575f61065c825f0151611055565b61066757601061066a565b60205b9050825b8551518110156106e857825f01516001600160a01b0316865f0151828151811061069a5761069a6123b2565b60200260200101515f01516001600160a01b0316036106e05781865f015182815181106106c9576106c96123b2565b602002602001015160600181815117915081815250505b60010161066e565b50505b5f60208260600151165f1490505f8061070d8315855f01518660200151611087565b91509150811580156107375750630556f18360e41b61072b82612527565b6001600160e01b031916145b1561074c57606084018051600117905261078c565b606084018051604017905282801561076357508051155b61077857816107785760608401805160021790525b80515f0361078c5760608401805160081790525b60409093019290925250505b600101610603565b506107aa8261111a565b5090565b60408051808201909152606080825260208201525f806107d0868801886125d9565b9150915080518251146107f65760405163252e18f560e11b815260040160405180910390fd5b61080284860186611f14565b92505f805b8451518110156109d2575f855f01518281518110610827576108276123b2565b6020026020010151905060408160600151165f036109c95783518310156109bd575f84848151811061085b5761085b6123b2565b60200260200101519050858481518110610877576108776123b2565b6020026020010151156108945760608201805160441790526109b7565b5f6108a28360400151611305565b90505f815f01516001600160a01b031682606001518484608001516040516024016108ce92919061268b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161090c91906126c6565b5f60405180830381855afa9150503d805f8114610944576040519150601f19603f3d011682016040523d82523d5f602084013e610949565b606091505b509350905080806109735750630556f18360e41b61096684612527565b6001600160e01b03191614155b156109b457606084018051604017905280158061098f57508251155b156109a05760608401805160021790525b82515f036109b45760608401805160081790525b50505b60408201525b6109c6836126e5565b92505b50600101610807565b50815181146109f45760405163252e18f560e11b815260040160405180910390fd5b6104268461111a565b5f80610a098484610f68565b5f915091505b9250929050565b5f81806020019051810190610a2b9190612713565b9050610a96815f01518260200151858460400151604051602401610a5092919061268b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a0860151611349565b505050565b6060866001600160a01b03163b5f03610aeb57856040517f5fe9a5df000000000000000000000000000000000000000000000000000000008152600401610ae29190611ca5565b60405180910390fd5b5f7fac9650d800000000000000000000000000000000000000000000000000000000610b1687612527565b6001600160e01b0319161490505f858015610b3d5750610b3d8963477cc53f60e11b61150c565b90505f8180610b585750610b588a639061b92360e01b61150c565b9050610b6b8a63582de3e760e01b61150c565b8015610bef5750821580610bef5750808015610bef575060405163582de3e760e01b81526312d6c5b760e31b60048201526001600160a01b038b169063582de3e790602401602060405180830381865afa158015610bcb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bef919061244c565b15610c39578015610c1457610c0f8a610c0a848c8c8b611592565b611624565b610c39565b610c398a89636d6dd54060e01b5f60e01b60405180602001604052805f815250611349565b60608315610c7357610c59896004808c51610c5491906127e2565b611649565b806020019051810190610c6c91906127f5565b9050610cbe565b60408051600180825281830190925290816020015b6060815260200190600190039081610c8857905050905088815f81518110610cb257610cb26123b2565b60200260200101819052505b8115610d1b575f5b8151811015610d1957610cf4848c848481518110610ce657610ce66123b2565b60200260200101518b611592565b828281518110610d0657610d066123b2565b6020908102919091010152600101610cc6565b505b610dc43080639f28e99d610d308f868c6116a5565b604051602401610d4091906120d4565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b94909417909352519092507f491fc4f900000000000000000000000000000000000000000000000000000000915f91610db0918b918a910191151582521515602082015260400190565b604051602081830303815290604052611349565b505050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b148061035e57506301ffc9a760e01b6001600160e01b031983161461035e565b6060825167ffffffffffffffff811115610e2257610e22611d24565b604051908082528060200260200182016040528015610e5557816020015b6060815260200190600190039081610e405790505b5090505f5b8351811015610f61575f848281518110610e7657610e766123b2565b60209081029190910101516040810151606082015191925090600e165f03610eba578415610eb55780806020019051810190610eb2919061241a565b90505b610f39565b805115610f39578051600403601f168015610f3757818167ffffffffffffffff811115610ee957610ee9611d24565b6040519080825280601f01601f191660200182016040528015610f13576020820181803683370190505b50604051602001610f2592919061289f565b60405160208183030381529060405291505b505b80848481518110610f4c57610f4c6123b2565b60209081029190910101525050600101610e5a565b5092915050565b5f80610fc97f000000000000000000000000000000000000000000000000000000000000000085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506117ba915050565b509093509150507f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae8114801561102757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b15610f6157507f00000000000000000000000000000000000000000000000000000000000000009392505050565b5f306001600160a01b0383160361106e57506001919050565b6113885a5f805f808786fa50815a909103109392505050565b5f6060836001600160a01b0316856110bf577f00000000000000000000000000000000000000000000000000000000000000006110c1565b5a5b846040516110cf91906126c6565b5f604051808303818686fa925050503d805f8114611108576040519150601f19603f3d011682016040523d82523d5f602084013e61110d565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff81111561113757611137611d24565b60405190808252806020026020018201604052801561119457816020015b61118160405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816111555790505b5090505f805b835151811015611245575f845f015182815181106111ba576111ba6123b2565b6020026020010151905060408160600151165f0361123c575f6111e08260400151611305565b90506040518060600160405280825f01516001600160a01b0316815260200182602001518152602001826040015181525085858061121d906126e5565b96508151811061122f5761122f6123b2565b6020026020010181905250505b5060010161119a565b508015610a96578082523083602001518360405160240161126691906128b3565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af7600000000000000000000000000000000000000000000000000000000916112da918991016120d4565b60408051601f1981840301815290829052630556f18360e41b8252610ae2959493929160040161294d565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915261035e611344836004808651610c5491906127e2565b61193f565b5f8061135e61135788611055565b8888611087565b91509150811580156113885750630556f18360e41b61137c82612527565b6001600160e01b031916145b15611436575f61139782611305565b9050876001600160a01b0316815f01516001600160a01b03160361143457308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b0319168152602001898152506040516020016112da91906129b0565b505b5f826114425784611444565b855b90506001600160e01b03198116156114f657306001600160a01b031681838660405160240161147492919061268b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114b291906126c6565b5f60405180830381855afa9150503d805f81146114ea576040519150601f19603f3d011682016040523d82523d5f602084013e6114ef565b606091505b5090935091505b821561150457815160208301f35b815160208301fd5b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f51905082801561157c575060208210155b801561158757505f81115b979650505050505050565b6060846115db5783836040516024016115ac92919061268b565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b17905261161b565b8383836040516024016115f093929190612a2c565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b1790525b95945050505050565b61164582825f60e01b5f60e01b60405180602001604052805f815250611349565b5050565b60608167ffffffffffffffff81111561166457611664611d24565b6040519080825280601f01601f19166020018201604052801561168e576020820181803683370190505b50905061169e8484835f866119aa565b9392505050565b60408051808201909152606080825260208201525f835167ffffffffffffffff8111156116d4576116d4611d24565b60405190808252806020026020018201604052801561173757816020015b61172460405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b8152602001906001900390816116f25790505b5090505f5b845181101561179d575f828281518110611758576117586123b2565b60209081029190910101516001600160a01b03881681528651909150869083908110611786576117866123b2565b60209081029190910181015191015260010161173c565b506040805180820190915290815260208101929092525092915050565b5f805f805f806117ca88886119e7565b9092509050816117e857508794505f93508392508591506119369050565b6117f38989836117ba565b929850909650945092506001600160a01b03861615611927575f6118178989611a14565b5090505f876001600160a01b031663e4ae7d77836040518263ffffffff1660e01b81526004016118479190611ca5565b602060405180830381865afa158015611862573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118869190612a6e565b90506001600160a01b0381161561189e578096508894505b6040517f35af62160000000000000000000000000000000000000000000000000000000081526001600160a01b038916906335af6216906118e3908590600401611ca5565b602060405180830381865afa1580156118fe573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119229190612a6e565b975050505b505f9283526020526040909120905b93509350935093565b6040805160a0810182525f8082526060602083018190529282018390528282015260808101919091528180602001905181019061197c9190612a89565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6119bd856119b88387612b32565b611a91565b6119cb836119b88385612b32565b6119e082602085010185602088010183611ad9565b5050505050565b5f805f6119f48585611b22565b9250905060ff811615611a0c57806021858701012092505b509250929050565b60605f80611a228585611b22565b925090505f60ff821667ffffffffffffffff811115611a4357611a43611d24565b6040519080825280601f01601f191660200182016040528015611a6d576020820181803683370190505b509050611a866020820160218888010160ff8516611ad9565b959194509092505050565b81518111156116455781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610ae2918391600401918252602082015260400190565b5b601f811115611afa578151835260209283019290910190601f1901611ada565b8015610a965790518251600160209390930360031b9290921b5f190180199091169116179052565b5f8083518310611b47578360405163ba4adc2360e01b8152600401610ae29190611ca5565b838381518110611b5957611b596123b2565b016020015160f81c91505081810160010181611b79578351811415611b7f565b83518110155b15610a0f578360405163ba4adc2360e01b8152600401610ae29190611ca5565b6001600160e01b031981168114611bb4575f80fd5b50565b5f60208284031215611bc7575f80fd5b813561169e81611b9f565b5f8083601f840112611be2575f80fd5b50813567ffffffffffffffff811115611bf9575f80fd5b602083019150836020828501011115610a0f575f80fd5b5f805f8060408587031215611c23575f80fd5b843567ffffffffffffffff80821115611c3a575f80fd5b611c4688838901611bd2565b90965094506020870135915080821115611c5e575f80fd5b50611c6b87828801611bd2565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61169e6020830184611c77565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b6001600160a01b0381168114611bb4575f80fd5b8035611d0481611ce5565b919050565b5f60208284031215611d19575f80fd5b813561169e81611ce5565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611d5b57611d5b611d24565b60405290565b6040516080810167ffffffffffffffff81118282101715611d5b57611d5b611d24565b60405160c0810167ffffffffffffffff81118282101715611d5b57611d5b611d24565b604051601f8201601f1916810167ffffffffffffffff81118282101715611dd057611dd0611d24565b604052919050565b5f67ffffffffffffffff821115611df157611df1611d24565b5060051b60200190565b5f67ffffffffffffffff821115611e1457611e14611d24565b50601f01601f191660200190565b5f611e34611e2f84611dfb565b611da7565b9050828152838383011115611e47575f80fd5b828260208301375f602084830101529392505050565b5f82601f830112611e6c575f80fd5b61169e83833560208501611e22565b5f82601f830112611e8a575f80fd5b81356020611e9a611e2f83611dd8565b82815260059290921b84018101918181019086841115611eb8575f80fd5b8286015b84811015611f0957803567ffffffffffffffff811115611eda575f80fd5b8701603f81018913611eea575f80fd5b611efb898683013560408401611e22565b845250918301918301611ebc565b509695505050505050565b5f6020808385031215611f25575f80fd5b823567ffffffffffffffff80821115611f3c575f80fd5b9084019060408287031215611f4f575f80fd5b611f57611d38565b823582811115611f65575f80fd5b8301601f81018813611f75575f80fd5b8035611f83611e2f82611dd8565b81815260059190911b8201860190868101908a831115611fa1575f80fd5b8784015b8381101561204957803587811115611fbb575f80fd5b85016080818e03601f19011215611fd0575f80fd5b611fd8611d61565b8a820135611fe581611ce5565b8152604082013589811115611ff8575f80fd5b6120068f8d83860101611e5d565b8c8301525060608201358981111561201c575f80fd5b61202a8f8d83860101611e5d565b6040830152506080919091013560608201528352918801918801611fa5565b508452505050828401358281111561205f575f80fd5b61206b88828601611e7b565b948201949094529695505050505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156120c757601f198684030189526120b5838351611c77565b98840198925090830190600101612099565b5090979650505050505050565b5f602080835260608084018551604080858801528282518085526080945060808901915060808160051b8a010187850194505f5b8281101561217257607f198b830301845285516001600160a01b03815116835289810151888b85015261213d89850182611c77565b905086820151848203888601526121548282611c77565b928b0151948b01949094525095890195938901939150600101612108565b50968a0151898803601f190160408b01529661218e818961207c565b9b9a5050505050505050505050565b5f80602083850312156121ae575f80fd5b823567ffffffffffffffff8111156121c4575f80fd5b6121d085828601611bd2565b90969095509350505050565b5f80604083850312156121ed575f80fd5b823567ffffffffffffffff80821115612204575f80fd5b61221086838701611e5d565b93506020850135915080821115612225575f80fd5b5061223285828601611e5d565b9150509250929050565b8015158114611bb4575f80fd5b8035611d048161223c565b5f805f805f8060c08789031215612269575f80fd5b61227287611cf9565b9550602087013567ffffffffffffffff8082111561228e575f80fd5b61229a8a838b01611e5d565b965060408901359150808211156122af575f80fd5b6122bb8a838b01611e5d565b95506122c960608a01612249565b945060808901359150808211156122de575f80fd5b6122ea8a838b01611e5d565b935060a08901359150808211156122ff575f80fd5b5061230c89828a01611e7b565b9150509295509295509295565b5f806040838503121561232a575f80fd5b82356123358161223c565b915060208301356123458161223c565b809150509250929050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b828110156123a557603f19888603018452612393858351611c77565b94509285019290850190600101612377565b5092979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f6123d3611e2f84611dfb565b90508281528383830111156123e6575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261240b575f80fd5b61169e838351602085016123c6565b5f6020828403121561242a575f80fd5b815167ffffffffffffffff811115612440575f80fd5b61042a848285016123fc565b5f6020828403121561245c575f80fd5b815161169e8161223c565b5f82601f830112612476575f80fd5b81516020612486611e2f83611dd8565b82815260059290921b840181019181810190868411156124a4575f80fd5b8286015b84811015611f0957805167ffffffffffffffff8111156124c6575f80fd5b8701603f810189136124d6575f80fd5b6124e78986830151604084016123c6565b8452509183019183016124a8565b5f60208284031215612505575f80fd5b815167ffffffffffffffff81111561251b575f80fd5b61042a84828501612467565b5f815160208301516001600160e01b0319808216935060048310156125565780818460040360031b1b83161693505b505050919050565b5f82601f83011261256d575f80fd5b8135602061257d611e2f83611dd8565b82815260059290921b8401810191818101908684111561259b575f80fd5b8286015b84811015611f0957803567ffffffffffffffff8111156125bd575f80fd5b6125cb8986838b0101611e5d565b84525091830191830161259f565b5f80604083850312156125ea575f80fd5b823567ffffffffffffffff80821115612601575f80fd5b818501915085601f830112612614575f80fd5b81356020612624611e2f83611dd8565b82815260059290921b84018101918181019089841115612642575f80fd5b948201945b8386101561266957853561265a8161223c565b82529482019490820190612647565b9650508601359250508082111561267e575f80fd5b506122328582860161255e565b604081525f61269d6040830185611c77565b828103602084015261161b8185611c77565b5f81518060208401855e5f93019283525090919050565b5f61169e82846126af565b634e487b7160e01b5f52601160045260245ffd5b5f600182016126f6576126f66126d1565b5060010190565b8051611d0481611ce5565b8051611d0481611b9f565b5f60208284031215612723575f80fd5b815167ffffffffffffffff8082111561273a575f80fd5b9083019060c0828603121561274d575f80fd5b612755611d84565b61275e836126fd565b815261276c60208401612708565b6020820152604083015182811115612782575f80fd5b61278e878286016123fc565b6040830152506127a060608401612708565b60608201526127b160808401612708565b608082015260a0830151828111156127c7575f80fd5b6127d3878286016123fc565b60a08301525095945050505050565b8181038181111561035e5761035e6126d1565b5f6020808385031215612806575f80fd5b825167ffffffffffffffff8082111561281d575f80fd5b818501915085601f830112612830575f80fd5b815161283e611e2f82611dd8565b81815260059190911b8301840190848101908883111561285c575f80fd5b8585015b8381101561289257805185811115612876575f80fd5b6128848b89838a01016123fc565b845250918601918601612860565b5098975050505050505050565b5f61042a6128ad83866126af565b846126af565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b8381101561293f57603f19898403018552815160606001600160a01b03825116855288820151818a8701526129118287018261207c565b9150508782015191508481038886015261292b8183611c77565b9689019694505050908601906001016128da565b509098975050505050505050565b6001600160a01b038616815260a060208201525f61296e60a083018761207c565b82810360408401526129808187611c77565b90506001600160e01b03198516606084015282810360808401526129a48185611c77565b98975050505050505050565b602081526001600160a01b0382511660208201525f60208301516001600160e01b031980821660408501526040850151915060c060608501526129f660e0850183611c77565b91508060608601511660808501528060808601511660a08501525060a0840151601f198483030160c085015261161b8282611c77565b606081525f612a3e6060830186611c77565b8281036020840152612a508186611c77565b90508281036040840152612a648185611c77565b9695505050505050565b5f60208284031215612a7e575f80fd5b815161169e81611ce5565b5f805f805f60a08688031215612a9d575f80fd5b8551612aa881611ce5565b602087015190955067ffffffffffffffff80821115612ac5575f80fd5b612ad189838a01612467565b95506040880151915080821115612ae6575f80fd5b612af289838a016123fc565b945060608801519150612b0482611b9f565b608088015191935080821115612b18575f80fd5b50612b25888289016123fc565b9150509295509295909350565b8082018082111561035e5761035e6126d156fea264697066735822122030b444cc06a7b17f3feb64d14e13f86f9a4546ada2b334d0eec58738fed358b064736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c80639061b92311610093578063d8b55d2711610063578063d8b55d271461026a578063eea330f914610291578063ef46c0b8146102c3578063f394443a146102d8575f80fd5b80639061b923146101fd5780639f28e99d14610210578063b536af7614610230578063c92cc49a14610243575f80fd5b8063582de3e7116100ce578063582de3e71461017b5780636ccb86601461019f5780636d6dd540146101c65780636f3ff726146101ea575f80fd5b806301ffc9a7146100f457806348ee1bcc1461011c578063491fc4f91461015b575b5f80fd5b610107610102366004611bb7565b6102eb565b60405190151581526020015b60405180910390f35b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610113565b61016e610169366004611c10565b610364565b6040516101139190611ca5565b610107610189366004611bb7565b6001600160e01b0319166312d6c5b760e31b1490565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101dc6101d4366004611c10565b509192909150565b604051610113929190611cb7565b6101076101f8366004611d09565b610432565b61016e61020b366004611c10565b6104be565b61022361021e366004611f14565b6105ed565b60405161011391906120d4565b61022361023e366004611c10565b6107ae565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6102a461029f36600461219d565b6109fd565b604080516001600160a01b039093168352901515602083015201610113565b6102d66102d13660046121dc565b610a16565b005b61016e6102e6366004612254565b610a9b565b5f639061b92360e01b6001600160e01b03198316148061033457507feea330f9000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b8061034f575063582de3e760e01b6001600160e01b03198316145b8061035e575061035e82610dd2565b92915050565b60605f61037385870187611f14565b5190505f8061038485870187612319565b9150915081156103c1576103988382610e06565b6040516020016103a89190612350565b604051602081830303815290604052935050505061042a565b5f835f815181106103d4576103d46123b2565b60209081029190910101516040810151606082015191925090600e16156103fd57805160208201fd5b821561041a5780806020019051810190610417919061241a565b90505b945061042a9350505050565b5050505b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561049a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061035e919061244c565b60606105e46104cd8686610f68565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f9201829052506040805160208101825282815281517f093a86d3000000000000000000000000000000000000000000000000000000008152915192955093506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063093a86d391600480830192879291908290030181865afa1580156105bd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526102e691908101906124f5565b50949350505050565b60408051808201909152606080825260208201525f5b8251518110156107a0575f835f01518281518110610623576106236123b2565b6020026020010151905060408160600151165f146106415750610798565b60608101516030165f036106eb575f61065c825f0151611055565b61066757601061066a565b60205b9050825b8551518110156106e857825f01516001600160a01b0316865f0151828151811061069a5761069a6123b2565b60200260200101515f01516001600160a01b0316036106e05781865f015182815181106106c9576106c96123b2565b602002602001015160600181815117915081815250505b60010161066e565b50505b5f60208260600151165f1490505f8061070d8315855f01518660200151611087565b91509150811580156107375750630556f18360e41b61072b82612527565b6001600160e01b031916145b1561074c57606084018051600117905261078c565b606084018051604017905282801561076357508051155b61077857816107785760608401805160021790525b80515f0361078c5760608401805160081790525b60409093019290925250505b600101610603565b506107aa8261111a565b5090565b60408051808201909152606080825260208201525f806107d0868801886125d9565b9150915080518251146107f65760405163252e18f560e11b815260040160405180910390fd5b61080284860186611f14565b92505f805b8451518110156109d2575f855f01518281518110610827576108276123b2565b6020026020010151905060408160600151165f036109c95783518310156109bd575f84848151811061085b5761085b6123b2565b60200260200101519050858481518110610877576108776123b2565b6020026020010151156108945760608201805160441790526109b7565b5f6108a28360400151611305565b90505f815f01516001600160a01b031682606001518484608001516040516024016108ce92919061268b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161090c91906126c6565b5f60405180830381855afa9150503d805f8114610944576040519150601f19603f3d011682016040523d82523d5f602084013e610949565b606091505b509350905080806109735750630556f18360e41b61096684612527565b6001600160e01b03191614155b156109b457606084018051604017905280158061098f57508251155b156109a05760608401805160021790525b82515f036109b45760608401805160081790525b50505b60408201525b6109c6836126e5565b92505b50600101610807565b50815181146109f45760405163252e18f560e11b815260040160405180910390fd5b6104268461111a565b5f80610a098484610f68565b5f915091505b9250929050565b5f81806020019051810190610a2b9190612713565b9050610a96815f01518260200151858460400151604051602401610a5092919061268b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a0860151611349565b505050565b6060866001600160a01b03163b5f03610aeb57856040517f5fe9a5df000000000000000000000000000000000000000000000000000000008152600401610ae29190611ca5565b60405180910390fd5b5f7fac9650d800000000000000000000000000000000000000000000000000000000610b1687612527565b6001600160e01b0319161490505f858015610b3d5750610b3d8963477cc53f60e11b61150c565b90505f8180610b585750610b588a639061b92360e01b61150c565b9050610b6b8a63582de3e760e01b61150c565b8015610bef5750821580610bef5750808015610bef575060405163582de3e760e01b81526312d6c5b760e31b60048201526001600160a01b038b169063582de3e790602401602060405180830381865afa158015610bcb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bef919061244c565b15610c39578015610c1457610c0f8a610c0a848c8c8b611592565b611624565b610c39565b610c398a89636d6dd54060e01b5f60e01b60405180602001604052805f815250611349565b60608315610c7357610c59896004808c51610c5491906127e2565b611649565b806020019051810190610c6c91906127f5565b9050610cbe565b60408051600180825281830190925290816020015b6060815260200190600190039081610c8857905050905088815f81518110610cb257610cb26123b2565b60200260200101819052505b8115610d1b575f5b8151811015610d1957610cf4848c848481518110610ce657610ce66123b2565b60200260200101518b611592565b828281518110610d0657610d066123b2565b6020908102919091010152600101610cc6565b505b610dc43080639f28e99d610d308f868c6116a5565b604051602401610d4091906120d4565b60408051601f19818403018152918152602080830180516001600160e01b031660e09590951b94909417909352519092507f491fc4f900000000000000000000000000000000000000000000000000000000915f91610db0918b918a910191151582521515602082015260400190565b604051602081830303815290604052611349565b505050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b148061035e57506301ffc9a760e01b6001600160e01b031983161461035e565b6060825167ffffffffffffffff811115610e2257610e22611d24565b604051908082528060200260200182016040528015610e5557816020015b6060815260200190600190039081610e405790505b5090505f5b8351811015610f61575f848281518110610e7657610e766123b2565b60209081029190910101516040810151606082015191925090600e165f03610eba578415610eb55780806020019051810190610eb2919061241a565b90505b610f39565b805115610f39578051600403601f168015610f3757818167ffffffffffffffff811115610ee957610ee9611d24565b6040519080825280601f01601f191660200182016040528015610f13576020820181803683370190505b50604051602001610f2592919061289f565b60405160208183030381529060405291505b505b80848481518110610f4c57610f4c6123b2565b60209081029190910101525050600101610e5a565b5092915050565b5f80610fc97f000000000000000000000000000000000000000000000000000000000000000085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506117ba915050565b509093509150507f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae8114801561102757507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615155b15610f6157507f00000000000000000000000000000000000000000000000000000000000000009392505050565b5f306001600160a01b0383160361106e57506001919050565b6113885a5f805f808786fa50815a909103109392505050565b5f6060836001600160a01b0316856110bf577f00000000000000000000000000000000000000000000000000000000000000006110c1565b5a5b846040516110cf91906126c6565b5f604051808303818686fa925050503d805f8114611108576040519150601f19603f3d011682016040523d82523d5f602084013e61110d565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff81111561113757611137611d24565b60405190808252806020026020018201604052801561119457816020015b61118160405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816111555790505b5090505f805b835151811015611245575f845f015182815181106111ba576111ba6123b2565b6020026020010151905060408160600151165f0361123c575f6111e08260400151611305565b90506040518060600160405280825f01516001600160a01b0316815260200182602001518152602001826040015181525085858061121d906126e5565b96508151811061122f5761122f6123b2565b6020026020010181905250505b5060010161119a565b508015610a96578082523083602001518360405160240161126691906128b3565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af7600000000000000000000000000000000000000000000000000000000916112da918991016120d4565b60408051601f1981840301815290829052630556f18360e41b8252610ae2959493929160040161294d565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915261035e611344836004808651610c5491906127e2565b61193f565b5f8061135e61135788611055565b8888611087565b91509150811580156113885750630556f18360e41b61137c82612527565b6001600160e01b031916145b15611436575f61139782611305565b9050876001600160a01b0316815f01516001600160a01b03160361143457308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b0319168152602001898152506040516020016112da91906129b0565b505b5f826114425784611444565b855b90506001600160e01b03198116156114f657306001600160a01b031681838660405160240161147492919061268b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516114b291906126c6565b5f60405180830381855afa9150503d805f81146114ea576040519150601f19603f3d011682016040523d82523d5f602084013e6114ef565b606091505b5090935091505b821561150457815160208301f35b815160208301fd5b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f51905082801561157c575060208210155b801561158757505f81115b979650505050505050565b6060846115db5783836040516024016115ac92919061268b565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b17905261161b565b8383836040516024016115f093929190612a2c565b60408051601f198184030181529190526020810180516001600160e01b031663477cc53f60e11b1790525b95945050505050565b61164582825f60e01b5f60e01b60405180602001604052805f815250611349565b5050565b60608167ffffffffffffffff81111561166457611664611d24565b6040519080825280601f01601f19166020018201604052801561168e576020820181803683370190505b50905061169e8484835f866119aa565b9392505050565b60408051808201909152606080825260208201525f835167ffffffffffffffff8111156116d4576116d4611d24565b60405190808252806020026020018201604052801561173757816020015b61172460405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b8152602001906001900390816116f25790505b5090505f5b845181101561179d575f828281518110611758576117586123b2565b60209081029190910101516001600160a01b03881681528651909150869083908110611786576117866123b2565b60209081029190910181015191015260010161173c565b506040805180820190915290815260208101929092525092915050565b5f805f805f806117ca88886119e7565b9092509050816117e857508794505f93508392508591506119369050565b6117f38989836117ba565b929850909650945092506001600160a01b03861615611927575f6118178989611a14565b5090505f876001600160a01b031663e4ae7d77836040518263ffffffff1660e01b81526004016118479190611ca5565b602060405180830381865afa158015611862573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118869190612a6e565b90506001600160a01b0381161561189e578096508894505b6040517f35af62160000000000000000000000000000000000000000000000000000000081526001600160a01b038916906335af6216906118e3908590600401611ca5565b602060405180830381865afa1580156118fe573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119229190612a6e565b975050505b505f9283526020526040909120905b93509350935093565b6040805160a0810182525f8082526060602083018190529282018390528282015260808101919091528180602001905181019061197c9190612a89565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6119bd856119b88387612b32565b611a91565b6119cb836119b88385612b32565b6119e082602085010185602088010183611ad9565b5050505050565b5f805f6119f48585611b22565b9250905060ff811615611a0c57806021858701012092505b509250929050565b60605f80611a228585611b22565b925090505f60ff821667ffffffffffffffff811115611a4357611a43611d24565b6040519080825280601f01601f191660200182016040528015611a6d576020820181803683370190505b509050611a866020820160218888010160ff8516611ad9565b959194509092505050565b81518111156116455781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610ae2918391600401918252602082015260400190565b5b601f811115611afa578151835260209283019290910190601f1901611ada565b8015610a965790518251600160209390930360031b9290921b5f190180199091169116179052565b5f8083518310611b47578360405163ba4adc2360e01b8152600401610ae29190611ca5565b838381518110611b5957611b596123b2565b016020015160f81c91505081810160010181611b79578351811415611b7f565b83518110155b15610a0f578360405163ba4adc2360e01b8152600401610ae29190611ca5565b6001600160e01b031981168114611bb4575f80fd5b50565b5f60208284031215611bc7575f80fd5b813561169e81611b9f565b5f8083601f840112611be2575f80fd5b50813567ffffffffffffffff811115611bf9575f80fd5b602083019150836020828501011115610a0f575f80fd5b5f805f8060408587031215611c23575f80fd5b843567ffffffffffffffff80821115611c3a575f80fd5b611c4688838901611bd2565b90965094506020870135915080821115611c5e575f80fd5b50611c6b87828801611bd2565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61169e6020830184611c77565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b6001600160a01b0381168114611bb4575f80fd5b8035611d0481611ce5565b919050565b5f60208284031215611d19575f80fd5b813561169e81611ce5565b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff81118282101715611d5b57611d5b611d24565b60405290565b6040516080810167ffffffffffffffff81118282101715611d5b57611d5b611d24565b60405160c0810167ffffffffffffffff81118282101715611d5b57611d5b611d24565b604051601f8201601f1916810167ffffffffffffffff81118282101715611dd057611dd0611d24565b604052919050565b5f67ffffffffffffffff821115611df157611df1611d24565b5060051b60200190565b5f67ffffffffffffffff821115611e1457611e14611d24565b50601f01601f191660200190565b5f611e34611e2f84611dfb565b611da7565b9050828152838383011115611e47575f80fd5b828260208301375f602084830101529392505050565b5f82601f830112611e6c575f80fd5b61169e83833560208501611e22565b5f82601f830112611e8a575f80fd5b81356020611e9a611e2f83611dd8565b82815260059290921b84018101918181019086841115611eb8575f80fd5b8286015b84811015611f0957803567ffffffffffffffff811115611eda575f80fd5b8701603f81018913611eea575f80fd5b611efb898683013560408401611e22565b845250918301918301611ebc565b509695505050505050565b5f6020808385031215611f25575f80fd5b823567ffffffffffffffff80821115611f3c575f80fd5b9084019060408287031215611f4f575f80fd5b611f57611d38565b823582811115611f65575f80fd5b8301601f81018813611f75575f80fd5b8035611f83611e2f82611dd8565b81815260059190911b8201860190868101908a831115611fa1575f80fd5b8784015b8381101561204957803587811115611fbb575f80fd5b85016080818e03601f19011215611fd0575f80fd5b611fd8611d61565b8a820135611fe581611ce5565b8152604082013589811115611ff8575f80fd5b6120068f8d83860101611e5d565b8c8301525060608201358981111561201c575f80fd5b61202a8f8d83860101611e5d565b6040830152506080919091013560608201528352918801918801611fa5565b508452505050828401358281111561205f575f80fd5b61206b88828601611e7b565b948201949094529695505050505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156120c757601f198684030189526120b5838351611c77565b98840198925090830190600101612099565b5090979650505050505050565b5f602080835260608084018551604080858801528282518085526080945060808901915060808160051b8a010187850194505f5b8281101561217257607f198b830301845285516001600160a01b03815116835289810151888b85015261213d89850182611c77565b905086820151848203888601526121548282611c77565b928b0151948b01949094525095890195938901939150600101612108565b50968a0151898803601f190160408b01529661218e818961207c565b9b9a5050505050505050505050565b5f80602083850312156121ae575f80fd5b823567ffffffffffffffff8111156121c4575f80fd5b6121d085828601611bd2565b90969095509350505050565b5f80604083850312156121ed575f80fd5b823567ffffffffffffffff80821115612204575f80fd5b61221086838701611e5d565b93506020850135915080821115612225575f80fd5b5061223285828601611e5d565b9150509250929050565b8015158114611bb4575f80fd5b8035611d048161223c565b5f805f805f8060c08789031215612269575f80fd5b61227287611cf9565b9550602087013567ffffffffffffffff8082111561228e575f80fd5b61229a8a838b01611e5d565b965060408901359150808211156122af575f80fd5b6122bb8a838b01611e5d565b95506122c960608a01612249565b945060808901359150808211156122de575f80fd5b6122ea8a838b01611e5d565b935060a08901359150808211156122ff575f80fd5b5061230c89828a01611e7b565b9150509295509295509295565b5f806040838503121561232a575f80fd5b82356123358161223c565b915060208301356123458161223c565b809150509250929050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b828110156123a557603f19888603018452612393858351611c77565b94509285019290850190600101612377565b5092979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f6123d3611e2f84611dfb565b90508281528383830111156123e6575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261240b575f80fd5b61169e838351602085016123c6565b5f6020828403121561242a575f80fd5b815167ffffffffffffffff811115612440575f80fd5b61042a848285016123fc565b5f6020828403121561245c575f80fd5b815161169e8161223c565b5f82601f830112612476575f80fd5b81516020612486611e2f83611dd8565b82815260059290921b840181019181810190868411156124a4575f80fd5b8286015b84811015611f0957805167ffffffffffffffff8111156124c6575f80fd5b8701603f810189136124d6575f80fd5b6124e78986830151604084016123c6565b8452509183019183016124a8565b5f60208284031215612505575f80fd5b815167ffffffffffffffff81111561251b575f80fd5b61042a84828501612467565b5f815160208301516001600160e01b0319808216935060048310156125565780818460040360031b1b83161693505b505050919050565b5f82601f83011261256d575f80fd5b8135602061257d611e2f83611dd8565b82815260059290921b8401810191818101908684111561259b575f80fd5b8286015b84811015611f0957803567ffffffffffffffff8111156125bd575f80fd5b6125cb8986838b0101611e5d565b84525091830191830161259f565b5f80604083850312156125ea575f80fd5b823567ffffffffffffffff80821115612601575f80fd5b818501915085601f830112612614575f80fd5b81356020612624611e2f83611dd8565b82815260059290921b84018101918181019089841115612642575f80fd5b948201945b8386101561266957853561265a8161223c565b82529482019490820190612647565b9650508601359250508082111561267e575f80fd5b506122328582860161255e565b604081525f61269d6040830185611c77565b828103602084015261161b8185611c77565b5f81518060208401855e5f93019283525090919050565b5f61169e82846126af565b634e487b7160e01b5f52601160045260245ffd5b5f600182016126f6576126f66126d1565b5060010190565b8051611d0481611ce5565b8051611d0481611b9f565b5f60208284031215612723575f80fd5b815167ffffffffffffffff8082111561273a575f80fd5b9083019060c0828603121561274d575f80fd5b612755611d84565b61275e836126fd565b815261276c60208401612708565b6020820152604083015182811115612782575f80fd5b61278e878286016123fc565b6040830152506127a060608401612708565b60608201526127b160808401612708565b608082015260a0830151828111156127c7575f80fd5b6127d3878286016123fc565b60a08301525095945050505050565b8181038181111561035e5761035e6126d1565b5f6020808385031215612806575f80fd5b825167ffffffffffffffff8082111561281d575f80fd5b818501915085601f830112612830575f80fd5b815161283e611e2f82611dd8565b81815260059190911b8301840190848101908883111561285c575f80fd5b8585015b8381101561289257805185811115612876575f80fd5b6128848b89838a01016123fc565b845250918601918601612860565b5098975050505050505050565b5f61042a6128ad83866126af565b846126af565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b8381101561293f57603f19898403018552815160606001600160a01b03825116855288820151818a8701526129118287018261207c565b9150508782015191508481038886015261292b8183611c77565b9689019694505050908601906001016128da565b509098975050505050505050565b6001600160a01b038616815260a060208201525f61296e60a083018761207c565b82810360408401526129808187611c77565b90506001600160e01b03198516606084015282810360808401526129a48185611c77565b98975050505050505050565b602081526001600160a01b0382511660208201525f60208301516001600160e01b031980821660408501526040850151915060c060608501526129f660e0850183611c77565b91508060608601511660808501528060808601511660a08501525060a0840151601f198483030160c085015261161b8282611c77565b606081525f612a3e6060830186611c77565b8281036020840152612a508186611c77565b90508281036040840152612a648185611c77565b9695505050505050565b5f60208284031215612a7e575f80fd5b815161169e81611ce5565b5f805f805f60a08688031215612a9d575f80fd5b8551612aa881611ce5565b602087015190955067ffffffffffffffff80821115612ac5575f80fd5b612ad189838a01612467565b95506040880151915080821115612ae6575f80fd5b612af289838a016123fc565b945060608801519150612b0482611b9f565b608088015191935080821115612b18575f80fd5b50612b25888289016123fc565b9150509295509295909350565b8082018082111561035e5761035e6126d156fea264697066735822122030b444cc06a7b17f3feb64d14e13f86f9a4546ada2b334d0eec58738fed358b064736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "1201": [ + { + "length": 32, + "start": 4251 + } + ], + "31341": [ + { + "length": 32, + "start": 420 + }, + { + "length": 32, + "start": 1396 + } + ], + "31484": [ + { + "length": 32, + "start": 584 + }, + { + "length": 32, + "start": 3951 + } + ], + "31487": [ + { + "length": 32, + "start": 623 + }, + { + "length": 32, + "start": 4092 + }, + { + "length": 32, + "start": 4143 + } + ], + "33410": [ + { + "length": 32, + "start": 289 + }, + { + "length": 32, + "start": 1107 + } + ] + }, + "inputSourceName": "project/src/resolver/ENSV2Resolver.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "InvalidBatchGatewayResponse()": [ + { + "details": "Error selector: `0x4a5c31ea`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "UnreachableName(bytes)": [ + { + "details": "`name` cannot be resolved. Error selector: `0x5fe9a5df`", + "params": { + "name": "The DNS-encoded ENS name." + } + } + ] + }, + "kind": "dev", + "methods": { + "callResolver(address,bytes,bytes,bool,bytes,string[])": { + "details": "Reverts `UnreachableName` if resolver is not a contract. This function never returns normally. The return type is necessary to define the result of the callback. Call this function externally or with `ccipRead()` to intercept the response.", + "params": { + "batchGateways": "The batch gateway URLs.", + "context": "The context for `IExtendedDNSResolver`.", + "data": "The calldata for the resolution.", + "hasContext": "True if `IExtendedDNSResolver` should be considered.", + "name": "The DNS-encoded ENS name.", + "resolver": "The resolver to call." + } + }, + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": { + "details": "Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`." + }, + "ccipBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \"done\".", + "params": { + "extraData": "The contextual data passed from `ccipBatch()`.", + "response": "The response from the batch gateway." + }, + "returns": { + "batch": "The batch where every lookup is \"done\"." + } + }, + "ccipReadCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.", + "params": { + "extraData": "The contextual data passed from `ccipRead()`.", + "response": "The response from offchain." + } + }, + "constructor": { + "params": { + "batchGatewayProvider": "The batch gateway provider.", + "contractNamer": "Delegated contract namer.", + "ethResolver": "The override resolver for \"eth\" or null to use ENSv2.", + "rootRegistry": "The ENSv2 root registry." + } + }, + "getResolver(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The underlying resolver address.", + "_1": "`true` if `resolver` is offchain." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "resolveBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `callResolver()` from batch calling a resolver.", + "params": { + "extraData": "The abi-encoded properties of the call.", + "response": "The response data from the batch gateway." + }, + "returns": { + "_0": "result The response from the resolver." + } + }, + "resolveDirectImmediateCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `callResolver()` from direct calling an immediate resolver." + }, + "supportsFeature(bytes4)": { + "params": { + "featureId": "The feature identifier." + }, + "returns": { + "_0": "`true` if the feature is supported by the contract." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "2226200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BATCH_GATEWAY_PROVIDER()": "infinite", + "CONTRACT_NAMER()": "infinite", + "ETH_RESOLVER()": "infinite", + "ROOT_REGISTRY()": "infinite", + "callResolver(address,bytes,bytes,bool,bytes,string[])": "infinite", + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": "infinite", + "ccipBatchCallback(bytes,bytes)": "infinite", + "ccipReadCallback(bytes,bytes)": "infinite", + "getResolver(bytes)": "infinite", + "isContractNamer(address)": "infinite", + "resolve(bytes,bytes)": "infinite", + "resolveBatchCallback(bytes,bytes)": "infinite", + "resolveDirectImmediateCallback(bytes,bytes)": "infinite", + "supportsFeature(bytes4)": "396", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_findResolver(bytes calldata)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"batchGatewayProvider\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"rootRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ethResolver\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBatchGatewayResponse\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"UnreachableName\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BATCH_GATEWAY_PROVIDER\",\"outputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"hasContext\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"batchGateways\",\"type\":\"string[]\"}],\"name\":\"callResolver\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"name\":\"ccipBatch\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipBatchCallback\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipReadCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveBatchCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"resolveDirectImmediateCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"feature\",\"type\":\"bytes4\"}],\"name\":\"supportsFeature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"InvalidBatchGatewayResponse()\":[{\"details\":\"Error selector: `0x4a5c31ea`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"UnreachableName(bytes)\":[{\"details\":\"`name` cannot be resolved. Error selector: `0x5fe9a5df`\",\"params\":{\"name\":\"The DNS-encoded ENS name.\"}}]},\"kind\":\"dev\",\"methods\":{\"callResolver(address,bytes,bytes,bool,bytes,string[])\":{\"details\":\"Reverts `UnreachableName` if resolver is not a contract. This function never returns normally. The return type is necessary to define the result of the callback. Call this function externally or with `ccipRead()` to intercept the response.\",\"params\":{\"batchGateways\":\"The batch gateway URLs.\",\"context\":\"The context for `IExtendedDNSResolver`.\",\"data\":\"The calldata for the resolution.\",\"hasContext\":\"True if `IExtendedDNSResolver` should be considered.\",\"name\":\"The DNS-encoded ENS name.\",\"resolver\":\"The resolver to call.\"}},\"ccipBatch(((address,bytes,bytes,uint256)[],string[]))\":{\"details\":\"Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`.\"},\"ccipBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\",\"params\":{\"extraData\":\"The contextual data passed from `ccipBatch()`.\",\"response\":\"The response from the batch gateway.\"},\"returns\":{\"batch\":\"The batch where every lookup is \\\"done\\\".\"}},\"ccipReadCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.\",\"params\":{\"extraData\":\"The contextual data passed from `ccipRead()`.\",\"response\":\"The response from offchain.\"}},\"constructor\":{\"params\":{\"batchGatewayProvider\":\"The batch gateway provider.\",\"contractNamer\":\"Delegated contract namer.\",\"ethResolver\":\"The override resolver for \\\"eth\\\" or null to use ENSv2.\",\"rootRegistry\":\"The ENSv2 root registry.\"}},\"getResolver(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The underlying resolver address.\",\"_1\":\"`true` if `resolver` is offchain.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"resolveBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `callResolver()` from batch calling a resolver.\",\"params\":{\"extraData\":\"The abi-encoded properties of the call.\",\"response\":\"The response data from the batch gateway.\"},\"returns\":{\"_0\":\"result The response from the resolver.\"}},\"resolveDirectImmediateCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `callResolver()` from direct calling an immediate resolver.\"},\"supportsFeature(bytes4)\":{\"params\":{\"featureId\":\"The feature identifier.\"},\"returns\":{\"_0\":\"`true` if the feature is supported by the contract.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBatchGatewayResponse()\":[{\"notice\":\"The batch gateway supplied an incorrect number of responses.\"}]},\"kind\":\"user\",\"methods\":{\"BATCH_GATEWAY_PROVIDER()\":{\"notice\":\"Shared batch gateway provider.\"},\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"ETH_RESOLVER()\":{\"notice\":\"The ENSv1 resolver for \\\"eth\\\".\"},\"ROOT_REGISTRY()\":{\"notice\":\"The ENSv2 root registry used to traverse the registry hierarchy and locate resolvers.\"},\"callResolver(address,bytes,bytes,bool,bytes,string[])\":{\"notice\":\"Perform forward resolution. Call this function with `ccipRead()` to intercept the response. Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers. - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features, the call is performed directly without the batch gateway. - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature, the call is performed directly without the batch gateway. - Otherwise, the call is performed with the batch gateway. The batch gateway is only invoked if any call reverts `OffchainLookup`. If the calldata is `multicall()` it is disassembled, called separately, and reassembled.\"},\"getResolver(bytes)\":{\"notice\":\"Fetch the underlying resolver for `name`. Callers should enable EIP-3668. * If `offchain`, additional information is necessary to locate `resolver`. * If `resolver` is null, `offchain` is irrelevant.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"supportsFeature(bytes4)\":{\"notice\":\"Check if a feature is supported.\"}},\"notice\":\"Resolver that performs resolutions using ENSv2 with override for ENSv1 \\\"eth\\\" resolver.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/resolver/ENSV2Resolver.sol\":\"ENSV2Resolver\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/CCIPBatcher.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {IBatchGateway} from \\\"./IBatchGateway.sol\\\";\\nimport {CCIPReader, EIP3668, OffchainLookup} from \\\"./CCIPReader.sol\\\";\\n\\n/// @dev CCIP-Read batch gateway client implementation.\\n///\\n/// Since requests are read-only, empty responses are considered an error.\\n///\\n/// Usage: `ccipRead(address(this), abi.encodeCall(this.ccipBatch, (createBatch(...))), ...)`\\n///\\nabstract contract CCIPBatcher is CCIPReader {\\n /// @notice The batch gateway supplied an incorrect number of responses.\\n /// @dev Error selector: `0x4a5c31ea`\\n error InvalidBatchGatewayResponse();\\n\\n uint256 constant FLAG_OFFCHAIN = 1 << 0; // the lookup reverted `OffchainLookup`\\n uint256 constant FLAG_CALL_ERROR = 1 << 1; // the initial call or callback reverted\\n uint256 constant FLAG_BATCH_ERROR = 1 << 2; // `OffchainLookup` failed on the batch gateway\\n uint256 constant FLAG_EMPTY_RESPONSE = 1 << 3; // the initial call or callback returned `0x`\\n uint256 constant FLAG_EIP140_BEFORE = 1 << 4; // does not have revert op code\\n uint256 constant FLAG_EIP140_AFTER = 1 << 5; // has revert op code\\n uint256 constant FLAG_DONE = 1 << 6; // the lookup has finished processing (private)\\n\\n uint256 constant FLAGS_ANY_ERROR =\\n FLAG_CALL_ERROR | FLAG_BATCH_ERROR | FLAG_EMPTY_RESPONSE;\\n uint256 constant FLAGS_ANY_EIP140 = FLAG_EIP140_BEFORE | FLAG_EIP140_AFTER;\\n\\n /// @dev An independent `OffchainLookup` session.\\n struct Lookup {\\n address target; // contract to call\\n bytes call; // initial calldata\\n bytes data; // response or error\\n uint256 flags; // see: FLAG_*\\n }\\n\\n /// @dev A batch gateway session.\\n struct Batch {\\n Lookup[] lookups;\\n string[] gateways;\\n }\\n\\n /// @dev Create a batch for a single target with multiple calls.\\n /// @param target The target contract.\\n /// @param calls The list of calldata.\\n /// @param gateways The batch gateway URLs.\\n function createBatch(\\n address target,\\n bytes[] memory calls,\\n string[] memory gateways\\n ) internal pure returns (Batch memory) {\\n Lookup[] memory lookups = new Lookup[](calls.length);\\n for (uint256 i; i < calls.length; ++i) {\\n Lookup memory lu = lookups[i];\\n lu.target = target;\\n lu.call = calls[i];\\n }\\n return Batch(lookups, gateways);\\n }\\n\\n /// @dev Use `ccipRead()` to call this function with a batch.\\n /// The callback response will be `abi.encode(batch)`.\\n function ccipBatch(\\n Batch memory batch\\n ) external view returns (Batch memory) {\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) != 0) {\\n continue; // don't call a lookup that's already done\\n }\\n if ((lu.flags & FLAGS_ANY_EIP140) == 0) {\\n uint256 flags = detectEIP140(lu.target)\\n ? FLAG_EIP140_AFTER\\n : FLAG_EIP140_BEFORE;\\n for (uint256 j = i; j < batch.lookups.length; ++j) {\\n if (batch.lookups[j].target == lu.target) {\\n batch.lookups[j].flags |= flags;\\n }\\n }\\n }\\n bool unsafe = (lu.flags & FLAG_EIP140_AFTER) == 0;\\n (bool ok, bytes memory v) = safeCall(!unsafe, lu.target, lu.call);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n lu.flags |= FLAG_OFFCHAIN;\\n } else {\\n lu.flags |= FLAG_DONE;\\n if (unsafe && v.length == 0) {\\n // unsafe contracts appear the same for throw and unimplemented fallback\\n // decision: interpret like an unimplemented function selector response\\n } else if (!ok) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n lu.data = v;\\n }\\n _revertBatchGateway(batch); // reverts if any offchain\\n return batch;\\n }\\n\\n /// @dev Check if the batch is \\\"done\\\". If not, revert `OffchainLookup` for batch gateway.\\n function _revertBatchGateway(Batch memory batch) internal view {\\n IBatchGateway.Request[] memory requests = new IBatchGateway.Request[](\\n batch.lookups.length\\n );\\n uint256 count;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n requests[count++] = IBatchGateway.Request(\\n p.sender,\\n p.urls,\\n p.callData\\n );\\n }\\n }\\n if (count > 0) {\\n assembly {\\n mstore(requests, count) // truncate to number of offchain requests\\n }\\n revert OffchainLookup(\\n address(this),\\n batch.gateways,\\n abi.encodeCall(IBatchGateway.query, (requests)),\\n this.ccipBatchCallback.selector,\\n abi.encode(batch)\\n );\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipBatch()`.\\n /// Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\\n /// @param response The response from the batch gateway.\\n /// @param extraData The contextual data passed from `ccipBatch()`.\\n /// @return batch The batch where every lookup is \\\"done\\\".\\n function ccipBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (Batch memory batch) {\\n (bool[] memory failures, bytes[] memory responses) = abi.decode(\\n response,\\n (bool[], bytes[])\\n );\\n if (failures.length != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n batch = abi.decode(extraData, (Batch));\\n uint256 expected;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n if (expected < responses.length) {\\n bytes memory v = responses[expected];\\n if (failures[expected]) {\\n lu.flags |= FLAG_DONE | FLAG_BATCH_ERROR;\\n } else {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n bool ok;\\n // assumption: unsafe contracts don't revert OffchainLookup()\\n (ok, v) = p.sender.staticcall(\\n abi.encodeWithSelector(\\n p.callbackFunction,\\n v,\\n p.extraData\\n )\\n );\\n if (ok || bytes4(v) != OffchainLookup.selector) {\\n lu.flags |= FLAG_DONE;\\n // decision: promote empty response from the callback => call error\\n // ie. the initial function was implemented but the callback was not\\n // this can be detected via FLAG_OFFCHAIN\\n if (!ok || v.length == 0) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n }\\n lu.data = v;\\n }\\n ++expected;\\n }\\n }\\n if (expected != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n _revertBatchGateway(batch);\\n }\\n\\n /// @dev Safely collapse `Lookup[]` into `bytes[]`.\\n /// If `FLAGS_ANY_ERROR` and response is non-empty, the response is zero-padded so that `length % 32 == 4`.\\n /// @param lookups Array of completed lookups.\\n /// @param wrapped If `true`, successful responses are unwrapped as `bytes`.\\n /// @return arr Array of call responses.\\n function _toResponseArray(Lookup[] memory lookups, bool wrapped) internal pure returns (bytes[] memory arr) {\\n arr = new bytes[](lookups.length);\\n for (uint256 i; i < lookups.length; ++i) {\\n Lookup memory lu = lookups[i];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) == 0) {\\n if (wrapped) {\\n v = abi.decode(v, (bytes));\\n }\\n } else if (v.length != 0) {\\n // force pad error response to length mod 32 == 4\\n // prevents unverified data from passing as valid response \\n unchecked {\\n uint256 pad = (4 - v.length) & 31;\\n if (pad > 0) {\\n v = abi.encodePacked(v, new bytes(pad)); \\n }\\n }\\n }\\n arr[i] = v;\\n }\\n return arr;\\n }\\n}\",\"keccak256\":\"0xc7fe6929199a1019dd0c3faf9884b5250786fb77d3c3df3e772cfd4ed823d684\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/CCIPReader.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n/// @author Modified from https://github.com/unruggable-labs/CCIPReader.sol/blob/341576fe7ff2b6e0c93fc08f37740cf6439f5873/contracts/CCIPReader.sol\\n\\n/// MIT License\\n/// Portions Copyright (c) 2025 Unruggable\\n/// Portions Copyright (c) 2025 ENS Labs Ltd\\n\\n/// @dev Instructions:\\n/// 1. inherit this contract\\n/// 2. call `ccipRead()` similar to `staticcall()`\\n/// 3. do not put logic after this invocation\\n/// 4. implement all response logic in callback\\n/// 5. ensure that return type of calling function == callback function\\n\\nimport {EIP3668, OffchainLookup} from \\\"./EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\n\\ncontract CCIPReader {\\n /// @dev Default unsafe call gas (sufficient for legacy ENS resolver profiles).\\n uint256 constant DEFAULT_UNSAFE_CALL_GAS = 50000;\\n\\n /// @dev Special-purpose value for identity callback: `f(x) = x`.\\n bytes4 constant IDENTITY_FUNCTION = bytes4(0);\\n\\n /// @dev The gas limit for calling functions on unsafe contracts.\\n uint256 immutable unsafeCallGas;\\n\\n constructor(uint256 _unsafeCallGas) {\\n unsafeCallGas = _unsafeCallGas;\\n }\\n\\n /// @dev A recursive CCIP-Read session.\\n struct Context {\\n address target;\\n bytes4 callbackFunction;\\n bytes extraData;\\n bytes4 successCallbackFunction;\\n bytes4 failureCallbackFunction;\\n bytes myExtraData;\\n }\\n\\n /// @dev Same as `ccipRead()` but the callback function is the identity.\\n function ccipRead(address target, bytes memory call) internal view {\\n ccipRead(target, call, IDENTITY_FUNCTION, IDENTITY_FUNCTION, \\\"\\\");\\n }\\n\\n /// @dev Performs a CCIP-Read and handles internal recursion.\\n /// Reverts `OffchainLookup` if necessary.\\n /// Use `IDENTITY_FUNCTION` as the callback function selector for return/revert behavior.\\n /// @param target The contract address.\\n /// @param call The calldata to `staticcall()` on `target`.\\n /// @param successCallbackFunction The function selector of callback on success.\\n /// @param failureCallbackFunction The function selector of callback on failure.\\n /// @param extraData The contextual data relayed to callback function.\\n function ccipRead(\\n address target,\\n bytes memory call,\\n bytes4 successCallbackFunction,\\n bytes4 failureCallbackFunction,\\n bytes memory extraData\\n ) internal view {\\n // We call the intended function that **could** revert with an `OffchainLookup`\\n // We destructure the response into an execution status bool and our return bytes\\n (bool ok, bytes memory v) = safeCall(\\n detectEIP140(target),\\n target,\\n call\\n );\\n // IF the function reverted with an `OffchainLookup`\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n // We decode the response error into a tuple\\n // tuples allow flexibility noting stack too deep constraints\\n EIP3668.Params memory p = decodeOffchainLookup(v);\\n if (p.sender == target) {\\n // We then wrap the error data in an `OffchainLookup` sent/'owned' by this contract\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n this.ccipReadCallback.selector,\\n abi.encode(\\n Context(\\n target,\\n p.callbackFunction,\\n p.extraData,\\n successCallbackFunction,\\n failureCallbackFunction,\\n extraData\\n )\\n )\\n );\\n }\\n }\\n // IF we have gotten here, the 'real' target does not revert with an `OffchainLookup` error\\n // figure out what callback to call\\n bytes4 callbackFunction = ok\\n ? successCallbackFunction\\n : failureCallbackFunction;\\n if (callbackFunction != IDENTITY_FUNCTION) {\\n // The exit point of this architecture is OUR callback in the 'real'\\n // We pass through the response to that callback\\n (ok, v) = address(this).staticcall(\\n abi.encodeWithSelector(callbackFunction, v, extraData)\\n );\\n }\\n // OR the call to the 'real' target reverts with a different error selector\\n // OR the call to OUR callback reverts with ANY error selector\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipRead()`.\\n /// @param response The response from offchain.\\n /// @param extraData The contextual data passed from `ccipRead()`.\\n /// @dev The return type of this function is polymorphic depending on the caller.\\n function ccipReadCallback(\\n bytes memory response,\\n bytes memory extraData\\n ) external view {\\n Context memory ctx = abi.decode(extraData, (Context));\\n // Since the callback can revert too (but has the same return structure)\\n // We can reuse the calling infrastructure to call the callback\\n ccipRead(\\n ctx.target,\\n abi.encodeWithSelector(\\n ctx.callbackFunction,\\n response,\\n ctx.extraData\\n ),\\n ctx.successCallbackFunction,\\n ctx.failureCallbackFunction,\\n ctx.myExtraData\\n );\\n }\\n\\n /// @dev Decode `OffchainLookup` error data into a struct.\\n /// @param v The error data of the revert.\\n /// @return p The decoded `OffchainLookup` params.\\n function decodeOffchainLookup(\\n bytes memory v\\n ) internal pure returns (EIP3668.Params memory p) {\\n p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n }\\n\\n /// @dev Determine if `target` uses `revert()` instead of `invalid()`.\\n // Assumption: only newer contracts revert `OffchainLookup`.\\n /// @param target The contract to test.\\n /// @return safe True if safe to call.\\n function detectEIP140(address target) internal view returns (bool safe) {\\n if (target == address(this)) return true;\\n // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md\\n assembly {\\n let G := 5000\\n let g := gas()\\n pop(staticcall(G, target, 0, 0, 0, 0))\\n safe := lt(sub(g, gas()), G)\\n }\\n }\\n\\n /// @dev Same as `staticcall()` but prevents OOG when not `safe`.\\n function safeCall(\\n bool safe,\\n address target,\\n bytes memory call\\n ) internal view returns (bool ok, bytes memory v) {\\n (ok, v) = target.staticcall{gas: safe ? gasleft() : unsafeCallGas}(\\n call\\n );\\n }\\n}\\n\",\"keccak256\":\"0xa6f483e89e779385c2b7ea6376d92cd3c05c98f91d1a3c7c43dc7422fe6b014f\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IBatchGateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for Batch Gateway Offchain Lookup Protocol.\\n/// https://docs.ens.domains/ensip/21/\\n/// @dev Interface selector: `0xa780bab6`\\ninterface IBatchGateway {\\n /// @notice An HTTP error occurred.\\n /// @dev Error selector: `0x01800152`\\n error HttpError(uint16 status, string message);\\n\\n /// @dev Information extracted from an `OffchainLookup` revert.\\n struct Request {\\n address sender;\\n string[] urls;\\n bytes data;\\n }\\n\\n /// @notice Perform multiple `OffchainLookup` in parallel.\\n /// Callers should enable EIP-3668.\\n /// @param requests The array of requests to lookup in parallel.\\n /// @return failures The failure status of the corresponding request.\\n /// @return responses The response or error data of the corresponding request.\\n function query(\\n Request[] memory requests\\n ) external view returns (bool[] memory failures, bytes[] memory responses);\\n}\\n\",\"keccak256\":\"0xfd7f0c7bdc29fc732ec54da2ebaea241873e55082e484729901811bc9374d6f6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IGatewayProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for shared gateway URLs.\\n/// @dev Interface selector: `0x093a86d3`\\ninterface IGatewayProvider {\\n /// @notice Get the gateways.\\n /// @return The gateway URLs.\\n function gateways() external view returns (string[] memory);\\n}\\n\",\"keccak256\":\"0x7c169843cfb65657a88fb4d5f7ec44612994d7d87cb7b1a67cbfdb18758823e0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverFeatures.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary ResolverFeatures {\\n /// @notice Implements `resolve(multicall([...]))`.\\n /// @dev Feature: `0x96b62db8`\\n bytes4 constant RESOLVE_MULTICALL =\\n bytes4(keccak256(\\\"eth.ens.resolver.extended.multicall\\\"));\\n\\n /// @notice Returns the same records independent of name or node.\\n /// @dev Feature: `0x86fb8da8`\\n bytes4 constant SINGULAR = bytes4(keccak256(\\\"eth.ens.resolver.singular\\\"));\\n}\\n\",\"keccak256\":\"0x87d131fcbdd7951a17b0a94f7f02470ec3f62c6004cf91c2d2acc54098373be6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ICompositeResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport {IExtendedResolver} from \\\"./IExtendedResolver.sol\\\";\\n\\n/// @notice A resolver that calls other resolvers.\\n/// @dev Interface selector: `0xeea330f9`\\ninterface ICompositeResolver is IExtendedResolver {\\n /// @notice Fetch the underlying resolver for `name`.\\n /// Callers should enable EIP-3668.\\n ///\\n /// * If `offchain`, additional information is necessary to locate `resolver`.\\n /// * If `resolver` is null, `offchain` is irrelevant.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return resolver The underlying resolver address.\\n /// @return offchain `true` if `resolver` is offchain.\\n function getResolver(\\n bytes memory name\\n ) external view returns (address resolver, bool offchain);\\n}\\n\",\"keccak256\":\"0xe267bef9a45073c92129ededa0275acf29394fa3fb30547bab8138dac485e2b2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedDNSResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data,\\n bytes memory context\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x541f8799c34ff9e7035d09f06ae0f0f8a16b6065e9b60a15670b957321630f72\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/ResolverCaller.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {\\n ERC165Checker\\n} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {CCIPBatcher} from \\\"../ccipRead/CCIPBatcher.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\nimport {IERC7996} from \\\"../utils/IERC7996.sol\\\";\\nimport {ResolverFeatures} from \\\"../resolvers/ResolverFeatures.sol\\\";\\n\\n// resolver profiles\\nimport {IExtendedResolver} from \\\"../resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {\\n IExtendedDNSResolver\\n} from \\\"../resolvers/profiles/IExtendedDNSResolver.sol\\\";\\nimport {IMulticallable} from \\\"../resolvers/IMulticallable.sol\\\";\\n\\nabstract contract ResolverCaller is CCIPBatcher {\\n /// @dev `name` cannot be resolved.\\n /// Error selector: `0x5fe9a5df`\\n /// @param name The DNS-encoded ENS name.\\n error UnreachableName(bytes name);\\n\\n /// @notice Perform forward resolution.\\n ///\\n /// Call this function with `ccipRead()` to intercept the response.\\n /// Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers.\\n ///\\n /// - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features,\\n /// the call is performed directly without the batch gateway.\\n /// - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature,\\n /// the call is performed directly without the batch gateway.\\n /// - Otherwise, the call is performed with the batch gateway.\\n /// The batch gateway is only invoked if any call reverts `OffchainLookup`.\\n /// If the calldata is `multicall()` it is disassembled, called separately, and reassembled.\\n ///\\n /// @dev Reverts `UnreachableName` if resolver is not a contract.\\n\\t/// This function never returns normally.\\n\\t/// The return type is necessary to define the result of the callback.\\n\\t/// Call this function externally or with `ccipRead()` to intercept the response.\\n /// @param resolver The resolver to call.\\n /// @param name The DNS-encoded ENS name.\\n /// @param data The calldata for the resolution.\\n /// @param hasContext True if `IExtendedDNSResolver` should be considered.\\n /// @param context The context for `IExtendedDNSResolver`.\\n /// @param batchGateways The batch gateway URLs.\\n function callResolver(\\n address resolver,\\n bytes memory name,\\n bytes memory data,\\n bool hasContext,\\n bytes memory context,\\n string[] memory batchGateways\\n ) public view returns (bytes memory) {\\n if (resolver.code.length == 0) {\\n revert UnreachableName(name);\\n }\\n bool multi = bytes4(data) == IMulticallable.multicall.selector;\\n bool extendedDNS = hasContext &&\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IExtendedDNSResolver).interfaceId\\n );\\n bool extended = extendedDNS ||\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IExtendedResolver).interfaceId\\n );\\n if (\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n resolver,\\n type(IERC7996).interfaceId\\n ) &&\\n (!multi ||\\n (extended &&\\n IERC7996(resolver).supportsFeature(\\n ResolverFeatures.RESOLVE_MULTICALL\\n )))\\n ) {\\n if (extended) {\\n // resolve() has the same return signature as callResolver()\\n ccipRead(\\n resolver,\\n _makeExtendedCall(extendedDNS, name, data, context)\\n );\\n } else {\\n ccipRead(\\n resolver,\\n data,\\n this.resolveDirectImmediateCallback.selector, // ==> step 2\\n IDENTITY_FUNCTION,\\n \\\"\\\"\\n );\\n }\\n }\\n bytes[] memory calls;\\n if (multi) {\\n calls = abi.decode(\\n BytesUtils.substring(data, 4, data.length - 4),\\n (bytes[])\\n );\\n } else {\\n calls = new bytes[](1);\\n calls[0] = data;\\n }\\n if (extended) {\\n for (uint256 i; i < calls.length; ++i) {\\n calls[i] = _makeExtendedCall(\\n extendedDNS,\\n name,\\n calls[i],\\n context\\n );\\n }\\n }\\n ccipRead(\\n address(this),\\n abi.encodeCall(\\n this.ccipBatch,\\n (createBatch(resolver, calls, batchGateways))\\n ),\\n this.resolveBatchCallback.selector, // ==> step 2\\n IDENTITY_FUNCTION,\\n abi.encode(multi, extended)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `callResolver()` from direct calling an immediate resolver.\\n function resolveDirectImmediateCallback(\\n bytes calldata response,\\n bytes calldata\\n ) external pure returns (bytes calldata) {\\n return response; // the calldata was direct, so wrap it\\n }\\n\\n /// @dev CCIP-Read callback for `callResolver()` from batch calling a resolver.\\n /// @param response The response data from the batch gateway.\\n /// @param extraData The abi-encoded properties of the call.\\n /// @return result The response from the resolver.\\n function resolveBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external pure returns (bytes memory) {\\n Lookup[] memory lookups = abi.decode(response, (Batch)).lookups;\\n (bool multi, bool extended) = abi.decode(extraData, (bool, bool));\\n if (multi) {\\n return abi.encode(_toResponseArray(lookups, extended));\\n } else {\\n Lookup memory lu = lookups[0];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) != 0) {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n if (extended) {\\n v = abi.decode(v, (bytes)); // unwrap resolve()\\n }\\n return v;\\n }\\n }\\n\\n /// @dev Create extended resolver calldata.\\n function _makeExtendedCall(\\n bool extendedDNS,\\n bytes memory name,\\n bytes memory call,\\n bytes memory context\\n ) internal pure returns (bytes memory) {\\n return\\n extendedDNS\\n ? abi.encodeCall(\\n IExtendedDNSResolver.resolve,\\n (name, call, context)\\n )\\n : abi.encodeCall(IExtendedResolver.resolve, (name, call));\\n }\\n}\\n\",\"keccak256\":\"0xf639a50d41e390b0c156667b59960b0422e738027a87a111464a196fb71638d7\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/IERC7996.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for expressing contract features not visible from the ABI.\\n/// @dev Interface selector: `0x582de3e7`\\ninterface IERC7996 {\\n /// @notice Check if a feature is supported.\\n /// @param featureId The feature identifier.\\n /// @return `true` if the feature is supported by the contract.\\n function supportsFeature(bytes4 featureId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf499a48e4e879ec7775f375d2cb5af047720ab6ae4b6f89a40a578c4e0f51631\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x5a08ad61f4e82b8a3323562661a86fb10b10190848073fdc13d4ac43710ffba5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/resolver/AbstractMirrorResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {CCIPReader} from \\\"@ens/contracts/ccipRead/CCIPReader.sol\\\";\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {ICompositeResolver} from \\\"@ens/contracts/resolvers/profiles/ICompositeResolver.sol\\\";\\nimport {IExtendedResolver} from \\\"@ens/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {ResolverFeatures} from \\\"@ens/contracts/resolvers/ResolverFeatures.sol\\\";\\nimport {ResolverCaller} from \\\"@ens/contracts/universalResolver/ResolverCaller.sol\\\";\\nimport {IERC7996} from \\\"@ens/contracts/utils/IERC7996.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\n/// @dev Resolver that mirrors resolution of the same name to a different registry.\\nabstract contract AbstractMirrorResolver is\\n ICompositeResolver,\\n IERC7996,\\n ResolverCaller,\\n DelegatedContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Shared batch gateway provider.\\n IGatewayProvider public immutable BATCH_GATEWAY_PROVIDER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n constructor(IGatewayProvider batchGatewayProvider, IContractNamer contractNamer)\\n CCIPReader(DEFAULT_UNSAFE_CALL_GAS)\\n DelegatedContractNamer(contractNamer)\\n {\\n BATCH_GATEWAY_PROVIDER = batchGatewayProvider;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(DelegatedContractNamer)\\n returns (bool)\\n {\\n return\\n type(IExtendedResolver).interfaceId == interfaceId ||\\n type(ICompositeResolver).interfaceId == interfaceId ||\\n type(IERC7996).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /// @inheritdoc IERC7996\\n function supportsFeature(bytes4 feature) external pure returns (bool) {\\n return ResolverFeatures.RESOLVE_MULTICALL == feature;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IExtendedResolver\\n function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory) {\\n callResolver(_findResolver(name), name, data, false, \\\"\\\", BATCH_GATEWAY_PROVIDER.gateways());\\n }\\n\\n /// @inheritdoc ICompositeResolver\\n function getResolver(bytes calldata name) external view returns (address, bool) {\\n return (_findResolver(name), false);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Determine the resolver for `name`.\\n function _findResolver(bytes calldata name) internal view virtual returns (address);\\n}\\n\",\"keccak256\":\"0x4297a896783bb27602ce3891ec9839fff69e81621c12bbdcce9f1ac73c14ed57\",\"license\":\"MIT\"},\"project/src/resolver/ENSV2Resolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {LibRegistry} from \\\"../universalResolver/libraries/LibRegistry.sol\\\";\\n\\nimport {AbstractMirrorResolver} from \\\"./AbstractMirrorResolver.sol\\\";\\n\\n/// @notice Resolver that performs resolutions using ENSv2 with override for ENSv1 \\\"eth\\\" resolver.\\ncontract ENSV2Resolver is AbstractMirrorResolver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 root registry used to traverse the registry hierarchy and locate resolvers.\\n IPermissionedRegistry public immutable ROOT_REGISTRY;\\n\\n /// @notice The ENSv1 resolver for \\\"eth\\\".\\n address public immutable ETH_RESOLVER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n /// @param rootRegistry The ENSv2 root registry.\\n /// @param ethResolver The override resolver for \\\"eth\\\" or null to use ENSv2.\\n constructor(\\n IGatewayProvider batchGatewayProvider,\\n IContractNamer contractNamer,\\n IPermissionedRegistry rootRegistry,\\n address ethResolver\\n )\\n AbstractMirrorResolver(batchGatewayProvider, contractNamer)\\n {\\n ROOT_REGISTRY = rootRegistry;\\n ETH_RESOLVER = ethResolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc AbstractMirrorResolver\\n function _findResolver(bytes calldata name) internal view override returns (address resolver) {\\n bytes32 node;\\n (, resolver, node, ) = LibRegistry.findResolver(ROOT_REGISTRY, name, 0);\\n if (node == NameCoder.ETH_NODE && address(ETH_RESOLVER) != address(0)) {\\n resolver = ETH_RESOLVER;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x85207e437c6723428d79e5a3ee47eb019d1fbbd6f0434bc01d8f1b880de226a9\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/universalResolver/libraries/LibRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"../../registry/interfaces/IOwnedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Recursive traversal helpers for the namechain registry tree \\u2014 resolver lookup, registry\\n/// discovery, canonical name construction, and ancestry enumeration.\\nlibrary LibRegistry {\\n /// @dev Find the resolver address for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return exactRegistry The exact registry or null if not exact.\\n /// @return resolver The resolver or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n // supply if end of name\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return (rootRegistry, address(0), bytes32(0), offset);\\n }\\n // lookup parent name\\n (exactRegistry, resolver, node, resolverOffset) = findResolver(rootRegistry, name, next);\\n // if there was a parent registry...\\n if (address(exactRegistry) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n // remember the resolver (if it exists)\\n address res = exactRegistry.getResolver(label);\\n if (res != address(0)) {\\n resolver = res;\\n resolverOffset = offset;\\n }\\n exactRegistry = exactRegistry.getSubregistry(label);\\n }\\n node = NameCoder.namehash(node, labelHash); // update namehash\\n }\\n\\n /// @dev Find the owner for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return owner The owner address or null if unowned or not found.\\n function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (address owner)\\n {\\n IRegistry registry = findParentRegistry(rootRegistry, name, offset);\\n if (\\n address(registry) != address(0) &&\\n ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId)\\n ) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n owner = IOwnedRegistry(address(registry)).findOwner(label);\\n }\\n }\\n\\n /// @dev Construct the canonical name for `registry`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param registry The registry to name.\\n /// @return name The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry rootRegistry, IRegistry registry)\\n internal\\n view\\n returns (bytes memory name)\\n {\\n if (address(registry) == address(0)) {\\n return \\\"\\\";\\n }\\n for (;;) {\\n if (address(registry) == address(rootRegistry)) {\\n return abi.encodePacked(name, uint8(0)); // add terminator\\n }\\n (IRegistry parent, string memory label) = registry.getParent();\\n if (address(parent) == address(0)) {\\n return \\\"\\\"; // no canonical parent\\n }\\n IRegistry child = parent.getSubregistry(label);\\n if (address(child) != address(registry)) {\\n return \\\"\\\"; // wrong canonical child\\n }\\n name = abi.encodePacked(name, NameCoder.assertLabelSize(label), label); // reverts if invalid label\\n registry = parent;\\n }\\n }\\n\\n /// @dev Find the registry for `name` and return it iff it is canonical for that name.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name)\\n internal\\n view\\n returns (IRegistry)\\n {\\n IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0);\\n return\\n address(registry) != address(0) &&\\n keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) ==\\n keccak256(name)\\n ? registry\\n : IRegistry(address(0));\\n }\\n\\n /// @dev Find the exact registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return exactRegistry The exact registry or null if not found.\\n function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return rootRegistry;\\n }\\n IRegistry parent = findExactRegistry(rootRegistry, name, next);\\n if (address(parent) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n exactRegistry = parent.getSubregistry(label);\\n }\\n }\\n\\n /// @dev Find the parent registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return parentRegistry The parent registry or null if not found.\\n function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry parentRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n parentRegistry = findExactRegistry(rootRegistry, name, next);\\n }\\n }\\n\\n /// @dev Find all registries in the ancestry of `name`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return registries Array of registries in label-order.\\n function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry[] memory registries)\\n {\\n registries = new IRegistry[](1 + NameCoder.countLabels(name, offset));\\n registries[registries.length - 1] = rootRegistry;\\n _findRegistries(name, offset, registries, 0);\\n }\\n\\n /// @dev Recursive function for building ancestry.\\n function _findRegistries(\\n bytes memory name,\\n uint256 offset,\\n IRegistry[] memory registries,\\n uint256 index\\n )\\n private\\n view\\n returns (IRegistry registry)\\n {\\n (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset);\\n if (bytes(label).length == 0) {\\n return registries[registries.length - 1];\\n }\\n registry = _findRegistries(name, nextOffset, registries, index + 1);\\n if (address(registry) != address(0)) {\\n registry = registry.getSubregistry(label);\\n registries[index] = registry;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0b5f34bcc76ee3e49d300444fbcbe1ed152faee49a91c87eaea5f6d61ce6fb0b\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "InvalidBatchGatewayResponse()": [ + { + "notice": "The batch gateway supplied an incorrect number of responses." + } + ] + }, + "kind": "user", + "methods": { + "BATCH_GATEWAY_PROVIDER()": { + "notice": "Shared batch gateway provider." + }, + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "ETH_RESOLVER()": { + "notice": "The ENSv1 resolver for \"eth\"." + }, + "ROOT_REGISTRY()": { + "notice": "The ENSv2 root registry used to traverse the registry hierarchy and locate resolvers." + }, + "callResolver(address,bytes,bytes,bool,bytes,string[])": { + "notice": "Perform forward resolution. Call this function with `ccipRead()` to intercept the response. Supports extended (`IExtendedDNSResolver` and `IExtendedResolver`) and immediate resolvers. - If extended, the calldata is not `multicall()`, and the resolver supports ENSIP-22 features, the call is performed directly without the batch gateway. - If extended, the calldata is `multicall()`, and the resolver supports `eth.ens.resolver.extended.multicall` feature, the call is performed directly without the batch gateway. - Otherwise, the call is performed with the batch gateway. The batch gateway is only invoked if any call reverts `OffchainLookup`. If the calldata is `multicall()` it is disassembled, called separately, and reassembled." + }, + "getResolver(bytes)": { + "notice": "Fetch the underlying resolver for `name`. Callers should enable EIP-3668. * If `offchain`, additional information is necessary to locate `resolver`. * If `resolver` is null, `offchain` is irrelevant." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "supportsFeature(bytes4)": { + "notice": "Check if a feature is supported." + } + }, + "notice": "Resolver that performs resolutions using ENSv2 with override for ENSv1 \"eth\" resolver.", + "version": 1 + }, + "argsData": "0x000000000000000000000000e4e7245716d12d0f6aea01dfe0e635c43d7d083c00000000000000000000000068658a771044873906fc9b6e9f278ac5a050134200000000000000000000000011b5bfbe9078d826b1edbdd1cfc12f5828d9f50c00000000000000000000000060c7c2a24b5e86c38639fd1586917a8fef66a56d", + "transaction": { + "hash": "0xac4f6e86337f01dc90f1a11c1ba02b1388b9f4563dda006c603f27a2ada47b82", + "nonce": "0x10", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x888b3d2a07e3f58eeb34f928cc531b9d0924775498b23479efb904ce0e6f43be", + "blockNumber": "0xaa56b9", + "transactionIndex": "0x78" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ETHRegistrar.json b/contracts/deployments/sepolia/ETHRegistrar.json new file mode 100644 index 000000000..236f826d3 --- /dev/null +++ b/contracts/deployments/sepolia/ETHRegistrar.json @@ -0,0 +1,1375 @@ +{ + "address": "0xa4449a0dd2b83007553d9b1d28b583a46a805a30", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + }, + { + "internalType": "uint64", + "name": "gracePeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minCommitmentAge", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "maxCommitmentAge", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minRegisterDuration", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "validFrom", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockTimestamp", + "type": "uint64" + } + ], + "name": "CommitmentTooNew", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "validTo", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockTimestamp", + "type": "uint64" + } + ], + "name": "CommitmentTooOld", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minDuration", + "type": "uint64" + } + ], + "name": "DurationTooShort", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCommitmentAgeTooLow", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "NameNotAvailable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "NameNotRenewable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + } + ], + "name": "UnexpiredCommitmentExists", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + } + ], + "name": "CommitmentMade", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "base", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "premium", + "type": "uint256" + } + ], + "name": "NameRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NameRenewed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + } + ], + "name": "RentPriceOracleUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "BENEFICIARY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GRACE_PERIOD", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_COMMITMENT_AGE", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_COMMITMENT_AGE", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_REGISTER_DURATION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_RENEW_DURATION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + } + ], + "name": "commit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "commitment", + "type": "bytes32" + } + ], + "name": "commitmentAt", + "outputs": [ + { + "internalType": "uint64", + "name": "commitTime", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRegisterPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "base", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "premium", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getRemainingGracePeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRenewPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "isAvailable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "isRenewable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "secret", + "type": "bytes32" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "makeCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "secret", + "type": "bytes32" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rentPriceOracle", + "outputs": [ + { + "internalType": "contract IRentPriceOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + } + ], + "name": "setRentPriceOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "ETHRegistrar", + "sourceName": "src/registrar/ETHRegistrar.sol", + "bytecode": "0x610140604052348015610010575f80fd5b5060405161203338038061203383398101604081905261002f916101a8565b87878787836001600160a01b03811661006157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006a81610127565b506001600160a01b0383811660805282811660a052600180546001600160a01b03191691831691821790556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac99060200160405180910390a150505050826001600160401b0316826001600160401b0316116100fe576040516307cb550760e31b815260040160405180910390fd5b6001600160401b0393841660c05291831660e05282166101005216610120525061024592505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038116811461018a575f80fd5b50565b80516001600160401b03811681146101a3575f80fd5b919050565b5f805f805f805f80610100898b0312156101c0575f80fd5b88516101cb81610176565b60208a01519098506101dc81610176565b60408a01519097506101ed81610176565b60608a01519096506101fe81610176565b945061020c60808a0161018d565b935061021a60a08a0161018d565b925061022860c08a0161018d565b915061023660e08a0161018d565b90509295985092959890939650565b60805160a05160c05160e0516101005161012051611d306103035f395f81816103880152818161105201526110ac01525f818161032b01528181610d5801526114d701525f818161022b015261144101525f81816103af01528181610735015281816110f701526115a701525f8181610252015281816108220152610b7601525f818161029901528181610466015281816106300152818161088c0152818161094201528181610bae01528181610f43015261123a0152611d305ff3fe608060405234801561000f575f80fd5b5060043610610184575f3560e01c8063802295ef116100dd578063a40938bd11610088578063ddf0effc11610063578063ddf0effc146103e4578063f14fcbc8146103f7578063f2fde38b1461040a575f80fd5b8063a40938bd14610383578063c1a287e2146103aa578063cff3e7c2146103d1575f80fd5b80638da5cb5b116100b85780638da5cb5b1461034d578063965306aa1461035d578063a2a11fbe14610370575f80fd5b8063802295ef1461030057806389d779c3146103135780638ccb9ea614610326575f80fd5b80632f99c6cc1161013d57806361907b121161011857806361907b12146102bb578063715018a6146102e35780637b39ba16146102ed575f80fd5b80632f99c6cc1461024d578063307a64a51461028c5780634750070814610294575f80fd5b806316a925351161016d57806316a92535146101c35780631e966f07146102055780632e4f692a14610226575f80fd5b806301ffc9a714610188578063130d6f00146101b0575b5f80fd5b61019b61019636600461167e565b61041d565b60405190151581526020015b60405180910390f35b61019b6101be3660046116ea565b610460565b6101ec6101d1366004611729565b60026020525f908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101a7565b610218610213366004611769565b61053a565b6040519081526020016101a7565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b6102747f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a7565b6101ec600181565b6102747f000000000000000000000000000000000000000000000000000000000000000081565b6102ce6102c9366004611805565b61057e565b604080519283526020830191909152016101a7565b6102eb610619565b005b600154610274906001600160a01b031681565b6101ec61030e3660046116ea565b61062c565b6102eb610321366004611869565b610762565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b0316610274565b61019b61036b3660046116ea565b61093c565b6102eb61037e3660046118d4565b610a0f565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b6102186103df3660046118ef565b610a79565b6102186103f2366004611805565b610cb4565b6102eb610405366004611729565b610d42565b6102eb6104183660046118d4565b610e2a565b5f6001600160e01b031982167fc1401b8000000000000000000000000000000000000000000000000000000000148061045a575061045a82610e80565b92915050565b5f6105337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286104d186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b81526004016104ef91815260200190565b60a060405180830381865afa15801561050a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061052e91906119b8565b610ef1565b9392505050565b5f888888888888888860405160200161055a989796959493929190611a72565b60405160208183030381529060405280519060200120905098975050505050505050565b6001545f9081906001600160a01b031663e1de9c8387876105ac6105a383838b610f17565b602001516110d9565b88886040518663ffffffff1660e01b81526004016105ce959493929190611acd565b6040805180830381865afa1580156105e8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061060c9190611b13565b9150915094509492505050565b610621611149565b61062a5f61118e565b565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861069b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b81526004016106b991815260200190565b60a060405180830381865afa1580156106d4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f891906119b8565b9050610703816111ea565b61070d575f61075a565b60208101516107269067ffffffffffffffff1642611b49565b61075a9067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611b49565b949350505050565b5f61076e86868661120e565b90505f8482602001516107819190611b5c565b60015460208401516040517f3ad860830000000000000000000000000000000000000000000000000000000081529293505f926001600160a01b0390921691633ad86083916107da918c918c918c908c90600401611acd565b602060405180830381865afa1580156107f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108199190611b84565b905061084785337f000000000000000000000000000000000000000000000000000000000000000084611386565b60608301516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff831660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b1580156108d5575f80fd5b505af11580156108e7573d5f803e3d5ffd5b505050508383606001517fbd0c01e5bf66003280556423db4a8bf79043c146ac57f657c30049dd433166498a8a8a878b8860405161092a96959493929190611b9b565b60405180910390a35050505050505050565b5f6105337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286109ad86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b81526004016109cb91815260200190565b60a060405180830381865afa1580156109e6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0a91906119b8565b611414565b610a17611149565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac9906020015b60405180910390a150565b5f6001600160a01b038816610aba576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad2610acd8b8b8b8b8b8b8b8a61053a565b61141f565b5f610ade8b8b87610f17565b60015460208201519192505f9182916001600160a01b03169063e1de9c83908f908f90610b0a906110d9565b8b8b6040518663ffffffff1660e01b8152600401610b2c959493929190611acd565b6040805180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190611b13565b9092509050610ba486337f0000000000000000000000000000000000000000000000000000000000000000610b9f8587611be6565b611386565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166385f3e6438e8e8e8d8d731110000000000000000000000000000001100000610bf78f42611b5c565b6040518863ffffffff1660e01b8152600401610c199796959493929190611bf9565b6020604051808303815f875af1158015610c35573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c599190611b84565b935084847febd3982eafd13b820e3edb2a4abd57a82ce3b8802e0cd45637a5de51383f9fac8f8f8f8e8e8e8e8b8b604051610c9c99989796959493929190611c4e565b60405180910390a35050509998505050505050505050565b6001545f906001600160a01b0316633ad860838686610cd482828961120e565b6020015187876040518663ffffffff1660e01b8152600401610cfa959493929190611acd565b602060405180830381865afa158015610d15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d399190611b84565b95945050505050565b5f818152600260205260409020544290610d87907f00000000000000000000000000000000000000000000000000000000000000009067ffffffffffffffff16611b5c565b67ffffffffffffffff161115610dd1576040517f0a059d71000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b5f81815260026020908152604091829020805467ffffffffffffffff19164267ffffffffffffffff1617905590518281527f561eb038a114723afa3c72b445add7b8602de546264da1e7e826af628316dbcb9101610a6e565b610e32611149565b6001600160a01b038116610e74576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610dc8565b610e7d8161118e565b50565b5f6001600160e01b031982167f06aaeb3200000000000000000000000000000000000000000000000000000000148061045a57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461045a565b805160209091012090565b5f600282516002811115610f0757610f07611cb2565b148061045a575061045a826111ea565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610fae86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b8152600401610fcc91815260200190565b60a060405180830381865afa158015610fe7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061100b91906119b8565b905061101681611414565b6110505783836040517f477707e8000000000000000000000000000000000000000000000000000000008152600401610dc8929190611cc6565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16101561053357604051632825ae1160e21b815267ffffffffffffffff80841660048301527f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610dc8565b5f4267ffffffffffffffff831682036110f25792915050565b61111c7f000000000000000000000000000000000000000000000000000000000000000084611b5c565b92508267ffffffffffffffff168167ffffffffffffffff161161113f575f610533565b6105338382611cd9565b5f546001600160a01b0316331461062a576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610dc8565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408101515f906001600160a01b03161580159061045a575061045a826001611588565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286112a586868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b81526004016112c391815260200190565b60a060405180830381865afa1580156112de573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061130291906119b8565b905061130d81610ef1565b6113475783836040517f1caefaa0000000000000000000000000000000000000000000000000000000008152600401610dc8929190611cc6565b600167ffffffffffffffff8316101561053357604051632825ae1160e21b815267ffffffffffffffff8316600482015260016024820152604401610dc8565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261140e9085906115f9565b50505050565b5f61045a825f611588565b5f81815260026020526040812054429167ffffffffffffffff909116906114667f000000000000000000000000000000000000000000000000000000000000000083611b5c565b90508067ffffffffffffffff168367ffffffffffffffff1610156114d1576040517f6be614e30000000000000000000000000000000000000000000000000000000081526004810185905267ffffffffffffffff808316602483015284166044820152606401610dc8565b5f6114fc7f000000000000000000000000000000000000000000000000000000000000000084611b5c565b90508067ffffffffffffffff168467ffffffffffffffff1610611566576040517f0cb9df3f0000000000000000000000000000000000000000000000000000000081526004810186905267ffffffffffffffff808316602483015285166044820152606401610dc8565b5050505f91825250600260205260409020805467ffffffffffffffff19169055565b5f808351600281111561159d5761159d611cb2565b14801561053357507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16836020015167ffffffffffffffff16426115ea9190611b49565b10151582151514905092915050565b5f8060205f8451602086015f885af180611618576040513d5f823e3d81fd5b50505f513d9150811561162f57806001141561163c565b6001600160a01b0384163b155b1561140e576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610dc8565b5f6020828403121561168e575f80fd5b81356001600160e01b031981168114610533575f80fd5b5f8083601f8401126116b5575f80fd5b50813567ffffffffffffffff8111156116cc575f80fd5b6020830191508360208285010111156116e3575f80fd5b9250929050565b5f80602083850312156116fb575f80fd5b823567ffffffffffffffff811115611711575f80fd5b61171d858286016116a5565b90969095509350505050565b5f60208284031215611739575f80fd5b5035919050565b6001600160a01b0381168114610e7d575f80fd5b67ffffffffffffffff81168114610e7d575f80fd5b5f805f805f805f8060e0898b031215611780575f80fd5b883567ffffffffffffffff811115611796575f80fd5b6117a28b828c016116a5565b90995097505060208901356117b681611740565b95506040890135945060608901356117cd81611740565b935060808901356117dd81611740565b925060a08901356117ed81611754565b8092505060c089013590509295985092959890939650565b5f805f8060608587031215611818575f80fd5b843567ffffffffffffffff81111561182e575f80fd5b61183a878288016116a5565b909550935050602085013561184e81611754565b9150604085013561185e81611740565b939692955090935050565b5f805f805f6080868803121561187d575f80fd5b853567ffffffffffffffff811115611893575f80fd5b61189f888289016116a5565b90965094505060208601356118b381611754565b925060408601356118c381611740565b949793965091946060013592915050565b5f602082840312156118e4575f80fd5b813561053381611740565b5f805f805f805f805f6101008a8c031215611908575f80fd5b893567ffffffffffffffff81111561191e575f80fd5b61192a8c828d016116a5565b909a5098505060208a013561193e81611740565b965060408a0135955060608a013561195581611740565b945060808a013561196581611740565b935060a08a013561197581611754565b925060c08a013561198581611740565b8092505060e08a013590509295985092959850929598565b80516119a881611754565b919050565b80516119a881611740565b5f60a082840312156119c8575f80fd5b60405160a0810181811067ffffffffffffffff821117156119f757634e487b7160e01b5f52604160045260245ffd5b604052825160038110611a08575f80fd5b8152611a166020840161199d565b6020820152611a27604084016119ad565b604082015260608301516060820152608083015160808201528091505092915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60e081525f611a8560e083018a8c611a4a565b6001600160a01b039889166020840152604083019790975250938616606085015291909416608083015267ffffffffffffffff90931660a082015260c0019190915292915050565b608081525f611ae0608083018789611a4a565b67ffffffffffffffff95861660208401529390941660408201526001600160a01b03919091166060909101529392505050565b5f8060408385031215611b24575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561045a5761045a611b35565b67ffffffffffffffff818116838216019080821115611b7d57611b7d611b35565b5092915050565b5f60208284031215611b94575f80fd5b5051919050565b60a081525f611bae60a08301888a611a4a565b67ffffffffffffffff96871660208401529490951660408201526001600160a01b039290921660608301526080909101529392505050565b8082018082111561045a5761045a611b35565b60c081525f611c0c60c08301898b611a4a565b6001600160a01b039788166020840152958716604083015250929094166060830152608082015267ffffffffffffffff90921660a09092019190915292915050565b5f610100808352611c628184018c8e611a4a565b6001600160a01b039a8b166020850152988a1660408401525050948716606086015267ffffffffffffffff939093166080850152941660a083015260c082019390935260e0019190915292915050565b634e487b7160e01b5f52602160045260245ffd5b602081525f61075a602083018486611a4a565b67ffffffffffffffff828116828216039080821115611b7d57611b7d611b3556fea2646970667358221220825c6bc9efe9e1bc07a03f44ccebeb467ab53c3aeb2676ff8f30c5cb4f327ab364736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610184575f3560e01c8063802295ef116100dd578063a40938bd11610088578063ddf0effc11610063578063ddf0effc146103e4578063f14fcbc8146103f7578063f2fde38b1461040a575f80fd5b8063a40938bd14610383578063c1a287e2146103aa578063cff3e7c2146103d1575f80fd5b80638da5cb5b116100b85780638da5cb5b1461034d578063965306aa1461035d578063a2a11fbe14610370575f80fd5b8063802295ef1461030057806389d779c3146103135780638ccb9ea614610326575f80fd5b80632f99c6cc1161013d57806361907b121161011857806361907b12146102bb578063715018a6146102e35780637b39ba16146102ed575f80fd5b80632f99c6cc1461024d578063307a64a51461028c5780634750070814610294575f80fd5b806316a925351161016d57806316a92535146101c35780631e966f07146102055780632e4f692a14610226575f80fd5b806301ffc9a714610188578063130d6f00146101b0575b5f80fd5b61019b61019636600461167e565b61041d565b60405190151581526020015b60405180910390f35b61019b6101be3660046116ea565b610460565b6101ec6101d1366004611729565b60026020525f908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101a7565b610218610213366004611769565b61053a565b6040519081526020016101a7565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b6102747f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101a7565b6101ec600181565b6102747f000000000000000000000000000000000000000000000000000000000000000081565b6102ce6102c9366004611805565b61057e565b604080519283526020830191909152016101a7565b6102eb610619565b005b600154610274906001600160a01b031681565b6101ec61030e3660046116ea565b61062c565b6102eb610321366004611869565b610762565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b0316610274565b61019b61036b3660046116ea565b61093c565b6102eb61037e3660046118d4565b610a0f565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b6102186103df3660046118ef565b610a79565b6102186103f2366004611805565b610cb4565b6102eb610405366004611729565b610d42565b6102eb6104183660046118d4565b610e2a565b5f6001600160e01b031982167fc1401b8000000000000000000000000000000000000000000000000000000000148061045a575061045a82610e80565b92915050565b5f6105337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286104d186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b81526004016104ef91815260200190565b60a060405180830381865afa15801561050a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061052e91906119b8565b610ef1565b9392505050565b5f888888888888888860405160200161055a989796959493929190611a72565b60405160208183030381529060405280519060200120905098975050505050505050565b6001545f9081906001600160a01b031663e1de9c8387876105ac6105a383838b610f17565b602001516110d9565b88886040518663ffffffff1660e01b81526004016105ce959493929190611acd565b6040805180830381865afa1580156105e8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061060c9190611b13565b9150915094509492505050565b610621611149565b61062a5f61118e565b565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861069b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b81526004016106b991815260200190565b60a060405180830381865afa1580156106d4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f891906119b8565b9050610703816111ea565b61070d575f61075a565b60208101516107269067ffffffffffffffff1642611b49565b61075a9067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016611b49565b949350505050565b5f61076e86868661120e565b90505f8482602001516107819190611b5c565b60015460208401516040517f3ad860830000000000000000000000000000000000000000000000000000000081529293505f926001600160a01b0390921691633ad86083916107da918c918c918c908c90600401611acd565b602060405180830381865afa1580156107f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108199190611b84565b905061084785337f000000000000000000000000000000000000000000000000000000000000000084611386565b60608301516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff831660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b1580156108d5575f80fd5b505af11580156108e7573d5f803e3d5ffd5b505050508383606001517fbd0c01e5bf66003280556423db4a8bf79043c146ac57f657c30049dd433166498a8a8a878b8860405161092a96959493929190611b9b565b60405180910390a35050505050505050565b5f6105337f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286109ad86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b81526004016109cb91815260200190565b60a060405180830381865afa1580156109e6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0a91906119b8565b611414565b610a17611149565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac9906020015b60405180910390a150565b5f6001600160a01b038816610aba576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad2610acd8b8b8b8b8b8b8b8a61053a565b61141f565b5f610ade8b8b87610f17565b60015460208201519192505f9182916001600160a01b03169063e1de9c83908f908f90610b0a906110d9565b8b8b6040518663ffffffff1660e01b8152600401610b2c959493929190611acd565b6040805180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190611b13565b9092509050610ba486337f0000000000000000000000000000000000000000000000000000000000000000610b9f8587611be6565b611386565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166385f3e6438e8e8e8d8d731110000000000000000000000000000001100000610bf78f42611b5c565b6040518863ffffffff1660e01b8152600401610c199796959493929190611bf9565b6020604051808303815f875af1158015610c35573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c599190611b84565b935084847febd3982eafd13b820e3edb2a4abd57a82ce3b8802e0cd45637a5de51383f9fac8f8f8f8e8e8e8e8b8b604051610c9c99989796959493929190611c4e565b60405180910390a35050509998505050505050505050565b6001545f906001600160a01b0316633ad860838686610cd482828961120e565b6020015187876040518663ffffffff1660e01b8152600401610cfa959493929190611acd565b602060405180830381865afa158015610d15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d399190611b84565b95945050505050565b5f818152600260205260409020544290610d87907f00000000000000000000000000000000000000000000000000000000000000009067ffffffffffffffff16611b5c565b67ffffffffffffffff161115610dd1576040517f0a059d71000000000000000000000000000000000000000000000000000000008152600481018290526024015b60405180910390fd5b5f81815260026020908152604091829020805467ffffffffffffffff19164267ffffffffffffffff1617905590518281527f561eb038a114723afa3c72b445add7b8602de546264da1e7e826af628316dbcb9101610a6e565b610e32611149565b6001600160a01b038116610e74576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f6004820152602401610dc8565b610e7d8161118e565b50565b5f6001600160e01b031982167f06aaeb3200000000000000000000000000000000000000000000000000000000148061045a57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b031983161461045a565b805160209091012090565b5f600282516002811115610f0757610f07611cb2565b148061045a575061045a826111ea565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610fae86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b8152600401610fcc91815260200190565b60a060405180830381865afa158015610fe7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061100b91906119b8565b905061101681611414565b6110505783836040517f477707e8000000000000000000000000000000000000000000000000000000008152600401610dc8929190611cc6565b7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff16101561053357604051632825ae1160e21b815267ffffffffffffffff80841660048301527f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610dc8565b5f4267ffffffffffffffff831682036110f25792915050565b61111c7f000000000000000000000000000000000000000000000000000000000000000084611b5c565b92508267ffffffffffffffff168167ffffffffffffffff161161113f575f610533565b6105338382611cd9565b5f546001600160a01b0316331461062a576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610dc8565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60408101515f906001600160a01b03161580159061045a575061045a826001611588565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af286112a586868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610ee692505050565b6040518263ffffffff1660e01b81526004016112c391815260200190565b60a060405180830381865afa1580156112de573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061130291906119b8565b905061130d81610ef1565b6113475783836040517f1caefaa0000000000000000000000000000000000000000000000000000000008152600401610dc8929190611cc6565b600167ffffffffffffffff8316101561053357604051632825ae1160e21b815267ffffffffffffffff8316600482015260016024820152604401610dc8565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905261140e9085906115f9565b50505050565b5f61045a825f611588565b5f81815260026020526040812054429167ffffffffffffffff909116906114667f000000000000000000000000000000000000000000000000000000000000000083611b5c565b90508067ffffffffffffffff168367ffffffffffffffff1610156114d1576040517f6be614e30000000000000000000000000000000000000000000000000000000081526004810185905267ffffffffffffffff808316602483015284166044820152606401610dc8565b5f6114fc7f000000000000000000000000000000000000000000000000000000000000000084611b5c565b90508067ffffffffffffffff168467ffffffffffffffff1610611566576040517f0cb9df3f0000000000000000000000000000000000000000000000000000000081526004810186905267ffffffffffffffff808316602483015285166044820152606401610dc8565b5050505f91825250600260205260409020805467ffffffffffffffff19169055565b5f808351600281111561159d5761159d611cb2565b14801561053357507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16836020015167ffffffffffffffff16426115ea9190611b49565b10151582151514905092915050565b5f8060205f8451602086015f885af180611618576040513d5f823e3d81fd5b50505f513d9150811561162f57806001141561163c565b6001600160a01b0384163b155b1561140e576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610dc8565b5f6020828403121561168e575f80fd5b81356001600160e01b031981168114610533575f80fd5b5f8083601f8401126116b5575f80fd5b50813567ffffffffffffffff8111156116cc575f80fd5b6020830191508360208285010111156116e3575f80fd5b9250929050565b5f80602083850312156116fb575f80fd5b823567ffffffffffffffff811115611711575f80fd5b61171d858286016116a5565b90969095509350505050565b5f60208284031215611739575f80fd5b5035919050565b6001600160a01b0381168114610e7d575f80fd5b67ffffffffffffffff81168114610e7d575f80fd5b5f805f805f805f8060e0898b031215611780575f80fd5b883567ffffffffffffffff811115611796575f80fd5b6117a28b828c016116a5565b90995097505060208901356117b681611740565b95506040890135945060608901356117cd81611740565b935060808901356117dd81611740565b925060a08901356117ed81611754565b8092505060c089013590509295985092959890939650565b5f805f8060608587031215611818575f80fd5b843567ffffffffffffffff81111561182e575f80fd5b61183a878288016116a5565b909550935050602085013561184e81611754565b9150604085013561185e81611740565b939692955090935050565b5f805f805f6080868803121561187d575f80fd5b853567ffffffffffffffff811115611893575f80fd5b61189f888289016116a5565b90965094505060208601356118b381611754565b925060408601356118c381611740565b949793965091946060013592915050565b5f602082840312156118e4575f80fd5b813561053381611740565b5f805f805f805f805f6101008a8c031215611908575f80fd5b893567ffffffffffffffff81111561191e575f80fd5b61192a8c828d016116a5565b909a5098505060208a013561193e81611740565b965060408a0135955060608a013561195581611740565b945060808a013561196581611740565b935060a08a013561197581611754565b925060c08a013561198581611740565b8092505060e08a013590509295985092959850929598565b80516119a881611754565b919050565b80516119a881611740565b5f60a082840312156119c8575f80fd5b60405160a0810181811067ffffffffffffffff821117156119f757634e487b7160e01b5f52604160045260245ffd5b604052825160038110611a08575f80fd5b8152611a166020840161199d565b6020820152611a27604084016119ad565b604082015260608301516060820152608083015160808201528091505092915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60e081525f611a8560e083018a8c611a4a565b6001600160a01b039889166020840152604083019790975250938616606085015291909416608083015267ffffffffffffffff90931660a082015260c0019190915292915050565b608081525f611ae0608083018789611a4a565b67ffffffffffffffff95861660208401529390941660408201526001600160a01b03919091166060909101529392505050565b5f8060408385031215611b24575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561045a5761045a611b35565b67ffffffffffffffff818116838216019080821115611b7d57611b7d611b35565b5092915050565b5f60208284031215611b94575f80fd5b5051919050565b60a081525f611bae60a08301888a611a4a565b67ffffffffffffffff96871660208401529490951660408201526001600160a01b039290921660608301526080909101529392505050565b8082018082111561045a5761045a611b35565b60c081525f611c0c60c08301898b611a4a565b6001600160a01b039788166020840152958716604083015250929094166060830152608082015267ffffffffffffffff90921660a09092019190915292915050565b5f610100808352611c628184018c8e611a4a565b6001600160a01b039a8b166020850152988a1660408401525050948716606086015267ffffffffffffffff939093166080850152941660a083015260c082019390935260e0019190915292915050565b634e487b7160e01b5f52602160045260245ffd5b602081525f61075a602083018486611a4a565b67ffffffffffffffff828116828216039080821115611b7d57611b7d611b3556fea2646970667358221220825c6bc9efe9e1bc07a03f44ccebeb467ab53c3aeb2676ff8f30c5cb4f327ab364736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "27081": [ + { + "length": 32, + "start": 665 + }, + { + "length": 32, + "start": 1126 + }, + { + "length": 32, + "start": 1584 + }, + { + "length": 32, + "start": 2188 + }, + { + "length": 32, + "start": 2370 + }, + { + "length": 32, + "start": 2990 + }, + { + "length": 32, + "start": 3907 + }, + { + "length": 32, + "start": 4666 + } + ], + "27084": [ + { + "length": 32, + "start": 594 + }, + { + "length": 32, + "start": 2082 + }, + { + "length": 32, + "start": 2934 + } + ], + "27543": [ + { + "length": 32, + "start": 943 + }, + { + "length": 32, + "start": 1845 + }, + { + "length": 32, + "start": 4343 + }, + { + "length": 32, + "start": 5543 + } + ], + "27546": [ + { + "length": 32, + "start": 555 + }, + { + "length": 32, + "start": 5185 + } + ], + "27549": [ + { + "length": 32, + "start": 811 + }, + { + "length": 32, + "start": 3416 + }, + { + "length": 32, + "start": 5335 + } + ], + "27552": [ + { + "length": 32, + "start": 904 + }, + { + "length": 32, + "start": 4178 + }, + { + "length": 32, + "start": 4268 + } + ] + }, + "inputSourceName": "project/src/registrar/ETHRegistrar.sol", + "devdoc": { + "errors": { + "CommitmentTooNew(bytes32,uint64,uint64)": [ + { + "details": "Error selector: `0x6be614e3`" + } + ], + "CommitmentTooOld(bytes32,uint64,uint64)": [ + { + "details": "Error selector: `0x0cb9df3f`" + } + ], + "DurationTooShort(uint64,uint64)": [ + { + "details": "Error selector: `0xa096b844`" + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "MaxCommitmentAgeTooLow()": [ + { + "details": "Error selector: `0x3e5aa838`" + } + ], + "NameNotAvailable(string)": [ + { + "details": "Error selector: `0x477707e8`" + } + ], + "NameNotRenewable(string)": [ + { + "details": "Error selector: `0x1caefaa0`" + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ], + "SafeERC20FailedOperation(address)": [ + { + "details": "An operation with an ERC-20 token failed." + } + ], + "UnexpiredCommitmentExists(bytes32)": [ + { + "details": "Error selector: `0x0a059d71`" + } + ] + }, + "events": { + "CommitmentMade(bytes32)": { + "params": { + "commitment": "The commitment hash from `makeCommitment()`." + } + }, + "NameRegistered(uint256,string,address,address,address,uint64,address,bytes32,uint256,uint256)": { + "params": { + "base": "The amount of `paymentToken` for the registration.", + "duration": "The registration duration, in seconds.", + "label": "The name of the registration.", + "owner": "The owner address.", + "paymentToken": "The payment token.", + "premium": "The amount of `paymentToken` due to premium.", + "referrer": "The referrer hash.", + "resolver": "The initial resolver address.", + "subregistry": "The initial registry address.", + "tokenId": "The registry token id." + } + }, + "NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)": { + "params": { + "amount": "The amount of `paymentToken`.", + "duration": "The duration extension, in seconds.", + "label": "The name of the renewal.", + "newExpiry": "The new expiry, in seconds.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash.", + "tokenId": "The registry token id." + } + }, + "RentPriceOracleUpdated(address)": { + "params": { + "oracle": "The new `IRentPriceOracle` contract." + } + } + }, + "kind": "dev", + "methods": { + "commit(bytes32)": { + "details": "Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.", + "params": { + "commitment": "The commitment hash." + } + }, + "constructor": { + "params": { + "beneficiary": "Address that receives payments.", + "ethRegistry": "ENSv2 .eth `PermissionedRegistry`.", + "gracePeriod": "Post-expiry period where still renewable and not available, in seconds.", + "maxCommitmentAge": "Maximum seconds a commitment remains valid; expired commitments are rejected.", + "minCommitmentAge": "Minimum seconds a commitment must age before registration can proceed.", + "minRegisterDuration": "Minimum register duration, in seconds.", + "oracle": "Initial oracle for registration and renewal costs.", + "owner_": "Contract owner." + } + }, + "getRegisterPrice(string,uint64,address)": { + "params": { + "duration": "The registration duration, in seconds.", + "label": "The name to register.", + "paymentToken": "The payment token." + }, + "returns": { + "base": "The amount of `paymentToken` for registration.", + "premium": "The amount of `paymentToken` due to premium." + } + }, + "getRemainingGracePeriod(string)": { + "details": "Defined over `[expiry, expiry + GRACE_PERIOD)`.", + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "The remaining grace period, in seconds." + } + }, + "getRenewPrice(string,uint64,address)": { + "params": { + "duration": "The duration extension, in seconds.", + "label": "The name to renew.", + "paymentToken": "The payment token." + }, + "returns": { + "_0": "The amount of `paymentToken`." + } + }, + "isAvailable(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "`true` if registerable." + } + }, + "isRenewable(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "`true` if renewable." + } + }, + "makeCommitment(string,address,bytes32,address,address,uint64,bytes32)": { + "params": { + "duration": "The registration duration, in seconds.", + "label": "The name to register.", + "owner": "The owner address.", + "referrer": "The referrer hash.", + "resolver": "The initial resolver address.", + "secret": "The secret for the registration.", + "subregistry": "The initial registry address." + }, + "returns": { + "_0": "The commitment hash." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "register(string,address,bytes32,address,address,uint64,address,bytes32)": { + "params": { + "duration": "The registration from commitment.", + "label": "The name from commitment.", + "owner": "The owner from commitment.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash.", + "resolver": "The resolver from commitment.", + "secret": "The secret from commitment.", + "subregistry": "The registry from commitment." + }, + "returns": { + "tokenId": "The registered token ID." + } + }, + "renew(string,uint64,address,bytes32)": { + "params": { + "duration": "The duration extension, in seconds.", + "label": "The name to renew.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash." + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setRentPriceOracle(address)": { + "params": { + "oracle": "The new `IRentPriceOracle` instance." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "stateVariables": { + "MIN_COMMITMENT_AGE": { + "details": "If zero, front-running protection is disabled." + }, + "commitmentAt": { + "params": { + "commitment": "The commitment hash." + }, + "return": "commitTime The commitment time, in seconds, or 0 if unknown.", + "returns": { + "commitTime": "The commitment time, in seconds, or 0 if unknown." + } + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1494400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BENEFICIARY()": "infinite", + "ETH_REGISTRY()": "infinite", + "GRACE_PERIOD()": "infinite", + "MAX_COMMITMENT_AGE()": "infinite", + "MIN_COMMITMENT_AGE()": "infinite", + "MIN_REGISTER_DURATION()": "infinite", + "MIN_RENEW_DURATION()": "271", + "commit(bytes32)": "infinite", + "commitmentAt(bytes32)": "2496", + "getRegisterPrice(string,uint64,address)": "infinite", + "getRemainingGracePeriod(string)": "infinite", + "getRenewPrice(string,uint64,address)": "infinite", + "isAvailable(string)": "infinite", + "isRenewable(string)": "infinite", + "makeCommitment(string,address,bytes32,address,address,uint64,bytes32)": "infinite", + "owner()": "2374", + "register(string,address,bytes32,address,address,uint64,address,bytes32)": "infinite", + "renew(string,uint64,address,bytes32)": "infinite", + "renounceOwnership()": "infinite", + "rentPriceOracle()": "2425", + "setRentPriceOracle(address)": "27857", + "supportsInterface(bytes4)": "infinite", + "transferOwnership(address)": "infinite" + }, + "internal": { + "_availablePeriod(uint64)": "infinite", + "_checkGrace(struct IPermissionedRegistry.State memory,bool)": "infinite", + "_consumeCommitment(bytes32)": "infinite", + "_isAvailable(struct IPermissionedRegistry.State memory)": "infinite", + "_isRenewable(struct IPermissionedRegistry.State memory)": "infinite", + "_isRenewableGrace(struct IPermissionedRegistry.State memory)": "infinite", + "_requireAvailable(string calldata,uint64)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"gracePeriod\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minCommitmentAge\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxCommitmentAge\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minRegisterDuration\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"validFrom\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"blockTimestamp\",\"type\":\"uint64\"}],\"name\":\"CommitmentTooNew\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"validTo\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"blockTimestamp\",\"type\":\"uint64\"}],\"name\":\"CommitmentTooOld\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minDuration\",\"type\":\"uint64\"}],\"name\":\"DurationTooShort\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxCommitmentAgeTooLow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"NameNotAvailable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"NameNotRenewable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"}],\"name\":\"UnexpiredCommitmentExists\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"}],\"name\":\"CommitmentMade\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"base\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"premium\",\"type\":\"uint256\"}],\"name\":\"NameRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NameRenewed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"RentPriceOracleUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BENEFICIARY\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GRACE_PERIOD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_COMMITMENT_AGE\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_COMMITMENT_AGE\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_REGISTER_DURATION\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_RENEW_DURATION\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"commitment\",\"type\":\"bytes32\"}],\"name\":\"commitmentAt\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"commitTime\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRegisterPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"base\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"premium\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getRemainingGracePeriod\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRenewPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"isAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"isRenewable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"secret\",\"type\":\"bytes32\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"makeCommitment\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"secret\",\"type\":\"bytes32\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rentPriceOracle\",\"outputs\":[{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"setRentPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CommitmentTooNew(bytes32,uint64,uint64)\":[{\"details\":\"Error selector: `0x6be614e3`\"}],\"CommitmentTooOld(bytes32,uint64,uint64)\":[{\"details\":\"Error selector: `0x0cb9df3f`\"}],\"DurationTooShort(uint64,uint64)\":[{\"details\":\"Error selector: `0xa096b844`\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"MaxCommitmentAgeTooLow()\":[{\"details\":\"Error selector: `0x3e5aa838`\"}],\"NameNotAvailable(string)\":[{\"details\":\"Error selector: `0x477707e8`\"}],\"NameNotRenewable(string)\":[{\"details\":\"Error selector: `0x1caefaa0`\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}],\"UnexpiredCommitmentExists(bytes32)\":[{\"details\":\"Error selector: `0x0a059d71`\"}]},\"events\":{\"CommitmentMade(bytes32)\":{\"params\":{\"commitment\":\"The commitment hash from `makeCommitment()`.\"}},\"NameRegistered(uint256,string,address,address,address,uint64,address,bytes32,uint256,uint256)\":{\"params\":{\"base\":\"The amount of `paymentToken` for the registration.\",\"duration\":\"The registration duration, in seconds.\",\"label\":\"The name of the registration.\",\"owner\":\"The owner address.\",\"paymentToken\":\"The payment token.\",\"premium\":\"The amount of `paymentToken` due to premium.\",\"referrer\":\"The referrer hash.\",\"resolver\":\"The initial resolver address.\",\"subregistry\":\"The initial registry address.\",\"tokenId\":\"The registry token id.\"}},\"NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)\":{\"params\":{\"amount\":\"The amount of `paymentToken`.\",\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name of the renewal.\",\"newExpiry\":\"The new expiry, in seconds.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\",\"tokenId\":\"The registry token id.\"}},\"RentPriceOracleUpdated(address)\":{\"params\":{\"oracle\":\"The new `IRentPriceOracle` contract.\"}}},\"kind\":\"dev\",\"methods\":{\"commit(bytes32)\":{\"details\":\"Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.\",\"params\":{\"commitment\":\"The commitment hash.\"}},\"constructor\":{\"params\":{\"beneficiary\":\"Address that receives payments.\",\"ethRegistry\":\"ENSv2 .eth `PermissionedRegistry`.\",\"gracePeriod\":\"Post-expiry period where still renewable and not available, in seconds.\",\"maxCommitmentAge\":\"Maximum seconds a commitment remains valid; expired commitments are rejected.\",\"minCommitmentAge\":\"Minimum seconds a commitment must age before registration can proceed.\",\"minRegisterDuration\":\"Minimum register duration, in seconds.\",\"oracle\":\"Initial oracle for registration and renewal costs.\",\"owner_\":\"Contract owner.\"}},\"getRegisterPrice(string,uint64,address)\":{\"params\":{\"duration\":\"The registration duration, in seconds.\",\"label\":\"The name to register.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"base\":\"The amount of `paymentToken` for registration.\",\"premium\":\"The amount of `paymentToken` due to premium.\"}},\"getRemainingGracePeriod(string)\":{\"details\":\"Defined over `[expiry, expiry + GRACE_PERIOD)`.\",\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"The remaining grace period, in seconds.\"}},\"getRenewPrice(string,uint64,address)\":{\"params\":{\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name to renew.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"_0\":\"The amount of `paymentToken`.\"}},\"isAvailable(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"`true` if registerable.\"}},\"isRenewable(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"`true` if renewable.\"}},\"makeCommitment(string,address,bytes32,address,address,uint64,bytes32)\":{\"params\":{\"duration\":\"The registration duration, in seconds.\",\"label\":\"The name to register.\",\"owner\":\"The owner address.\",\"referrer\":\"The referrer hash.\",\"resolver\":\"The initial resolver address.\",\"secret\":\"The secret for the registration.\",\"subregistry\":\"The initial registry address.\"},\"returns\":{\"_0\":\"The commitment hash.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"register(string,address,bytes32,address,address,uint64,address,bytes32)\":{\"params\":{\"duration\":\"The registration from commitment.\",\"label\":\"The name from commitment.\",\"owner\":\"The owner from commitment.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\",\"resolver\":\"The resolver from commitment.\",\"secret\":\"The secret from commitment.\",\"subregistry\":\"The registry from commitment.\"},\"returns\":{\"tokenId\":\"The registered token ID.\"}},\"renew(string,uint64,address,bytes32)\":{\"params\":{\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name to renew.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setRentPriceOracle(address)\":{\"params\":{\"oracle\":\"The new `IRentPriceOracle` instance.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"stateVariables\":{\"MIN_COMMITMENT_AGE\":{\"details\":\"If zero, front-running protection is disabled.\"},\"commitmentAt\":{\"params\":{\"commitment\":\"The commitment hash.\"},\"return\":\"commitTime The commitment time, in seconds, or 0 if unknown.\",\"returns\":{\"commitTime\":\"The commitment time, in seconds, or 0 if unknown.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"CommitmentTooNew(bytes32,uint64,uint64)\":[{\"notice\":\"`commitment` cannot be consumed yet.\"}],\"CommitmentTooOld(bytes32,uint64,uint64)\":[{\"notice\":\"`commitment` has expired.\"}],\"DurationTooShort(uint64,uint64)\":[{\"notice\":\"`duration` less than `minDuration`.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"MaxCommitmentAgeTooLow()\":[{\"notice\":\"`maxCommitmentAge` was not greater than `minCommitmentAge`.\"}],\"NameNotAvailable(string)\":[{\"notice\":\"`label` cannot be registered.\"}],\"NameNotRenewable(string)\":[{\"notice\":\"`label` cannot be renewed.\"}],\"UnexpiredCommitmentExists(bytes32)\":[{\"notice\":\"`commitment` is still usable for registration.\"}]},\"events\":{\"CommitmentMade(bytes32)\":{\"notice\":\"`commitment` was recorded onchain at `block.timestamp`.\"},\"NameRegistered(uint256,string,address,address,address,uint64,address,bytes32,uint256,uint256)\":{\"notice\":\"A name was registered.\"},\"NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)\":{\"notice\":\"A name was extended by `duration`.\"},\"RentPriceOracleUpdated(address)\":{\"notice\":\"`IRentPriceOracle` was replaced.\"}},\"kind\":\"user\",\"methods\":{\"BENEFICIARY()\":{\"notice\":\"Address that receives payments.\"},\"ETH_REGISTRY()\":{\"notice\":\"ENSv2 .eth `PermissionedRegistry`.\"},\"GRACE_PERIOD()\":{\"notice\":\"Post-expiry period where still renewable and not available, in seconds.\"},\"MAX_COMMITMENT_AGE()\":{\"notice\":\"Maximum seconds a commitment remains valid; expired commitments are rejected.\"},\"MIN_COMMITMENT_AGE()\":{\"notice\":\"Minimum seconds a commitment must age before registration can proceed.\"},\"MIN_REGISTER_DURATION()\":{\"notice\":\"Minimum register duration, in seconds.\"},\"MIN_RENEW_DURATION()\":{\"notice\":\"Minimum renew duration, in seconds.\"},\"commit(bytes32)\":{\"notice\":\"Registration step #1: record intent to register without revealing any information.\"},\"commitmentAt(bytes32)\":{\"notice\":\"Get timestamp of a prior commitment.\"},\"getRegisterPrice(string,uint64,address)\":{\"notice\":\"Determine register price for a name.\"},\"getRemainingGracePeriod(string)\":{\"notice\":\"Determine remaining grace period.\"},\"getRenewPrice(string,uint64,address)\":{\"notice\":\"Determine renew price for a name.\"},\"isAvailable(string)\":{\"notice\":\"Check if name is available.\"},\"isRenewable(string)\":{\"notice\":\"Check if name is renewable.\"},\"makeCommitment(string,address,bytes32,address,address,uint64,bytes32)\":{\"notice\":\"Compute hash of registration parameters.\"},\"register(string,address,bytes32,address,address,uint64,address,bytes32)\":{\"notice\":\"Register a name.\"},\"renew(string,uint64,address,bytes32)\":{\"notice\":\"Renew a name.\"},\"rentPriceOracle()\":{\"notice\":\"Oracle for registration and renewal costs.\"},\"setRentPriceOracle(address)\":{\"notice\":\"Change the rent price oracle.\"}},\"notice\":\"Commit-reveal registrar for .eth names. Registration requires two transactions: first `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment age but before the maximum commitment age has elapsed. The commitment hash binds all registration parameters (label, owner, secret, subregistry, resolver, duration, referrer) to prevent front-running. Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed set of roles (set subregistry, set resolver, and transfer \\u2014 each with their admin counterpart). Pricing and payment are delegated to a swappable `IRentPriceOracle`.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/ETHRegistrar.sol\":\"ETHRegistrar\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n /*\\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n * 0xb0202a11 ===\\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n */\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @param data Additional data with no specified format, sent in call to `spender`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\",\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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 /**\\n * @dev An operation with an ERC-20 token failed.\\n */\\n error SafeERC20FailedOperation(address token);\\n\\n /**\\n * @dev Indicates a failed `decreaseAllowance` request.\\n */\\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n forceApprove(token, spender, oldAllowance + value);\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n * value, non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n unchecked {\\n uint256 currentAllowance = token.allowance(address(this), spender);\\n if (currentAllowance < requestedDecrease) {\\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n }\\n forceApprove(token, spender, currentAllowance - requestedDecrease);\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n *\\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n * set here.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n safeTransfer(token, to, value);\\n } else if (!token.transferAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferFromAndCallRelaxed(\\n IERC1363 token,\\n address from,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length == 0) {\\n safeTransferFrom(token, from, to, value);\\n } else if (!token.transferFromAndCall(from, to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n * once without retrying, and relies on the returned value to be true.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n forceApprove(token, to, value);\\n } else if (!token.approveAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n // bubble errors\\n if iszero(success) {\\n let ptr := mload(0x40)\\n returndatacopy(ptr, 0, returndatasize())\\n revert(ptr, returndatasize())\\n }\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n\\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\n }\\n}\\n\",\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`.\\nabstract contract AbstractETHRegistrar is Ownable, ERC165, IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Minimum renew duration, in seconds.\\n uint64 public constant MIN_RENEW_DURATION = 1;\\n\\n /// @notice ENSv2 .eth `PermissionedRegistry`.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice Address that receives payments.\\n address public immutable BENEFICIARY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Oracle for registration and renewal costs.\\n IRentPriceOracle public rentPriceOracle;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `IRentPriceOracle` was replaced.\\n /// @param oracle The new `IRentPriceOracle` contract.\\n event RentPriceOracleUpdated(IRentPriceOracle oracle);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n constructor(\\n address owner_,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle\\n )\\n Ownable(owner_)\\n {\\n ETH_REGISTRY = ethRegistry;\\n BENEFICIARY = beneficiary;\\n\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Change the rent price oracle.\\n /// @param oracle The new `IRentPriceOracle` instance.\\n function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner {\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external\\n {\\n IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not\\n uint64 newExpiry = state.expiry + duration; // reverts if overflow\\n uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, amount); // reverts if payment failed\\n ETH_REGISTRY.renew(state.tokenId, newExpiry);\\n _onRenew(label, duration);\\n emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function isRenewable(string calldata label) external view returns (bool) {\\n return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n public\\n view\\n returns (uint256)\\n {\\n return\\n rentPriceOracle.getRenewPrice(\\n label,\\n _requireRenewable(label, duration).expiry,\\n duration,\\n paymentToken\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Callback for when a name is renewed.\\n function _onRenew(string calldata label, uint64 duration) internal virtual {}\\n\\n /// @dev Returns whether the name is renewable by this contract.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n virtual\\n returns (bool);\\n\\n /// @dev Ensure name is renewable.\\n function _requireRenewable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isRenewable(state)) {\\n revert NameNotRenewable(label);\\n }\\n if (duration < MIN_RENEW_DURATION) {\\n revert DurationTooShort(duration, MIN_RENEW_DURATION);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x03c6381eaa4b6f36c842a32396b8f9a5a573a4257d7a9d263e77c015486a9458\",\"license\":\"MIT\"},\"project/src/registrar/ETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"../registry/libraries/RegistryRolesLib.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {AbstractETHRegistrar} from \\\"./AbstractETHRegistrar.sol\\\";\\nimport {IETHRegistrar} from \\\"./interfaces/IETHRegistrar.sol\\\";\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Roles assigned to owners at registration. Includes set-subregistry, set-resolver, and can-transfer (with admin variants).\\nuint256 constant REGISTRATION_ROLE_BITMAP =\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY |\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN |\\n RegistryRolesLib.ROLE_SET_RESOLVER |\\n RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN |\\n RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN;\\n\\n/// @notice Commit-reveal registrar for .eth names. Registration requires two transactions: first\\n/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment\\n/// age but before the maximum commitment age has elapsed. The commitment hash binds all\\n/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer)\\n/// to prevent front-running.\\n///\\n/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed\\n/// set of roles (set subregistry, set resolver, and transfer \\u2014 each with their admin\\n/// counterpart).\\n///\\n/// Pricing and payment are delegated to a swappable `IRentPriceOracle`.\\n///\\ncontract ETHRegistrar is AbstractETHRegistrar, IETHRegistrar {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRenewer\\n uint64 public immutable GRACE_PERIOD;\\n\\n /// @notice Minimum seconds a commitment must age before registration can proceed.\\n /// @dev If zero, front-running protection is disabled.\\n uint64 public immutable MIN_COMMITMENT_AGE;\\n\\n /// @notice Maximum seconds a commitment remains valid; expired commitments are rejected.\\n uint64 public immutable MAX_COMMITMENT_AGE;\\n\\n /// @notice Minimum register duration, in seconds.\\n uint64 public immutable MIN_REGISTER_DURATION;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n mapping(bytes32 commitment => uint64 commitTime) public commitmentAt;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`.\\n /// @dev Error selector: `0x3e5aa838`\\n error MaxCommitmentAgeTooLow();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n /// @param gracePeriod Post-expiry period where still renewable and not available, in seconds.\\n /// @param minCommitmentAge Minimum seconds a commitment must age before registration can proceed.\\n /// @param maxCommitmentAge Maximum seconds a commitment remains valid; expired commitments are rejected.\\n /// @param minRegisterDuration Minimum register duration, in seconds.\\n constructor(\\n address owner_,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle,\\n uint64 gracePeriod,\\n uint64 minCommitmentAge,\\n uint64 maxCommitmentAge,\\n uint64 minRegisterDuration\\n )\\n AbstractETHRegistrar(owner_, ethRegistry, beneficiary, oracle)\\n {\\n if (maxCommitmentAge <= minCommitmentAge) {\\n revert MaxCommitmentAgeTooLow();\\n }\\n GRACE_PERIOD = gracePeriod;\\n MIN_COMMITMENT_AGE = minCommitmentAge;\\n MAX_COMMITMENT_AGE = maxCommitmentAge;\\n MIN_REGISTER_DURATION = minRegisterDuration;\\n }\\n\\n /// @inheritdoc AbstractETHRegistrar\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return\\n interfaceId == type(IETHRegistrar).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n function commit(bytes32 commitment) external {\\n if (commitmentAt[commitment] + MAX_COMMITMENT_AGE > block.timestamp) {\\n revert UnexpiredCommitmentExists(commitment);\\n }\\n commitmentAt[commitment] = uint64(block.timestamp);\\n emit CommitmentMade(commitment);\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function register(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256 tokenId)\\n {\\n if (owner == address(0)) {\\n revert InvalidOwner();\\n }\\n _consumeCommitment(\\n makeCommitment(label, owner, secret, subregistry, resolver, duration, referrer)\\n ); // reverts if no commitment\\n IPermissionedRegistry.State memory state = _requireAvailable(label, duration); // reverts if not\\n (uint256 base, uint256 premium) =\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(state.expiry),\\n duration,\\n paymentToken\\n ); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, base + premium); // reverts if payment failed\\n tokenId = ETH_REGISTRY.register(\\n label,\\n owner,\\n subregistry,\\n resolver,\\n REGISTRATION_ROLE_BITMAP,\\n uint64(block.timestamp) + duration // new expiry\\n ); // should not revert\\n emit NameRegistered(\\n tokenId,\\n label,\\n owner,\\n subregistry,\\n resolver,\\n duration,\\n paymentToken,\\n referrer,\\n base,\\n premium\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function isAvailable(string calldata label) external view returns (bool) {\\n return _isAvailable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium)\\n {\\n return\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(_requireAvailable(label, duration).expiry),\\n duration,\\n paymentToken\\n );\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n return\\n uint64(\\n _isRenewableGrace(state)\\n ? GRACE_PERIOD - (block.timestamp - state.expiry)\\n : 0\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n public\\n pure\\n override\\n returns (bytes32)\\n {\\n return\\n keccak256(abi.encode(label, owner, secret, subregistry, resolver, duration, referrer));\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates that the given `commitment` was recorded within the allowed time window\\n /// (between minimum and maximum commitment age), then deletes it so it cannot be reused.\\n /// @param commitment The commitment hash to validate and consume.\\n function _consumeCommitment(bytes32 commitment) internal {\\n uint64 t = uint64(block.timestamp);\\n uint64 t0 = commitmentAt[commitment];\\n uint64 tMin = t0 + MIN_COMMITMENT_AGE;\\n if (t < tMin) {\\n revert CommitmentTooNew(commitment, tMin, t);\\n }\\n uint64 tMax = t0 + MAX_COMMITMENT_AGE;\\n if (t >= tMax) {\\n revert CommitmentTooOld(commitment, tMax, t);\\n }\\n delete commitmentAt[commitment];\\n }\\n\\n /// @dev Ensure name is registerable.\\n function _requireAvailable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isAvailable(state)) {\\n revert NameNotAvailable(label);\\n }\\n if (duration < MIN_REGISTER_DURATION) {\\n revert DurationTooShort(duration, MIN_REGISTER_DURATION);\\n }\\n }\\n\\n /// @dev Determine if `AVAILABLE` and not in grace.\\n function _isAvailable(IPermissionedRegistry.State memory state) internal view returns (bool) {\\n return _checkGrace(state, false);\\n }\\n\\n /// @dev Determine if `REGISTERED` or in grace was `REGISTERED`.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n override\\n returns (bool)\\n {\\n return state.status == IPermissionedRegistry.Status.REGISTERED || _isRenewableGrace(state);\\n }\\n\\n /// @dev Determine if was `REGISTERED` and in grace.\\n function _isRenewableGrace(IPermissionedRegistry.State memory state)\\n internal\\n view\\n returns (bool)\\n {\\n return state.latestOwner != address(0) && _checkGrace(state, true);\\n }\\n\\n /// @dev Check if `AVAILABLE` and conditionally in grace.\\n function _checkGrace(IPermissionedRegistry.State memory state, bool grace)\\n internal\\n view\\n returns (bool)\\n {\\n return\\n state.status == IPermissionedRegistry.Status.AVAILABLE &&\\n (grace == (block.timestamp - state.expiry) < GRACE_PERIOD);\\n }\\n\\n /// @dev Determine duration name has been available.\\n function _availablePeriod(uint64 expiry) internal view returns (uint64) {\\n uint64 t = uint64(block.timestamp);\\n if (expiry == 0) {\\n return t; // never registered\\n }\\n expiry += GRACE_PERIOD;\\n return t > expiry ? t - expiry : 0;\\n }\\n}\\n\",\"keccak256\":\"0x601a5929b1b2eba60dd566dd6967c3dba1a471d6b24ffe292f4aa660af1cd5f1\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./IETHRenewer.sol\\\";\\n\\n/// @notice Interface for registering \\\".eth\\\" names.\\n/// @dev Interface selector: `0xc1401b80`\\ninterface IETHRegistrar is IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` was recorded onchain at `block.timestamp`.\\n /// @param commitment The commitment hash from `makeCommitment()`.\\n event CommitmentMade(bytes32 commitment);\\n\\n /// @notice A name was registered.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the registration.\\n /// @param owner The owner address.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param base The amount of `paymentToken` for the registration.\\n /// @param premium The amount of `paymentToken` due to premium.\\n event NameRegistered(\\n uint256 indexed tokenId,\\n string label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 base,\\n uint256 premium\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` is still usable for registration.\\n /// @dev Error selector: `0x0a059d71`\\n error UnexpiredCommitmentExists(bytes32 commitment);\\n\\n /// @notice `commitment` cannot be consumed yet.\\n /// @dev Error selector: `0x6be614e3`\\n error CommitmentTooNew(bytes32 commitment, uint64 validFrom, uint64 blockTimestamp);\\n\\n /// @notice `commitment` has expired.\\n /// @dev Error selector: `0x0cb9df3f`\\n error CommitmentTooOld(bytes32 commitment, uint64 validTo, uint64 blockTimestamp);\\n\\n /// @notice `label` cannot be registered.\\n /// @dev Error selector: `0x477707e8`\\n error NameNotAvailable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registration step #1: record intent to register without revealing any information.\\n /// @dev Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.\\n /// @param commitment The commitment hash.\\n function commit(bytes32 commitment) external;\\n\\n /// @notice Register a name.\\n /// @param label The name from commitment.\\n /// @param owner The owner from commitment.\\n /// @param secret The secret from commitment.\\n /// @param subregistry The registry from commitment.\\n /// @param resolver The resolver from commitment.\\n /// @param duration The registration from commitment.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @return The registered token ID.\\n function register(\\n string memory label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256);\\n\\n /// @notice Get timestamp of a prior commitment.\\n /// @param commitment The commitment hash.\\n /// @return The commitment time, in seconds, or 0 if unknown.\\n function commitmentAt(bytes32 commitment) external view returns (uint64);\\n\\n /// @notice Determine register price for a name.\\n /// @param label The name to register.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Check if name is available.\\n /// @param label The name to check.\\n /// @return `true` if registerable.\\n function isAvailable(string memory label) external view returns (bool);\\n\\n /// @notice Compute hash of registration parameters.\\n /// @param label The name to register.\\n /// @param owner The owner address.\\n /// @param secret The secret for the registration.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param referrer The referrer hash.\\n /// @return The commitment hash.\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n external\\n pure\\n returns (bytes32);\\n}\\n\",\"keccak256\":\"0x7e824c5019f8eb7d7a283451700234716353e01d649c811b5ced5cf58b476289\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for renewing \\\".eth\\\" names.\\n/// @dev Interface selector: `0x06aaeb32`\\ninterface IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A name was extended by `duration`.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the renewal.\\n /// @param duration The duration extension, in seconds.\\n /// @param newExpiry The new expiry, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param amount The amount of `paymentToken`.\\n event NameRenewed(\\n uint256 indexed tokenId,\\n string label,\\n uint64 duration,\\n uint64 newExpiry,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 amount\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `duration` less than `minDuration`.\\n /// @dev Error selector: `0xa096b844`\\n error DurationTooShort(uint64 duration, uint64 minDuration);\\n\\n /// @notice `label` cannot be renewed.\\n /// @dev Error selector: `0x1caefaa0`\\n error NameNotRenewable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Renew a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external;\\n\\n /// @notice Determine renew price for a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice Check if name is renewable.\\n /// @param label The name to check.\\n /// @return `true` if renewable.\\n function isRenewable(string calldata label) external view returns (bool);\\n\\n /// @notice Determine remaining grace period.\\n /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`.\\n /// @param label The name to check.\\n /// @return The remaining grace period, in seconds.\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64);\\n\\n /// @notice Post-expiry period where still renewable and not available, in seconds.\\n function GRACE_PERIOD() external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 39: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 62: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x01771816c1c5b16c10f29b33083dbd1cc2eb64dbfec60fb45a1a1969cec06624\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 14920, + "contract": "project/src/registrar/ETHRegistrar.sol:ETHRegistrar", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 27088, + "contract": "project/src/registrar/ETHRegistrar.sol:ETHRegistrar", + "label": "rentPriceOracle", + "offset": 0, + "slot": "1", + "type": "t_contract(IRentPriceOracle)28752" + }, + { + "astId": 27557, + "contract": "project/src/registrar/ETHRegistrar.sol:ETHRegistrar", + "label": "commitmentAt", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_uint64)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRentPriceOracle)28752": { + "encoding": "inplace", + "label": "contract IRentPriceOracle", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint64)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint64)", + "numberOfBytes": "32", + "value": "t_uint64" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CommitmentTooNew(bytes32,uint64,uint64)": [ + { + "notice": "`commitment` cannot be consumed yet." + } + ], + "CommitmentTooOld(bytes32,uint64,uint64)": [ + { + "notice": "`commitment` has expired." + } + ], + "DurationTooShort(uint64,uint64)": [ + { + "notice": "`duration` less than `minDuration`." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "MaxCommitmentAgeTooLow()": [ + { + "notice": "`maxCommitmentAge` was not greater than `minCommitmentAge`." + } + ], + "NameNotAvailable(string)": [ + { + "notice": "`label` cannot be registered." + } + ], + "NameNotRenewable(string)": [ + { + "notice": "`label` cannot be renewed." + } + ], + "UnexpiredCommitmentExists(bytes32)": [ + { + "notice": "`commitment` is still usable for registration." + } + ] + }, + "events": { + "CommitmentMade(bytes32)": { + "notice": "`commitment` was recorded onchain at `block.timestamp`." + }, + "NameRegistered(uint256,string,address,address,address,uint64,address,bytes32,uint256,uint256)": { + "notice": "A name was registered." + }, + "NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)": { + "notice": "A name was extended by `duration`." + }, + "RentPriceOracleUpdated(address)": { + "notice": "`IRentPriceOracle` was replaced." + } + }, + "kind": "user", + "methods": { + "BENEFICIARY()": { + "notice": "Address that receives payments." + }, + "ETH_REGISTRY()": { + "notice": "ENSv2 .eth `PermissionedRegistry`." + }, + "GRACE_PERIOD()": { + "notice": "Post-expiry period where still renewable and not available, in seconds." + }, + "MAX_COMMITMENT_AGE()": { + "notice": "Maximum seconds a commitment remains valid; expired commitments are rejected." + }, + "MIN_COMMITMENT_AGE()": { + "notice": "Minimum seconds a commitment must age before registration can proceed." + }, + "MIN_REGISTER_DURATION()": { + "notice": "Minimum register duration, in seconds." + }, + "MIN_RENEW_DURATION()": { + "notice": "Minimum renew duration, in seconds." + }, + "commit(bytes32)": { + "notice": "Registration step #1: record intent to register without revealing any information." + }, + "commitmentAt(bytes32)": { + "notice": "Get timestamp of a prior commitment." + }, + "getRegisterPrice(string,uint64,address)": { + "notice": "Determine register price for a name." + }, + "getRemainingGracePeriod(string)": { + "notice": "Determine remaining grace period." + }, + "getRenewPrice(string,uint64,address)": { + "notice": "Determine renew price for a name." + }, + "isAvailable(string)": { + "notice": "Check if name is available." + }, + "isRenewable(string)": { + "notice": "Check if name is renewable." + }, + "makeCommitment(string,address,bytes32,address,address,uint64,bytes32)": { + "notice": "Compute hash of registration parameters." + }, + "register(string,address,bytes32,address,address,uint64,address,bytes32)": { + "notice": "Register a name." + }, + "renew(string,uint64,address,bytes32)": { + "notice": "Renew a name." + }, + "rentPriceOracle()": { + "notice": "Oracle for registration and renewal costs." + }, + "setRentPriceOracle(address)": { + "notice": "Change the rent price oracle." + } + }, + "notice": "Commit-reveal registrar for .eth names. Registration requires two transactions: first `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment age but before the maximum commitment age has elapsed. The commitment hash binds all registration parameters (label, owner, secret, subregistry, resolver, duration, referrer) to prevent front-running. Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed set of roles (set subregistry, set resolver, and transfer — each with their admin counterpart). Pricing and payment are delegated to a swappable `IRentPriceOracle`.", + "version": 1 + }, + "argsData": "0x00000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d300000000000000000000000067b728a792e789a8978b30cf1b3b641f19354b4300000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d300000000000000000000000009340d50a6489e7bfb2959acc4e32bcbc401e203000000000000000000000000000000000000000000000000000000000024ea00000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000024ea00", + "transaction": { + "hash": "0xe7b8e54740a49a0ff12a299bb3b8ef53bee64444a86b0d04862bbb4606070a31", + "nonce": "0x57", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xf9bc7c6e1fd43cc1728acaa869c72a9dc5dc08a4802e3e5dd42674833aad04d4", + "blockNumber": "0xaa570b", + "transactionIndex": "0x89" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ETHRegistry.json b/contracts/deployments/sepolia/ETHRegistry.json new file mode 100644 index 000000000..0f64ba039 --- /dev/null +++ b/contracts/deployments/sepolia/ETHRegistry.json @@ -0,0 +1,2795 @@ +{ + "address": "0x67b728a792e789a8978b30cf1b3b641f19354b43", + "abi": [ + { + "inputs": [ + { + "internalType": "contract ILabelStore", + "name": "labelStore", + "type": "address" + }, + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "oldExpiry", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "CannotReduceExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "CannotSetPastExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "LabelExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "TransferDisallowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExpiryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ParentUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RegistryCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ResolverUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SubregistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTokenId", + "type": "uint256" + } + ], + "name": "TokenRegenerated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "TokenResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "renderer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "URIUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "LABEL_STORE", + "outputs": [ + { + "internalType": "contract ILabelStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParent", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getResource", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "internalType": "address", + "name": "latestOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "internalType": "struct IPermissionedRegistry.State", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getStatus", + "outputs": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getSubregistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "latestOwnerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setParent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "setSubregistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + }, + { + "internalType": "contract IRegistryURIRenderer", + "name": "renderer", + "type": "address" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "PermissionedRegistry", + "sourceName": "src/registry/PermissionedRegistry.sol", + "bytecode": "0x60a060405234801561000f575f80fd5b5060405161490d38038061490d83398101604081905261002e91610d06565b6040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16001600160a01b03831660805261006f5f828482610078565b50505050610f37565b5f835f0361008757505f610182565b6100908461018a565b6001600160a01b0383166100b75760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461017c575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616610117888260016101d6565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561017057610170888785858b610306565b60019350505050610182565b5f925050505b949350505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156101d357604051630153d96960e51b8152600481018290526024015b60405180910390fd5b50565b5f6101e083610316565b90508115610276575f848152600360205260409020546102269082161980195f805160206148ed83398151915291909101165f805160206148cd83398151915216151590565b1561024e57604051631f22ca6960e31b815260048101859052602481018490526044016101ca565b5f848152600360205260408120805485929061026b908490610d5a565b909155506103009050565b5f848152600360205260409020546102b5901982161980195f805160206148ed83398151915291909101165f805160206148cd83398151915216151590565b156102dd57604051631f80c19b60e01b815260048101859052602481018490526044016101ca565b5f84815260036020526040812080548592906102fa908490610d6d565b90915550505b50505050565b61030f85610330565b5050505050565b5f6103208261018a565b50600181901b17600281901b1790565b80156101d35763ffffffff811681185f9081526101086020526040812090610358838361041c565b5f818152602081905260409020549091506001600160a01b031661037e8183600161043f565b8254839060049061039c90640100000000900463ffffffff16610d80565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6103cb838561041c60201b60201c565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a361030f8282600160405180602001604052805f8152506104a660201b60201c565b80545f9063ffffffff808516851864010000000090920416185b90505b92915050565b6001600160a01b03831661046757604051626a0d4560e21b81525f60048201526024016101ca565b604080516001808252602082018590528183019081526060820184905260a082019092525f6080820181815291929161030f918791859085908361051b565b6001600160a01b0384166104cf57604051632bfa23e760e11b81525f60048201526024016101ca565b604080516001808252602082018690528183019081526060820185905260808201909252906105025f878484878461051b565b505050505050565b63ffffffff82811690921891161890565b61052786868686610571565b6001600160a01b0385161561050257801561054f5761054a33878787878761064c565b610502565b60208481015190840151610567338989858589610776565b5050505050505050565b61057d8484848461085d565b6001600160a01b0383161580159061059d57506001600160a01b03841615155b15610300575f5b825181101561030f575f8382815181106105c0576105c0610da2565b602002602001015190506105df816001609c1b88610a4360201b60201c565b61060e576040516372c7b6ad60e11b8152600481018290526001600160a01b03871660248201526044016101ca565b5f83838151811061062157610621610da2565b602002602001015111156106435761064361063b82610a57565b87875f610a7e565b506001016105a4565b6001600160a01b0384163b156105025760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906106909089908990889088908890600401610e1e565b6020604051808303815f875af19250505080156106ca575060408051601f3d908101601f191682019092526106c791810190610e7b565b60015b610731573d8080156106f7576040519150601f19603f3d011682016040523d82523d5f602084013e6106fc565b606091505b5080515f0361072957604051632bfa23e760e11b81526001600160a01b03861660048201526024016101ca565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461076d57604051632bfa23e760e11b81526001600160a01b03861660048201526024016101ca565b50505050505050565b6001600160a01b0384163b156105025760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906107ba9089908990889088908890600401610ea9565b6020604051808303815f875af19250505080156107f4575060408051601f3d908101601f191682019092526107f191810190610e7b565b60015b610821573d8080156106f7576040519150601f19603f3d011682016040523d82523d5f602084013e6106fc565b6001600160e01b0319811663f23a6e6160e01b1461076d57604051632bfa23e760e11b81526001600160a01b03861660048201526024016101ca565b805182511461088c5781518151604051635b05999160e01b8152600481019290925260248201526044016101ca565b5f5b825181101561097d576020818102848101820151908401909101518015610973575f828152602081905260409020546001600160a01b039081169088168114610909576040516303dee4c560e01b81526001600160a01b03891660048201525f602482015260448101839052606481018490526084016101ca565b600182111561094b576040516303dee4c560e01b81526001600160a01b03891660048201526001602482015260448101839052606481018490526084016101ca565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0388161790555b505060010161088e565b5081516001036109e6576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050610300565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051610a35929190610eed565b60405180910390a450505050565b5f610182610a5085610a57565b8484610abf565b5f61043982610a798163ffffffff8116185f9081526101086020526040902090565b610ad6565b5f8481526002602090815260408083206001600160a01b0387168452909152902054801561030f57610ab285828685610b24565b5061050285828585610078565b5f8280610acc8685610b90565b1614949350505050565b5f82610ae3575081610439565b60018201546104369084906001600160401b0316421015610b1157835463ffffffff82811690921891161890565b835461050a9063ffffffff166001610f1a565b5f610b2e8461018a565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461017c575f8781526002602090815260408083206001600160a01b038916845290915281208290558683169061011790899083906101d6565b5f610b9b8383610bad565b610ba55f84610bad565b179392505050565b5f8281526002602090815260408083206001600160a01b03851684529091529020548215610439575f610bdf84610c6e565b90506001600160a01b03811615801590610c0b5750826001600160a01b0316816001600160a01b031614155b8015610c3b57506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b15610c67575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b63ffffffff811681185f90815261010860205260408120600101546001600160401b0316421015610cc457610cbf610ca583610ccb565b5f908152602081905260409020546001600160a01b031690565b610439565b5f92915050565b5f61043982610ced8163ffffffff8116185f9081526101086020526040902090565b61041c565b6001600160a01b03811681146101d3575f80fd5b5f805f60608486031215610d18575f80fd5b8351610d2381610cf2565b6020850151909350610d3481610cf2565b80925050604084015190509250925092565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561043957610439610d46565b8181038181111561043957610439610d46565b5f63ffffffff808316818103610d9857610d98610d46565b6001019392505050565b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b83811015610de557815187529582019590820190600101610dc9565b509495945050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0386811682528516602082015260a0604082018190525f90610e4990830186610db6565b8281036060840152610e5b8186610db6565b90508281036080840152610e6f8185610df0565b98975050505050505050565b5f60208284031215610e8b575f80fd5b81516001600160e01b031981168114610ea2575f80fd5b9392505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f90610ee290830184610df0565b979650505050505050565b604081525f610eff6040830185610db6565b8281036020840152610f118185610db6565b95945050505050565b63ffffffff818116838216019080821115610c6757610c67610d46565b608051613977610f565f395f81816105c70152611b0901526139775ff3fe608060405234801561000f575f80fd5b50600436106102cc575f3560e01c80636352211e1161017c578063a02b161e116100dd578063ce156e8211610093578063e4ae7d771161006e578063e4ae7d7714610681578063e985e9c514610694578063f242432a146106cf575f80fd5b8063ce156e8214610648578063d3bf89b11461065b578063dfa70d8b1461066e575f80fd5b8063bc7b6d62116100c3578063bc7b6d621461060f578063bd242bcb14610622578063c41a360a14610635575f80fd5b8063a02b161e146105e9578063a22cb465146105fc575f80fd5b80637c3005861161013257806385f3e6431161011857806385f3e6431461059c57806391b3c037146105af5780639dbba19d146105c2575f80fd5b80637c3005861461057357806380f7602114610586575f80fd5b80636f3ff726116101625780636f3ff7261461053a5780636f537c721461054d578063781ef8db14610560575f80fd5b80636352211e1461051457806363560a8e14610527575f80fd5b80632f27fa241161023157806348688f95116101e75780635569f33d116101c25780635569f33d146104ce5780635adf4724146104e15780635c622a0e146104f4575f80fd5b806348688f95146104885780634e1273f41461049b5780635357263f146104bb575f80fd5b806335af62161161021757806335af6216146104155780633634f9111461044057806344c9af2814610468575f80fd5b80632f27fa24146103ef578063341ec55914610402575f80fd5b806313c72608116102865780631c3fc3eb1161026c5780631c3fc3eb146103c05780631e8fca2d146103c75780632eb2c2d6146103da575f80fd5b806313c726081461035f57806314ff5ea3146103ad575f80fd5b8063072d5d77116102b6578063072d5d77146103195780630e89341c1461032c57806311b8e00a1461034c575f80fd5b8062fdd58e146102d057806301ffc9a7146102f6575b5f80fd5b6102e36102de366004612d2c565b6106e2565b6040519081526020015b60405180910390f35b610309610304366004612d6b565b61072d565b60405190151581526020016102ed565b610309610327366004612d86565b6108a2565b61033f61033a366004612db4565b6108c6565b6040516102ed9190612df9565b61030961035a366004612e0b565b6109f6565b61039461036d366004612db4565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016102ed565b6102e36103bb366004612db4565b610a10565b6102e35f81565b6102e36103d5366004612db4565b610a37565b6103ed6103e8366004612f73565b610a5e565b005b6102e36103fd366004612db4565b610a7c565b6103ed610410366004612d86565b610a9a565b610428610423366004613058565b610b22565b6040516001600160a01b0390911681526020016102ed565b61045361044e366004612e0b565b610bbd565b604080519283526020830191909152016102ed565b61047b610476366004612db4565b610bdd565b6040516102ed91906130cb565b6103ed61049636600461311e565b610caf565b6104ae6104a9366004613171565b610d3c565b6040516102ed9190613267565b6103ed6104c9366004613279565b610e0c565b6103ed6104dc3660046132d8565b610ea1565b6102e36104ef366004612d86565b610fef565b610507610502366004612db4565b611002565b6040516102ed9190613302565b610428610522366004612db4565b611058565b610428610535366004613058565b6110bd565b610309610548366004613310565b6110ff565b61039461055b366004613058565b61111a565b61030961056e366004612d86565b61115c565b61030961058136600461332b565b611172565b61058e611186565b6040516102ed929190613356565b6102e36105aa366004613377565b611231565b6102e36105bd366004613058565b61124d565b6104287f000000000000000000000000000000000000000000000000000000000000000081565b6103ed6105f7366004612db4565b61128f565b6103ed61060a366004613400565b61138b565b6103ed61061d366004612d86565b61139a565b610428610630366004612db4565b611428565b610428610643366004612db4565b611444565b610309610656366004612d86565b611488565b61030961066936600461332b565b6114a3565b61030961067c36600461332b565b6114b7565b61042861068f366004613058565b6114cb565b6103096106a2366004613430565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6103ed6106dd36600461345c565b611546565b5f6001600160a01b038316158015906107145750826001600160a01b031661070983611058565b6001600160a01b0316145b61071e575f610721565b60015b60ff1690505b92915050565b5f6001600160e01b031982167f6be50c6900000000000000000000000000000000000000000000000000000000148061078f57506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b806107c357506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b806107f757506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b8061082b57506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b8061085f57506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b8061089357506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061072757506107278261155d565b5f80836108b082823361159a565b6108bd5f868660016115e8565b95945050505050565b610107546060906001600160a01b03166109695761010680546108e8906134c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610914906134c0565b801561095f5780601f106109365761010080835404028352916020019161095f565b820191905f5260205f20905b81548152906001019060200180831161094257829003601f168201915b5050505050610727565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa1580156109cf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261072791908101906134f8565b5f610a09610a0384610a37565b83611711565b9392505050565b5f61072782610a328463ffffffff8116185f9081526101086020526040902090565b611728565b5f61072782610a598463ffffffff8116185f9081526101086020526040902090565b611746565b610a6885336117a0565b610a758585858585611831565b5050505050565b5f610727610a8983610a37565b5f9081526003602052604090205490565b5f80610aa98462100000611891565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038716908102919091178255604051929450909250339184907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a450505050565b5f80610b7e610b6585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610bb35780546801000000000000000090046001600160a01b0316610bb5565b5f5b949350505050565b5f80610bd1610bcb85610a37565b84611905565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610c3b8584611728565b606085018190529050610c4e8584611746565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610c7c8382611928565b85906002811115610c8f57610c8f613097565b90816002811115610ca257610ca2613097565b8152505050505050919050565b641000000000610cc05f823361195f565b610106610cce8486836135b1565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905560405133907fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd590610d2e9087908790879061366b565b60405180910390a250505050565b60608151835114610d725781518351604051635b05999160e01b8152600481019290925260248201526044015b60405180910390fd5b5f835167ffffffffffffffff811115610d8d57610d8d612e2b565b604051908082528060200260200182016040528015610db6578160200160208202803683370190505b5090505f5b8451811015610e0457602080820286010151610ddf906020808402870101516106e2565b828281518110610df157610df16136ab565b6020908102919091010152600101610dbb565b509392505050565b610100610e1a5f823361195f565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105610e5083826136bf565b50336001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff484604051610e949190612df9565b60405180910390a3505050565b63ffffffff821682185f9081526101086020526040812090610ec38483611728565b600183015490915067ffffffffffffffff16428111610f205767ffffffffffffffff81161580610efa5750610ef882336119be565b155b15610f1b5760405163311388dd60e21b815260048101839052602401610d69565b610f37565b610f37610f2d8685611746565b620100003361195f565b8067ffffffffffffffff168467ffffffffffffffff161015610f99576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015285166024820152604401610d69565b60018301805467ffffffffffffffff191667ffffffffffffffff861690811790915560405133919084907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a45050505050565b5f610a09610ffc84610a37565b836119cc565b63ffffffff811681185f908152610108602052604081206001810154610a099067ffffffffffffffff166110536110398685611728565b5f908152602081905260409020546001600160a01b031690565b611928565b63ffffffff811681185f908152610108602052604081206110798382611728565b831415806110955750600181015467ffffffffffffffff164210155b6110b5575f838152602081905260409020546001600160a01b0316610a09565b5f9392505050565b5f610a0961064384848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f6107276f010000000000000000000000000000008361115c565b5f610a0961036d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f82836111695f856119d3565b16149392505050565b5f610bb561117f85610a37565b8484611a94565b6101045461010580545f926060926001600160a01b039091169181906111ab906134c0565b80601f01602080910402602001604051908101604052809291908181526020018280546111d7906134c0565b80156112225780601f106111f957610100808354040283529160200191611222565b820191905f5260205f20905b81548152906001019060200180831161120557829003601f168201915b50505050509050915091509091565b5f6112428787878787876001611ad7565b979650505050505050565b5f610a096103bb84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f8061129d83611000611891565b6040519193509150339083907f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea8905f90a35f828152602081905260409020546001600160a01b03168015611368576112f78184600161200d565b815482905f9061130c9063ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166113499061378f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b611396338383612074565b5050565b5f806113aa846301000000611891565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b03881690810291909117909155604051929450909250339184907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a450505050565b5f818152602081905260408120546001600160a01b0316610727565b63ffffffff811681185f908152610108602052604081206001015467ffffffffffffffff164210156114815761147c61103983610a10565b610727565b5f92915050565b5f808361149682823361211a565b6108bd5f8686600161217b565b5f610bb56114b085610a37565b84846121e7565b5f610bb56114c485610a37565b84846121fe565b5f8061150e610b6585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b600181015490915067ffffffffffffffff16421015610bb35760018101546801000000000000000090046001600160a01b0316610bb5565b61155085336117a0565b610a758585858585612237565b5f6001600160e01b031982167f8f452d620000000000000000000000000000000000000000000000000000000014806107275750610727826122c4565b5f6115a58483612392565b905080198316156115e25760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610d69565b50505050565b5f835f036115f757505f610bb5565b611600846123db565b6001600160a01b038316611640576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611705575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166116a08882600161243b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a384156116f9576116f9888785858b6125d0565b60019350505050610bb5565b505f9695505050505050565b5f8061171d8484610bbd565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610a09565b5f82611753575081610727565b6001820154610a0990849067ffffffffffffffff1642101561177c57835463ffffffff1661178f565b835461178f9063ffffffff1660016137b1565b63ffffffff82811690921891161890565b806001600160a01b0316826001600160a01b0316141580156117e757506001600160a01b038083165f9081526001602090815260408083209385168352929052205460ff16155b15611396576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b03808316600483015283166024820152604401610d69565b6001600160a01b03841661185a57604051632bfa23e760e11b81525f6004820152602401610d69565b6001600160a01b03851661188257604051626a0d4560e21b81525f6004820152602401610d69565b610a75858585858560016125d9565b63ffffffff821682185f908152610108602052604081206118b28482611728565b600182015490925067ffffffffffffffff1642106118e65760405163311388dd60e21b815260048101839052602401610d69565b610bd66118f38583611746565b843361195f565b805160209091012090565b5f8061191083612630565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff8316421061194157505f610727565b6001600160a01b03821661195757506001610727565b506002610727565b61196a8383836114a3565b6119b9576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610d69565b505050565b5f610a09620100008361115c565b5f610a0983835b5f8281526002602090815260408083206001600160a01b03851684529091529020548215610727575f611a0584611444565b90506001600160a01b03811615801590611a315750826001600160a01b0316816001600160a01b031614155b8015611a6157506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b15611a8d575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b5f8383611aa282823361159a565b85611ac057604051631850848b60e31b815260040160405180910390fd5b611acd86868660016115e8565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990611b3e908b90600401612df9565b5f604051808303815f87803b158015611b55575f80fd5b505af1158015611b67573d5f803e3d5ffd5b5050895160208b012091505f9050611b928263ffffffff8116185f9081526101086020526040902090565b9050611b9e8282611728565b5f8181526020819052604090205460018301549194506001600160a01b03169067ffffffffffffffff164210611c28578415611be057611be05f60013361195f565b6001600160a01b038a16158015611bf657508615155b15611c235760405163d1a3b35560e01b81525f600482015260248101889052336044820152606401610d69565b611ced565b6001600160a01b03811615611c6b578a6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610d699190612df9565b6001600160a01b038a16611cad578a6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610d699190612df9565b8415611cbf57611cbf5f60103361195f565b8567ffffffffffffffff165f03611ce257600182015467ffffffffffffffff1695505b640100000000871796505b6001600160a01b038a1615611d0f5767ffffffffffffffff8616421015611d1c565b67ffffffffffffffff8616155b15611d5f576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602401610d69565b6001600160a01b03811615611df757611d7a8185600161200d565b815482905f90611d8f9063ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff16611dcc9061378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550611df48483611728565b93505b60018201805483546001600160a01b03808d16680100000000000000009081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921786558b81169091026001600160e01b031990921667ffffffffffffffff8a1617919091179091558a16611eb857336001600160a01b0316835f1b857f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88e8a604051611eab9291906137ce565b60405180910390a4611f71565b336001600160a01b0316835f1b857f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8e8e8b604051611ef9939291906137f9565b60405180910390a4611f1c8a85600160405180602001604052805f81525061264a565b5f611f278584611746565b905080611f3657611f36613834565b604051819086907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a3611f6e81898d5f6115e8565b50505b6001600160a01b03891615611fb85760405133906001600160a01b038b169086907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a45b6001600160a01b03881615611fff5760405133906001600160a01b038a169086907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a45b505050979650505050505050565b6001600160a01b03831661203557604051626a0d4560e21b81525f6004820152602401610d69565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291610a7591879185908590836125d9565b6001600160a01b0382166120b6576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610d69565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610e94565b5f61212584836126a6565b905080198316156115e2576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610d69565b5f612185846123db565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611705575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906116a0908990839061243b565b5f82836121f486856126e1565b1614949350505050565b5f838361220c82823361211a565b8561222a57604051631850848b60e31b815260040160405180910390fd5b611acd868686600161217b565b6001600160a01b03841661226057604051632bfa23e760e11b81525f6004820152602401610d69565b6001600160a01b03851661228857604051626a0d4560e21b81525f6004820152602401610d69565b604080516001808252602082018690528183019081526060820185905260808201909252906122bb87878484875f6125d9565b50505050505050565b5f6001600160e01b031982167fd9b67a2600000000000000000000000000000000000000000000000000000000148061232657506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b8061235a57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061072757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610727565b5f82158015906123b257505f6123a784611444565b6001600160a01b0316145b156123be57505f610727565b5f6123c984846126a6565b90508315610a0957608081901c610bb5565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612438576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610d69565b50565b5f61244583612630565b9050811561250e575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156124e6576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610d69565b5f8481526003602052604081208054859290612503908490613848565b909155506115e29050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156125a8576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610d69565b5f84815260036020526040812080548592906125c590849061385b565b909155505050505050565b610a75856126fe565b6125e5868686866127de565b6001600160a01b0385161561262857801561260d576126083387878787876128dc565b612628565b602084810151908401516126253389898585896129fd565b50505b505050505050565b5f61263a826123db565b50600181901b17600281901b1790565b6001600160a01b03841661267357604051632bfa23e760e11b81525f6004820152602401610d69565b604080516001808252602082018690528183019081526060820185905260808201909252906126285f87848487846125d9565b5f610a096126b484846126e1565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000811660809190911c1790565b5f6126ec83836119d3565b6126f65f846119d3565b179392505050565b80156124385763ffffffff811681185f90815261010860205260408120906127268383611728565b5f818152602081905260409020549091506001600160a01b031661274c8183600161200d565b8254839060049061276a90640100000000900463ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6127938385611728565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3610a758282600160405180602001604052805f81525061264a565b6127ea84848484612ae4565b6001600160a01b0383161580159061280a57506001600160a01b03841615155b156115e2575f5b8251811015610a75575f83828151811061282d5761282d6136ab565b6020026020010151905061285681731000000000000000000000000000000000000000886114a3565b61289e576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610d69565b5f8383815181106128b1576128b16136ab565b602002602001015111156128d3576128d36128cb82610a37565b87875f612cd7565b50600101612811565b6001600160a01b0384163b156126285760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612920908990899088908890889060040161386e565b6020604051808303815f875af192505050801561295a575060408051601f3d908101601f19168201909252612957918101906138cb565b60015b6129c1573d808015612987576040519150601f19603f3d011682016040523d82523d5f602084013e61298c565b606091505b5080515f036129b957604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b146122bb57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b6001600160a01b0384163b156126285760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612a4190899089908890889088906004016138e6565b6020604051808303815f875af1925050508015612a7b575060408051601f3d908101601f19168201909252612a78918101906138cb565b60015b612aa8573d808015612987576040519150601f19603f3d011682016040523d82523d5f602084013e61298c565b6001600160e01b0319811663f23a6e6160e01b146122bb57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b8051825114612b135781518151604051635b05999160e01b815260048101929092526024820152604401610d69565b5f5b8251811015612c11576020818102848101820151908401909101518015612c07575f828152602081905260409020546001600160a01b039081169088168114612b90576040516303dee4c560e01b81526001600160a01b03891660048201525f60248201526044810183905260648101849052608401610d69565b6001821115612bd2576040516303dee4c560e01b81526001600160a01b0389166004820152600160248201526044810183905260648101849052608401610d69565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388161790555b5050600101612b15565b508151600103612c7a576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450506115e2565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051612cc992919061391d565b60405180910390a450505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015610a7557612d0b8582868561217b565b50612628858285856115e8565b6001600160a01b0381168114612438575f80fd5b5f8060408385031215612d3d575f80fd5b8235612d4881612d18565b946020939093013593505050565b6001600160e01b031981168114612438575f80fd5b5f60208284031215612d7b575f80fd5b8135610a0981612d56565b5f8060408385031215612d97575f80fd5b823591506020830135612da981612d18565b809150509250929050565b5f60208284031215612dc4575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610a096020830184612dcb565b5f8060408385031215612e1c575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e6857612e68612e2b565b604052919050565b5f67ffffffffffffffff821115612e8957612e89612e2b565b5060051b60200190565b5f82601f830112612ea2575f80fd5b81356020612eb7612eb283612e70565b612e3f565b8083825260208201915060208460051b870101935086841115612ed8575f80fd5b602086015b84811015612ef45780358352918301918301612edd565b509695505050505050565b5f67ffffffffffffffff821115612f1857612f18612e2b565b50601f01601f191660200190565b5f82601f830112612f35575f80fd5b8135612f43612eb282612eff565b818152846020838601011115612f57575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a08688031215612f87575f80fd5b8535612f9281612d18565b94506020860135612fa281612d18565b9350604086013567ffffffffffffffff80821115612fbe575f80fd5b612fca89838a01612e93565b94506060880135915080821115612fdf575f80fd5b612feb89838a01612e93565b93506080880135915080821115613000575f80fd5b5061300d88828901612f26565b9150509295509295909350565b5f8083601f84011261302a575f80fd5b50813567ffffffffffffffff811115613041575f80fd5b602083019150836020828501011115610bd6575f80fd5b5f8060208385031215613069575f80fd5b823567ffffffffffffffff81111561307f575f80fd5b61308b8582860161301a565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600381106130c757634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506130dd8284516130ab565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f60408486031215613130575f80fd5b833567ffffffffffffffff811115613146575f80fd5b6131528682870161301a565b909450925050602084013561316681612d18565b809150509250925092565b5f8060408385031215613182575f80fd5b823567ffffffffffffffff80821115613199575f80fd5b818501915085601f8301126131ac575f80fd5b813560206131bc612eb283612e70565b82815260059290921b840181019181810190898411156131da575f80fd5b948201945b838610156132015785356131f281612d18565b825294820194908201906131df565b96505086013592505080821115613216575f80fd5b5061322385828601612e93565b9150509250929050565b5f815180845260208085019450602084015f5b8381101561325c57815187529582019590820190600101613240565b509495945050505050565b602081525f610a09602083018461322d565b5f806040838503121561328a575f80fd5b823561329581612d18565b9150602083013567ffffffffffffffff8111156132b0575f80fd5b61322385828601612f26565b803567ffffffffffffffff811681146132d3575f80fd5b919050565b5f80604083850312156132e9575f80fd5b823591506132f9602084016132bc565b90509250929050565b6020810161072782846130ab565b5f60208284031215613320575f80fd5b8135610a0981612d18565b5f805f6060848603121561333d575f80fd5b8335925060208401359150604084013561316681612d18565b6001600160a01b0383168152604060208201525f610bb56040830184612dcb565b5f805f805f8060c0878903121561338c575f80fd5b863567ffffffffffffffff8111156133a2575f80fd5b6133ae89828a01612f26565b96505060208701356133bf81612d18565b945060408701356133cf81612d18565b935060608701356133df81612d18565b9250608087013591506133f460a088016132bc565b90509295509295509295565b5f8060408385031215613411575f80fd5b823561341c81612d18565b915060208301358015158114612da9575f80fd5b5f8060408385031215613441575f80fd5b823561344c81612d18565b91506020830135612da981612d18565b5f805f805f60a08688031215613470575f80fd5b853561347b81612d18565b9450602086013561348b81612d18565b93506040860135925060608601359150608086013567ffffffffffffffff8111156134b4575f80fd5b61300d88828901612f26565b600181811c908216806134d457607f821691505b6020821081036134f257634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613508575f80fd5b815167ffffffffffffffff81111561351e575f80fd5b8201601f8101841361352e575f80fd5b805161353c612eb282612eff565b818152856020838501011115613550575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b601f8211156119b957805f5260205f20601f840160051c810160208510156135925750805b601f840160051c820191505b81811015610a75575f815560010161359e565b67ffffffffffffffff8311156135c9576135c9612e2b565b6135dd836135d783546134c0565b8361356d565b5f601f84116001811461360e575f85156135f75750838201355b5f19600387901b1c1916600186901b178355610a75565b5f83815260208120601f198716915b8281101561363d578685013582556020948501946001909201910161361d565b5086821015613659575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff8111156136d9576136d9612e2b565b6136ed816136e784546134c0565b8461356d565b602080601f831160018114613720575f84156137095750858301515b5f19600386901b1c1916600185901b178555612628565b5f85815260208120601f198616915b8281101561374e5788860151825594840194600190910190840161372f565b508582101561376b57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036137a7576137a761377b565b6001019392505050565b63ffffffff818116838216019080821115611a8d57611a8d61377b565b604081525f6137e06040830185612dcb565b905067ffffffffffffffff831660208301529392505050565b606081525f61380b6060830186612dcb565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b808201808211156107275761072761377b565b818103818111156107275761072761377b565b5f6001600160a01b03808816835280871660208401525060a0604083015261389960a083018661322d565b82810360608401526138ab818661322d565b905082810360808401526138bf8185612dcb565b98975050505050505050565b5f602082840312156138db575f80fd5b8151610a0981612d56565b5f6001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261124260a0830184612dcb565b604081525f61392f604083018561322d565b82810360208401526108bd818561322d56fea2646970667358221220d5c76270adee32355114bf29e4bad3cec273a3f6ceb196bf34b709a3beebecc164736f6c634300081900338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102cc575f3560e01c80636352211e1161017c578063a02b161e116100dd578063ce156e8211610093578063e4ae7d771161006e578063e4ae7d7714610681578063e985e9c514610694578063f242432a146106cf575f80fd5b8063ce156e8214610648578063d3bf89b11461065b578063dfa70d8b1461066e575f80fd5b8063bc7b6d62116100c3578063bc7b6d621461060f578063bd242bcb14610622578063c41a360a14610635575f80fd5b8063a02b161e146105e9578063a22cb465146105fc575f80fd5b80637c3005861161013257806385f3e6431161011857806385f3e6431461059c57806391b3c037146105af5780639dbba19d146105c2575f80fd5b80637c3005861461057357806380f7602114610586575f80fd5b80636f3ff726116101625780636f3ff7261461053a5780636f537c721461054d578063781ef8db14610560575f80fd5b80636352211e1461051457806363560a8e14610527575f80fd5b80632f27fa241161023157806348688f95116101e75780635569f33d116101c25780635569f33d146104ce5780635adf4724146104e15780635c622a0e146104f4575f80fd5b806348688f95146104885780634e1273f41461049b5780635357263f146104bb575f80fd5b806335af62161161021757806335af6216146104155780633634f9111461044057806344c9af2814610468575f80fd5b80632f27fa24146103ef578063341ec55914610402575f80fd5b806313c72608116102865780631c3fc3eb1161026c5780631c3fc3eb146103c05780631e8fca2d146103c75780632eb2c2d6146103da575f80fd5b806313c726081461035f57806314ff5ea3146103ad575f80fd5b8063072d5d77116102b6578063072d5d77146103195780630e89341c1461032c57806311b8e00a1461034c575f80fd5b8062fdd58e146102d057806301ffc9a7146102f6575b5f80fd5b6102e36102de366004612d2c565b6106e2565b6040519081526020015b60405180910390f35b610309610304366004612d6b565b61072d565b60405190151581526020016102ed565b610309610327366004612d86565b6108a2565b61033f61033a366004612db4565b6108c6565b6040516102ed9190612df9565b61030961035a366004612e0b565b6109f6565b61039461036d366004612db4565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016102ed565b6102e36103bb366004612db4565b610a10565b6102e35f81565b6102e36103d5366004612db4565b610a37565b6103ed6103e8366004612f73565b610a5e565b005b6102e36103fd366004612db4565b610a7c565b6103ed610410366004612d86565b610a9a565b610428610423366004613058565b610b22565b6040516001600160a01b0390911681526020016102ed565b61045361044e366004612e0b565b610bbd565b604080519283526020830191909152016102ed565b61047b610476366004612db4565b610bdd565b6040516102ed91906130cb565b6103ed61049636600461311e565b610caf565b6104ae6104a9366004613171565b610d3c565b6040516102ed9190613267565b6103ed6104c9366004613279565b610e0c565b6103ed6104dc3660046132d8565b610ea1565b6102e36104ef366004612d86565b610fef565b610507610502366004612db4565b611002565b6040516102ed9190613302565b610428610522366004612db4565b611058565b610428610535366004613058565b6110bd565b610309610548366004613310565b6110ff565b61039461055b366004613058565b61111a565b61030961056e366004612d86565b61115c565b61030961058136600461332b565b611172565b61058e611186565b6040516102ed929190613356565b6102e36105aa366004613377565b611231565b6102e36105bd366004613058565b61124d565b6104287f000000000000000000000000000000000000000000000000000000000000000081565b6103ed6105f7366004612db4565b61128f565b6103ed61060a366004613400565b61138b565b6103ed61061d366004612d86565b61139a565b610428610630366004612db4565b611428565b610428610643366004612db4565b611444565b610309610656366004612d86565b611488565b61030961066936600461332b565b6114a3565b61030961067c36600461332b565b6114b7565b61042861068f366004613058565b6114cb565b6103096106a2366004613430565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6103ed6106dd36600461345c565b611546565b5f6001600160a01b038316158015906107145750826001600160a01b031661070983611058565b6001600160a01b0316145b61071e575f610721565b60015b60ff1690505b92915050565b5f6001600160e01b031982167f6be50c6900000000000000000000000000000000000000000000000000000000148061078f57506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b806107c357506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b806107f757506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b8061082b57506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b8061085f57506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b8061089357506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061072757506107278261155d565b5f80836108b082823361159a565b6108bd5f868660016115e8565b95945050505050565b610107546060906001600160a01b03166109695761010680546108e8906134c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610914906134c0565b801561095f5780601f106109365761010080835404028352916020019161095f565b820191905f5260205f20905b81548152906001019060200180831161094257829003601f168201915b5050505050610727565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa1580156109cf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261072791908101906134f8565b5f610a09610a0384610a37565b83611711565b9392505050565b5f61072782610a328463ffffffff8116185f9081526101086020526040902090565b611728565b5f61072782610a598463ffffffff8116185f9081526101086020526040902090565b611746565b610a6885336117a0565b610a758585858585611831565b5050505050565b5f610727610a8983610a37565b5f9081526003602052604090205490565b5f80610aa98462100000611891565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038716908102919091178255604051929450909250339184907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a450505050565b5f80610b7e610b6585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610bb35780546801000000000000000090046001600160a01b0316610bb5565b5f5b949350505050565b5f80610bd1610bcb85610a37565b84611905565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610c3b8584611728565b606085018190529050610c4e8584611746565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610c7c8382611928565b85906002811115610c8f57610c8f613097565b90816002811115610ca257610ca2613097565b8152505050505050919050565b641000000000610cc05f823361195f565b610106610cce8486836135b1565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905560405133907fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd590610d2e9087908790879061366b565b60405180910390a250505050565b60608151835114610d725781518351604051635b05999160e01b8152600481019290925260248201526044015b60405180910390fd5b5f835167ffffffffffffffff811115610d8d57610d8d612e2b565b604051908082528060200260200182016040528015610db6578160200160208202803683370190505b5090505f5b8451811015610e0457602080820286010151610ddf906020808402870101516106e2565b828281518110610df157610df16136ab565b6020908102919091010152600101610dbb565b509392505050565b610100610e1a5f823361195f565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105610e5083826136bf565b50336001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff484604051610e949190612df9565b60405180910390a3505050565b63ffffffff821682185f9081526101086020526040812090610ec38483611728565b600183015490915067ffffffffffffffff16428111610f205767ffffffffffffffff81161580610efa5750610ef882336119be565b155b15610f1b5760405163311388dd60e21b815260048101839052602401610d69565b610f37565b610f37610f2d8685611746565b620100003361195f565b8067ffffffffffffffff168467ffffffffffffffff161015610f99576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015285166024820152604401610d69565b60018301805467ffffffffffffffff191667ffffffffffffffff861690811790915560405133919084907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a45050505050565b5f610a09610ffc84610a37565b836119cc565b63ffffffff811681185f908152610108602052604081206001810154610a099067ffffffffffffffff166110536110398685611728565b5f908152602081905260409020546001600160a01b031690565b611928565b63ffffffff811681185f908152610108602052604081206110798382611728565b831415806110955750600181015467ffffffffffffffff164210155b6110b5575f838152602081905260409020546001600160a01b0316610a09565b5f9392505050565b5f610a0961064384848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f6107276f010000000000000000000000000000008361115c565b5f610a0961036d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f82836111695f856119d3565b16149392505050565b5f610bb561117f85610a37565b8484611a94565b6101045461010580545f926060926001600160a01b039091169181906111ab906134c0565b80601f01602080910402602001604051908101604052809291908181526020018280546111d7906134c0565b80156112225780601f106111f957610100808354040283529160200191611222565b820191905f5260205f20905b81548152906001019060200180831161120557829003601f168201915b50505050509050915091509091565b5f6112428787878787876001611ad7565b979650505050505050565b5f610a096103bb84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f8061129d83611000611891565b6040519193509150339083907f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea8905f90a35f828152602081905260409020546001600160a01b03168015611368576112f78184600161200d565b815482905f9061130c9063ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166113499061378f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b611396338383612074565b5050565b5f806113aa846301000000611891565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b03881690810291909117909155604051929450909250339184907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a450505050565b5f818152602081905260408120546001600160a01b0316610727565b63ffffffff811681185f908152610108602052604081206001015467ffffffffffffffff164210156114815761147c61103983610a10565b610727565b5f92915050565b5f808361149682823361211a565b6108bd5f8686600161217b565b5f610bb56114b085610a37565b84846121e7565b5f610bb56114c485610a37565b84846121fe565b5f8061150e610b6585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b600181015490915067ffffffffffffffff16421015610bb35760018101546801000000000000000090046001600160a01b0316610bb5565b61155085336117a0565b610a758585858585612237565b5f6001600160e01b031982167f8f452d620000000000000000000000000000000000000000000000000000000014806107275750610727826122c4565b5f6115a58483612392565b905080198316156115e25760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610d69565b50505050565b5f835f036115f757505f610bb5565b611600846123db565b6001600160a01b038316611640576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611705575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166116a08882600161243b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a384156116f9576116f9888785858b6125d0565b60019350505050610bb5565b505f9695505050505050565b5f8061171d8484610bbd565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610a09565b5f82611753575081610727565b6001820154610a0990849067ffffffffffffffff1642101561177c57835463ffffffff1661178f565b835461178f9063ffffffff1660016137b1565b63ffffffff82811690921891161890565b806001600160a01b0316826001600160a01b0316141580156117e757506001600160a01b038083165f9081526001602090815260408083209385168352929052205460ff16155b15611396576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b03808316600483015283166024820152604401610d69565b6001600160a01b03841661185a57604051632bfa23e760e11b81525f6004820152602401610d69565b6001600160a01b03851661188257604051626a0d4560e21b81525f6004820152602401610d69565b610a75858585858560016125d9565b63ffffffff821682185f908152610108602052604081206118b28482611728565b600182015490925067ffffffffffffffff1642106118e65760405163311388dd60e21b815260048101839052602401610d69565b610bd66118f38583611746565b843361195f565b805160209091012090565b5f8061191083612630565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff8316421061194157505f610727565b6001600160a01b03821661195757506001610727565b506002610727565b61196a8383836114a3565b6119b9576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610d69565b505050565b5f610a09620100008361115c565b5f610a0983835b5f8281526002602090815260408083206001600160a01b03851684529091529020548215610727575f611a0584611444565b90506001600160a01b03811615801590611a315750826001600160a01b0316816001600160a01b031614155b8015611a6157506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b15611a8d575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b5f8383611aa282823361159a565b85611ac057604051631850848b60e31b815260040160405180910390fd5b611acd86868660016115e8565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990611b3e908b90600401612df9565b5f604051808303815f87803b158015611b55575f80fd5b505af1158015611b67573d5f803e3d5ffd5b5050895160208b012091505f9050611b928263ffffffff8116185f9081526101086020526040902090565b9050611b9e8282611728565b5f8181526020819052604090205460018301549194506001600160a01b03169067ffffffffffffffff164210611c28578415611be057611be05f60013361195f565b6001600160a01b038a16158015611bf657508615155b15611c235760405163d1a3b35560e01b81525f600482015260248101889052336044820152606401610d69565b611ced565b6001600160a01b03811615611c6b578a6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610d699190612df9565b6001600160a01b038a16611cad578a6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610d699190612df9565b8415611cbf57611cbf5f60103361195f565b8567ffffffffffffffff165f03611ce257600182015467ffffffffffffffff1695505b640100000000871796505b6001600160a01b038a1615611d0f5767ffffffffffffffff8616421015611d1c565b67ffffffffffffffff8616155b15611d5f576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602401610d69565b6001600160a01b03811615611df757611d7a8185600161200d565b815482905f90611d8f9063ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff16611dcc9061378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550611df48483611728565b93505b60018201805483546001600160a01b03808d16680100000000000000009081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921786558b81169091026001600160e01b031990921667ffffffffffffffff8a1617919091179091558a16611eb857336001600160a01b0316835f1b857f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88e8a604051611eab9291906137ce565b60405180910390a4611f71565b336001600160a01b0316835f1b857f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8e8e8b604051611ef9939291906137f9565b60405180910390a4611f1c8a85600160405180602001604052805f81525061264a565b5f611f278584611746565b905080611f3657611f36613834565b604051819086907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a3611f6e81898d5f6115e8565b50505b6001600160a01b03891615611fb85760405133906001600160a01b038b169086907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a45b6001600160a01b03881615611fff5760405133906001600160a01b038a169086907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a45b505050979650505050505050565b6001600160a01b03831661203557604051626a0d4560e21b81525f6004820152602401610d69565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291610a7591879185908590836125d9565b6001600160a01b0382166120b6576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610d69565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610e94565b5f61212584836126a6565b905080198316156115e2576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610d69565b5f612185846123db565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611705575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906116a0908990839061243b565b5f82836121f486856126e1565b1614949350505050565b5f838361220c82823361211a565b8561222a57604051631850848b60e31b815260040160405180910390fd5b611acd868686600161217b565b6001600160a01b03841661226057604051632bfa23e760e11b81525f6004820152602401610d69565b6001600160a01b03851661228857604051626a0d4560e21b81525f6004820152602401610d69565b604080516001808252602082018690528183019081526060820185905260808201909252906122bb87878484875f6125d9565b50505050505050565b5f6001600160e01b031982167fd9b67a2600000000000000000000000000000000000000000000000000000000148061232657506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b8061235a57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061072757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610727565b5f82158015906123b257505f6123a784611444565b6001600160a01b0316145b156123be57505f610727565b5f6123c984846126a6565b90508315610a0957608081901c610bb5565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612438576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610d69565b50565b5f61244583612630565b9050811561250e575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156124e6576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610d69565b5f8481526003602052604081208054859290612503908490613848565b909155506115e29050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156125a8576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610d69565b5f84815260036020526040812080548592906125c590849061385b565b909155505050505050565b610a75856126fe565b6125e5868686866127de565b6001600160a01b0385161561262857801561260d576126083387878787876128dc565b612628565b602084810151908401516126253389898585896129fd565b50505b505050505050565b5f61263a826123db565b50600181901b17600281901b1790565b6001600160a01b03841661267357604051632bfa23e760e11b81525f6004820152602401610d69565b604080516001808252602082018690528183019081526060820185905260808201909252906126285f87848487846125d9565b5f610a096126b484846126e1565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000811660809190911c1790565b5f6126ec83836119d3565b6126f65f846119d3565b179392505050565b80156124385763ffffffff811681185f90815261010860205260408120906127268383611728565b5f818152602081905260409020549091506001600160a01b031661274c8183600161200d565b8254839060049061276a90640100000000900463ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6127938385611728565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3610a758282600160405180602001604052805f81525061264a565b6127ea84848484612ae4565b6001600160a01b0383161580159061280a57506001600160a01b03841615155b156115e2575f5b8251811015610a75575f83828151811061282d5761282d6136ab565b6020026020010151905061285681731000000000000000000000000000000000000000886114a3565b61289e576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610d69565b5f8383815181106128b1576128b16136ab565b602002602001015111156128d3576128d36128cb82610a37565b87875f612cd7565b50600101612811565b6001600160a01b0384163b156126285760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612920908990899088908890889060040161386e565b6020604051808303815f875af192505050801561295a575060408051601f3d908101601f19168201909252612957918101906138cb565b60015b6129c1573d808015612987576040519150601f19603f3d011682016040523d82523d5f602084013e61298c565b606091505b5080515f036129b957604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b146122bb57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b6001600160a01b0384163b156126285760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612a4190899089908890889088906004016138e6565b6020604051808303815f875af1925050508015612a7b575060408051601f3d908101601f19168201909252612a78918101906138cb565b60015b612aa8573d808015612987576040519150601f19603f3d011682016040523d82523d5f602084013e61298c565b6001600160e01b0319811663f23a6e6160e01b146122bb57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b8051825114612b135781518151604051635b05999160e01b815260048101929092526024820152604401610d69565b5f5b8251811015612c11576020818102848101820151908401909101518015612c07575f828152602081905260409020546001600160a01b039081169088168114612b90576040516303dee4c560e01b81526001600160a01b03891660048201525f60248201526044810183905260648101849052608401610d69565b6001821115612bd2576040516303dee4c560e01b81526001600160a01b0389166004820152600160248201526044810183905260648101849052608401610d69565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388161790555b5050600101612b15565b508151600103612c7a576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450506115e2565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051612cc992919061391d565b60405180910390a450505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015610a7557612d0b8582868561217b565b50612628858285856115e8565b6001600160a01b0381168114612438575f80fd5b5f8060408385031215612d3d575f80fd5b8235612d4881612d18565b946020939093013593505050565b6001600160e01b031981168114612438575f80fd5b5f60208284031215612d7b575f80fd5b8135610a0981612d56565b5f8060408385031215612d97575f80fd5b823591506020830135612da981612d18565b809150509250929050565b5f60208284031215612dc4575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610a096020830184612dcb565b5f8060408385031215612e1c575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e6857612e68612e2b565b604052919050565b5f67ffffffffffffffff821115612e8957612e89612e2b565b5060051b60200190565b5f82601f830112612ea2575f80fd5b81356020612eb7612eb283612e70565b612e3f565b8083825260208201915060208460051b870101935086841115612ed8575f80fd5b602086015b84811015612ef45780358352918301918301612edd565b509695505050505050565b5f67ffffffffffffffff821115612f1857612f18612e2b565b50601f01601f191660200190565b5f82601f830112612f35575f80fd5b8135612f43612eb282612eff565b818152846020838601011115612f57575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a08688031215612f87575f80fd5b8535612f9281612d18565b94506020860135612fa281612d18565b9350604086013567ffffffffffffffff80821115612fbe575f80fd5b612fca89838a01612e93565b94506060880135915080821115612fdf575f80fd5b612feb89838a01612e93565b93506080880135915080821115613000575f80fd5b5061300d88828901612f26565b9150509295509295909350565b5f8083601f84011261302a575f80fd5b50813567ffffffffffffffff811115613041575f80fd5b602083019150836020828501011115610bd6575f80fd5b5f8060208385031215613069575f80fd5b823567ffffffffffffffff81111561307f575f80fd5b61308b8582860161301a565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600381106130c757634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506130dd8284516130ab565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f60408486031215613130575f80fd5b833567ffffffffffffffff811115613146575f80fd5b6131528682870161301a565b909450925050602084013561316681612d18565b809150509250925092565b5f8060408385031215613182575f80fd5b823567ffffffffffffffff80821115613199575f80fd5b818501915085601f8301126131ac575f80fd5b813560206131bc612eb283612e70565b82815260059290921b840181019181810190898411156131da575f80fd5b948201945b838610156132015785356131f281612d18565b825294820194908201906131df565b96505086013592505080821115613216575f80fd5b5061322385828601612e93565b9150509250929050565b5f815180845260208085019450602084015f5b8381101561325c57815187529582019590820190600101613240565b509495945050505050565b602081525f610a09602083018461322d565b5f806040838503121561328a575f80fd5b823561329581612d18565b9150602083013567ffffffffffffffff8111156132b0575f80fd5b61322385828601612f26565b803567ffffffffffffffff811681146132d3575f80fd5b919050565b5f80604083850312156132e9575f80fd5b823591506132f9602084016132bc565b90509250929050565b6020810161072782846130ab565b5f60208284031215613320575f80fd5b8135610a0981612d18565b5f805f6060848603121561333d575f80fd5b8335925060208401359150604084013561316681612d18565b6001600160a01b0383168152604060208201525f610bb56040830184612dcb565b5f805f805f8060c0878903121561338c575f80fd5b863567ffffffffffffffff8111156133a2575f80fd5b6133ae89828a01612f26565b96505060208701356133bf81612d18565b945060408701356133cf81612d18565b935060608701356133df81612d18565b9250608087013591506133f460a088016132bc565b90509295509295509295565b5f8060408385031215613411575f80fd5b823561341c81612d18565b915060208301358015158114612da9575f80fd5b5f8060408385031215613441575f80fd5b823561344c81612d18565b91506020830135612da981612d18565b5f805f805f60a08688031215613470575f80fd5b853561347b81612d18565b9450602086013561348b81612d18565b93506040860135925060608601359150608086013567ffffffffffffffff8111156134b4575f80fd5b61300d88828901612f26565b600181811c908216806134d457607f821691505b6020821081036134f257634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613508575f80fd5b815167ffffffffffffffff81111561351e575f80fd5b8201601f8101841361352e575f80fd5b805161353c612eb282612eff565b818152856020838501011115613550575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b601f8211156119b957805f5260205f20601f840160051c810160208510156135925750805b601f840160051c820191505b81811015610a75575f815560010161359e565b67ffffffffffffffff8311156135c9576135c9612e2b565b6135dd836135d783546134c0565b8361356d565b5f601f84116001811461360e575f85156135f75750838201355b5f19600387901b1c1916600186901b178355610a75565b5f83815260208120601f198716915b8281101561363d578685013582556020948501946001909201910161361d565b5086821015613659575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff8111156136d9576136d9612e2b565b6136ed816136e784546134c0565b8461356d565b602080601f831160018114613720575f84156137095750858301515b5f19600386901b1c1916600185901b178555612628565b5f85815260208120601f198616915b8281101561374e5788860151825594840194600190910190840161372f565b508582101561376b57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036137a7576137a761377b565b6001019392505050565b63ffffffff818116838216019080821115611a8d57611a8d61377b565b604081525f6137e06040830185612dcb565b905067ffffffffffffffff831660208301529392505050565b606081525f61380b6060830186612dcb565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b808201808211156107275761072761377b565b818103818111156107275761072761377b565b5f6001600160a01b03808816835280871660208401525060a0604083015261389960a083018661322d565b82810360608401526138ab818661322d565b905082810360808401526138bf8185612dcb565b98975050505050505050565b5f602082840312156138db575f80fd5b8151610a0981612d56565b5f6001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261124260a0830184612dcb565b604081525f61392f604083018561322d565b82810360208401526108bd818561322d56fea2646970667358221220d5c76270adee32355114bf29e4bad3cec273a3f6ceb196bf34b709a3beebecc164736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "28814": [ + { + "length": 32, + "start": 1479 + }, + { + "length": 32, + "start": 6921 + } + ] + }, + "inputSourceName": "project/src/registry/PermissionedRegistry.sol", + "devdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "details": "Error selector: `0x68c1425a`" + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "details": "Error selector: `0xf1d446c3`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1155InsufficientBalance(address,uint256,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred.", + "tokenId": "Identifier number of a token." + } + } + ], + "ERC1155InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "ERC1155InvalidOperator(address)": [ + { + "details": "Indicates a failure with the `operator` to be approved. Used in approvals.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC1155InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC1155InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC1155MissingApprovalForAll(address,address)": [ + { + "details": "Indicates a failure with the `operator`’s approval. Used in transfers.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner.", + "owner": "Address of the current owner of a token." + } + } + ], + "LabelAlreadyRegistered(string)": [ + { + "details": "Error selector: `0xdef545a4`" + } + ], + "LabelAlreadyReserved(string)": [ + { + "details": "Error selector: `0xf60759e0`" + } + ], + "LabelExpired(uint256)": [ + { + "details": "Error selector: `0xc44e2374`" + } + ], + "TransferDisallowed(uint256,address)": [ + { + "details": "Error selector: `0xe58f6d5a`" + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "ExpiryUpdated(uint256,uint64,address)": { + "params": { + "newExpiry": "The new expiry of the label.", + "sender": "The sender of the call to update the expiry.", + "tokenId": "The token ID of the label." + } + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label registered.", + "labelHash": "The label hash registered.", + "owner": "The owner of the label.", + "sender": "The sender of the call to register.", + "tokenId": "The token ID registered." + } + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label reserved.", + "labelHash": "The label hash reserved.", + "sender": "The sender of the call to reserve.", + "tokenId": "The token ID reserved." + } + }, + "LabelUnregistered(uint256,address)": { + "params": { + "sender": "The sender of the call to unregister.", + "tokenId": "The token ID unregistered." + } + }, + "ParentUpdated(address,string,address)": { + "params": { + "label": "The new label.", + "parent": "The new parent.", + "sender": "The sender of the call to update the parent." + } + }, + "ResolverUpdated(uint256,address,address)": { + "params": { + "resolver": "The new resolver.", + "sender": "The sender of the call to update the resolver.", + "tokenId": "The token ID of the label." + } + }, + "SubregistryUpdated(uint256,address,address)": { + "params": { + "sender": "The sender of the call to update the subregistry.", + "subregistry": "The new subregistry.", + "tokenId": "The token ID of the label." + } + }, + "TokenRegenerated(uint256,uint256)": { + "params": { + "newTokenId": "The new token ID.", + "oldTokenId": "The old token ID." + } + }, + "TokenResource(uint256,uint256)": { + "params": { + "resource": "The EAC resource.", + "tokenId": "The token ID." + } + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + }, + "URIUpdated(string,address,address)": { + "params": { + "renderer": "The new render address.", + "sender": "The sender of the call to update the URI.", + "uri": "The new URI." + } + } + }, + "kind": "dev", + "methods": { + "balanceOf(address,uint256)": { + "params": { + "account": "The account to get the balance for.", + "id": "The token ID." + }, + "returns": { + "_0": "balance The balance of the token for the account. This will only ever be 1 or 0." + } + }, + "balanceOfBatch(address[],uint256[])": { + "details": "`accounts` and `ids` must have the same length.", + "params": { + "accounts": "The accounts to get the balances for.", + "ids": "The token IDs." + }, + "returns": { + "_0": "batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0." + } + }, + "constructor": { + "params": { + "labelStore": "The shared label database.", + "roleBitmap": "The role bitmap granted to `rootAccount`.", + "rootAccount": "Account granted root roles." + } + }, + "findExpiry(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The expiry of the label." + } + }, + "findOwner(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The owner of the label." + } + }, + "findTokenId(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The token ID of the label." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getExpiry(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The expiry of the label, in seconds." + } + }, + "getOwner(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token owner." + } + }, + "getParent()": { + "returns": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "getResolver(string)": { + "params": { + "label": "The label to fetch a resolver for." + }, + "returns": { + "_0": "resolver The address of a resolver responsible for this label, or `address(0)` if none exists." + } + }, + "getResource(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The resource." + } + }, + "getState(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "state": "The state of the label." + } + }, + "getStatus(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The status of the label." + } + }, + "getSubregistry(string)": { + "params": { + "label": "The label to resolve." + }, + "returns": { + "_0": "The address of the registry for this label, or `address(0)` if none exists." + } + }, + "getTokenId(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token ID." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "account": "The account to get the approval for.", + "operator": "The operator to get the approval for." + }, + "returns": { + "_0": "approved The approval status." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "latestOwnerOf(uint256)": { + "params": { + "tokenId": "The token ID to query." + }, + "returns": { + "_0": "The latest owner address." + } + }, + "ownerOf(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The owner of the token." + } + }, + "register(string,address,address,address,uint256,uint64)": { + "params": { + "expiry": "The expiry of the label, in seconds.", + "label": "The label to register.", + "owner": "The address of the owner of the label.", + "registry": "The registry to set as the label.", + "resolver": "The resolver to set for the label.", + "roleBitmap": "The role bitmap to set for the label." + }, + "returns": { + "_0": "The token ID." + } + }, + "renew(uint256,uint64)": { + "details": "If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.", + "params": { + "anyId": "The labelhash, token ID, or resource.", + "newExpiry": "The new expiry, in seconds." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the tokens from.", + "ids": "The token IDs.", + "to": "The address to transfer the tokens to.", + "values": "The amounts of tokens to transfer." + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the token from.", + "id": "The token ID.", + "to": "The address to transfer the token to.", + "value": "The amount of tokens to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "The approval status.", + "operator": "The operator to set the approval for." + } + }, + "setParent(address,string)": { + "details": "Should emit `ParentUpdated`.", + "params": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "setResolver(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "resolver": "The new resolver." + } + }, + "setSubregistry(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "registry": "The new registry." + } + }, + "setURI(string,address)": { + "params": { + "renderer": "The new renderer address.", + "uri_": "The new URI." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "unregister(uint256)": { + "details": "Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.", + "params": { + "anyId": "The labelhash, token ID, or resource." + } + }, + "uri(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The URI for the token." + } + } + }, + "stateVariables": { + "__gap": { + "details": "Storage gap for future changes." + }, + "_childLabel": { + "details": "The child label of this registry." + }, + "_entries": { + "details": "The entries of this registry." + }, + "_parentRegistry": { + "details": "The parent registry of this registry." + }, + "_uri": { + "details": "The metadata URI." + }, + "_uriRenderer": { + "details": "The metadata renderer." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "2942200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "LABEL_STORE()": "infinite", + "ROOT_RESOURCE()": "250", + "balanceOf(address,uint256)": "infinite", + "balanceOfBatch(address[],uint256[])": "infinite", + "findExpiry(string)": "infinite", + "findOwner(string)": "infinite", + "findTokenId(string)": "infinite", + "getAssigneeCount(uint256,uint256)": "7372", + "getExpiry(uint256)": "2537", + "getOwner(uint256)": "infinite", + "getParent()": "infinite", + "getResolver(string)": "infinite", + "getResource(uint256)": "4918", + "getState(uint256)": "infinite", + "getStatus(uint256)": "infinite", + "getSubregistry(string)": "infinite", + "getTokenId(uint256)": "2663", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "infinite", + "hasRoles(uint256,uint256,address)": "infinite", + "hasRootRoles(uint256,address)": "2843", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "infinite", + "latestOwnerOf(uint256)": "2597", + "ownerOf(uint256)": "infinite", + "register(string,address,address,address,uint256,uint64)": "infinite", + "renew(uint256,uint64)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "infinite", + "roles(uint256,address)": "infinite", + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": "infinite", + "safeTransferFrom(address,address,uint256,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "26752", + "setParent(address,string)": "infinite", + "setResolver(uint256,address)": "infinite", + "setSubregistry(uint256,address)": "infinite", + "setURI(string,address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "unregister(uint256)": "infinite", + "uri(uint256)": "infinite" + }, + "internal": { + "_canRevive(uint256,address)": "2402", + "_checkExpiryAndTokenRoles(uint256,uint256)": "infinite", + "_constructResource(uint256,struct PermissionedRegistry.Entry storage pointer)": "4435", + "_constructStatus(uint64,address)": "101", + "_constructTokenId(uint256,struct PermissionedRegistry.Entry storage pointer)": "2179", + "_entry(uint256)": "infinite", + "_getRoles(uint256,address)": "infinite", + "_getSettableRoles(uint256,address)": "infinite", + "_isExpired(uint64)": "infinite", + "_onRolesGranted(uint256,address,uint256,uint256,uint256)": "infinite", + "_onRolesRevoked(uint256,address,uint256,uint256,uint256)": "infinite", + "_regenerate(uint256)": "infinite", + "_register(string memory,address,contract IRegistry,address,uint256,uint64,bool)": "infinite", + "_update(address,address,uint256[] memory,uint256[] memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"labelStore\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"oldExpiry\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"CannotReduceExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"CannotSetPastExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyReserved\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"LabelExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"TransferDisallowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ExpiryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelReserved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelUnregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ParentUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RegistryCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ResolverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SubregistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldTokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newTokenId\",\"type\":\"uint256\"}],\"name\":\"TokenRegenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"TokenResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"renderer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"URIUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"LABEL_STORE\",\"outputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getParent\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getResource\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"latestOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"internalType\":\"struct IPermissionedRegistry.State\",\"name\":\"state\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getSubregistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"latestOwnerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setParent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"setSubregistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"},{\"internalType\":\"contract IRegistryURIRenderer\",\"name\":\"renderer\",\"type\":\"address\"}],\"name\":\"setURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"details\":\"Error selector: `0x68c1425a`\"}],\"CannotSetPastExpiry(uint64)\":[{\"details\":\"Error selector: `0xf1d446c3`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1155InsufficientBalance(address,uint256,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\",\"tokenId\":\"Identifier number of a token.\"}}],\"ERC1155InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"ERC1155InvalidOperator(address)\":[{\"details\":\"Indicates a failure with the `operator` to be approved. Used in approvals.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC1155InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC1155InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC1155MissingApprovalForAll(address,address)\":[{\"details\":\"Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\",\"owner\":\"Address of the current owner of a token.\"}}],\"LabelAlreadyRegistered(string)\":[{\"details\":\"Error selector: `0xdef545a4`\"}],\"LabelAlreadyReserved(string)\":[{\"details\":\"Error selector: `0xf60759e0`\"}],\"LabelExpired(uint256)\":[{\"details\":\"Error selector: `0xc44e2374`\"}],\"TransferDisallowed(uint256,address)\":[{\"details\":\"Error selector: `0xe58f6d5a`\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"ExpiryUpdated(uint256,uint64,address)\":{\"params\":{\"newExpiry\":\"The new expiry of the label.\",\"sender\":\"The sender of the call to update the expiry.\",\"tokenId\":\"The token ID of the label.\"}},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label registered.\",\"labelHash\":\"The label hash registered.\",\"owner\":\"The owner of the label.\",\"sender\":\"The sender of the call to register.\",\"tokenId\":\"The token ID registered.\"}},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label reserved.\",\"labelHash\":\"The label hash reserved.\",\"sender\":\"The sender of the call to reserve.\",\"tokenId\":\"The token ID reserved.\"}},\"LabelUnregistered(uint256,address)\":{\"params\":{\"sender\":\"The sender of the call to unregister.\",\"tokenId\":\"The token ID unregistered.\"}},\"ParentUpdated(address,string,address)\":{\"params\":{\"label\":\"The new label.\",\"parent\":\"The new parent.\",\"sender\":\"The sender of the call to update the parent.\"}},\"ResolverUpdated(uint256,address,address)\":{\"params\":{\"resolver\":\"The new resolver.\",\"sender\":\"The sender of the call to update the resolver.\",\"tokenId\":\"The token ID of the label.\"}},\"SubregistryUpdated(uint256,address,address)\":{\"params\":{\"sender\":\"The sender of the call to update the subregistry.\",\"subregistry\":\"The new subregistry.\",\"tokenId\":\"The token ID of the label.\"}},\"TokenRegenerated(uint256,uint256)\":{\"params\":{\"newTokenId\":\"The new token ID.\",\"oldTokenId\":\"The old token ID.\"}},\"TokenResource(uint256,uint256)\":{\"params\":{\"resource\":\"The EAC resource.\",\"tokenId\":\"The token ID.\"}},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"},\"URIUpdated(string,address,address)\":{\"params\":{\"renderer\":\"The new render address.\",\"sender\":\"The sender of the call to update the URI.\",\"uri\":\"The new URI.\"}}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"params\":{\"account\":\"The account to get the balance for.\",\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"balance The balance of the token for the account. This will only ever be 1 or 0.\"}},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"`accounts` and `ids` must have the same length.\",\"params\":{\"accounts\":\"The accounts to get the balances for.\",\"ids\":\"The token IDs.\"},\"returns\":{\"_0\":\"batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\"}},\"constructor\":{\"params\":{\"labelStore\":\"The shared label database.\",\"roleBitmap\":\"The role bitmap granted to `rootAccount`.\",\"rootAccount\":\"Account granted root roles.\"}},\"findExpiry(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The expiry of the label.\"}},\"findOwner(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The owner of the label.\"}},\"findTokenId(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The token ID of the label.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getExpiry(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The expiry of the label, in seconds.\"}},\"getOwner(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token owner.\"}},\"getParent()\":{\"returns\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"getResolver(string)\":{\"params\":{\"label\":\"The label to fetch a resolver for.\"},\"returns\":{\"_0\":\"resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\"}},\"getResource(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The resource.\"}},\"getState(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"state\":\"The state of the label.\"}},\"getStatus(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The status of the label.\"}},\"getSubregistry(string)\":{\"params\":{\"label\":\"The label to resolve.\"},\"returns\":{\"_0\":\"The address of the registry for this label, or `address(0)` if none exists.\"}},\"getTokenId(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"account\":\"The account to get the approval for.\",\"operator\":\"The operator to get the approval for.\"},\"returns\":{\"_0\":\"approved The approval status.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"latestOwnerOf(uint256)\":{\"params\":{\"tokenId\":\"The token ID to query.\"},\"returns\":{\"_0\":\"The latest owner address.\"}},\"ownerOf(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The owner of the token.\"}},\"register(string,address,address,address,uint256,uint64)\":{\"params\":{\"expiry\":\"The expiry of the label, in seconds.\",\"label\":\"The label to register.\",\"owner\":\"The address of the owner of the label.\",\"registry\":\"The registry to set as the label.\",\"resolver\":\"The resolver to set for the label.\",\"roleBitmap\":\"The role bitmap to set for the label.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"renew(uint256,uint64)\":{\"details\":\"If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"newExpiry\":\"The new expiry, in seconds.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the tokens from.\",\"ids\":\"The token IDs.\",\"to\":\"The address to transfer the tokens to.\",\"values\":\"The amounts of tokens to transfer.\"}},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the token from.\",\"id\":\"The token ID.\",\"to\":\"The address to transfer the token to.\",\"value\":\"The amount of tokens to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"The approval status.\",\"operator\":\"The operator to set the approval for.\"}},\"setParent(address,string)\":{\"details\":\"Should emit `ParentUpdated`.\",\"params\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"setResolver(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"resolver\":\"The new resolver.\"}},\"setSubregistry(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"registry\":\"The new registry.\"}},\"setURI(string,address)\":{\"params\":{\"renderer\":\"The new renderer address.\",\"uri_\":\"The new URI.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"unregister(uint256)\":{\"details\":\"Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"}},\"uri(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The URI for the token.\"}}},\"stateVariables\":{\"__gap\":{\"details\":\"Storage gap for future changes.\"},\"_childLabel\":{\"details\":\"The child label of this registry.\"},\"_entries\":{\"details\":\"The entries of this registry.\"},\"_parentRegistry\":{\"details\":\"The parent registry of this registry.\"},\"_uri\":{\"details\":\"The metadata URI.\"},\"_uriRenderer\":{\"details\":\"The metadata renderer.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"notice\":\"Label expiry cannot be reduced.\"}],\"CannotSetPastExpiry(uint64)\":[{\"notice\":\"Label expiry cannot be before now.\"}],\"LabelAlreadyRegistered(string)\":[{\"notice\":\"Label is already registered.\"}],\"LabelAlreadyReserved(string)\":[{\"notice\":\"Label cannot be reserved again.\"}],\"LabelExpired(uint256)\":[{\"notice\":\"Label is expired/unregistered.\"}],\"TransferDisallowed(uint256,address)\":[{\"notice\":\"Transfer is not allowed due to missing transfer admin role.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"ExpiryUpdated(uint256,uint64,address)\":{\"notice\":\"Expiry of label was changed.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"notice\":\"A label was registered.\"},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"notice\":\"A label was reserved.\"},\"LabelUnregistered(uint256,address)\":{\"notice\":\"A label was unregistered.\"},\"ParentUpdated(address,string,address)\":{\"notice\":\"Parent was changed.\"},\"RegistryCreated()\":{\"notice\":\"A registry was created/initialized.\"},\"ResolverUpdated(uint256,address,address)\":{\"notice\":\"Resolver of label was changed.\"},\"SubregistryUpdated(uint256,address,address)\":{\"notice\":\"Subregistry of label was changed.\"},\"TokenRegenerated(uint256,uint256)\":{\"notice\":\"Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance.\"},\"TokenResource(uint256,uint256)\":{\"notice\":\"Associate a token with an EAC resource.\"},\"URIUpdated(string,address,address)\":{\"notice\":\"URI was changed.\"}},\"kind\":\"user\",\"methods\":{\"LABEL_STORE()\":{\"notice\":\"The shared label database.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"balanceOf(address,uint256)\":{\"notice\":\"Returns the balance of a token for an account.\"},\"balanceOfBatch(address[],uint256[])\":{\"notice\":\"Returns the balances of a batch of tokens for an account.\"},\"findExpiry(string)\":{\"notice\":\"Fetches the label expiry.\"},\"findOwner(string)\":{\"notice\":\"Fetches the label owner.\"},\"findTokenId(string)\":{\"notice\":\"Fetches the token ID for a label.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getExpiry(uint256)\":{\"notice\":\"Get expiry of label.\"},\"getOwner(uint256)\":{\"notice\":\"Get token owner from `anyId`.\"},\"getParent()\":{\"notice\":\"Get canonical \\\"location\\\" of this registry.\"},\"getResolver(string)\":{\"notice\":\"Fetches the resolver responsible for the specified label.\"},\"getResource(uint256)\":{\"notice\":\"Get `resource` from `anyId`.\"},\"getState(uint256)\":{\"notice\":\"Get the state of a label.\"},\"getStatus(uint256)\":{\"notice\":\"Get `Status` from `anyId`.\"},\"getSubregistry(string)\":{\"notice\":\"Fetches the registry for a label.\"},\"getTokenId(uint256)\":{\"notice\":\"Get `tokenId` from `anyId`.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Returns the approval for all operator.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"latestOwnerOf(uint256)\":{\"notice\":\"Get the latest owner of a token. If the token was burned, returns null.\"},\"ownerOf(uint256)\":{\"notice\":\"Returns the owner of a token.\"},\"register(string,address,address,address,uint256,uint64)\":{\"notice\":\"Registers a new label.\"},\"renew(uint256,uint64)\":{\"notice\":\"Renew a label.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Transfers multiple tokens from one address to another.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"notice\":\"Transfers a single token from one address to another.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Sets the approval for all operator.\"},\"setParent(address,string)\":{\"notice\":\"Change canonical \\\"location\\\".\"},\"setResolver(uint256,address)\":{\"notice\":\"Change resolver of label.\"},\"setSubregistry(uint256,address)\":{\"notice\":\"Change registry of label.\"},\"setURI(string,address)\":{\"notice\":\"Set the URI for the registry.\"},\"unregister(uint256)\":{\"notice\":\"Delete a label.\"},\"uri(uint256)\":{\"notice\":\"Returns the URI for a token.\"}},\"notice\":\"A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`) to resolve any of these to the canonical storage slot for the name. The registry maintains two independent version counters per name: - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form the EAC resource ID. This means a re-registered name gets a fresh permission scope. - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint) due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring changes to roles create new tokens and prevent frontrunning a transfer with a role revocation. Names are treated as `AVAILABLE` once `block.timestamp >= expiry`. State diagram: register() +ROLE_REGISTRAR +------------------->----------------------+ | | | renew() | renew() | +ROLE_RENEW | +ROLE_RENEW | +------+ | +------+ | | | | | | \\u028c \\u028c v v v | AVAILABLE --------> RESERVED -------------> REGISTERED >--+ \\u028c register() v register() v | w/owner=0 | +ROLE_REGISTER_RESERVED | | +ROLE_REGISTRAR | | | | | +--------<---------+------------<------------+ unregister() +ROLE_UNREGISTER\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/PermissionedRegistry.sol\":\"PermissionedRegistry\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155} from \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x35d120c427299af1525aaf07955314d9e36a62f14408eb93dec71a2e001f74d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/utils/ERC1155Utils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\nimport {IERC1155Errors} from \\\"../../../interfaces/draft-IERC6093.sol\\\";\\n\\n/**\\n * @dev Library that provide common ERC-1155 utility functions.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].\\n *\\n * _Available since v5.1._\\n */\\nlibrary ERC1155Utils {\\n /**\\n * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155Received(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver.onERC1155Received.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155BatchReceived(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x22f099c02c252dd1f6ddc464916ce683294a63b23b3c6ee3d290b77398e2474b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)\\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\\n\\npragma solidity ^0.8.20;\\n\\nimport {Comparators} from \\\"./Comparators.sol\\\";\\nimport {SlotDerivation} from \\\"./SlotDerivation.sol\\\";\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\nimport {Math} from \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to array types.\\n */\\nlibrary Arrays {\\n using SlotDerivation for bytes32;\\n using StorageSlot for bytes32;\\n\\n /**\\n * @dev Sort an array of uint256 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n uint256[] memory array,\\n function(uint256, uint256) pure returns (bool) comp\\n ) internal pure returns (uint256[] memory) {\\n _quickSort(_begin(array), _end(array), comp);\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\\n */\\n function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\\n sort(array, Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of address (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n address[] memory array,\\n function(address, address) pure returns (bool) comp\\n ) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of address in increasing order.\\n */\\n function sort(address[] memory array) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n bytes32[] memory array,\\n function(bytes32, bytes32) pure returns (bool) comp\\n ) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\\n */\\n function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\\n * at end (exclusive). Sorting follows the `comp` comparator.\\n *\\n * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\\n *\\n * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\\n * be used only if the limits are within a memory array.\\n */\\n function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\\n unchecked {\\n if (end - begin < 0x40) return;\\n\\n // Use first element as pivot\\n uint256 pivot = _mload(begin);\\n // Position where the pivot should be at the end of the loop\\n uint256 pos = begin;\\n\\n for (uint256 it = begin + 0x20; it < end; it += 0x20) {\\n if (comp(_mload(it), pivot)) {\\n // If the value stored at the iterator's position comes before the pivot, we increment the\\n // position of the pivot and move the value there.\\n pos += 0x20;\\n _swap(pos, it);\\n }\\n }\\n\\n _swap(begin, pos); // Swap pivot into place\\n _quickSort(begin, pos, comp); // Sort the left side of the pivot\\n _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first element of `array`.\\n */\\n function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\\n assembly (\\\"memory-safe\\\") {\\n ptr := add(array, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\\n * that comes just after the last element of the array.\\n */\\n function _end(uint256[] memory array) private pure returns (uint256 ptr) {\\n unchecked {\\n return _begin(array) + array.length * 0x20;\\n }\\n }\\n\\n /**\\n * @dev Load memory word (as a uint256) at location `ptr`.\\n */\\n function _mload(uint256 ptr) private pure returns (uint256 value) {\\n assembly {\\n value := mload(ptr)\\n }\\n }\\n\\n /**\\n * @dev Swaps the elements memory location `ptr1` and `ptr2`.\\n */\\n function _swap(uint256 ptr1, uint256 ptr2) private pure {\\n assembly {\\n let value1 := mload(ptr1)\\n let value2 := mload(ptr2)\\n mstore(ptr1, value2)\\n mstore(ptr2, value1)\\n }\\n }\\n\\n /// @dev Helper: low level cast address memory array to uint256 memory array\\n function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\\n function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast address comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(address, address) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(bytes32, bytes32) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /**\\n * @dev Searches a sorted `array` and returns the first index that contains\\n * a value greater or equal to `element`. If no such index exists (i.e. all\\n * values in the array are strictly less than `element`), the array length is\\n * returned. Time complexity O(log n).\\n *\\n * NOTE: The `array` is expected to be sorted in ascending order, and to\\n * contain no repeated elements.\\n *\\n * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\\n * support for repeated elements in the array. The {lowerBound} function should\\n * be used instead.\\n */\\n function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n low = mid + 1;\\n }\\n }\\n\\n // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\\n if (low > 0 && unsafeAccess(array, low - 1).value == element) {\\n return low - 1;\\n } else {\\n return low;\\n }\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value greater or equal than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\\n */\\n function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value strictly greater than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\\n */\\n function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {lowerBound}, but with an array in memory.\\n */\\n function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {upperBound}, but with an array in memory.\\n */\\n function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getAddressSlot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getBytes32Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getUint256Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(address[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(uint256[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55a4fdb408e3db950b48f4a6131e538980be8c5f48ee59829d92d66477140cd6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides a set of functions to compare values.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Comparators {\\n function lt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a < b;\\n }\\n\\n function gt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a > b;\\n }\\n}\\n\",\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\\n * the solidity language / compiler.\\n *\\n * 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.].\\n *\\n * Example usage:\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using StorageSlot for bytes32;\\n * using SlotDerivation for bytes32;\\n *\\n * // Declare a namespace\\n * string private constant _NAMESPACE = \\\"\\\"; // eg. OpenZeppelin.Slot\\n *\\n * function setValueInNamespace(uint256 key, address newValue) internal {\\n * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\\n * }\\n *\\n * function getValueInNamespace(uint256 key) internal view returns (address) {\\n * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {StorageSlot}.\\n *\\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\\n * upgrade safety will ignore the slots accessed through this library.\\n *\\n * _Available since v5.1._\\n */\\nlibrary SlotDerivation {\\n /**\\n * @dev Derive an ERC-7201 slot from a string (namespace).\\n */\\n function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\\n slot := and(keccak256(0x00, 0x20), not(0xff))\\n }\\n }\\n\\n /**\\n * @dev Add an offset to a slot to get the n-th element of a structure or an array.\\n */\\n function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\\n unchecked {\\n return bytes32(uint256(slot) + pos);\\n }\\n }\\n\\n /**\\n * @dev Derive the location of the first element in an array from the slot where the length is stored.\\n */\\n function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, slot)\\n result := keccak256(0x00, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, and(key, shr(96, not(0))))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, iszero(iszero(key)))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x67672e4ca1dafdcc661d4eba8475cfac631fa0933309258e3af7644b92e1fb26\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, msg.sender);\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _getRoles(resource, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _getRoles(ROOT_RESOURCE, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return _effectiveRoles(resource, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the roles bitmap for an account for permission checks.\\n function _getRoles(uint256 resource, address account) internal view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the effective roles bitmap for an account for permission checks.\\n function _effectiveRoles(uint256 resource, address account) private view returns (uint256) {\\n return _getRoles(ROOT_RESOURCE, account) | _getRoles(resource, account);\\n }\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n}\\n\",\"keccak256\":\"0x934655016f502e7a2f8e5cbd294ef48e85f238821f5608de5675c023f48037af\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Admin roles imply their corresponding regular roles.\\n function withAdminRolesApplied(uint256 roleBitmap) internal pure returns (uint256) {\\n roleBitmap >>= 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Derive roles bitmap from assignee counts.\\n /// @param counts Packed role counts (0-15) as `uint4x64`.\\n function fromCounts(uint256 counts) internal pure returns (uint256) {\\n return (counts | (counts >> 1) | (counts >> 2) | (counts >> 3)) & ALL_ROLES;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function hasZeroNybbles(uint256 value) internal pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 zeroNybbles;\\n unchecked {\\n zeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return zeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xc14f05abd508e75c9f16a35e31d0fb9f1f1dd904b65d058201c788a9ddd562eb\",\"license\":\"MIT\"},\"project/src/erc1155/ERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {\\n IERC1155MetadataURI\\n} from \\\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\\\";\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport {ERC1155Utils} from \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol\\\";\\nimport {Arrays} from \\\"@openzeppelin/contracts/utils/Arrays.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {IERC1155Singleton} from \\\"./interfaces/IERC1155Singleton.sol\\\";\\n\\n/// @notice ERC1155 variant enforcing exactly one owner per token ID.\\n///\\n/// Instead of the standard nested balance mapping (`id \\u2192 address \\u2192 balance`), uses a flat\\n/// `id \\u2192 address` ownership mapping. `balanceOf` returns 1 if the account is the owner,\\n/// 0 otherwise. Transferring value > 1 reverts.\\n///\\n/// Used by `PermissionedRegistry` to represent domain name ownership as non-divisible tokens.\\n/// The registry overrides `ownerOf` to add expiry and version validation on top of raw ownership.\\n///\\n/// @author OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC1155/ERC1155.sol)\\n/// @dev This contract has been modified from the implementation at the above link.\\nabstract contract ERC1155Singleton is\\n ERC165,\\n IERC1155Singleton,\\n IERC1155Errors,\\n IERC1155MetadataURI\\n{\\n using Arrays for uint256[];\\n\\n using Arrays for address[];\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Maps each token ID to its single owner address.\\n mapping(uint256 id => address account) private _owners;\\n\\n /// @dev Standard ERC1155 operator approval mapping.\\n mapping(address account => mapping(address operator => bool)) private _operatorApprovals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155Singleton).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Sets the approval for all operator.\\n /// @param operator The operator to set the approval for.\\n /// @param approved The approval status.\\n function setApprovalForAll(address operator, bool approved) public virtual {\\n _setApprovalForAll(msg.sender, operator, approved);\\n }\\n\\n /// @notice Transfers a single token from one address to another.\\n /// @param from The address to transfer the token from.\\n /// @param to The address to transfer the token to.\\n /// @param id The token ID.\\n /// @param value The amount of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `to` cannot be the zero address.\\n /// @dev If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.\\n /// @dev `from` must have a balance of tokens of type `id` of at least `value` amount.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the\\n /// acceptance magic value.\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data)\\n public\\n virtual\\n {\\n _checkApproval(from, msg.sender);\\n _safeTransferFrom(from, to, id, value, data);\\n }\\n\\n /// @notice Transfers multiple tokens from one address to another.\\n /// @param from The address to transfer the tokens from.\\n /// @param to The address to transfer the tokens to.\\n /// @param ids The token IDs.\\n /// @param values The amounts of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `ids` and `values` must have the same length.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the\\n /// acceptance magic value.\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n public\\n virtual\\n {\\n _checkApproval(from, msg.sender);\\n _safeBatchTransferFrom(from, to, ids, values, data);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 id) public view virtual returns (address owner) {\\n return _owners[id];\\n }\\n\\n /// @notice Returns the URI for a token.\\n /// @param id The token ID.\\n /// @return uri The URI for the token.\\n function uri(uint256 id) public view virtual returns (string memory uri);\\n\\n /// @notice Returns the balance of a token for an account.\\n /// @param account The account to get the balance for.\\n /// @param id The token ID.\\n /// @return balance The balance of the token for the account. This will only ever be 1 or 0.\\n function balanceOf(address account, uint256 id) public view virtual returns (uint256) {\\n return account != address(0) && ownerOf(id) == account ? 1 : 0;\\n }\\n\\n /// @notice Returns the balances of a batch of tokens for an account.\\n /// @param accounts The accounts to get the balances for.\\n /// @param ids The token IDs.\\n /// @return batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\\n /// @dev `accounts` and `ids` must have the same length.\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n returns (uint256[] memory)\\n {\\n if (accounts.length != ids.length) {\\n revert ERC1155InvalidArrayLength(ids.length, accounts.length);\\n }\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));\\n }\\n\\n return batchBalances;\\n }\\n\\n /// @notice Returns the approval for all operator.\\n /// @param account The account to get the approval for.\\n /// @param operator The operator to get the approval for.\\n /// @return approved The approval status.\\n function isApprovedForAll(address account, address operator) public view virtual returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Apply token updates for each pair in `ids` and `values`.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not the current owner or `value > 1`.\\n /// @dev This function does not perform ERC-1155 receiver acceptance checks.\\n /// @dev Emits `TransferSingle` when one token ID is updated, otherwise emits `TransferBatch`.\\n function _update(address from, address to, uint256[] memory ids, uint256[] memory values)\\n internal\\n virtual\\n {\\n if (ids.length != values.length) {\\n revert ERC1155InvalidArrayLength(ids.length, values.length);\\n }\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids.unsafeMemoryAccess(i);\\n uint256 value = values.unsafeMemoryAccess(i);\\n\\n if (value > 0) {\\n address owner = _owners[id];\\n if (owner != from) {\\n revert ERC1155InsufficientBalance(from, 0, value, id);\\n } else if (value > 1) {\\n revert ERC1155InsufficientBalance(from, 1, value, id);\\n }\\n _owners[id] = to;\\n }\\n }\\n\\n if (ids.length == 1) {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n emit TransferSingle(msg.sender, from, to, id, value);\\n } else {\\n emit TransferBatch(msg.sender, from, to, ids, values);\\n }\\n }\\n\\n /// @notice Apply token updates and run ERC-1155 receiver acceptance checks.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @param batch `true` if a batch operation.\\n /// @dev Calls `_update` before external receiver callbacks.\\n /// @dev If `to` is a contract, this calls `onERC1155Received` or `onERC1155BatchReceived`.\\n /// @dev Overriding is discouraged because post-callback state writes can introduce reentrancy bugs.\\n function _updateWithAcceptanceCheck(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data,\\n bool batch\\n )\\n internal\\n virtual\\n {\\n _update(from, to, ids, values);\\n if (to != address(0)) {\\n if (batch) {\\n ERC1155Utils.checkOnERC1155BatchReceived(msg.sender, from, to, ids, values, data);\\n } else {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n ERC1155Utils.checkOnERC1155Received(msg.sender, from, to, id, value, data);\\n }\\n }\\n }\\n\\n /// @notice Safely transfer `value` tokens of token ID `id` from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param id Token ID to transfer.\\n /// @param value Amount to transfer.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, to, ids, values, data, false);\\n }\\n\\n /// @notice Safely transfer multiple token IDs from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param ids Token IDs to transfer.\\n /// @param values Amounts to transfer for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferBatch`.\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n _updateWithAcceptanceCheck(from, to, ids, values, data, true);\\n }\\n\\n /// @notice Mint `value` tokens of token ID `id` to `to`.\\n /// @param to Address receiving the minted token.\\n /// @param id Token ID to mint.\\n /// @param value Amount to mint.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(address(0), to, ids, values, data, false);\\n }\\n\\n /// @notice Burn `value` tokens of token ID `id` from `from`.\\n /// @param from Address to burn from.\\n /// @param id Token ID to burn.\\n /// @param value Amount to burn.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not current owner or `value > 1`.\\n /// @dev Emits `TransferSingle`.\\n function _burn(address from, uint256 id, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, address(0), ids, values, \\\"\\\", false);\\n }\\n\\n /// @notice Set or clear approval for `operator` to manage all tokens owned by `owner`.\\n /// @param owner Token owner granting or revoking approval.\\n /// @param operator Operator receiving approval.\\n /// @param approved Approval status to set.\\n /// @dev Reverts with `ERC1155InvalidOperator` if `operator` is the zero address.\\n /// @dev Emits `ApprovalForAll`.\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n if (operator == address(0)) {\\n revert ERC1155InvalidOperator(address(0));\\n }\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Ensure operator is approved.\\n function _checkApproval(address from, address operator) private view {\\n if (from != operator && !isApprovedForAll(from, operator)) {\\n revert ERC1155MissingApprovalForAll(operator, from);\\n }\\n }\\n\\n /// @dev Gas-optimized assembly helper that creates two length-1 memory arrays without Solidity's\\n /// default zero-initialization overhead. Used to adapt single-token operations (`_mint`,\\n /// `_burn`, `_safeTransferFrom`) to the array-based `_update` function.\\n function _asSingletonArrays(uint256 element1, uint256 element2)\\n private\\n pure\\n returns (uint256[] memory array1, uint256[] memory array2)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Load the free memory pointer\\n array1 := mload(0x40)\\n // Set array length to 1\\n mstore(array1, 1)\\n // Store the single element at the next word after the length (where content starts)\\n mstore(add(array1, 0x20), element1)\\n\\n // Repeat for next array locating it right after the first array\\n array2 := add(array1, 0x40)\\n mstore(array2, 1)\\n mstore(add(array2, 0x20), element2)\\n\\n // Update the free memory pointer by pointing after the second array\\n mstore(0x40, add(array2, 0x40))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7e1c260a1b1791a63a658f049251b2b5390d9e11cdb20d99a2d115083251d37e\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/PermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IEnhancedAccessControl} from \\\"../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {ERC1155Singleton} from \\\"../erc1155/ERC1155Singleton.sol\\\";\\nimport {IERC1155Singleton} from \\\"../erc1155/interfaces/IERC1155Singleton.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {ILabelStore} from \\\"../utils/interfaces/ILabelStore.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./interfaces/IOwnedRegistry.sol\\\";\\nimport {IPermissionedRegistry} from \\\"./interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"./interfaces/IRegistry.sol\\\";\\nimport {IRegistryURIRenderer} from \\\"./interfaces/IRegistryURIRenderer.sol\\\";\\nimport {IStandardRegistry} from \\\"./interfaces/IStandardRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./interfaces/ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./interfaces/ITokenizedRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"./libraries/RegistryRolesLib.sol\\\";\\n\\n/// @notice A tokenized (ERC1155) registry with resource-scoped access control for subdomain management.\\n///\\n/// Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource\\n/// interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`)\\n/// to resolve any of these to the canonical storage slot for the name.\\n///\\n/// The registry maintains two independent version counters per name:\\n/// - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form\\n/// the EAC resource ID. This means a re-registered name gets a fresh permission scope.\\n/// - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint)\\n/// due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring\\n/// changes to roles create new tokens and prevent frontrunning a transfer with a role revocation.\\n///\\n/// Names are treated as `AVAILABLE` once `block.timestamp >= expiry`.\\n///\\n/// State diagram:\\n///\\n/// register()\\n/// +ROLE_REGISTRAR\\n/// +------------------->----------------------+\\n/// | |\\n/// | renew() | renew()\\n/// | +ROLE_RENEW | +ROLE_RENEW\\n/// | +------+ | +------+\\n/// | | | | | |\\n/// \\u028c \\u028c v v v |\\n/// AVAILABLE --------> RESERVED -------------> REGISTERED >--+\\n/// \\u028c register() v register() v\\n/// | w/owner=0 | +ROLE_REGISTER_RESERVED |\\n/// | +ROLE_REGISTRAR | |\\n/// | | |\\n/// +--------<---------+------------<------------+\\n/// unregister()\\n/// +ROLE_UNREGISTER\\n///\\ncontract PermissionedRegistry is ERC1155Singleton, EnhancedAccessControl, IPermissionedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n struct Entry {\\n /// @dev Incremented on unregister; combined with labelhash to form the EAC resource ID.\\n uint32 eacVersionId;\\n /// @dev Incremented on unregister and on token regeneration; combined with labelhash to form the ERC1155 token ID.\\n uint32 tokenVersionId;\\n /// @dev Child registry for this name.\\n IRegistry subregistry;\\n /// @dev Timestamp at or after which the name is considered expired/available.\\n uint64 expiry;\\n /// @dev Resolver address for this name.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The shared label database.\\n ILabelStore public immutable LABEL_STORE;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The parent registry of this registry.\\n IRegistry internal _parentRegistry;\\n\\n /// @dev The child label of this registry.\\n string internal _childLabel;\\n\\n /// @dev The metadata URI.\\n string internal _uri;\\n\\n /// @dev The metadata renderer.\\n IRegistryURIRenderer internal _uriRenderer;\\n\\n /// @dev The entries of this registry.\\n mapping(uint256 storageId => Entry entry) internal _entries;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param labelStore The shared label database.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n constructor(ILabelStore labelStore, address rootAccount, uint256 roleBitmap) {\\n emit RegistryCreated();\\n LABEL_STORE = labelStore;\\n _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false);\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(IERC165, ERC1155Singleton, EnhancedAccessControl)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IPermissionedRegistry).interfaceId ||\\n interfaceId == type(IStandardRegistry).interfaceId ||\\n interfaceId == type(ITokenizedRegistry).interfaceId ||\\n interfaceId == type(ITemporalRegistry).interfaceId ||\\n interfaceId == type(IOwnedRegistry).interfaceId ||\\n interfaceId == type(IRegistry).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IStandardRegistry\\n function setSubregistry(uint256 anyId, IRegistry registry) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_SUBREGISTRY);\\n entry.subregistry = registry;\\n emit SubregistryUpdated(tokenId, registry, msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setResolver(uint256 anyId, address resolver) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_RESOLVER);\\n entry.resolver = resolver;\\n emit ResolverUpdated(tokenId, resolver, msg.sender);\\n }\\n\\n /// @notice Set the URI for the registry.\\n /// @param uri_ The new URI.\\n /// @param renderer The new renderer address.\\n function setURI(string calldata uri_, IRegistryURIRenderer renderer)\\n public\\n virtual\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_URI)\\n {\\n _uri = uri_;\\n _uriRenderer = renderer;\\n emit URIUpdated(uri_, address(renderer), msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setParent(IRegistry parent, string memory label)\\n public\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_PARENT)\\n {\\n _parentRegistry = parent;\\n _childLabel = label;\\n emit ParentUpdated(parent, label, msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n public\\n virtual\\n returns (uint256)\\n {\\n return _register(label, owner, registry, resolver, roleBitmap, expiry, true);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\\n function unregister(uint256 anyId) public {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_UNREGISTER);\\n emit LabelUnregistered(tokenId, msg.sender);\\n address owner = super.ownerOf(tokenId);\\n if (owner != address(0)) {\\n _burn(owner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n }\\n entry.expiry = uint64(block.timestamp);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev If `REGISTERED | RESERVED`, requires `ROLE_RENEW`.\\n /// If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\\n function renew(uint256 anyId, uint64 newExpiry) public override {\\n Entry storage entry = _entry(anyId);\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n uint64 expiry = entry.expiry;\\n if (_isExpired(expiry)) {\\n if (expiry == 0 || !_canRevive(tokenId, msg.sender)) {\\n revert LabelExpired(tokenId); // never registered OR cannot revive\\n }\\n } else {\\n _checkRoles(_constructResource(anyId, entry), RegistryRolesLib.ROLE_RENEW, msg.sender);\\n }\\n if (newExpiry < expiry) {\\n revert CannotReduceExpiry(expiry, newExpiry);\\n }\\n entry.expiry = newExpiry;\\n emit ExpiryUpdated(tokenId, newExpiry, msg.sender);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function grantRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.grantRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function revokeRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.revokeRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IRegistry\\n function getSubregistry(string calldata label) public view virtual returns (IRegistry) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? IRegistry(address(0)) : entry.subregistry;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getResolver(string calldata label) public view virtual returns (address) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? address(0) : entry.resolver;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getParent() public view returns (IRegistry parent, string memory label) {\\n return (_parentRegistry, _childLabel);\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) public view virtual returns (bool) {\\n return hasRootRoles(RegistryRolesLib.ROLE_CAN_NAME, namer);\\n }\\n\\n /// @inheritdoc ITemporalRegistry\\n function findExpiry(string calldata label) public view returns (uint64) {\\n return getExpiry(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc IOwnedRegistry\\n function findOwner(string calldata label) public view returns (address) {\\n return getOwner(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ITokenizedRegistry\\n function findTokenId(string calldata label) public view returns (uint256) {\\n return getTokenId(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ERC1155Singleton\\n function uri(uint256 tokenId) public view override returns (string memory) {\\n return\\n address(_uriRenderer) != address(0)\\n ? _uriRenderer.renderURI(this, tokenId)\\n : _uri;\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function getExpiry(uint256 anyId) public view returns (uint64) {\\n return _entry(anyId).expiry;\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getResource(uint256 anyId) public view returns (uint256) {\\n return _constructResource(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getTokenId(uint256 anyId) public view returns (uint256) {\\n return _constructTokenId(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getOwner(uint256 anyId) public view returns (address) {\\n return _isExpired(getExpiry(anyId)) ? address(0) : super.ownerOf(getTokenId(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getStatus(uint256 anyId) public view returns (Status) {\\n Entry storage entry = _entry(anyId);\\n return _constructStatus(entry.expiry, super.ownerOf(_constructTokenId(anyId, entry)));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getState(uint256 anyId) public view returns (State memory state) {\\n Entry storage entry = _entry(anyId);\\n uint64 expiry = entry.expiry;\\n state.expiry = expiry;\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n state.tokenId = tokenId;\\n state.resource = _constructResource(anyId, entry);\\n address owner = super.ownerOf(tokenId);\\n state.latestOwner = owner;\\n state.status = _constructStatus(expiry, owner);\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function latestOwnerOf(uint256 tokenId) public view returns (address) {\\n return super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 tokenId)\\n public\\n view\\n override(ERC1155Singleton, IERC1155Singleton)\\n returns (address)\\n {\\n Entry storage entry = _entry(tokenId);\\n return\\n tokenId != _constructTokenId(tokenId, entry) || _isExpired(entry.expiry)\\n ? address(0)\\n : super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 anyId, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roles(getResource(anyId), account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 anyId)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roleCount(getResource(anyId));\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasAssignees(getResource(anyId), roleBitmap);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256 counts, uint256 mask)\\n {\\n return super.getAssigneeCount(getResource(anyId), roleBitmap);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev If `AVAILABLE`, requires `ROLE_REGISTRAR` on root and status becomes `REGISTERED`.\\n /// * If `owner` is null (`roleBitmap` must be 0), status becomes `RESERVED`.\\n /// If `RESERVED`, requires `ROLE_REGISTER_RESERVED` on root and status becomes `REGISTERED`.\\n /// * If `expiry` is 0, uses current expiry.\\n function _register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry,\\n bool checkRoles\\n )\\n internal\\n returns (uint256 tokenId)\\n {\\n LABEL_STORE.setLabel(label);\\n uint256 labelId = LibLabel.id(label);\\n Entry storage entry = _entry(labelId);\\n tokenId = _constructTokenId(labelId, entry);\\n address prevOwner = super.ownerOf(tokenId);\\n if (_isExpired(entry.expiry)) {\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTRAR, msg.sender);\\n }\\n if (owner == address(0) && roleBitmap != 0) {\\n revert EACCannotGrantRoles(ROOT_RESOURCE, roleBitmap, msg.sender); // strict\\n }\\n } else {\\n if (prevOwner != address(0)) {\\n revert LabelAlreadyRegistered(label); // cannot overwrite REGISTERED\\n } else if (owner == address(0)) {\\n revert LabelAlreadyReserved(label); // cannot overwrite RESERVED\\n }\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTER_RESERVED, msg.sender);\\n }\\n if (expiry == 0) {\\n expiry = entry.expiry; // use RESERVED expiry\\n }\\n roleBitmap |= RegistryRolesLib.ROLE_WAS_RESERVED; // remember\\n }\\n if (owner == address(0) ? expiry == 0 : _isExpired(expiry)) {\\n revert CannotSetPastExpiry(expiry);\\n }\\n if (prevOwner != address(0)) {\\n _burn(prevOwner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n tokenId = _constructTokenId(tokenId, entry);\\n }\\n entry.expiry = expiry;\\n entry.subregistry = registry;\\n entry.resolver = resolver;\\n if (owner == address(0)) {\\n emit LabelReserved(tokenId, bytes32(labelId), label, expiry, msg.sender);\\n } else {\\n emit LabelRegistered(tokenId, bytes32(labelId), label, owner, expiry, msg.sender);\\n _mint(owner, tokenId, 1, \\\"\\\");\\n uint256 resource = _constructResource(tokenId, entry);\\n assert(resource != ROOT_RESOURCE);\\n emit TokenResource(tokenId, resource);\\n _grantRoles(resource, roleBitmap, owner, false);\\n }\\n if (address(registry) != address(0)) {\\n emit SubregistryUpdated(tokenId, registry, msg.sender);\\n }\\n if (address(resolver) != address(0)) {\\n emit ResolverUpdated(tokenId, resolver, msg.sender);\\n }\\n }\\n\\n /// @dev Override `ERC1155Singleton._update()` to transfer the roles to the new owner if the token is transferred.\\n function _update(address from, address to, uint256[] memory tokenIds, uint256[] memory amounts)\\n internal\\n override\\n {\\n super._update(from, to, tokenIds, amounts); // ensures amounts[i] is 0 or 1\\n if (to != address(0) && from != address(0)) {\\n // only transfers (skip mint and burn)\\n for (uint256 i; i < tokenIds.length; ++i) {\\n uint256 tokenId = tokenIds[i];\\n // only check ROLE_CAN_TRANSFER_ADMIN on original owner (from)\\n // ROLE_CAN_TRANSFER_ADMIN is technically a property of the token\\n if (!hasRoles(tokenId, RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, from)) {\\n revert TransferDisallowed(tokenId, from);\\n } else if (amounts[i] > 0) {\\n _transferRoles(getResource(tokenId), from, to, false);\\n }\\n }\\n }\\n }\\n\\n /// @dev Override the base registry _onRolesGranted function to regenerate the token when the roles are granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Override the base registry _onRolesRevoked function to regenerate the token when the roles are revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Bump `tokenVersionId` via burn+mint if token is not expired.\\n function _regenerate(uint256 resource) internal {\\n if (resource != ROOT_RESOURCE) {\\n Entry storage entry = _entry(resource);\\n uint256 tokenId = _constructTokenId(resource, entry);\\n address owner = super.ownerOf(tokenId); // grant/revoke only on registered\\n _burn(owner, tokenId, 1);\\n ++entry.tokenVersionId;\\n uint256 newTokenId = _constructTokenId(tokenId, entry);\\n emit TokenRegenerated(tokenId, newTokenId); // resource is unchanged\\n _mint(owner, newTokenId, 1, \\\"\\\");\\n }\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token non-admin roles can only be granted to registered tokens.\\n ///\\n /// Token admin roles are only assigned during name registration to maintain\\n /// controlled permission management. This ensures that role delegation\\n /// follows the intended security model where admin privileges are granted at\\n /// registration time and cannot be arbitrarily granted afterward.\\n ///\\n /// Root admin roles are unaffected.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles (regular roles only, not admin roles).\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n if (resource != ROOT_RESOURCE && getOwner(resource) == address(0)) {\\n return 0;\\n }\\n uint256 roleBitmap = super._getSettableRoles(resource, account);\\n return resource == ROOT_RESOURCE ? roleBitmap : roleBitmap >> 128;\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// * if caller is approved by token owner, combine the caller's roles with the owner's roles\\n ///\\n function _getRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n override\\n returns (uint256 roleBitmap)\\n {\\n roleBitmap = super._getRoles(resource, account);\\n if (resource != ROOT_RESOURCE) {\\n address owner = getOwner(resource);\\n if (owner != address(0) && owner != account && isApprovedForAll(owner, account)) {\\n roleBitmap |= super._getRoles(resource, owner);\\n }\\n }\\n }\\n\\n /// @dev Zeroes version bits in `anyId` to return the canonical storage entry for the name.\\n function _entry(uint256 anyId) internal view returns (Entry storage) {\\n return _entries[LibLabel.withVersion(anyId, 0)];\\n }\\n\\n /// @dev Determine if token can be revived.\\n function _canRevive(\\n uint256 /*tokenId*/,\\n address sender\\n )\\n internal\\n view\\n virtual\\n returns (bool)\\n {\\n return hasRootRoles(RegistryRolesLib.ROLE_RENEW, sender);\\n }\\n\\n /// @dev Assert token is not expired and caller has necessary roles.\\n function _checkExpiryAndTokenRoles(uint256 anyId, uint256 roleBitmap)\\n internal\\n view\\n returns (uint256 tokenId, Entry storage entry)\\n {\\n entry = _entry(anyId);\\n tokenId = _constructTokenId(anyId, entry);\\n if (_isExpired(entry.expiry)) {\\n revert LabelExpired(tokenId);\\n }\\n _checkRoles(_constructResource(anyId, entry), roleBitmap, msg.sender);\\n }\\n\\n /// @dev Internal logic for expired status.\\n function _isExpired(uint64 expiry) internal view returns (bool) {\\n return block.timestamp >= expiry;\\n }\\n\\n /// @dev Create `resource` from parts.\\n /// Does nothing if `ROOT_RESOURCE`.\\n /// Returns next resource if expired.\\n function _constructResource(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n if (anyId == ROOT_RESOURCE) {\\n return anyId;\\n }\\n return\\n LibLabel.withVersion(\\n anyId,\\n _isExpired(entry.expiry)\\n ? entry.eacVersionId + 1\\n : entry.eacVersionId\\n );\\n }\\n\\n /// @dev Create `tokenId` from parts.\\n function _constructTokenId(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n return LibLabel.withVersion(anyId, entry.tokenVersionId);\\n }\\n\\n /// @dev Create `Status` from parts.\\n function _constructStatus(uint64 expiry, address owner) internal view returns (Status) {\\n if (_isExpired(expiry)) {\\n return Status.AVAILABLE;\\n } else if (owner == address(0)) {\\n return Status.RESERVED;\\n } else {\\n return Status.REGISTERED;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7df0d16fb74e67612b88f2143f142410c70a4079a21c0980b2063824e291942b\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryURIRenderer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6c55e19b`\\ninterface IRegistryURIRenderer {\\n /// @notice Generate URI for `tokenId` from `registry`.\\n /// @param registry The registry.\\n /// @param tokenId The token ID in the registry.\\n /// @return The generated URI.\\n function renderURI(IRegistry registry, uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa6ea64ff73d10fa58118ae9c0d0c2caa72f2f3488776227a22bd0cd9cd6586f6\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 39: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 62: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x01771816c1c5b16c10f29b33083dbd1cc2eb64dbfec60fb45a1a1969cec06624\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/interfaces/ILabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @notice Interface for a shared label database.\\n/// @dev Interface selector: `0x0d48fe93`\\ninterface ILabelStore {\\n /// @notice A label was recorded.\\n /// @param labelHash The hash of `label`.\\n /// @param label The recorded label.\\n event Label(bytes32 indexed labelHash, string label);\\n\\n /// @notice Ensure `label` can be inverted from `anyId`.\\n /// @param label The label.\\n function setLabel(string calldata label) external;\\n\\n /// @notice Invert `anyId` to the corresponding label.\\n /// @param anyId The truncated labelhash.\\n /// @return The label or null if unknown.\\n function getLabel(uint256 anyId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 24185, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_owners", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 24192, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 21770, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_roles", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 21775, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_roleCount", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 21780, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "__gap", + "offset": 0, + "slot": "4", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 28818, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_parentRegistry", + "offset": 0, + "slot": "260", + "type": "t_contract(IRegistry)30865" + }, + { + "astId": 28821, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_childLabel", + "offset": 0, + "slot": "261", + "type": "t_string_storage" + }, + { + "astId": 28824, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_uri", + "offset": 0, + "slot": "262", + "type": "t_string_storage" + }, + { + "astId": 28828, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_uriRenderer", + "offset": 0, + "slot": "263", + "type": "t_contract(IRegistryURIRenderer)30980" + }, + { + "astId": 28834, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_entries", + "offset": 0, + "slot": "264", + "type": "t_mapping(t_uint256,t_struct(Entry)28810_storage)" + }, + { + "astId": 28839, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "__gap", + "offset": 0, + "slot": "265", + "type": "t_array(t_uint256)256_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRegistry)30865": { + "encoding": "inplace", + "label": "contract IRegistry", + "numberOfBytes": "20" + }, + "t_contract(IRegistryURIRenderer)30980": { + "encoding": "inplace", + "label": "contract IRegistryURIRenderer", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "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_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_struct(Entry)28810_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct PermissionedRegistry.Entry)", + "numberOfBytes": "32", + "value": "t_struct(Entry)28810_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Entry)28810_storage": { + "encoding": "inplace", + "label": "struct PermissionedRegistry.Entry", + "members": [ + { + "astId": 28796, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "eacVersionId", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 28799, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "tokenVersionId", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 28803, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "subregistry", + "offset": 8, + "slot": "0", + "type": "t_contract(IRegistry)30865" + }, + { + "astId": 28806, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "expiry", + "offset": 0, + "slot": "1", + "type": "t_uint64" + }, + { + "astId": 28809, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "resolver", + "offset": 8, + "slot": "1", + "type": "t_address" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "notice": "Label expiry cannot be reduced." + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "notice": "Label expiry cannot be before now." + } + ], + "LabelAlreadyRegistered(string)": [ + { + "notice": "Label is already registered." + } + ], + "LabelAlreadyReserved(string)": [ + { + "notice": "Label cannot be reserved again." + } + ], + "LabelExpired(uint256)": [ + { + "notice": "Label is expired/unregistered." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "notice": "Transfer is not allowed due to missing transfer admin role." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "ExpiryUpdated(uint256,uint64,address)": { + "notice": "Expiry of label was changed." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "notice": "A label was registered." + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "notice": "A label was reserved." + }, + "LabelUnregistered(uint256,address)": { + "notice": "A label was unregistered." + }, + "ParentUpdated(address,string,address)": { + "notice": "Parent was changed." + }, + "RegistryCreated()": { + "notice": "A registry was created/initialized." + }, + "ResolverUpdated(uint256,address,address)": { + "notice": "Resolver of label was changed." + }, + "SubregistryUpdated(uint256,address,address)": { + "notice": "Subregistry of label was changed." + }, + "TokenRegenerated(uint256,uint256)": { + "notice": "Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance." + }, + "TokenResource(uint256,uint256)": { + "notice": "Associate a token with an EAC resource." + }, + "URIUpdated(string,address,address)": { + "notice": "URI was changed." + } + }, + "kind": "user", + "methods": { + "LABEL_STORE()": { + "notice": "The shared label database." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "balanceOf(address,uint256)": { + "notice": "Returns the balance of a token for an account." + }, + "balanceOfBatch(address[],uint256[])": { + "notice": "Returns the balances of a batch of tokens for an account." + }, + "findExpiry(string)": { + "notice": "Fetches the label expiry." + }, + "findOwner(string)": { + "notice": "Fetches the label owner." + }, + "findTokenId(string)": { + "notice": "Fetches the token ID for a label." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getExpiry(uint256)": { + "notice": "Get expiry of label." + }, + "getOwner(uint256)": { + "notice": "Get token owner from `anyId`." + }, + "getParent()": { + "notice": "Get canonical \"location\" of this registry." + }, + "getResolver(string)": { + "notice": "Fetches the resolver responsible for the specified label." + }, + "getResource(uint256)": { + "notice": "Get `resource` from `anyId`." + }, + "getState(uint256)": { + "notice": "Get the state of a label." + }, + "getStatus(uint256)": { + "notice": "Get `Status` from `anyId`." + }, + "getSubregistry(string)": { + "notice": "Fetches the registry for a label." + }, + "getTokenId(uint256)": { + "notice": "Get `tokenId` from `anyId`." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "isApprovedForAll(address,address)": { + "notice": "Returns the approval for all operator." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "latestOwnerOf(uint256)": { + "notice": "Get the latest owner of a token. If the token was burned, returns null." + }, + "ownerOf(uint256)": { + "notice": "Returns the owner of a token." + }, + "register(string,address,address,address,uint256,uint64)": { + "notice": "Registers a new label." + }, + "renew(uint256,uint64)": { + "notice": "Renew a label." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "notice": "Transfers multiple tokens from one address to another." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "notice": "Transfers a single token from one address to another." + }, + "setApprovalForAll(address,bool)": { + "notice": "Sets the approval for all operator." + }, + "setParent(address,string)": { + "notice": "Change canonical \"location\"." + }, + "setResolver(uint256,address)": { + "notice": "Change resolver of label." + }, + "setSubregistry(uint256,address)": { + "notice": "Change registry of label." + }, + "setURI(string,address)": { + "notice": "Set the URI for the registry." + }, + "unregister(uint256)": { + "notice": "Delete a label." + }, + "uri(uint256)": { + "notice": "Returns the URI for a token." + } + }, + "notice": "A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`) to resolve any of these to the canonical storage slot for the name. The registry maintains two independent version counters per name: - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form the EAC resource ID. This means a re-registered name gets a fresh permission scope. - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint) due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring changes to roles create new tokens and prevent frontrunning a transfer with a role revocation. Names are treated as `AVAILABLE` once `block.timestamp >= expiry`. State diagram: register() +ROLE_REGISTRAR +------------------->----------------------+ | | | renew() | renew() | +ROLE_RENEW | +ROLE_RENEW | +------+ | +------+ | | | | | | ʌ ʌ v v v | AVAILABLE --------> RESERVED -------------> REGISTERED >--+ ʌ register() v register() v | w/owner=0 | +ROLE_REGISTER_RESERVED | | +ROLE_REGISTRAR | | | | | +--------<---------+------------<------------+ unregister() +ROLE_UNREGISTER", + "version": 1 + }, + "argsData": "0x000000000000000000000000b03524289c16424f71802a1794c29c7bd1b9f57700000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d30100000000000000000000100001011101000000000000000000001000000100", + "transaction": { + "hash": "0x5700e0b4ea84267da71a17def83bcdcdc49d7b1b6ee1b1de8b718e7ca5f2a7e4", + "nonce": "0x4b", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x17cc37f0762dc26123a3f9488379009a8a0410c76be8f20a9d5cccf274d9cbfb", + "blockNumber": "0xaa56ff", + "transactionIndex": "0x68" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ETHRenewerV1.json b/contracts/deployments/sepolia/ETHRenewerV1.json new file mode 100644 index 000000000..262e2773e --- /dev/null +++ b/contracts/deployments/sepolia/ETHRenewerV1.json @@ -0,0 +1,905 @@ +{ + "address": "0x1be516ae1b72765ae55bd5e9ca628c9058a1c622", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + }, + { + "internalType": "uint64", + "name": "gracePeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "bonusPeriod", + "type": "uint64" + }, + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "address", + "name": "wrappedController", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "minDuration", + "type": "uint64" + } + ], + "name": "DurationTooShort", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "NameNotRenewable", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NameRenewed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + } + ], + "name": "RentPriceOracleUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "BASE_REGISTRAR", + "outputs": [ + { + "internalType": "contract BaseRegistrarImplementation", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BENEFICIARY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GRACE_PERIOD", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_RENEW_DURATION", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WRAPPED_CONTROLLER", + "outputs": [ + { + "internalType": "contract IWrappedETHRegistrarController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getRemainingGracePeriod", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRenewPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "isRenewable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "referrer", + "type": "bytes32" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rentPriceOracle", + "outputs": [ + { + "internalType": "contract IRentPriceOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setRegistrarResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRentPriceOracle", + "name": "oracle", + "type": "address" + } + ], + "name": "setRentPriceOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "labels", + "type": "string[]" + } + ], + "name": "syncWrapper", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferRegistrarOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "ETHRenewerV1", + "sourceName": "src/registrar/ETHRenewerV1.sol", + "bytecode": "0x610160604052348015610010575f80fd5b50604051611ad2380380611ad283398101604081905261002f916101fa565b87878787836001600160a01b03811661006157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61006a81610179565b506001600160a01b0383811660805282811660a052600180546001600160a01b03191691831691821790556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac99060200160405180910390a15050505083836100d8919061029e565b6001600160401b0390811660c052841660e0526001600160a01b03821661010081905260408051632b20e39760e01b81529051632b20e397916004808201926020929091908290030181865afa158015610134573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061015891906102d1565b6001600160a01b03908116610120521661014052506102f395505050505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146101dc575f80fd5b50565b80516001600160401b03811681146101f5575f80fd5b919050565b5f805f805f805f80610100898b031215610212575f80fd5b885161021d816101c8565b60208a015190985061022e816101c8565b60408a015190975061023f816101c8565b60608a0151909650610250816101c8565b945061025e60808a016101df565b935061026c60a08a016101df565b925060c089015161027c816101c8565b60e08a015190925061028d816101c8565b809150509295985092959890939650565b6001600160401b038181168382160190808211156102ca57634e487b7160e01b5f52601160045260245ffd5b5092915050565b5f602082840312156102e1575f80fd5b81516102ec816101c8565b9392505050565b60805160a05160c05160e0516101005161012051610140516117176103bb5f395f81816103420152610aa801525f818161031b0152818161051a015281816105b501528181610a4501528181610ba901526110bf01525f81816101bc01528181610a1d0152610b8101525f81816106cb0152610db301525f81816102f4015281816106ec0152818161077b01526107cc01525f818161020e01526108c801525f818161025601528181610406015281816105fb015281816109320152610eca01526117175ff3fe608060405234801561000f575f80fd5b5060043610610163575f3560e01c8063802295ef116100c7578063c1a287e21161007d578063dba1002111610063578063dba100211461033d578063ddf0effc14610364578063f2fde38b14610385575f80fd5b8063c1a287e2146102ef578063cd93adf514610316575f80fd5b80638da5cb5b116100ad5780638da5cb5b146102b9578063a2596702146102c9578063a2a11fbe146102dc575f80fd5b8063802295ef1461029357806389d779c3146102a6575f80fd5b80632f99c6cc1161011c57806347500708116101025780634750070814610251578063715018a6146102785780637b39ba1614610280575f80fd5b80632f99c6cc14610209578063307a64a514610230575f80fd5b8063154fbf151161014c578063154fbf15146101a2578063192cf07d146101b7578063198e4236146101f6575f80fd5b806301ffc9a714610167578063130d6f001461018f575b5f80fd5b61017a61017536600461121e565b610398565b60405190151581526020015b60405180910390f35b61017a61019d36600461128a565b610400565b6101b56101b03660046112dd565b6104da565b005b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610186565b6101b56102043660046112dd565b610575565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b610238600181565b60405167ffffffffffffffff9091168152602001610186565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b6101b56105e4565b6001546101de906001600160a01b031681565b6102386102a136600461128a565b6105f7565b6101b56102b436600461130d565b610808565b5f546001600160a01b03166101de565b6101b56102d7366004611378565b6109ed565b6101b56102ea3660046112dd565b610c04565b6102387f000000000000000000000000000000000000000000000000000000000000000081565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b6103776103723660046113e7565b610c6d565b604051908152602001610186565b6101b56103933660046112dd565b610cfb565b5f6001600160e01b031982167f06aaeb320000000000000000000000000000000000000000000000000000000014806103fa57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b5f6104d37f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861047186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610d5692505050565b6040518263ffffffff1660e01b815260040161048f91815260200190565b60a060405180830381865afa1580156104aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ce9190611466565b610d61565b9392505050565b6104e2610dfd565b6040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f2fde38b906024015b5f604051808303815f87803b15801561055c575f80fd5b505af115801561056e573d5f803e3d5ffd5b5050505050565b61057d610dfd565b6040517f4e543b260000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634e543b2690602401610545565b6105ec610dfd565b6105f55f610e42565b565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861066686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610d5692505050565b6040518263ffffffff1660e01b815260040161068491815260200190565b60a060405180830381865afa15801561069f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106c39190611466565b90505f6107107f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061150c565b60408301519091506001600160a01b031615801561074557508067ffffffffffffffff16826020015167ffffffffffffffff16115b156107fe575f81836020015161075b919061150c565b90504267ffffffffffffffff808316908216108015906107b757506107a07f000000000000000000000000000000000000000000000000000000000000000083611534565b67ffffffffffffffff168167ffffffffffffffff16105b156107fb576107c6828261150c565b6107f0907f000000000000000000000000000000000000000000000000000000000000000061150c565b9450505050506103fa565b50505b505f949350505050565b5f610814868686610e9e565b90505f8482602001516108279190611534565b60015460208401516040517f3ad860830000000000000000000000000000000000000000000000000000000081529293505f926001600160a01b0390921691633ad8608391610880918c918c918c908c9060040161157d565b602060405180830381865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf91906115c3565b90506108ed85337f00000000000000000000000000000000000000000000000000000000000000008461102f565b60608301516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff831660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b15801561097b575f80fd5b505af115801561098d573d5f803e3d5ffd5b5050505061099c8888886110bd565b8383606001517fbd0c01e5bf66003280556423db4a8bf79043c146ac57f657c30049dd433166498a8a8a878b886040516109db969594939291906115da565b60405180910390a35050505050505050565b6040517fa7fc7a070000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063a7fc7a07906024015f604051808303815f87803b158015610a86575f80fd5b505af1158015610a98573d5f803e3d5ffd5b505050505f5b81811015610b50577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663acf1a841848484818110610ae757610ae7611625565b9050602002810190610af99190611639565b5f6040518463ffffffff1660e01b8152600401610b189392919061167c565b5f604051808303815f87803b158015610b2f575f80fd5b505af1158015610b41573d5f803e3d5ffd5b50505050806001019050610a9e565b506040517ff6a74ed70000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f6a74ed7906024015f604051808303815f87803b158015610bea575f80fd5b505af1158015610bfc573d5f803e3d5ffd5b505050505050565b610c0c610dfd565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac99060200160405180910390a150565b6001545f906001600160a01b0316633ad860838686610c8d828289610e9e565b6020015187876040518663ffffffff1660e01b8152600401610cb395949392919061157d565b602060405180830381865afa158015610cce573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cf291906115c3565b95945050505050565b610d03610dfd565b6001600160a01b038116610d4a576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b610d5381610e42565b50565b805160209091012090565b5f600182516002811115610d7757610d7761169f565b14806103fa57505f82516002811115610d9257610d9261169f565b148015610daa575060408201516001600160a01b0316155b80156103fa57507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16826020015167ffffffffffffffff1642610df691906116b3565b1092915050565b5f546001600160a01b031633146105f5576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610d41565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610f3586868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610d5692505050565b6040518263ffffffff1660e01b8152600401610f5391815260200190565b60a060405180830381865afa158015610f6e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f929190611466565b9050610f9d81610d61565b610fd75783836040517f1caefaa0000000000000000000000000000000000000000000000000000000008152600401610d419291906116c6565b600167ffffffffffffffff831610156104d3576040517fa096b84400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8316600482015260016024820152604401610d41565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526110b7908590611199565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c475abff61112a85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610d5692505050565b6040516001600160e01b031960e084901b168152600481019190915267ffffffffffffffff841660248201526044016020604051808303815f875af1158015611175573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110b791906115c3565b5f8060205f8451602086015f885af1806111b8576040513d5f823e3d81fd5b50505f513d915081156111cf5780600114156111dc565b6001600160a01b0384163b155b156110b7576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610d41565b5f6020828403121561122e575f80fd5b81356001600160e01b0319811681146104d3575f80fd5b5f8083601f840112611255575f80fd5b50813567ffffffffffffffff81111561126c575f80fd5b602083019150836020828501011115611283575f80fd5b9250929050565b5f806020838503121561129b575f80fd5b823567ffffffffffffffff8111156112b1575f80fd5b6112bd85828601611245565b90969095509350505050565b6001600160a01b0381168114610d53575f80fd5b5f602082840312156112ed575f80fd5b81356104d3816112c9565b67ffffffffffffffff81168114610d53575f80fd5b5f805f805f60808688031215611321575f80fd5b853567ffffffffffffffff811115611337575f80fd5b61134388828901611245565b9096509450506020860135611357816112f8565b92506040860135611367816112c9565b949793965091946060013592915050565b5f8060208385031215611389575f80fd5b823567ffffffffffffffff808211156113a0575f80fd5b818501915085601f8301126113b3575f80fd5b8135818111156113c1575f80fd5b8660208260051b85010111156113d5575f80fd5b60209290920196919550909350505050565b5f805f80606085870312156113fa575f80fd5b843567ffffffffffffffff811115611410575f80fd5b61141c87828801611245565b9095509350506020850135611430816112f8565b91506040850135611440816112c9565b939692955090935050565b8051611456816112f8565b919050565b8051611456816112c9565b5f60a08284031215611476575f80fd5b60405160a0810181811067ffffffffffffffff821117156114a557634e487b7160e01b5f52604160045260245ffd5b6040528251600381106114b6575f80fd5b81526114c46020840161144b565b60208201526114d56040840161145b565b604082015260608301516060820152608083015160808201528091505092915050565b634e487b7160e01b5f52601160045260245ffd5b67ffffffffffffffff82811682821603908082111561152d5761152d6114f8565b5092915050565b67ffffffffffffffff81811683821601908082111561152d5761152d6114f8565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b608081525f611590608083018789611555565b67ffffffffffffffff95861660208401529390941660408201526001600160a01b03919091166060909101529392505050565b5f602082840312156115d3575f80fd5b5051919050565b60a081525f6115ed60a08301888a611555565b67ffffffffffffffff96871660208401529490951660408201526001600160a01b039290921660608301526080909101529392505050565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e1984360301811261164e575f80fd5b83018035915067ffffffffffffffff821115611668575f80fd5b602001915036819003821315611283575f80fd5b604081525f61168f604083018587611555565b9050826020830152949350505050565b634e487b7160e01b5f52602160045260245ffd5b818103818111156103fa576103fa6114f8565b602081525f6116d9602083018486611555565b94935050505056fea26469706673582212206fe545939da308167f689183291a3de6f7414bc05f77d9f7ec6cf697ab9a484664736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610163575f3560e01c8063802295ef116100c7578063c1a287e21161007d578063dba1002111610063578063dba100211461033d578063ddf0effc14610364578063f2fde38b14610385575f80fd5b8063c1a287e2146102ef578063cd93adf514610316575f80fd5b80638da5cb5b116100ad5780638da5cb5b146102b9578063a2596702146102c9578063a2a11fbe146102dc575f80fd5b8063802295ef1461029357806389d779c3146102a6575f80fd5b80632f99c6cc1161011c57806347500708116101025780634750070814610251578063715018a6146102785780637b39ba1614610280575f80fd5b80632f99c6cc14610209578063307a64a514610230575f80fd5b8063154fbf151161014c578063154fbf15146101a2578063192cf07d146101b7578063198e4236146101f6575f80fd5b806301ffc9a714610167578063130d6f001461018f575b5f80fd5b61017a61017536600461121e565b610398565b60405190151581526020015b60405180910390f35b61017a61019d36600461128a565b610400565b6101b56101b03660046112dd565b6104da565b005b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610186565b6101b56102043660046112dd565b610575565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b610238600181565b60405167ffffffffffffffff9091168152602001610186565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b6101b56105e4565b6001546101de906001600160a01b031681565b6102386102a136600461128a565b6105f7565b6101b56102b436600461130d565b610808565b5f546001600160a01b03166101de565b6101b56102d7366004611378565b6109ed565b6101b56102ea3660046112dd565b610c04565b6102387f000000000000000000000000000000000000000000000000000000000000000081565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b6103776103723660046113e7565b610c6d565b604051908152602001610186565b6101b56103933660046112dd565b610cfb565b5f6001600160e01b031982167f06aaeb320000000000000000000000000000000000000000000000000000000014806103fa57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b5f6104d37f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861047186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610d5692505050565b6040518263ffffffff1660e01b815260040161048f91815260200190565b60a060405180830381865afa1580156104aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ce9190611466565b610d61565b9392505050565b6104e2610dfd565b6040517ff2fde38b0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f2fde38b906024015b5f604051808303815f87803b15801561055c575f80fd5b505af115801561056e573d5f803e3d5ffd5b5050505050565b61057d610dfd565b6040517f4e543b260000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634e543b2690602401610545565b6105ec610dfd565b6105f55f610e42565b565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af2861066686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610d5692505050565b6040518263ffffffff1660e01b815260040161068491815260200190565b60a060405180830381865afa15801561069f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106c39190611466565b90505f6107107f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000061150c565b60408301519091506001600160a01b031615801561074557508067ffffffffffffffff16826020015167ffffffffffffffff16115b156107fe575f81836020015161075b919061150c565b90504267ffffffffffffffff808316908216108015906107b757506107a07f000000000000000000000000000000000000000000000000000000000000000083611534565b67ffffffffffffffff168167ffffffffffffffff16105b156107fb576107c6828261150c565b6107f0907f000000000000000000000000000000000000000000000000000000000000000061150c565b9450505050506103fa565b50505b505f949350505050565b5f610814868686610e9e565b90505f8482602001516108279190611534565b60015460208401516040517f3ad860830000000000000000000000000000000000000000000000000000000081529293505f926001600160a01b0390921691633ad8608391610880918c918c918c908c9060040161157d565b602060405180830381865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf91906115c3565b90506108ed85337f00000000000000000000000000000000000000000000000000000000000000008461102f565b60608301516040517f5569f33d000000000000000000000000000000000000000000000000000000008152600481019190915267ffffffffffffffff831660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635569f33d906044015f604051808303815f87803b15801561097b575f80fd5b505af115801561098d573d5f803e3d5ffd5b5050505061099c8888886110bd565b8383606001517fbd0c01e5bf66003280556423db4a8bf79043c146ac57f657c30049dd433166498a8a8a878b886040516109db969594939291906115da565b60405180910390a35050505050505050565b6040517fa7fc7a070000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063a7fc7a07906024015f604051808303815f87803b158015610a86575f80fd5b505af1158015610a98573d5f803e3d5ffd5b505050505f5b81811015610b50577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663acf1a841848484818110610ae757610ae7611625565b9050602002810190610af99190611639565b5f6040518463ffffffff1660e01b8152600401610b189392919061167c565b5f604051808303815f87803b158015610b2f575f80fd5b505af1158015610b41573d5f803e3d5ffd5b50505050806001019050610a9e565b506040517ff6a74ed70000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f6a74ed7906024015f604051808303815f87803b158015610bea575f80fd5b505af1158015610bfc573d5f803e3d5ffd5b505050505050565b610c0c610dfd565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040519081527f1c7fc0b502196498c71ac9519a0d4b981ad9332bb9f67a3688f7beda68fb7ac99060200160405180910390a150565b6001545f906001600160a01b0316633ad860838686610c8d828289610e9e565b6020015187876040518663ffffffff1660e01b8152600401610cb395949392919061157d565b602060405180830381865afa158015610cce573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cf291906115c3565b95945050505050565b610d03610dfd565b6001600160a01b038116610d4a576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081525f60048201526024015b60405180910390fd5b610d5381610e42565b50565b805160209091012090565b5f600182516002811115610d7757610d7761169f565b14806103fa57505f82516002811115610d9257610d9261169f565b148015610daa575060408201516001600160a01b0316155b80156103fa57507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16826020015167ffffffffffffffff1642610df691906116b3565b1092915050565b5f546001600160a01b031633146105f5576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610d41565b5f80546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166344c9af28610f3586868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610d5692505050565b6040518263ffffffff1660e01b8152600401610f5391815260200190565b60a060405180830381865afa158015610f6e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f929190611466565b9050610f9d81610d61565b610fd75783836040517f1caefaa0000000000000000000000000000000000000000000000000000000008152600401610d419291906116c6565b600167ffffffffffffffff831610156104d3576040517fa096b84400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8316600482015260016024820152604401610d41565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526110b7908590611199565b50505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c475abff61112a85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610d5692505050565b6040516001600160e01b031960e084901b168152600481019190915267ffffffffffffffff841660248201526044016020604051808303815f875af1158015611175573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110b791906115c3565b5f8060205f8451602086015f885af1806111b8576040513d5f823e3d81fd5b50505f513d915081156111cf5780600114156111dc565b6001600160a01b0384163b155b156110b7576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610d41565b5f6020828403121561122e575f80fd5b81356001600160e01b0319811681146104d3575f80fd5b5f8083601f840112611255575f80fd5b50813567ffffffffffffffff81111561126c575f80fd5b602083019150836020828501011115611283575f80fd5b9250929050565b5f806020838503121561129b575f80fd5b823567ffffffffffffffff8111156112b1575f80fd5b6112bd85828601611245565b90969095509350505050565b6001600160a01b0381168114610d53575f80fd5b5f602082840312156112ed575f80fd5b81356104d3816112c9565b67ffffffffffffffff81168114610d53575f80fd5b5f805f805f60808688031215611321575f80fd5b853567ffffffffffffffff811115611337575f80fd5b61134388828901611245565b9096509450506020860135611357816112f8565b92506040860135611367816112c9565b949793965091946060013592915050565b5f8060208385031215611389575f80fd5b823567ffffffffffffffff808211156113a0575f80fd5b818501915085601f8301126113b3575f80fd5b8135818111156113c1575f80fd5b8660208260051b85010111156113d5575f80fd5b60209290920196919550909350505050565b5f805f80606085870312156113fa575f80fd5b843567ffffffffffffffff811115611410575f80fd5b61141c87828801611245565b9095509350506020850135611430816112f8565b91506040850135611440816112c9565b939692955090935050565b8051611456816112f8565b919050565b8051611456816112c9565b5f60a08284031215611476575f80fd5b60405160a0810181811067ffffffffffffffff821117156114a557634e487b7160e01b5f52604160045260245ffd5b6040528251600381106114b6575f80fd5b81526114c46020840161144b565b60208201526114d56040840161145b565b604082015260608301516060820152608083015160808201528091505092915050565b634e487b7160e01b5f52601160045260245ffd5b67ffffffffffffffff82811682821603908082111561152d5761152d6114f8565b5092915050565b67ffffffffffffffff81811683821601908082111561152d5761152d6114f8565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b608081525f611590608083018789611555565b67ffffffffffffffff95861660208401529390941660408201526001600160a01b03919091166060909101529392505050565b5f602082840312156115d3575f80fd5b5051919050565b60a081525f6115ed60a08301888a611555565b67ffffffffffffffff96871660208401529490951660408201526001600160a01b039290921660608301526080909101529392505050565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e1984360301811261164e575f80fd5b83018035915067ffffffffffffffff821115611668575f80fd5b602001915036819003821315611283575f80fd5b604081525f61168f604083018587611555565b9050826020830152949350505050565b634e487b7160e01b5f52602160045260245ffd5b818103818111156103fa576103fa6114f8565b602081525f6116d9602083018486611555565b94935050505056fea26469706673582212206fe545939da308167f689183291a3de6f7414bc05f77d9f7ec6cf697ab9a484664736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "27081": [ + { + "length": 32, + "start": 598 + }, + { + "length": 32, + "start": 1030 + }, + { + "length": 32, + "start": 1531 + }, + { + "length": 32, + "start": 2354 + }, + { + "length": 32, + "start": 3786 + } + ], + "27084": [ + { + "length": 32, + "start": 526 + }, + { + "length": 32, + "start": 2248 + } + ], + "28173": [ + { + "length": 32, + "start": 756 + }, + { + "length": 32, + "start": 1772 + }, + { + "length": 32, + "start": 1915 + }, + { + "length": 32, + "start": 1996 + } + ], + "28176": [ + { + "length": 32, + "start": 1739 + }, + { + "length": 32, + "start": 3507 + } + ], + "28180": [ + { + "length": 32, + "start": 444 + }, + { + "length": 32, + "start": 2589 + }, + { + "length": 32, + "start": 2945 + } + ], + "28184": [ + { + "length": 32, + "start": 795 + }, + { + "length": 32, + "start": 1306 + }, + { + "length": 32, + "start": 1461 + }, + { + "length": 32, + "start": 2629 + }, + { + "length": 32, + "start": 2985 + }, + { + "length": 32, + "start": 4287 + } + ], + "28188": [ + { + "length": 32, + "start": 834 + }, + { + "length": 32, + "start": 2728 + } + ] + }, + "inputSourceName": "project/src/registrar/ETHRenewerV1.sol", + "devdoc": { + "errors": { + "DurationTooShort(uint64,uint64)": [ + { + "details": "Error selector: `0xa096b844`" + } + ], + "NameNotRenewable(string)": [ + { + "details": "Error selector: `0x1caefaa0`" + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ], + "SafeERC20FailedOperation(address)": [ + { + "details": "An operation with an ERC-20 token failed." + } + ] + }, + "events": { + "NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)": { + "params": { + "amount": "The amount of `paymentToken`.", + "duration": "The duration extension, in seconds.", + "label": "The name of the renewal.", + "newExpiry": "The new expiry, in seconds.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash.", + "tokenId": "The registry token id." + } + }, + "RentPriceOracleUpdated(address)": { + "params": { + "oracle": "The new `IRentPriceOracle` contract." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "beneficiary": "Address that receives payments.", + "bonusPeriod": "Duration added by premigration, in seconds.", + "ethRegistry": "ENSv2 .eth `PermissionedRegistry`.", + "gracePeriod": "Post-expiry period where renewable and not available, in seconds.", + "nameWrapper": "ENSv1 `NameWrapper` contract.", + "oracle": "Initial oracle for registration and renewal costs.", + "owner_": "Contract owner.", + "wrappedController": "ENSv1 `ETHRegistrarController` that is a `NameWrapper` controller." + } + }, + "getRemainingGracePeriod(string)": { + "details": "Defined over `[expiry, expiry + GRACE_PERIOD)`.", + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "The remaining grace period, in seconds." + } + }, + "getRenewPrice(string,uint64,address)": { + "params": { + "duration": "The duration extension, in seconds.", + "label": "The name to renew.", + "paymentToken": "The payment token." + }, + "returns": { + "_0": "The amount of `paymentToken`." + } + }, + "isRenewable(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "`true` if renewable." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renew(string,uint64,address,bytes32)": { + "params": { + "duration": "The duration extension, in seconds.", + "label": "The name to renew.", + "paymentToken": "The payment token.", + "referrer": "The referrer hash." + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "setRegistrarResolver(address)": { + "details": "Same as `RegistrarSecurityController`.", + "params": { + "resolver": "The resolver address to set." + } + }, + "setRentPriceOracle(address)": { + "params": { + "oracle": "The new `IRentPriceOracle` instance." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "syncWrapper(string[])": { + "params": { + "labels": "The labels to sync." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferRegistrarOwnership(address)": { + "details": "Same as `RegistrarSecurityController`.", + "params": { + "newOwner": "The new owner for the registrar." + } + } + }, + "stateVariables": { + "_GRACE_PERIOD_V2": { + "details": "ENSv2 `GRACE_PERIOD`." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1182200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "BASE_REGISTRAR()": "infinite", + "BENEFICIARY()": "infinite", + "ETH_REGISTRY()": "infinite", + "GRACE_PERIOD()": "infinite", + "MIN_RENEW_DURATION()": "271", + "NAME_WRAPPER()": "infinite", + "WRAPPED_CONTROLLER()": "infinite", + "getRemainingGracePeriod(string)": "infinite", + "getRenewPrice(string,uint64,address)": "infinite", + "isRenewable(string)": "infinite", + "owner()": "2374", + "renew(string,uint64,address,bytes32)": "infinite", + "renounceOwnership()": "infinite", + "rentPriceOracle()": "2425", + "setRegistrarResolver(address)": "infinite", + "setRentPriceOracle(address)": "27856", + "supportsInterface(bytes4)": "458", + "syncWrapper(string[])": "infinite", + "transferOwnership(address)": "infinite", + "transferRegistrarOwnership(address)": "infinite" + }, + "internal": { + "_isRenewable(struct IPermissionedRegistry.State memory)": "infinite", + "_onRenew(string calldata,uint64)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"gracePeriod\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"bonusPeriod\",\"type\":\"uint64\"},{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"wrappedController\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minDuration\",\"type\":\"uint64\"}],\"name\":\"DurationTooShort\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"NameNotRenewable\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NameRenewed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"RentPriceOracleUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BASE_REGISTRAR\",\"outputs\":[{\"internalType\":\"contract BaseRegistrarImplementation\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"BENEFICIARY\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GRACE_PERIOD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_RENEW_DURATION\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WRAPPED_CONTROLLER\",\"outputs\":[{\"internalType\":\"contract IWrappedETHRegistrarController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getRemainingGracePeriod\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRenewPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"isRenewable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"referrer\",\"type\":\"bytes32\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rentPriceOracle\",\"outputs\":[{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setRegistrarResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRentPriceOracle\",\"name\":\"oracle\",\"type\":\"address\"}],\"name\":\"setRentPriceOracle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"labels\",\"type\":\"string[]\"}],\"name\":\"syncWrapper\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferRegistrarOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DurationTooShort(uint64,uint64)\":[{\"details\":\"Error selector: `0xa096b844`\"}],\"NameNotRenewable(string)\":[{\"details\":\"Error selector: `0x1caefaa0`\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}],\"SafeERC20FailedOperation(address)\":[{\"details\":\"An operation with an ERC-20 token failed.\"}]},\"events\":{\"NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)\":{\"params\":{\"amount\":\"The amount of `paymentToken`.\",\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name of the renewal.\",\"newExpiry\":\"The new expiry, in seconds.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\",\"tokenId\":\"The registry token id.\"}},\"RentPriceOracleUpdated(address)\":{\"params\":{\"oracle\":\"The new `IRentPriceOracle` contract.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"beneficiary\":\"Address that receives payments.\",\"bonusPeriod\":\"Duration added by premigration, in seconds.\",\"ethRegistry\":\"ENSv2 .eth `PermissionedRegistry`.\",\"gracePeriod\":\"Post-expiry period where renewable and not available, in seconds.\",\"nameWrapper\":\"ENSv1 `NameWrapper` contract.\",\"oracle\":\"Initial oracle for registration and renewal costs.\",\"owner_\":\"Contract owner.\",\"wrappedController\":\"ENSv1 `ETHRegistrarController` that is a `NameWrapper` controller.\"}},\"getRemainingGracePeriod(string)\":{\"details\":\"Defined over `[expiry, expiry + GRACE_PERIOD)`.\",\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"The remaining grace period, in seconds.\"}},\"getRenewPrice(string,uint64,address)\":{\"params\":{\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name to renew.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"_0\":\"The amount of `paymentToken`.\"}},\"isRenewable(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"`true` if renewable.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renew(string,uint64,address,bytes32)\":{\"params\":{\"duration\":\"The duration extension, in seconds.\",\"label\":\"The name to renew.\",\"paymentToken\":\"The payment token.\",\"referrer\":\"The referrer hash.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setRegistrarResolver(address)\":{\"details\":\"Same as `RegistrarSecurityController`.\",\"params\":{\"resolver\":\"The resolver address to set.\"}},\"setRentPriceOracle(address)\":{\"params\":{\"oracle\":\"The new `IRentPriceOracle` instance.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"syncWrapper(string[])\":{\"params\":{\"labels\":\"The labels to sync.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferRegistrarOwnership(address)\":{\"details\":\"Same as `RegistrarSecurityController`.\",\"params\":{\"newOwner\":\"The new owner for the registrar.\"}}},\"stateVariables\":{\"_GRACE_PERIOD_V2\":{\"details\":\"ENSv2 `GRACE_PERIOD`.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"DurationTooShort(uint64,uint64)\":[{\"notice\":\"`duration` less than `minDuration`.\"}],\"NameNotRenewable(string)\":[{\"notice\":\"`label` cannot be renewed.\"}]},\"events\":{\"NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)\":{\"notice\":\"A name was extended by `duration`.\"},\"RentPriceOracleUpdated(address)\":{\"notice\":\"`IRentPriceOracle` was replaced.\"}},\"kind\":\"user\",\"methods\":{\"BASE_REGISTRAR()\":{\"notice\":\"ENSv1 `BaseRegistrarImplementation` contract.\"},\"BENEFICIARY()\":{\"notice\":\"Address that receives payments.\"},\"ETH_REGISTRY()\":{\"notice\":\"ENSv2 .eth `PermissionedRegistry`.\"},\"GRACE_PERIOD()\":{\"notice\":\"Post-expiry period where still renewable and not available, in seconds.\"},\"MIN_RENEW_DURATION()\":{\"notice\":\"Minimum renew duration, in seconds.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract.\"},\"WRAPPED_CONTROLLER()\":{\"notice\":\"ENSv1 `ETHRegistrarController` that is an active `NameWrapper` controller.\"},\"getRemainingGracePeriod(string)\":{\"notice\":\"Determine remaining grace period.\"},\"getRenewPrice(string,uint64,address)\":{\"notice\":\"Determine renew price for a name.\"},\"isRenewable(string)\":{\"notice\":\"Check if name is renewable.\"},\"renew(string,uint64,address,bytes32)\":{\"notice\":\"Renew a name.\"},\"rentPriceOracle()\":{\"notice\":\"Oracle for registration and renewal costs.\"},\"setRegistrarResolver(address)\":{\"notice\":\"Sets the registrar's resolver for the base node.\"},\"setRentPriceOracle(address)\":{\"notice\":\"Change the rent price oracle.\"},\"syncWrapper(string[])\":{\"notice\":\"Sync `NameWrapper` expiry with `BaseRegistrarImplementation` expiry.\"},\"transferRegistrarOwnership(address)\":{\"notice\":\"Transfers ownership of the registrar.\"}},\"notice\":\".eth registrar that only renews premigrated ENSv2 reservations and syncs with ENSv1. Pricing and payment are delegated to a swappable `IRentPriceOracle`. Provides a mechanism for syncing `NameWrapper` expiry.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/ETHRenewerV1.sol\":\"ETHRenewerV1\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/BaseRegistrarImplementation.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"./IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract BaseRegistrarImplementation is ERC721, IBaseRegistrar, Ownable {\\n // A map of expiry times\\n mapping(uint256 => uint256) expiries;\\n // The ENS registry\\n ENS public ens;\\n // The namehash of the TLD this registrar owns (eg, .eth)\\n bytes32 public baseNode;\\n // A map of addresses that are authorised to register and renew names.\\n mapping(address => bool) public controllers;\\n uint256 public constant GRACE_PERIOD = 90 days;\\n bytes4 private constant INTERFACE_META_ID =\\n bytes4(keccak256(\\\"supportsInterface(bytes4)\\\"));\\n bytes4 private constant ERC721_ID =\\n bytes4(\\n keccak256(\\\"balanceOf(address)\\\") ^\\n keccak256(\\\"ownerOf(uint256)\\\") ^\\n keccak256(\\\"approve(address,uint256)\\\") ^\\n keccak256(\\\"getApproved(uint256)\\\") ^\\n keccak256(\\\"setApprovalForAll(address,bool)\\\") ^\\n keccak256(\\\"isApprovedForAll(address,address)\\\") ^\\n keccak256(\\\"transferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256,bytes)\\\")\\n );\\n bytes4 private constant RECLAIM_ID =\\n bytes4(keccak256(\\\"reclaim(uint256,address)\\\"));\\n\\n /// v2.1.3 version of _isApprovedOrOwner which calls ownerOf(tokenId) and takes grace period into consideration instead of ERC721.ownerOf(tokenId);\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.1.3/contracts/token/ERC721/ERC721.sol#L187\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param spender address of the spender to query\\n /// @param tokenId uint256 ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID,\\n /// is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(\\n address spender,\\n uint256 tokenId\\n ) internal view override returns (bool) {\\n address owner = ownerOf(tokenId);\\n return (spender == owner ||\\n getApproved(tokenId) == spender ||\\n isApprovedForAll(owner, spender));\\n }\\n\\n constructor(ENS _ens, bytes32 _baseNode) ERC721(\\\"\\\", \\\"\\\") {\\n ens = _ens;\\n baseNode = _baseNode;\\n }\\n\\n modifier live() {\\n require(ens.owner(baseNode) == address(this));\\n _;\\n }\\n\\n modifier onlyController() {\\n require(controllers[msg.sender]);\\n _;\\n }\\n\\n /// @dev Gets the owner of the specified token ID. Names become unowned\\n /// when their registration expires.\\n /// @param tokenId uint256 ID of the token to query the owner of\\n /// @return address currently marked as the owner of the given token ID\\n function ownerOf(\\n uint256 tokenId\\n ) public view override(IERC721, ERC721) returns (address) {\\n require(expiries[tokenId] > block.timestamp);\\n return super.ownerOf(tokenId);\\n }\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external override onlyOwner {\\n controllers[controller] = true;\\n emit ControllerAdded(controller);\\n }\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external override onlyOwner {\\n controllers[controller] = false;\\n emit ControllerRemoved(controller);\\n }\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external override onlyOwner {\\n ens.setResolver(baseNode, resolver);\\n }\\n\\n // Returns the expiration timestamp of the specified id.\\n function nameExpires(uint256 id) external view override returns (uint256) {\\n return expiries[id];\\n }\\n\\n // Returns true iff the specified name is available for registration.\\n function available(uint256 id) public view override returns (bool) {\\n // Not available if it's registered here or in its grace period.\\n return expiries[id] + GRACE_PERIOD < block.timestamp;\\n }\\n\\n /// @dev Register a name.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external override returns (uint256) {\\n return _register(id, owner, duration, true);\\n }\\n\\n /// @dev Register a name, without modifying the registry.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function registerOnly(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256) {\\n return _register(id, owner, duration, false);\\n }\\n\\n function _register(\\n uint256 id,\\n address owner,\\n uint256 duration,\\n bool updateRegistry\\n ) internal live onlyController returns (uint256) {\\n require(available(id));\\n require(\\n block.timestamp + duration + GRACE_PERIOD >\\n block.timestamp + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] = block.timestamp + duration;\\n if (_exists(id)) {\\n // Name was previously owned, and expired\\n _burn(id);\\n }\\n _mint(owner, id);\\n if (updateRegistry) {\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n emit NameRegistered(id, owner, block.timestamp + duration);\\n\\n return block.timestamp + duration;\\n }\\n\\n function renew(\\n uint256 id,\\n uint256 duration\\n ) external override live onlyController returns (uint256) {\\n require(expiries[id] + GRACE_PERIOD >= block.timestamp); // Name must be registered here or in grace period\\n require(\\n expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] += duration;\\n emit NameRenewed(id, expiries[id]);\\n return expiries[id];\\n }\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external override live {\\n require(_isApprovedOrOwner(msg.sender, id));\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view override(ERC721, IERC165) returns (bool) {\\n return\\n interfaceID == INTERFACE_META_ID ||\\n interfaceID == ERC721_ID ||\\n interfaceID == RECLAIM_ID;\\n }\\n}\\n\",\"keccak256\":\"0xf7d55afacf1b9b2c54e2ac3603af9a8a1bcafcb9209d246a7854a28a884f1142\"},\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: address zero is not a valid owner\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _ownerOf(tokenId);\\n require(owner != address(0), \\\"ERC721: invalid token ID\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n _requireMinted(tokenId);\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not token owner or approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n _requireMinted(tokenId);\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n _safeTransfer(from, to, tokenId, data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\\n */\\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\\n return _owners[tokenId];\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _ownerOf(tokenId) != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId, 1);\\n\\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n unchecked {\\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\\n // Given that tokens are minted one by one, it is impossible in practice that\\n // this ever happens. Might change if we allow batch minting.\\n // The ERC fails to describe this case.\\n _balances[to] += 1;\\n }\\n\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n * This is an internal function that does not check if the sender is authorized to operate on the token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\\n\\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\\n owner = ERC721.ownerOf(tokenId);\\n\\n // Clear approvals\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // Cannot overflow, as that would require more tokens to be burned/transferred\\n // out than the owner initially received through minting and transferring in.\\n _balances[owner] -= 1;\\n }\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId, 1);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId, 1);\\n\\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n\\n // Clear approvals from the previous owner\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\\n // `from`'s balance is the number of token held, which is at least one before the current\\n // transfer.\\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\\n // all 2**256 token ids to be minted, which in practice is impossible.\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n }\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits an {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Reverts if the `tokenId` has not been minted yet.\\n */\\n function _requireMinted(uint256 tokenId) internal view virtual {\\n require(_exists(tokenId), \\\"ERC721: invalid token ID\\\");\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n /// @solidity memory-safe-assembly\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\\n * - When `from` is zero, the tokens will be minted for `to`.\\n * - When `to` is zero, ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\\n * - When `from` is zero, the tokens were minted for `to`.\\n * - When `to` is zero, ``from``'s tokens were burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Unsafe write access to the balances, used by extensions that \\\"mint\\\" tokens using an {ownerOf} override.\\n *\\n * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\\n * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\\n * that `ownerOf(tokenId)` is `a`.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __unsafe_increaseBalance(address account, uint256 amount) internal {\\n _balances[account] += amount;\\n }\\n}\\n\",\"keccak256\":\"0x2c309e7df9e05e6ce15bedfe74f3c61b467fc37e0fae9eab496acf5ea0bbd7ff\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\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://consensys.net/diligence/blog/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.8.0/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(address target, bytes memory data, uint256 value) 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\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.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 `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\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 /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(uint256 x, uint256 y, uint256 denominator) 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 // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\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(uint256 x, uint256 y, uint256 denominator, Rounding rounding) 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 256, 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 << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n /*\\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n * 0xb0202a11 ===\\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n */\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @param data Additional data with no specified format, sent in call to `spender`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\",\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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 /**\\n * @dev An operation with an ERC-20 token failed.\\n */\\n error SafeERC20FailedOperation(address token);\\n\\n /**\\n * @dev Indicates a failed `decreaseAllowance` request.\\n */\\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n forceApprove(token, spender, oldAllowance + value);\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n * value, non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n unchecked {\\n uint256 currentAllowance = token.allowance(address(this), spender);\\n if (currentAllowance < requestedDecrease) {\\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n }\\n forceApprove(token, spender, currentAllowance - requestedDecrease);\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n *\\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n * set here.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n safeTransfer(token, to, value);\\n } else if (!token.transferAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferFromAndCallRelaxed(\\n IERC1363 token,\\n address from,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length == 0) {\\n safeTransferFrom(token, from, to, value);\\n } else if (!token.transferFromAndCall(from, to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n * once without retrying, and relies on the returned value to be true.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n forceApprove(token, to, value);\\n } else if (!token.approveAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n // bubble errors\\n if iszero(success) {\\n let ptr := mload(0x40)\\n returndatacopy(ptr, 0, returndatasize())\\n revert(ptr, returndatasize())\\n }\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n\\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\n }\\n}\\n\",\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`.\\nabstract contract AbstractETHRegistrar is Ownable, ERC165, IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Minimum renew duration, in seconds.\\n uint64 public constant MIN_RENEW_DURATION = 1;\\n\\n /// @notice ENSv2 .eth `PermissionedRegistry`.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice Address that receives payments.\\n address public immutable BENEFICIARY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Oracle for registration and renewal costs.\\n IRentPriceOracle public rentPriceOracle;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `IRentPriceOracle` was replaced.\\n /// @param oracle The new `IRentPriceOracle` contract.\\n event RentPriceOracleUpdated(IRentPriceOracle oracle);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n constructor(\\n address owner_,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle\\n )\\n Ownable(owner_)\\n {\\n ETH_REGISTRY = ethRegistry;\\n BENEFICIARY = beneficiary;\\n\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Change the rent price oracle.\\n /// @param oracle The new `IRentPriceOracle` instance.\\n function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner {\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external\\n {\\n IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not\\n uint64 newExpiry = state.expiry + duration; // reverts if overflow\\n uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, amount); // reverts if payment failed\\n ETH_REGISTRY.renew(state.tokenId, newExpiry);\\n _onRenew(label, duration);\\n emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function isRenewable(string calldata label) external view returns (bool) {\\n return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n public\\n view\\n returns (uint256)\\n {\\n return\\n rentPriceOracle.getRenewPrice(\\n label,\\n _requireRenewable(label, duration).expiry,\\n duration,\\n paymentToken\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Callback for when a name is renewed.\\n function _onRenew(string calldata label, uint64 duration) internal virtual {}\\n\\n /// @dev Returns whether the name is renewable by this contract.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n virtual\\n returns (bool);\\n\\n /// @dev Ensure name is renewable.\\n function _requireRenewable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isRenewable(state)) {\\n revert NameNotRenewable(label);\\n }\\n if (duration < MIN_RENEW_DURATION) {\\n revert DurationTooShort(duration, MIN_RENEW_DURATION);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x03c6381eaa4b6f36c842a32396b8f9a5a573a4257d7a9d263e77c015486a9458\",\"license\":\"MIT\"},\"project/src/registrar/ETHRenewerV1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n BaseRegistrarImplementation\\n} from \\\"@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {AbstractETHRegistrar} from \\\"./AbstractETHRegistrar.sol\\\";\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @notice `ETHRegistrarController.renew()` stub interface.\\n/// @dev Interface selector: `0xacf1a841`\\n// https://github.com/ensdomains/ens-contracts/blob/staging/deployments/mainnet/WrappedETHRegistrarController.json\\n/// @dev Interface selector: `0xacf1a841`\\ninterface IWrappedETHRegistrarController {\\n /// @notice Renew an ENSv1 name.\\n /// @param label The name to renew.\\n /// @param duration The expiry extension, in seconds.\\n function renew(string calldata label, uint256 duration) external payable;\\n}\\n\\n\\n/// @notice .eth registrar that only renews premigrated ENSv2 reservations\\n/// and syncs with ENSv1.\\n///\\n/// Pricing and payment are delegated to a swappable `IRentPriceOracle`.\\n///\\n/// Provides a mechanism for syncing `NameWrapper` expiry.\\n///\\ncontract ETHRenewerV1 is AbstractETHRegistrar {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRenewer\\n uint64 public immutable GRACE_PERIOD;\\n\\n /// @dev ENSv2 `GRACE_PERIOD`.\\n uint64 internal immutable _GRACE_PERIOD_V2;\\n\\n /// @notice The ENSv1 `NameWrapper` contract.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice ENSv1 `BaseRegistrarImplementation` contract.\\n BaseRegistrarImplementation public immutable BASE_REGISTRAR;\\n\\n /// @notice ENSv1 `ETHRegistrarController` that is an active `NameWrapper` controller.\\n IWrappedETHRegistrarController public immutable WRAPPED_CONTROLLER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n /// @param gracePeriod Post-expiry period where renewable and not available, in seconds.\\n /// @param bonusPeriod Duration added by premigration, in seconds.\\n /// @param nameWrapper ENSv1 `NameWrapper` contract.\\n /// @param wrappedController ENSv1 `ETHRegistrarController` that is a `NameWrapper` controller.\\n constructor(\\n address owner_,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle,\\n uint64 gracePeriod,\\n uint64 bonusPeriod,\\n INameWrapper nameWrapper,\\n address wrappedController\\n )\\n AbstractETHRegistrar(owner_, ethRegistry, beneficiary, oracle)\\n {\\n GRACE_PERIOD = bonusPeriod + gracePeriod;\\n _GRACE_PERIOD_V2 = gracePeriod;\\n NAME_WRAPPER = nameWrapper;\\n BASE_REGISTRAR = BaseRegistrarImplementation(address(nameWrapper.registrar()));\\n WRAPPED_CONTROLLER = IWrappedETHRegistrarController(wrappedController);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Transfers ownership of the registrar.\\n /// @dev Same as `RegistrarSecurityController`.\\n /// @param newOwner The new owner for the registrar.\\n function transferRegistrarOwnership(address newOwner) external onlyOwner {\\n BASE_REGISTRAR.transferOwnership(newOwner);\\n }\\n\\n /// @notice Sets the registrar's resolver for the base node.\\n /// @dev Same as `RegistrarSecurityController`.\\n /// @param resolver The resolver address to set.\\n function setRegistrarResolver(address resolver) external onlyOwner {\\n BASE_REGISTRAR.setResolver(resolver);\\n }\\n\\n /// @notice Sync `NameWrapper` expiry with `BaseRegistrarImplementation` expiry.\\n /// @param labels The labels to sync.\\n function syncWrapper(string[] calldata labels) external {\\n BASE_REGISTRAR.addController(address(NAME_WRAPPER));\\n for (uint256 i; i < labels.length; ++i) {\\n WRAPPED_CONTROLLER.renew(labels[i], 0);\\n }\\n BASE_REGISTRAR.removeController(address(NAME_WRAPPER));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n uint64 bonusPeriod = GRACE_PERIOD - _GRACE_PERIOD_V2;\\n if (state.latestOwner == address(0) && state.expiry > bonusPeriod) {\\n uint64 expiryV1 = state.expiry - bonusPeriod;\\n uint64 t = uint64(block.timestamp);\\n if (t >= expiryV1 && t < expiryV1 + GRACE_PERIOD) {\\n return GRACE_PERIOD - (t - expiryV1);\\n }\\n }\\n return 0;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Update ENSv1 during renew.\\n function _onRenew(string calldata label, uint64 duration) internal override {\\n BASE_REGISTRAR.renew(LibLabel.id(label), duration);\\n }\\n\\n /// @dev Determine if `RESERVED` or in grace was `RESERVED`.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n override\\n returns (bool)\\n {\\n return\\n state.status == IPermissionedRegistry.Status.RESERVED ||\\n (state.status == IPermissionedRegistry.Status.AVAILABLE &&\\n state.latestOwner == address(0) &&\\n (block.timestamp - state.expiry) < _GRACE_PERIOD_V2);\\n }\\n}\\n\",\"keccak256\":\"0xc4b6b63175cb4c08b75fa247be3cfffa3d418a6c0cc33ce583a4bbf511f23145\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for renewing \\\".eth\\\" names.\\n/// @dev Interface selector: `0x06aaeb32`\\ninterface IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A name was extended by `duration`.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the renewal.\\n /// @param duration The duration extension, in seconds.\\n /// @param newExpiry The new expiry, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param amount The amount of `paymentToken`.\\n event NameRenewed(\\n uint256 indexed tokenId,\\n string label,\\n uint64 duration,\\n uint64 newExpiry,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 amount\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `duration` less than `minDuration`.\\n /// @dev Error selector: `0xa096b844`\\n error DurationTooShort(uint64 duration, uint64 minDuration);\\n\\n /// @notice `label` cannot be renewed.\\n /// @dev Error selector: `0x1caefaa0`\\n error NameNotRenewable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Renew a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external;\\n\\n /// @notice Determine renew price for a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice Check if name is renewable.\\n /// @param label The name to check.\\n /// @return `true` if renewable.\\n function isRenewable(string calldata label) external view returns (bool);\\n\\n /// @notice Determine remaining grace period.\\n /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`.\\n /// @param label The name to check.\\n /// @return The remaining grace period, in seconds.\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64);\\n\\n /// @notice Post-expiry period where still renewable and not available, in seconds.\\n function GRACE_PERIOD() external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 14920, + "contract": "project/src/registrar/ETHRenewerV1.sol:ETHRenewerV1", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 27088, + "contract": "project/src/registrar/ETHRenewerV1.sol:ETHRenewerV1", + "label": "rentPriceOracle", + "offset": 0, + "slot": "1", + "type": "t_contract(IRentPriceOracle)28752" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_contract(IRentPriceOracle)28752": { + "encoding": "inplace", + "label": "contract IRentPriceOracle", + "numberOfBytes": "20" + } + } + }, + "userdoc": { + "errors": { + "DurationTooShort(uint64,uint64)": [ + { + "notice": "`duration` less than `minDuration`." + } + ], + "NameNotRenewable(string)": [ + { + "notice": "`label` cannot be renewed." + } + ] + }, + "events": { + "NameRenewed(uint256,string,uint64,uint64,address,bytes32,uint256)": { + "notice": "A name was extended by `duration`." + }, + "RentPriceOracleUpdated(address)": { + "notice": "`IRentPriceOracle` was replaced." + } + }, + "kind": "user", + "methods": { + "BASE_REGISTRAR()": { + "notice": "ENSv1 `BaseRegistrarImplementation` contract." + }, + "BENEFICIARY()": { + "notice": "Address that receives payments." + }, + "ETH_REGISTRY()": { + "notice": "ENSv2 .eth `PermissionedRegistry`." + }, + "GRACE_PERIOD()": { + "notice": "Post-expiry period where still renewable and not available, in seconds." + }, + "MIN_RENEW_DURATION()": { + "notice": "Minimum renew duration, in seconds." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract." + }, + "WRAPPED_CONTROLLER()": { + "notice": "ENSv1 `ETHRegistrarController` that is an active `NameWrapper` controller." + }, + "getRemainingGracePeriod(string)": { + "notice": "Determine remaining grace period." + }, + "getRenewPrice(string,uint64,address)": { + "notice": "Determine renew price for a name." + }, + "isRenewable(string)": { + "notice": "Check if name is renewable." + }, + "renew(string,uint64,address,bytes32)": { + "notice": "Renew a name." + }, + "rentPriceOracle()": { + "notice": "Oracle for registration and renewal costs." + }, + "setRegistrarResolver(address)": { + "notice": "Sets the registrar's resolver for the base node." + }, + "setRentPriceOracle(address)": { + "notice": "Change the rent price oracle." + }, + "syncWrapper(string[])": { + "notice": "Sync `NameWrapper` expiry with `BaseRegistrarImplementation` expiry." + }, + "transferRegistrarOwnership(address)": { + "notice": "Transfers ownership of the registrar." + } + }, + "notice": ".eth registrar that only renews premigrated ENSv2 reservations and syncs with ENSv1. Pricing and payment are delegated to a swappable `IRentPriceOracle`. Provides a mechanism for syncing `NameWrapper` expiry.", + "version": 1 + }, + "argsData": "0x00000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d300000000000000000000000067b728a792e789a8978b30cf1b3b641f19354b4300000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d300000000000000000000000009340d50a6489e7bfb2959acc4e32bcbc401e203000000000000000000000000000000000000000000000000000000000024ea00000000000000000000000000000000000000000000000000000000000051bd010000000000000000000000000635513f179d50a207757e05759cbd106d7dfce8000000000000000000000000fed6a969aaa60e4961fcd3ebf1a2e8913ac65b72", + "transaction": { + "hash": "0xcdd2a80d214cb7e411e811e15c71cb824b8dc7bfabf022c1d9ea1126f56cf6c4", + "nonce": "0x58", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xfe0b890ce329a7ddf11c8e26b1bf27ceab020e44bf67e1b38eca7740d8f3e7eb", + "blockNumber": "0xaa570c", + "transactionIndex": "0x68" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/Graveyard.json b/contracts/deployments/sepolia/Graveyard.json new file mode 100644 index 000000000..5e38d69db --- /dev/null +++ b/contracts/deployments/sepolia/Graveyard.json @@ -0,0 +1,441 @@ +{ + "address": "0x6f4bf58ac55e0018589b2d9734ed8bb82740124d", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [], + "name": "NameNotClearable", + "type": "error" + }, + { + "inputs": [], + "name": "NameRequiresPreimage", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "names", + "type": "bytes[]" + } + ], + "name": "clear", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "Graveyard", + "sourceName": "src/migration/Graveyard.sol", + "bytecode": "0x610120604052348015610010575f80fd5b506040516116eb3803806116eb83398101604081905261002f916101a8565b6001600160a01b03808216608052821660a081905260408051633f15457f60e01b81529051633f15457f916004808201926020929091908290030181865afa15801561007d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a191906101e0565b6001600160a01b031660c0816001600160a01b031681525050816001600160a01b0316632b20e3976040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061011a91906101e0565b6001600160a01b031660e0819052604080516360d143f160e11b8152905163c1a287e2916004808201926020929091908290030181865afa158015610161573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101859190610202565b61010052506102199050565b6001600160a01b03811681146101a5575f80fd5b50565b5f80604083850312156101b9575f80fd5b82516101c481610191565b60208401519092506101d581610191565b809150509250929050565b5f602082840312156101f0575f80fd5b81516101fb81610191565b9392505050565b5f60208284031215610212575f80fd5b5051919050565b60805160a05160c05160e0516101005161144f61029c5f395f61072701525f818161066401526106fe01525f81816104d201528181610810015281816108bc0152818161098f0152610b0701525f81816101060152818161057c01528181610a1601528181610bfd0152610ce101525f8181610145015261024a015261144f5ff3fe608060405234801561000f575f80fd5b5060043610610085575f3560e01c80636f3ff726116100585780636f3ff72614610167578063bc197c811461017a578063d62f4d37146101b2578063f23a6e61146101c7575f80fd5b806301ffc9a714610089578063150b7a02146100b1578063192cf07d1461010157806348ee1bcc14610140575b5f80fd5b61009c610097366004610e37565b6101ff565b60405190151581526020015b60405180910390f35b6100e86100bf366004610f2d565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040516001600160e01b031990911681526020016100a8565b6101287f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a8565b6101287f000000000000000000000000000000000000000000000000000000000000000081565b61009c610175366004610f95565b610229565b6100e861018836600461102d565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b6101c56101c03660046110d4565b6102b5565b005b6100e86101d5366004611143565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b5f6001600160e01b0319821663379ffb9360e11b14806102235750610223826102fb565b92915050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610291573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022391906111a7565b5f5b818110156102f6576102ec8383838181106102d4576102d46111c6565b90506020028101906102e691906111da565b5f61031f565b50506001016102b7565b505050565b5f6001600160e01b0319821663379ffb9360e11b1480610223575061022382610d20565b5f8080808561032f866001611231565b1080156103555750868686818110610349576103496111c6565b919091013560f81c1590505b156103bd57610365856021611231565b905085811061039457868660405163ba4adc2360e01b815260040161038b92919061126c565b60405180910390fd5b86866103a1876001611231565b6103ad92849290611287565b6103b6916112ae565b9150610415565b6103fd87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250899250610d86915050565b90925090508161041557505f9250829150610d189050565b5f8061042289898561031f565b9150915061043982855f9182526020526040902090565b95505f81600381111561044e5761044e6112cb565b036104a1577f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae86146104935760405163acae6b3b60e01b815260040160405180910390fd5b5060019350610d1892505050565b60018160038111156104b5576104b56112cb565b0361092d576040516302571be360e01b8152600481018790525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa15801561051f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061054391906112df565b9050306001600160a01b03821603610564575060029450610d189350505050565b604051630178fe3f60e01b8152600481018890525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156105c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105ed91906112fa565b5090925090506001811615610635576001600160a01b03821630146106255760405163acae6b3b60e01b815260040160405180910390fd5b5060039550610d18945050505050565b6040517fd6e4fa86000000000000000000000000000000000000000000000000000000008152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d6e4fa8690602401602060405180830381865afa1580156106b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106d59190611358565b5f036106f45760405163acae6b3b60e01b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663fca247ac87307f00000000000000000000000000000000000000000000000000000000000000006107584267ffffffffffffffff61136f565b610762919061136f565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b03909116602483015260448201526064016020604051808303815f875af11580156107b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d69190611358565b506040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018990525f906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630178b8bf90602401602060405180830381865afa158015610855573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087991906112df565b6001600160a01b03161461091d576040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018990525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015b5f604051808303815f87803b158015610906575f80fd5b505af1158015610918573d5f803e3d5ffd5b505050505b5060029550610d18945050505050565b6002816003811115610941576109416112cb565b036109fc576040517f5ef2c7f000000000000000000000000000000000000000000000000000000000815260048101839052602481018590523060448201525f6064820181905260848201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635ef2c7f09060a4015f604051808303815f87803b1580156109d8575f80fd5b505af11580156109ea573d5f803e3d5ffd5b5060029750610d189650505050505050565b604051630178fe3f60e01b8152600481018790525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015610a63573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8791906112fa565b5091509150610a9881600116151590565b15610ac6576001600160a01b03821630146106255760405163acae6b3b60e01b815260040160405180910390fd5b6201000062030000821603610b9f576001600160a01b038216151580610b7c57506040516302571be360e01b81526004810189905230906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015610b4c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b7091906112df565b6001600160a01b031614155b15610b9a5760405163acae6b3b60e01b815260040160405180910390fd5b61091d565b8a8a8a818110610bb157610bb16111c6565b919091013560f81c5f039050610bf3576040517fa3f28cee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166324c1af44858d8d610c308e6001611231565b610c3c928b9290611287565b305f805f806040518963ffffffff1660e01b8152600401610c64989796959493929190611382565b6020604051808303815f875af1158015610c80573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca49190611358565b506040517fd8c9921a00000000000000000000000000000000000000000000000000000000815260048101859052602481018790523060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d8c9921a906064016108ef565b935093915050565b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061022357507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610223565b5f805f610d938585610db3565b9250905060ff811615610dab57806021858701012092505b509250929050565b5f8083518310610dd8578360405163ba4adc2360e01b815260040161038b91906113e4565b838381518110610dea57610dea6111c6565b016020015160f81c91505081810160010181610e0a578351811415610e10565b83518110155b15610e30578360405163ba4adc2360e01b815260040161038b91906113e4565b9250929050565b5f60208284031215610e47575f80fd5b81356001600160e01b031981168114610e5e575f80fd5b9392505050565b6001600160a01b0381168114610e79575f80fd5b50565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610eb957610eb9610e7c565b604052919050565b5f82601f830112610ed0575f80fd5b813567ffffffffffffffff811115610eea57610eea610e7c565b610efd601f8201601f1916602001610e90565b818152846020838601011115610f11575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215610f40575f80fd5b8435610f4b81610e65565b93506020850135610f5b81610e65565b925060408501359150606085013567ffffffffffffffff811115610f7d575f80fd5b610f8987828801610ec1565b91505092959194509250565b5f60208284031215610fa5575f80fd5b8135610e5e81610e65565b5f82601f830112610fbf575f80fd5b8135602067ffffffffffffffff821115610fdb57610fdb610e7c565b8160051b610fea828201610e90565b9283528481018201928281019087851115611003575f80fd5b83870192505b8483101561102257823582529183019190830190611009565b979650505050505050565b5f805f805f60a08688031215611041575f80fd5b853561104c81610e65565b9450602086013561105c81610e65565b9350604086013567ffffffffffffffff80821115611078575f80fd5b61108489838a01610fb0565b94506060880135915080821115611099575f80fd5b6110a589838a01610fb0565b935060808801359150808211156110ba575f80fd5b506110c788828901610ec1565b9150509295509295909350565b5f80602083850312156110e5575f80fd5b823567ffffffffffffffff808211156110fc575f80fd5b818501915085601f83011261110f575f80fd5b81358181111561111d575f80fd5b8660208260051b8501011115611131575f80fd5b60209290920196919550909350505050565b5f805f805f60a08688031215611157575f80fd5b853561116281610e65565b9450602086013561117281610e65565b93506040860135925060608601359150608086013567ffffffffffffffff81111561119b575f80fd5b6110c788828901610ec1565b5f602082840312156111b7575f80fd5b81518015158114610e5e575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f808335601e198436030181126111ef575f80fd5b83018035915067ffffffffffffffff821115611209575f80fd5b602001915036819003821315610e30575f80fd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156102235761022361121d565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f61127f602083018486611244565b949350505050565b5f8085851115611295575f80fd5b838611156112a1575f80fd5b5050820193919092039150565b80356020831015610223575f19602084900360031b1b1692915050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156112ef575f80fd5b8151610e5e81610e65565b5f805f6060848603121561130c575f80fd5b835161131781610e65565b602085015190935063ffffffff81168114611330575f80fd5b604085015190925067ffffffffffffffff8116811461134d575f80fd5b809150509250925092565b5f60208284031215611368575f80fd5b5051919050565b818103818111156102235761022361121d565b88815260e060208201525f61139b60e08301898b611244565b6001600160a01b03978816604084015295909616606082015267ffffffffffffffff938416608082015263ffffffff9290921660a083015290911660c090910152949350505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fea26469706673582212208ed13c5f069f009ba970dab168d2ed28f855b3e338ac86cd4d422e0cbe3993a864736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610085575f3560e01c80636f3ff726116100585780636f3ff72614610167578063bc197c811461017a578063d62f4d37146101b2578063f23a6e61146101c7575f80fd5b806301ffc9a714610089578063150b7a02146100b1578063192cf07d1461010157806348ee1bcc14610140575b5f80fd5b61009c610097366004610e37565b6101ff565b60405190151581526020015b60405180910390f35b6100e86100bf366004610f2d565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040516001600160e01b031990911681526020016100a8565b6101287f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a8565b6101287f000000000000000000000000000000000000000000000000000000000000000081565b61009c610175366004610f95565b610229565b6100e861018836600461102d565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b6101c56101c03660046110d4565b6102b5565b005b6100e86101d5366004611143565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b5f6001600160e01b0319821663379ffb9360e11b14806102235750610223826102fb565b92915050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610291573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022391906111a7565b5f5b818110156102f6576102ec8383838181106102d4576102d46111c6565b90506020028101906102e691906111da565b5f61031f565b50506001016102b7565b505050565b5f6001600160e01b0319821663379ffb9360e11b1480610223575061022382610d20565b5f8080808561032f866001611231565b1080156103555750868686818110610349576103496111c6565b919091013560f81c1590505b156103bd57610365856021611231565b905085811061039457868660405163ba4adc2360e01b815260040161038b92919061126c565b60405180910390fd5b86866103a1876001611231565b6103ad92849290611287565b6103b6916112ae565b9150610415565b6103fd87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250899250610d86915050565b90925090508161041557505f9250829150610d189050565b5f8061042289898561031f565b9150915061043982855f9182526020526040902090565b95505f81600381111561044e5761044e6112cb565b036104a1577f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae86146104935760405163acae6b3b60e01b815260040160405180910390fd5b5060019350610d1892505050565b60018160038111156104b5576104b56112cb565b0361092d576040516302571be360e01b8152600481018790525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906302571be390602401602060405180830381865afa15801561051f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061054391906112df565b9050306001600160a01b03821603610564575060029450610d189350505050565b604051630178fe3f60e01b8152600481018890525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156105c9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105ed91906112fa565b5090925090506001811615610635576001600160a01b03821630146106255760405163acae6b3b60e01b815260040160405180910390fd5b5060039550610d18945050505050565b6040517fd6e4fa86000000000000000000000000000000000000000000000000000000008152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d6e4fa8690602401602060405180830381865afa1580156106b1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106d59190611358565b5f036106f45760405163acae6b3b60e01b815260040160405180910390fd5b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663fca247ac87307f00000000000000000000000000000000000000000000000000000000000000006107584267ffffffffffffffff61136f565b610762919061136f565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b03909116602483015260448201526064016020604051808303815f875af11580156107b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d69190611358565b506040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018990525f906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630178b8bf90602401602060405180830381865afa158015610855573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087991906112df565b6001600160a01b03161461091d576040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018990525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015b5f604051808303815f87803b158015610906575f80fd5b505af1158015610918573d5f803e3d5ffd5b505050505b5060029550610d18945050505050565b6002816003811115610941576109416112cb565b036109fc576040517f5ef2c7f000000000000000000000000000000000000000000000000000000000815260048101839052602481018590523060448201525f6064820181905260848201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635ef2c7f09060a4015f604051808303815f87803b1580156109d8575f80fd5b505af11580156109ea573d5f803e3d5ffd5b5060029750610d189650505050505050565b604051630178fe3f60e01b8152600481018790525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015610a63573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a8791906112fa565b5091509150610a9881600116151590565b15610ac6576001600160a01b03821630146106255760405163acae6b3b60e01b815260040160405180910390fd5b6201000062030000821603610b9f576001600160a01b038216151580610b7c57506040516302571be360e01b81526004810189905230906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015610b4c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b7091906112df565b6001600160a01b031614155b15610b9a5760405163acae6b3b60e01b815260040160405180910390fd5b61091d565b8a8a8a818110610bb157610bb16111c6565b919091013560f81c5f039050610bf3576040517fa3f28cee00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166324c1af44858d8d610c308e6001611231565b610c3c928b9290611287565b305f805f806040518963ffffffff1660e01b8152600401610c64989796959493929190611382565b6020604051808303815f875af1158015610c80573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca49190611358565b506040517fd8c9921a00000000000000000000000000000000000000000000000000000000815260048101859052602481018790523060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d8c9921a906064016108ef565b935093915050565b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061022357507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610223565b5f805f610d938585610db3565b9250905060ff811615610dab57806021858701012092505b509250929050565b5f8083518310610dd8578360405163ba4adc2360e01b815260040161038b91906113e4565b838381518110610dea57610dea6111c6565b016020015160f81c91505081810160010181610e0a578351811415610e10565b83518110155b15610e30578360405163ba4adc2360e01b815260040161038b91906113e4565b9250929050565b5f60208284031215610e47575f80fd5b81356001600160e01b031981168114610e5e575f80fd5b9392505050565b6001600160a01b0381168114610e79575f80fd5b50565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610eb957610eb9610e7c565b604052919050565b5f82601f830112610ed0575f80fd5b813567ffffffffffffffff811115610eea57610eea610e7c565b610efd601f8201601f1916602001610e90565b818152846020838601011115610f11575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215610f40575f80fd5b8435610f4b81610e65565b93506020850135610f5b81610e65565b925060408501359150606085013567ffffffffffffffff811115610f7d575f80fd5b610f8987828801610ec1565b91505092959194509250565b5f60208284031215610fa5575f80fd5b8135610e5e81610e65565b5f82601f830112610fbf575f80fd5b8135602067ffffffffffffffff821115610fdb57610fdb610e7c565b8160051b610fea828201610e90565b9283528481018201928281019087851115611003575f80fd5b83870192505b8483101561102257823582529183019190830190611009565b979650505050505050565b5f805f805f60a08688031215611041575f80fd5b853561104c81610e65565b9450602086013561105c81610e65565b9350604086013567ffffffffffffffff80821115611078575f80fd5b61108489838a01610fb0565b94506060880135915080821115611099575f80fd5b6110a589838a01610fb0565b935060808801359150808211156110ba575f80fd5b506110c788828901610ec1565b9150509295509295909350565b5f80602083850312156110e5575f80fd5b823567ffffffffffffffff808211156110fc575f80fd5b818501915085601f83011261110f575f80fd5b81358181111561111d575f80fd5b8660208260051b8501011115611131575f80fd5b60209290920196919550909350505050565b5f805f805f60a08688031215611157575f80fd5b853561116281610e65565b9450602086013561117281610e65565b93506040860135925060608601359150608086013567ffffffffffffffff81111561119b575f80fd5b6110c788828901610ec1565b5f602082840312156111b7575f80fd5b81518015158114610e5e575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f808335601e198436030181126111ef575f80fd5b83018035915067ffffffffffffffff821115611209575f80fd5b602001915036819003821315610e30575f80fd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156102235761022361121d565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f61127f602083018486611244565b949350505050565b5f8085851115611295575f80fd5b838611156112a1575f80fd5b5050820193919092039150565b80356020831015610223575f19602084900360031b1b1692915050565b634e487b7160e01b5f52602160045260245ffd5b5f602082840312156112ef575f80fd5b8151610e5e81610e65565b5f805f6060848603121561130c575f80fd5b835161131781610e65565b602085015190935063ffffffff81168114611330575f80fd5b604085015190925067ffffffffffffffff8116811461134d575f80fd5b809150509250925092565b5f60208284031215611368575f80fd5b5051919050565b818103818111156102235761022361121d565b88815260e060208201525f61139b60e08301898b611244565b6001600160a01b03978816604084015295909616606082015267ffffffffffffffff938416608082015263ffffffff9290921660a083015290911660c090910152949350505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fea26469706673582212208ed13c5f069f009ba970dab168d2ed28f855b3e338ac86cd4d422e0cbe3993a864736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "25371": [ + { + "length": 32, + "start": 262 + }, + { + "length": 32, + "start": 1404 + }, + { + "length": 32, + "start": 2582 + }, + { + "length": 32, + "start": 3069 + }, + { + "length": 32, + "start": 3297 + } + ], + "25375": [ + { + "length": 32, + "start": 1234 + }, + { + "length": 32, + "start": 2064 + }, + { + "length": 32, + "start": 2236 + }, + { + "length": 32, + "start": 2447 + }, + { + "length": 32, + "start": 2823 + } + ], + "25379": [ + { + "length": 32, + "start": 1636 + }, + { + "length": 32, + "start": 1790 + } + ], + "25382": [ + { + "length": 32, + "start": 1831 + } + ], + "33410": [ + { + "length": 32, + "start": 325 + }, + { + "length": 32, + "start": 586 + } + ] + }, + "inputSourceName": "project/src/migration/Graveyard.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "NameNotClearable()": [ + { + "details": "Error selector: `0xacae6b3b`" + } + ], + "NameRequiresPreimage()": [ + { + "details": "Error selector: `0xa3f28cee`" + } + ] + }, + "kind": "dev", + "methods": { + "clear(bytes[])": { + "params": { + "names": "The array of names to clear." + } + }, + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "nameWrapper": "The ENSv1 `NameWrapper` contract." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "onERC721Received(address,address,uint256,bytes)": { + "details": "See {IERC721Receiver-onERC721Received}. Always returns `IERC721Receiver.onERC721Received.selector`." + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + } + }, + "stateVariables": { + "_BASE_REGISTRAR": { + "details": "The ENSv1 `BaseRegistrar` contract." + }, + "_GRACE_PERIOD": { + "details": "Same as `BaseRegistrarImplementation.GRACE_PERIOD()`." + }, + "_REGISTRY_V1": { + "details": "The ENSv1 `ENSRegistry` contract." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1039800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "NAME_WRAPPER()": "infinite", + "clear(bytes[])": "infinite", + "isContractNamer(address)": "infinite", + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": "infinite", + "onERC1155Received(address,address,uint256,uint256,bytes)": "infinite", + "onERC721Received(address,address,uint256,bytes)": "infinite", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_clear(bytes calldata,uint256)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NameNotClearable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NameRequiresPreimage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"names\",\"type\":\"bytes[]\"}],\"name\":\"clear\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"NameNotClearable()\":[{\"details\":\"Error selector: `0xacae6b3b`\"}],\"NameRequiresPreimage()\":[{\"details\":\"Error selector: `0xa3f28cee`\"}]},\"kind\":\"dev\",\"methods\":{\"clear(bytes[])\":{\"params\":{\"names\":\"The array of names to clear.\"}},\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"nameWrapper\":\"The ENSv1 `NameWrapper` contract.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"See {IERC721Receiver-onERC721Received}. Always returns `IERC721Receiver.onERC721Received.selector`.\"},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"stateVariables\":{\"_BASE_REGISTRAR\":{\"details\":\"The ENSv1 `BaseRegistrar` contract.\"},\"_GRACE_PERIOD\":{\"details\":\"Same as `BaseRegistrarImplementation.GRACE_PERIOD()`.\"},\"_REGISTRY_V1\":{\"details\":\"The ENSv1 `ENSRegistry` contract.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"NameNotClearable()\":[{\"notice\":\"Name cannot be cleared.\"}],\"NameRequiresPreimage()\":[{\"notice\":\"Wrapped names require preimage. \"}]},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract.\"},\"clear(bytes[])\":{\"notice\":\"Clear registry for migrated names.\"},\"constructor\":{\"notice\":\"Create a graveyard.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"}},\"notice\":\"The ENSv1 ETHRegistrarController for ENSv2 launch which becomes the burn address for migrated tokens. 1. Claim any expired ENSv1 name and assign ownership to this contract. 2. Clear the registry for any owned token.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/migration/Graveyard.sol\":\"Graveyard\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/BaseRegistrarImplementation.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"./IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\ncontract BaseRegistrarImplementation is ERC721, IBaseRegistrar, Ownable {\\n // A map of expiry times\\n mapping(uint256 => uint256) expiries;\\n // The ENS registry\\n ENS public ens;\\n // The namehash of the TLD this registrar owns (eg, .eth)\\n bytes32 public baseNode;\\n // A map of addresses that are authorised to register and renew names.\\n mapping(address => bool) public controllers;\\n uint256 public constant GRACE_PERIOD = 90 days;\\n bytes4 private constant INTERFACE_META_ID =\\n bytes4(keccak256(\\\"supportsInterface(bytes4)\\\"));\\n bytes4 private constant ERC721_ID =\\n bytes4(\\n keccak256(\\\"balanceOf(address)\\\") ^\\n keccak256(\\\"ownerOf(uint256)\\\") ^\\n keccak256(\\\"approve(address,uint256)\\\") ^\\n keccak256(\\\"getApproved(uint256)\\\") ^\\n keccak256(\\\"setApprovalForAll(address,bool)\\\") ^\\n keccak256(\\\"isApprovedForAll(address,address)\\\") ^\\n keccak256(\\\"transferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256)\\\") ^\\n keccak256(\\\"safeTransferFrom(address,address,uint256,bytes)\\\")\\n );\\n bytes4 private constant RECLAIM_ID =\\n bytes4(keccak256(\\\"reclaim(uint256,address)\\\"));\\n\\n /// v2.1.3 version of _isApprovedOrOwner which calls ownerOf(tokenId) and takes grace period into consideration instead of ERC721.ownerOf(tokenId);\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.1.3/contracts/token/ERC721/ERC721.sol#L187\\n /// @dev Returns whether the given spender can transfer a given token ID\\n /// @param spender address of the spender to query\\n /// @param tokenId uint256 ID of the token to be transferred\\n /// @return bool whether the msg.sender is approved for the given token ID,\\n /// is an operator of the owner, or is the owner of the token\\n function _isApprovedOrOwner(\\n address spender,\\n uint256 tokenId\\n ) internal view override returns (bool) {\\n address owner = ownerOf(tokenId);\\n return (spender == owner ||\\n getApproved(tokenId) == spender ||\\n isApprovedForAll(owner, spender));\\n }\\n\\n constructor(ENS _ens, bytes32 _baseNode) ERC721(\\\"\\\", \\\"\\\") {\\n ens = _ens;\\n baseNode = _baseNode;\\n }\\n\\n modifier live() {\\n require(ens.owner(baseNode) == address(this));\\n _;\\n }\\n\\n modifier onlyController() {\\n require(controllers[msg.sender]);\\n _;\\n }\\n\\n /// @dev Gets the owner of the specified token ID. Names become unowned\\n /// when their registration expires.\\n /// @param tokenId uint256 ID of the token to query the owner of\\n /// @return address currently marked as the owner of the given token ID\\n function ownerOf(\\n uint256 tokenId\\n ) public view override(IERC721, ERC721) returns (address) {\\n require(expiries[tokenId] > block.timestamp);\\n return super.ownerOf(tokenId);\\n }\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external override onlyOwner {\\n controllers[controller] = true;\\n emit ControllerAdded(controller);\\n }\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external override onlyOwner {\\n controllers[controller] = false;\\n emit ControllerRemoved(controller);\\n }\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external override onlyOwner {\\n ens.setResolver(baseNode, resolver);\\n }\\n\\n // Returns the expiration timestamp of the specified id.\\n function nameExpires(uint256 id) external view override returns (uint256) {\\n return expiries[id];\\n }\\n\\n // Returns true iff the specified name is available for registration.\\n function available(uint256 id) public view override returns (bool) {\\n // Not available if it's registered here or in its grace period.\\n return expiries[id] + GRACE_PERIOD < block.timestamp;\\n }\\n\\n /// @dev Register a name.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external override returns (uint256) {\\n return _register(id, owner, duration, true);\\n }\\n\\n /// @dev Register a name, without modifying the registry.\\n /// @param id The token ID (keccak256 of the label).\\n /// @param owner The address that should own the registration.\\n /// @param duration Duration in seconds for the registration.\\n function registerOnly(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256) {\\n return _register(id, owner, duration, false);\\n }\\n\\n function _register(\\n uint256 id,\\n address owner,\\n uint256 duration,\\n bool updateRegistry\\n ) internal live onlyController returns (uint256) {\\n require(available(id));\\n require(\\n block.timestamp + duration + GRACE_PERIOD >\\n block.timestamp + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] = block.timestamp + duration;\\n if (_exists(id)) {\\n // Name was previously owned, and expired\\n _burn(id);\\n }\\n _mint(owner, id);\\n if (updateRegistry) {\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n emit NameRegistered(id, owner, block.timestamp + duration);\\n\\n return block.timestamp + duration;\\n }\\n\\n function renew(\\n uint256 id,\\n uint256 duration\\n ) external override live onlyController returns (uint256) {\\n require(expiries[id] + GRACE_PERIOD >= block.timestamp); // Name must be registered here or in grace period\\n require(\\n expiries[id] + duration + GRACE_PERIOD > duration + GRACE_PERIOD\\n ); // Prevent future overflow\\n\\n expiries[id] += duration;\\n emit NameRenewed(id, expiries[id]);\\n return expiries[id];\\n }\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external override live {\\n require(_isApprovedOrOwner(msg.sender, id));\\n ens.setSubnodeOwner(baseNode, bytes32(id), owner);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view override(ERC721, IERC165) returns (bool) {\\n return\\n interfaceID == INTERFACE_META_ID ||\\n interfaceID == ERC721_ID ||\\n interfaceID == RECLAIM_ID;\\n }\\n}\\n\",\"keccak256\":\"0xf7d55afacf1b9b2c54e2ac3603af9a8a1bcafcb9209d246a7854a28a884f1142\"},\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: address zero is not a valid owner\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _ownerOf(tokenId);\\n require(owner != address(0), \\\"ERC721: invalid token ID\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n _requireMinted(tokenId);\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not token owner or approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n _requireMinted(tokenId);\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n _safeTransfer(from, to, tokenId, data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\\n */\\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\\n return _owners[tokenId];\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _ownerOf(tokenId) != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId, 1);\\n\\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n unchecked {\\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\\n // Given that tokens are minted one by one, it is impossible in practice that\\n // this ever happens. Might change if we allow batch minting.\\n // The ERC fails to describe this case.\\n _balances[to] += 1;\\n }\\n\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n * This is an internal function that does not check if the sender is authorized to operate on the token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\\n\\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\\n owner = ERC721.ownerOf(tokenId);\\n\\n // Clear approvals\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // Cannot overflow, as that would require more tokens to be burned/transferred\\n // out than the owner initially received through minting and transferring in.\\n _balances[owner] -= 1;\\n }\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId, 1);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(address from, address to, uint256 tokenId) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId, 1);\\n\\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n\\n // Clear approvals from the previous owner\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\\n // `from`'s balance is the number of token held, which is at least one before the current\\n // transfer.\\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\\n // all 2**256 token ids to be minted, which in practice is impossible.\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n }\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits an {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Reverts if the `tokenId` has not been minted yet.\\n */\\n function _requireMinted(uint256 tokenId) internal view virtual {\\n require(_exists(tokenId), \\\"ERC721: invalid token ID\\\");\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n /// @solidity memory-safe-assembly\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\\n * - When `from` is zero, the tokens will be minted for `to`.\\n * - When `to` is zero, ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\\n * - When `from` is zero, the tokens were minted for `to`.\\n * - When `to` is zero, ``from``'s tokens were burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {}\\n\\n /**\\n * @dev Unsafe write access to the balances, used by extensions that \\\"mint\\\" tokens using an {ownerOf} override.\\n *\\n * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant\\n * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such\\n * that `ownerOf(tokenId)` is `a`.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function __unsafe_increaseBalance(address account, uint256 amount) internal {\\n _balances[account] += amount;\\n }\\n}\\n\",\"keccak256\":\"0x2c309e7df9e05e6ce15bedfe74f3c61b467fc37e0fae9eab496acf5ea0bbd7ff\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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 * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\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://consensys.net/diligence/blog/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.8.0/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(address target, bytes memory data, uint256 value) 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\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\nimport \\\"./math/SignedMath.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 `int256` to its ASCII `string` decimal representation.\\n */\\n function toString(int256 value) internal pure returns (string memory) {\\n return string(abi.encodePacked(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value))));\\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 /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n}\\n\",\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.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(uint256 x, uint256 y, uint256 denominator) 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 // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1, \\\"Math: mulDiv overflow\\\");\\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(uint256 x, uint256 y, uint256 denominator, Rounding rounding) 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 256, 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 << 3) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // must be unchecked in order to support `n = type(int256).min`\\n return uint256(n >= 0 ? n : -n);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Holder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165, ERC165} from \\\"../../../utils/introspection/ERC165.sol\\\";\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\n\\n/**\\n * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.\\n *\\n * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be\\n * stuck.\\n */\\nabstract contract ERC1155Holder is ERC165, IERC1155Receiver {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155Received.selector;\\n }\\n\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] memory,\\n uint256[] memory,\\n bytes memory\\n ) public virtual override returns (bytes4) {\\n return this.onERC1155BatchReceived.selector;\\n }\\n}\\n\",\"keccak256\":\"0xe103e95f854ef0cd1bba5f469175f67cd332f5c2561941f165e3dd65cee94d6d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @title ERC-721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC-721 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\\n * 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\":\"0xb5afb8e8eebc4d1c6404df2f5e1e6d2c3d24fd01e5dfc855314951ecfaae462d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Holder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC721Receiver} from \\\"../IERC721Receiver.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC721Receiver} interface.\\n *\\n * Accepts all token transfers.\\n * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or\\n * {IERC721-setApprovalForAll}.\\n */\\nabstract contract ERC721Holder is IERC721Receiver {\\n /**\\n * @dev See {IERC721Receiver-onERC721Received}.\\n *\\n * Always returns `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {\\n return this.onERC721Received.selector;\\n }\\n}\\n\",\"keccak256\":\"0xaad20f8713b5cd98114278482d5d91b9758f9727048527d582e8e88fd4901fd8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/migration/Graveyard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n BaseRegistrarImplementation\\n} from \\\"@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol\\\";\\nimport {IBaseRegistrar} from \\\"@ens/contracts/ethregistrar/IBaseRegistrar.sol\\\";\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {ERC1155Holder} from \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol\\\";\\nimport {ERC721Holder} from \\\"@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @notice The ENSv1 ETHRegistrarController for ENSv2 launch which becomes the burn address for migrated tokens.\\n///\\n/// 1. Claim any expired ENSv1 name and assign ownership to this contract.\\n/// 2. Clear the registry for any owned token.\\n///\\ncontract Graveyard is ERC721Holder, ERC1155Holder, DelegatedContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The internal states of registry ownership.\\n enum State {\\n ROOT,\\n ETH,\\n OWNED,\\n LOCKED\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @dev The ENSv1 `ENSRegistry` contract.\\n ENS internal immutable _REGISTRY_V1;\\n\\n /// @dev The ENSv1 `BaseRegistrar` contract.\\n IBaseRegistrar internal immutable _BASE_REGISTRAR;\\n\\n /// @dev Same as `BaseRegistrarImplementation.GRACE_PERIOD()`.\\n uint256 internal immutable _GRACE_PERIOD;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be cleared.\\n /// @dev Error selector: `0xacae6b3b`\\n error NameNotClearable();\\n\\n /// @notice Wrapped names require preimage. \\n /// @dev Error selector: `0xa3f28cee`\\n error NameRequiresPreimage();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Create a graveyard.\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param contractNamer Delegated contract namer.\\n constructor(INameWrapper nameWrapper, IContractNamer contractNamer)\\n DelegatedContractNamer(contractNamer)\\n {\\n NAME_WRAPPER = nameWrapper;\\n _REGISTRY_V1 = nameWrapper.ens();\\n _BASE_REGISTRAR = nameWrapper.registrar();\\n _GRACE_PERIOD = BaseRegistrarImplementation(address(_BASE_REGISTRAR)).GRACE_PERIOD();\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n override(ERC1155Holder, DelegatedContractNamer)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Clear registry for migrated names.\\n /// @param names The array of names to clear.\\n function clear(bytes[] calldata names) external {\\n for (uint256 i; i < names.length; ++i) {\\n _clear(names[i], 0);\\n }\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Recursively clear ancestor namespace.\\n ///\\n /// Wrapped labels are 1-255 bytes and always have a preimage.\\n /// see: V1Fixture.t.sol: `test_nameWrapper_labelTooShort` and `test_nameWrapper_labelTooLong`\\n /// see: https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/NameWrapper.sol#L865-L876\\n ///\\n /// This function supports a modified DNS-encoding where zero-length labels\\n /// in the middle of name must be followed with exactly 32 bytes of labelhash.\\n ///\\n /// This is safe because zero-length non-terminating labels normally revert.\\n ///\\n function _clear(bytes calldata name, uint256 offset) internal returns (bytes32 node, State) {\\n bytes32 labelHash;\\n uint256 nextOffset;\\n // modified DNS-encoding: interpret zero-length labels differently\\n if (offset + 1 < name.length && uint8(name[offset]) == 0) {\\n nextOffset = offset + 33; // skip length and ensure next 32 bytes exist\\n if (nextOffset >= name.length) {\\n revert NameCoder.DNSDecodingFailed(name);\\n }\\n labelHash = bytes32(name[offset + 1:nextOffset]); // cast as literal bytes32\\n } else {\\n (labelHash, nextOffset) = NameCoder.readLabel(name, offset); // use standard logic\\n if (labelHash == bytes32(0)) {\\n return (bytes32(0), State.ROOT);\\n }\\n }\\n (bytes32 parentNode, State parentState) = _clear(name, nextOffset);\\n node = NameCoder.namehash(parentNode, labelHash);\\n if (parentState == State.ROOT) {\\n if (node != NameCoder.ETH_NODE) {\\n revert NameNotClearable();\\n }\\n return (node, State.ETH);\\n } else if (parentState == State.ETH) {\\n address owner = _REGISTRY_V1.owner(node);\\n if (owner == address(this)) {\\n // resolver is cleared by migration\\n return (node, State.OWNED);\\n }\\n uint32 fuses;\\n (owner, fuses, ) = NAME_WRAPPER.getData(uint256(node));\\n if (LibMigration.isLocked(fuses)) {\\n if (owner != address(this)) {\\n revert NameNotClearable();\\n }\\n // resolver is cleared by migration\\n return (node, State.LOCKED);\\n }\\n if (_BASE_REGISTRAR.nameExpires(uint256(labelHash)) == 0) {\\n revert NameNotClearable();\\n }\\n _BASE_REGISTRAR.register(\\n uint256(labelHash),\\n address(this),\\n type(uint64).max - block.timestamp - _GRACE_PERIOD // max duration?\\n );\\n // lock expired? so clear it\\n if (_REGISTRY_V1.resolver(node) != address(0)) {\\n _REGISTRY_V1.setResolver(node, address(0));\\n }\\n return (node, State.OWNED);\\n } else if (parentState == State.OWNED) {\\n _REGISTRY_V1.setSubnodeRecord(parentNode, labelHash, address(this), address(0), 0);\\n return (node, State.OWNED);\\n } else {\\n (address owner, uint32 fuses, ) = NAME_WRAPPER.getData(uint256(node));\\n if (LibMigration.isLocked(fuses)) {\\n if (owner != address(this)) {\\n revert NameNotClearable();\\n }\\n // resolver is cleared by migration\\n return (node, State.LOCKED);\\n } else if (LibMigration.isEmancipatedChild(fuses)) {\\n if (owner != address(0) || _REGISTRY_V1.owner(node) != address(this)) {\\n revert NameNotClearable();\\n }\\n // resolver is cleared by migration\\n } else {\\n if (uint8(name[offset]) == 0) {\\n revert NameRequiresPreimage();\\n }\\n NAME_WRAPPER.setSubnodeRecord(\\n parentNode,\\n string(name[offset + 1:nextOffset]),\\n address(this), // owner\\n address(0), // resolver is cleared\\n 0, // ttl\\n 0, // fuses\\n 0 // expiry (uses min)\\n ); // reverts if not migrated\\n NAME_WRAPPER.unwrap(parentNode, labelHash, address(this));\\n }\\n return (node, State.OWNED);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9c12b9f07798fd2062f653a3b3ad1ddbb0b6cb3b6e001ed443a4c8380f4719fa\",\"license\":\"MIT\"},\"project/src/migration/libraries/LibMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n CANNOT_BURN_FUSES,\\n CANNOT_UNWRAP,\\n IS_DOT_ETH,\\n PARENT_CANNOT_CONTROL\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Primitives for migration.\\nlibrary LibMigration {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Typed arguments for migration via transfer payload.\\n struct Data {\\n /// @dev Subdomain being migrated.\\n string label;\\n /// @dev Address that will own the name in the v2 registry.\\n address owner;\\n /// @dev Address of the child registry.\\n /// Ignored by locked migration.\\n IRegistry subregistry;\\n /// @dev Resolver address to set for the migrated name.\\n /// Ignored if locked and `CANNOT_SET_RESOLVER`.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Minimum size of `abi.encode(Data({...}))`.\\n uint256 internal constant MIN_DATA_SIZE = 7 * 32;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be registered because unmigrated NameWrapper token exists.\\n /// @dev Error selector: `0x408fa1b8`\\n error NameRequiresMigration();\\n\\n /// @notice NameWrapper token is unlocked.\\n /// @dev Error selector: `0x1bfe8f0a`\\n error NameNotLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper token is locked.\\n /// @dev Error selector: `0xe7c290e2`\\n error NameIsLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper or BaseRegistrar token does not match supplied data.\\n /// @dev Error selector: `0xedec3569`\\n error NameDataMismatch(uint256 tokenId);\\n\\n /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\\n /// @dev Error selector: `0xa4f07713`\\n error FrozenTokenApproval(uint256 tokenId);\\n\\n /// @notice The encoded data is invalid.\\n /// @dev Error selector: `0x5cb045db`\\n error InvalidData();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns `true` if the NameWrapper token is locked.\\n function isLocked(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient\\n // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()`\\n return (fuses & CANNOT_UNWRAP) != 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token fuses are not frozen.\\n function notFrozen(uint32 fuses) internal pure returns (bool) {\\n return (fuses & CANNOT_BURN_FUSES) == 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth.\\n function isEmancipatedChild(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL must be set for the entire ancestory.\\n // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()`\\n return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL;\\n }\\n}\\n\",\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "NameNotClearable()": [ + { + "notice": "Name cannot be cleared." + } + ], + "NameRequiresPreimage()": [ + { + "notice": "Wrapped names require preimage. " + } + ] + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract." + }, + "clear(bytes[])": { + "notice": "Clear registry for migrated names." + }, + "constructor": { + "notice": "Create a graveyard." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + } + }, + "notice": "The ENSv1 ETHRegistrarController for ENSv2 launch which becomes the burn address for migrated tokens. 1. Claim any expired ENSv1 name and assign ownership to this contract. 2. Clear the registry for any owned token.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce800000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0xa16a26be8b8511b36d854df2de33d5f88d05385dc60a61305192bdcb2f98306f", + "nonce": "0x54", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x324274f81001cd72347945bad0d4b97832d9c231ae5cf159099a2c80279883b2", + "blockNumber": "0xaa5708", + "transactionIndex": "0x67" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/LabelStore.json b/contracts/deployments/sepolia/LabelStore.json new file mode 100644 index 000000000..b517ca16c --- /dev/null +++ b/contracts/deployments/sepolia/LabelStore.json @@ -0,0 +1,299 @@ +{ + "address": "0xb03524289c16424f71802a1794c29c7bd1b9f577", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "LabelIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelIsTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "Label", + "type": "event" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getLabel", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setLabel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "LabelStore", + "sourceName": "src/utils/LabelStore.sol", + "bytecode": "0x60a0604052348015600e575f80fd5b5060405161080e38038061080e833981016040819052602b91603b565b6001600160a01b03166080526066565b5f60208284031215604a575f80fd5b81516001600160a01b0381168114605f575f80fd5b9392505050565b60805161078a6100845f395f818160950152610195015261078a5ff3fe608060405234801561000f575f80fd5b5060043610610064575f3560e01c80636f3ff7261161004d5780636f3ff726146100dc578063b21bf7fa146100ef578063bf5309691461010f575f80fd5b806301ffc9a71461006857806348ee1bcc14610090575b5f80fd5b61007b61007636600461049c565b610124565b60405190151581526020015b60405180910390f35b6100b77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610087565b61007b6100ea3660046104ca565b610167565b6101026100fd3660046104fd565b610200565b6040516100879190610514565b61012261011d366004610549565b6102a8565b005b5f6001600160e01b031982167f0d48fe930000000000000000000000000000000000000000000000000000000014806101615750610161826103b2565b92915050565b60405163379ffb9360e11b815273ffffffffffffffffffffffffffffffffffffffff82811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa1580156101dc573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016191906105b5565b60605f8061020d846103ff565b81526020019081526020015f208054610225906105d4565b80601f0160208091040260200160405190810160405280929190818152602001828054610251906105d4565b801561029c5780601f106102735761010080835404028352916020019161029c565b820191905f5260205f20905b81548152906001019060200180831161027f57829003601f168201915b50505050509050919050565b6102e682828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061040e92505050565b505f61032683838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049192505050565b90505f610332826103ff565b5f81815260208190526040902080549192509061034e906105d4565b90505f036103ac575f81815260208190526040902061036e84868361066c565b50815f1b7f4acabfe38b19342d926f219b03cae7c02831d64c4449ccd3d6726b8ef1f9963085856040516103a3929190610726565b60405180910390a25b50505050565b5f6001600160e01b0319821663379ffb9360e11b148061016157507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610161565b5f63ffffffff82168218610161565b80515f9080820361044b576040517fbf9a274000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff81111561016157826040517fdab6c73c0000000000000000000000000000000000000000000000000000000081526004016104889190610514565b60405180910390fd5b805160209091012090565b5f602082840312156104ac575f80fd5b81356001600160e01b0319811681146104c3575f80fd5b9392505050565b5f602082840312156104da575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146104c3575f80fd5b5f6020828403121561050d575f80fd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f806020838503121561055a575f80fd5b823567ffffffffffffffff80821115610571575f80fd5b818501915085601f830112610584575f80fd5b813581811115610592575f80fd5b8660208285010111156105a3575f80fd5b60209290920196919550909350505050565b5f602082840312156105c5575f80fd5b815180151581146104c3575f80fd5b600181811c908216806105e857607f821691505b60208210810361060657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52604160045260245ffd5b601f82111561066757805f5260205f20601f840160051c810160208510156106455750805b601f840160051c820191505b81811015610664575f8155600101610651565b50505b505050565b67ffffffffffffffff8311156106845761068461060c565b6106988361069283546105d4565b83610620565b5f601f8411600181146106c9575f85156106b25750838201355b5f19600387901b1c1916600186901b178355610664565b5f83815260208120601f198716915b828110156106f857868501358255602094850194600190920191016106d8565b5086821015610714575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f1916010191905056fea26469706673582212204049cef197fa705a58931c9389c7c0a63c089cf53eb98190f2b783e47efaeb7664736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610064575f3560e01c80636f3ff7261161004d5780636f3ff726146100dc578063b21bf7fa146100ef578063bf5309691461010f575f80fd5b806301ffc9a71461006857806348ee1bcc14610090575b5f80fd5b61007b61007636600461049c565b610124565b60405190151581526020015b60405180910390f35b6100b77f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610087565b61007b6100ea3660046104ca565b610167565b6101026100fd3660046104fd565b610200565b6040516100879190610514565b61012261011d366004610549565b6102a8565b005b5f6001600160e01b031982167f0d48fe930000000000000000000000000000000000000000000000000000000014806101615750610161826103b2565b92915050565b60405163379ffb9360e11b815273ffffffffffffffffffffffffffffffffffffffff82811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa1580156101dc573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016191906105b5565b60605f8061020d846103ff565b81526020019081526020015f208054610225906105d4565b80601f0160208091040260200160405190810160405280929190818152602001828054610251906105d4565b801561029c5780601f106102735761010080835404028352916020019161029c565b820191905f5260205f20905b81548152906001019060200180831161027f57829003601f168201915b50505050509050919050565b6102e682828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061040e92505050565b505f61032683838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049192505050565b90505f610332826103ff565b5f81815260208190526040902080549192509061034e906105d4565b90505f036103ac575f81815260208190526040902061036e84868361066c565b50815f1b7f4acabfe38b19342d926f219b03cae7c02831d64c4449ccd3d6726b8ef1f9963085856040516103a3929190610726565b60405180910390a25b50505050565b5f6001600160e01b0319821663379ffb9360e11b148061016157507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610161565b5f63ffffffff82168218610161565b80515f9080820361044b576040517fbf9a274000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff81111561016157826040517fdab6c73c0000000000000000000000000000000000000000000000000000000081526004016104889190610514565b60405180910390fd5b805160209091012090565b5f602082840312156104ac575f80fd5b81356001600160e01b0319811681146104c3575f80fd5b9392505050565b5f602082840312156104da575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146104c3575f80fd5b5f6020828403121561050d575f80fd5b5035919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f806020838503121561055a575f80fd5b823567ffffffffffffffff80821115610571575f80fd5b818501915085601f830112610584575f80fd5b813581811115610592575f80fd5b8660208285010111156105a3575f80fd5b60209290920196919550909350505050565b5f602082840312156105c5575f80fd5b815180151581146104c3575f80fd5b600181811c908216806105e857607f821691505b60208210810361060657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52604160045260245ffd5b601f82111561066757805f5260205f20601f840160051c810160208510156106455750805b601f840160051c820191505b81811015610664575f8155600101610651565b50505b505050565b67ffffffffffffffff8311156106845761068461060c565b6106988361069283546105d4565b83610620565b5f601f8411600181146106c9575f85156106b25750838201355b5f19600387901b1c1916600186901b178355610664565b5f83815260208120601f198716915b828110156106f857868501358255602094850194600190920191016106d8565b5086821015610714575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f1916010191905056fea26469706673582212204049cef197fa705a58931c9389c7c0a63c089cf53eb98190f2b783e47efaeb7664736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "75299": [ + { + "length": 32, + "start": 149 + }, + { + "length": 32, + "start": 405 + } + ] + }, + "inputSourceName": "project/src/utils/LabelStore.sol", + "devdoc": { + "errors": { + "LabelIsEmpty()": [ + { + "details": "The label was empty. Error selector: `0xbf9a2740`" + } + ], + "LabelIsTooLong(string)": [ + { + "details": "The label was more than 255 bytes. Error selector: `0xdab6c73c`" + } + ] + }, + "events": { + "Label(bytes32,string)": { + "params": { + "label": "The recorded label.", + "labelHash": "The hash of `label`." + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "contractNamer": "Delegated contract namer." + } + }, + "getLabel(uint256)": { + "params": { + "anyId": "The truncated labelhash." + }, + "returns": { + "_0": "The label or null if unknown." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "setLabel(string)": { + "params": { + "label": "The label." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "stateVariables": { + "_labels": { + "details": "The truncated labelhash to label mapping." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "386000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "getLabel(uint256)": "infinite", + "isContractNamer(address)": "infinite", + "setLabel(string)": "infinite", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_storageId(uint256)": "48" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"LabelIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelIsTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"Label\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getLabel\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setLabel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"LabelIsEmpty()\":[{\"details\":\"The label was empty. Error selector: `0xbf9a2740`\"}],\"LabelIsTooLong(string)\":[{\"details\":\"The label was more than 255 bytes. Error selector: `0xdab6c73c`\"}]},\"events\":{\"Label(bytes32,string)\":{\"params\":{\"label\":\"The recorded label.\",\"labelHash\":\"The hash of `label`.\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\"}},\"getLabel(uint256)\":{\"params\":{\"anyId\":\"The truncated labelhash.\"},\"returns\":{\"_0\":\"The label or null if unknown.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"setLabel(string)\":{\"params\":{\"label\":\"The label.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"_labels\":{\"details\":\"The truncated labelhash to label mapping.\"}},\"version\":1},\"userdoc\":{\"events\":{\"Label(bytes32,string)\":{\"notice\":\"A label was recorded.\"}},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"getLabel(uint256)\":{\"notice\":\"Invert `anyId` to the corresponding label.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"setLabel(string)\":{\"notice\":\"Ensure `label` can be inverted from `anyId`.\"}},\"notice\":\"Shared label database.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/utils/LabelStore.sol\":\"LabelStore\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"},\"project/src/utils/LabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {DelegatedContractNamer} from \\\"./DelegatedContractNamer.sol\\\";\\nimport {ILabelStore} from \\\"./interfaces/ILabelStore.sol\\\";\\nimport {LibLabel} from \\\"./LibLabel.sol\\\";\\n\\n/// @notice Shared label database.\\ncontract LabelStore is DelegatedContractNamer, ILabelStore {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The truncated labelhash to label mapping.\\n mapping(uint256 storageId => string label) internal _labels;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) DelegatedContractNamer(contractNamer) {}\\n\\n /// @inheritdoc DelegatedContractNamer\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return interfaceId == type(ILabelStore).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ILabelStore\\n function setLabel(string calldata label) external {\\n NameCoder.assertLabelSize(label);\\n uint256 labelId = LibLabel.id(label);\\n uint256 storageId = _storageId(labelId);\\n if (bytes(_labels[storageId]).length == 0) {\\n _labels[storageId] = label;\\n emit Label(bytes32(labelId), label);\\n }\\n }\\n\\n /// @inheritdoc ILabelStore\\n function getLabel(uint256 anyId) public view returns (string memory) {\\n return _labels[_storageId(anyId)];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Convert `anyId` to `storageId`.\\n function _storageId(uint256 anyId) internal pure returns (uint256) {\\n return LibLabel.withVersion(anyId, 0);\\n }\\n}\\n\",\"keccak256\":\"0x2f9cb8449c35bde2bcadc6735e271e9d1cd6998f62681cffe5344fb8e5c76178\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/interfaces/ILabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @notice Interface for a shared label database.\\n/// @dev Interface selector: `0x0d48fe93`\\ninterface ILabelStore {\\n /// @notice A label was recorded.\\n /// @param labelHash The hash of `label`.\\n /// @param label The recorded label.\\n event Label(bytes32 indexed labelHash, string label);\\n\\n /// @notice Ensure `label` can be inverted from `anyId`.\\n /// @param label The label.\\n function setLabel(string calldata label) external;\\n\\n /// @notice Invert `anyId` to the corresponding label.\\n /// @param anyId The truncated labelhash.\\n /// @return The label or null if unknown.\\n function getLabel(uint256 anyId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 75370, + "contract": "project/src/utils/LabelStore.sol:LabelStore", + "label": "_labels", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_string_storage)" + } + ], + "types": { + "t_mapping(t_uint256,t_string_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + }, + "userdoc": { + "events": { + "Label(bytes32,string)": { + "notice": "A label was recorded." + } + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "getLabel(uint256)": { + "notice": "Invert `anyId` to the corresponding label." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "setLabel(string)": { + "notice": "Ensure `label` can be inverted from `anyId`." + } + }, + "notice": "Shared label database.", + "version": 1 + }, + "argsData": "0x00000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0xd187c67a1dbd0d32004653a4a8bf03ef5807f56081041ec331452a0573920b85", + "nonce": "0xd", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x642b988dbc27cee5d0c54971e2a6f3fa95e2b44b445c11cdd10d72cc313cb6fa", + "blockNumber": "0xaa56b6", + "transactionIndex": "0xe1" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/LockedMigrationController.json b/contracts/deployments/sepolia/LockedMigrationController.json new file mode 100644 index 000000000..7f8e53ae7 --- /dev/null +++ b/contracts/deployments/sepolia/LockedMigrationController.json @@ -0,0 +1,754 @@ +{ + "address": "0x681802eff57b83edce99d688c023ab1284495176", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "address", + "name": "graveyard", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry", + "type": "address" + }, + { + "internalType": "contract VerifiableFactory", + "name": "verifiableFactory", + "type": "address" + }, + { + "internalType": "address", + "name": "wrapperRegistryImpl", + "type": "address" + }, + { + "internalType": "contract IAddressSet", + "name": "publicResolverSet", + "type": "address" + }, + { + "internalType": "address", + "name": "publicResolver", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "FrozenTokenApproval", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameDataMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameNotLocked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GRAVEYARD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_RESOLVER_SET", + "outputs": [ + { + "internalType": "contract IAddressSet", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERIFIABLE_FACTORY", + "outputs": [ + { + "internalType": "contract IVerifiableFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WRAPPER_REGISTRY_IMPL", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[]", + "name": "mds", + "type": "tuple[]" + } + ], + "name": "finishERC1155Migration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedName", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNode", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "LockedMigrationController", + "sourceName": "src/migration/LockedMigrationController.sol", + "bytecode": "0x6101a0604052348015610010575f80fd5b5060405161213838038061213883398101604081905261002f9161012a565b808888878787878585816001600160a01b03166080816001600160a01b031681525050806001600160a01b031660a0816001600160a01b031681525050816001600160a01b0316633f15457f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100cc91906101d5565b6001600160a01b0390811660c05295861660e0525050918316610100528216610120528116610140529283166101605250509590951661018052506101f795505050505050565b6001600160a01b0381168114610127575f80fd5b50565b5f805f805f805f80610100898b031215610142575f80fd5b885161014d81610113565b60208a015190985061015e81610113565b60408a015190975061016f81610113565b60608a015190965061018081610113565b60808a015190955061019181610113565b60a08a01519094506101a281610113565b60c08a01519093506101b381610113565b60e08a01519092506101c481610113565b809150509295985092959890939650565b5f602082840312156101e5575f80fd5b81516101f081610113565b9392505050565b60805160a05160c05160e0516101005161012051610140516101605161018051611e5e6102da5f395f8181610187015281816108d701526112f601525f81816101ae01526103c301525f81816102f40152610da701525f81816102cd0152610d3701525f81816101d50152610ecb01525f81816101210152610e9c01525f610c7901525f81816101fc01528181610dff015261109f01525f81816101600152818161047f01528181610503015281816106b201528181610a4401528181610b1101528181610be601528181610e420152818161100401526110c70152611e5e5ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c80635d05f04911610093578063bc197c8111610063578063bc197c8114610289578063f23a6e61146102b5578063f923b685146102c8578063ffeb4a30146102ef575f80fd5b80635d05f0491461021e5780636e7a2116146102335780636f3ff726146102615780639b224b1d14610274575f80fd5b806347500708116100ce578063475007081461018257806348ee1bcc146101a9578063547c9d2d146101d05780635c1a6b68146101f7575f80fd5b806301ffc9a7146100f457806318ad9b711461011c578063192cf07d1461015b575b5f80fd5b610107610102366004611513565b610316565b60405190151581526020015b60405180910390f35b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610113565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b61023161022c366004611589565b610326565b005b6040517f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae8152602001610113565b61010761026f366004611612565b6103a2565b61027c61042e565b604051610113919061165b565b61029c6102973660046116ab565b6104f7565b6040516001600160e01b03199091168152602001610113565b61029c6102c3366004611762565b6106a6565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b5f610320826108b1565b92915050565b33301461034d5760405163d86ad9cf60e01b81523360048201526024015b60405180910390fd5b828114610390576040517f5b0599910000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610344565b61039c848484846108d5565b50505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561040a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032091906117d9565b6040517f20c38e2b0000000000000000000000000000000000000000000000000000000081527f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae60048201526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906320c38e2b906024015f60405180830381865afa1580156104cb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104f2919081019061188d565b905090565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610579576040513360248201526105799063d86ad9cf60e01b906044015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526111bf565b828261058660e08961191b565b610591906040611932565b808210156105cb576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b1790526105cb906111bf565b5f6105d8868801886119f3565b604051635d05f04960e01b81529091503090635d05f04990610602908e908e908690600401611b3d565b5f604051808303815f87803b158015610619575f80fd5b505af192505050801561062a575060015b61066c573d808015610657576040519150601f19603f3d011682016040523d82523d5f602084013e61065c565b606091505b50610666816111bf565b50610695565b507fbc197c81000000000000000000000000000000000000000000000000000000009350610697565b505b50505098975050505050505050565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106f5576040513360248201526106f59063d86ad9cf60e01b90604401610542565b828260e080821015610733576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b179052610733906111bf565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f1990920191018161076b57905050905089825f815181106107b3576107b3611ba4565b60209081029190910101526107ca87890189611bb8565b815f815181106107dc576107dc611ba4565b6020908102919091010152604051635d05f04960e01b81523090635d05f0499061080c9085908590600401611bf2565b5f604051808303815f87803b158015610823575f80fd5b505af1925050508015610834575060015b610876573d808015610861576040519150601f19603f3d011682016040523d82523d5f602084013e610866565b606091505b50610870816111bf565b506108a1565b507ff23a6e610000000000000000000000000000000000000000000000000000000094506108a49050565b50505b5050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b14806103205750610320826111d2565b7f00000000000000000000000000000000000000000000000000000000000000007f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae5f5b858110156111b6575f85858381811061093457610934611ba4565b90506020028101906109469190611c3f565b61094f90611c5d565b60208101519091506001600160a01b0316610996576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8888848181106109a9576109a9611ba4565b845180516020918201209102929092013592506109d1905085825f9182526020526040902090565b8214610a0c576040517fedec356900000000000000000000000000000000000000000000000000000000815260048101839052602401610344565b60608301516040517f0178fe3f000000000000000000000000000000000000000000000000000000008152600481018490525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015610a91573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab59190611c68565b9250925050610ac682600116151590565b15610fd9576040821615801590610b8657506040517f081812fc000000000000000000000000000000000000000000000000000000008152600481018690525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063081812fc90602401602060405180830381865afa158015610b56573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b7a9190611cc6565b6001600160a01b031614155b15610bc0576040517fa4f0771300000000000000000000000000000000000000000000000000000000815260048101869052602401610344565b600882165f03610c4a57604051630c4b7b8560e11b8152600481018690525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015610c2f575f80fd5b505af1158015610c41573d5f803e3d5ffd5b50505050610dc9565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178b8bf90602401602060405180830381865afa158015610cc6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cea9190611cc6565b92506001600160a01b03831615801590610da057506040517f1aedefda0000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301527f00000000000000000000000000000000000000000000000000000000000000001690631aedefda90602401602060405180830381865afa158015610d7c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610da091906117d9565b15610dc9577f000000000000000000000000000000000000000000000000000000000000000092505b6040517ff242432a0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526001606483015260a060848301525f60a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c4015f604051808303815f87803b158015610e83575f80fd5b505af1158015610e95573d5f803e3d5ffd5b505050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d84121a7f0000000000000000000000000000000000000000000000000000000000000000885f1c898e8c5f0151610efc8a611238565b604051602401610f0f9493929190611ce1565b60408051601f198184030181529181526020820180516001600160e01b03167f1542c01a00000000000000000000000000000000000000000000000000000000179052516001600160e01b031960e086901b168152610f7393929190600401611d19565b6020604051808303815f875af1158015610f8f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fb39190611cc6565b9050610fd2875f015188602001518387610fcc8861126d565b876112c4565b50506111a5565b620100006203000083160361117057604051630c4b7b8560e11b8152600481018690525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b15801561104d575f80fd5b505af115801561105f573d5f803e3d5ffd5b50506040517fd8c9921a000000000000000000000000000000000000000000000000000000008152600481018b9052602481018790526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448301527f000000000000000000000000000000000000000000000000000000000000000016925063d8c9921a91506064015f604051808303815f87803b15801561110a575f80fd5b505af115801561111c573d5f803e3d5ffd5b507311100000000000000000000000000000011000009250505062040000831615611157577201000000000000000000000000000000010000175b610fd2875f0151886020015189604001518785876112c4565b6040517f1bfe8f0a00000000000000000000000000000000000000000000000000000000815260048101869052602401610344565b505050505050806001019050610919565b50505050505050565b6111c881611380565b9050805160208201fd5b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061032057507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610320565b5f602082168103611247576001175b6f11000000000000000000000000010000176002821661126857608081901b175b919050565b5f6204000082161561127f5762010000175b600882165f03611290576301000000175b6002821661129f57608081901b175b600482165f036112685773100000000000000000000000000000000000000017919050565b6040517f85f3e6430000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385f3e64390611335908a908a908a908a908a908990600401611d49565b6020604051808303815f875af1158015611351573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113759190611d9c565b979650505050505050565b60605f82511180156113aa575062461bcd60e51b61139d83611db3565b6001600160e01b03191614155b156114435762461bcd60e51b7f577261707065644572726f723a3a3078000000000000000000000000000000006113e084611447565b6040516020016113f1929190611de6565b60408051601f198184030181529082905261140e9160240161165b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b805160609060011b8067ffffffffffffffff811115611468576114686117f8565b6040519080825280601f01601f191660200182016040528015611492576020820181803683370190505b50915060208381019083016114a88282856114b0565b505050919050565b8181015b8083101561039c5783516101005b82851080156114d057505f81115b156115065760031901600f82821c16600a81106114f057806057016114f5565b806030015b9050808653506001909401936114c2565b50506020840193506114b4565b5f60208284031215611523575f80fd5b81356001600160e01b03198116811461153a575f80fd5b9392505050565b5f8083601f840112611551575f80fd5b50813567ffffffffffffffff811115611568575f80fd5b6020830191508360208260051b8501011115611582575f80fd5b9250929050565b5f805f806040858703121561159c575f80fd5b843567ffffffffffffffff808211156115b3575f80fd5b6115bf88838901611541565b909650945060208701359150808211156115d7575f80fd5b506115e487828801611541565b95989497509550505050565b6001600160a01b0381168114611604575f80fd5b50565b8035611268816115f0565b5f60208284031215611622575f80fd5b813561153a816115f0565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61153a602083018461162d565b5f8083601f84011261167d575f80fd5b50813567ffffffffffffffff811115611694575f80fd5b602083019150836020828501011115611582575f80fd5b5f805f805f805f8060a0898b0312156116c2575f80fd5b88356116cd816115f0565b975060208901356116dd816115f0565b9650604089013567ffffffffffffffff808211156116f9575f80fd5b6117058c838d01611541565b909850965060608b013591508082111561171d575f80fd5b6117298c838d01611541565b909650945060808b0135915080821115611741575f80fd5b5061174e8b828c0161166d565b999c989b5096995094979396929594505050565b5f805f805f8060a08789031215611777575f80fd5b8635611782816115f0565b95506020870135611792816115f0565b94506040870135935060608701359250608087013567ffffffffffffffff8111156117bb575f80fd5b6117c789828a0161166d565b979a9699509497509295939492505050565b5f602082840312156117e9575f80fd5b8151801515811461153a575f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff8111828210171561182f5761182f6117f8565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561185e5761185e6117f8565b604052919050565b5f67ffffffffffffffff82111561187f5761187f6117f8565b50601f01601f191660200190565b5f6020828403121561189d575f80fd5b815167ffffffffffffffff8111156118b3575f80fd5b8201601f810184136118c3575f80fd5b80516118d66118d182611866565b611835565b8181528560208385010111156118ea575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761032057610320611907565b8082018082111561032057610320611907565b5f60808284031215611955575f80fd5b61195d61180c565b9050813567ffffffffffffffff811115611975575f80fd5b8201601f81018413611985575f80fd5b803560206119956118d183611866565b82815286828486010111156119a8575f80fd5b82828501838301375f81840183015284526119c4858201611607565b818501525050506119d760408301611607565b60408201526119e860608301611607565b606082015292915050565b5f6020808385031215611a04575f80fd5b823567ffffffffffffffff80821115611a1b575f80fd5b818501915085601f830112611a2e575f80fd5b813581811115611a4057611a406117f8565b8060051b611a4f858201611835565b9182528381018501918581019089841115611a68575f80fd5b86860192505b83831015611aa257823585811115611a84575f80fd5b611a928b89838a0101611945565b8352509186019190860190611a6e565b9998505050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b84811015611b3057601f19868403018952815160808151818652611af08287018261162d565b838801516001600160a01b03908116888a015260408086015182169089015260609485015116939096019290925250509783019790830190600101611aca565b5090979650505050505050565b604081528260408201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841115611b74575f80fd5b8360051b80866060850137820182810360609081016020850152611b9a90820185611aaf565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611bc8575f80fd5b813567ffffffffffffffff811115611bde575f80fd5b611bea84828501611945565b949350505050565b604080825283519082018190525f906020906060840190828701845b82811015611c2a57815184529284019290840190600101611c0e565b5050508381036020850152611b9a8186611aaf565b5f8235607e19833603018112611c53575f80fd5b9190910192915050565b5f6103203683611945565b5f805f60608486031215611c7a575f80fd5b8351611c85816115f0565b602085015190935063ffffffff81168114611c9e575f80fd5b604085015190925067ffffffffffffffff81168114611cbb575f80fd5b809150509250925092565b5f60208284031215611cd6575f80fd5b815161153a816115f0565b8481526001600160a01b0384166020820152608060408201525f611d08608083018561162d565b905082606083015295945050505050565b6001600160a01b0384168152826020820152606060408201525f611d40606083018461162d565b95945050505050565b60c081525f611d5b60c083018961162d565b6001600160a01b039788166020840152958716604083015250929094166060830152608082015267ffffffffffffffff90921660a090920191909152919050565b5f60208284031215611dac575f80fd5b5051919050565b5f815160208301516001600160e01b0319808216935060048310156114a85760049290920360031b82901b161692915050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000831681525f82518060208501601085015e5f9201601001918252509291505056fea2646970667358221220b11d7d3b35ad292473efbbcdf627897a9a7f7f2cfc7208ca444c76831b19f66964736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c80635d05f04911610093578063bc197c8111610063578063bc197c8114610289578063f23a6e61146102b5578063f923b685146102c8578063ffeb4a30146102ef575f80fd5b80635d05f0491461021e5780636e7a2116146102335780636f3ff726146102615780639b224b1d14610274575f80fd5b806347500708116100ce578063475007081461018257806348ee1bcc146101a9578063547c9d2d146101d05780635c1a6b68146101f7575f80fd5b806301ffc9a7146100f457806318ad9b711461011c578063192cf07d1461015b575b5f80fd5b610107610102366004611513565b610316565b60405190151581526020015b60405180910390f35b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610113565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b61023161022c366004611589565b610326565b005b6040517f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae8152602001610113565b61010761026f366004611612565b6103a2565b61027c61042e565b604051610113919061165b565b61029c6102973660046116ab565b6104f7565b6040516001600160e01b03199091168152602001610113565b61029c6102c3366004611762565b6106a6565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b6101437f000000000000000000000000000000000000000000000000000000000000000081565b5f610320826108b1565b92915050565b33301461034d5760405163d86ad9cf60e01b81523360048201526024015b60405180910390fd5b828114610390576040517f5b0599910000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610344565b61039c848484846108d5565b50505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561040a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032091906117d9565b6040517f20c38e2b0000000000000000000000000000000000000000000000000000000081527f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae60048201526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906320c38e2b906024015f60405180830381865afa1580156104cb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104f2919081019061188d565b905090565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610579576040513360248201526105799063d86ad9cf60e01b906044015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526111bf565b828261058660e08961191b565b610591906040611932565b808210156105cb576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b1790526105cb906111bf565b5f6105d8868801886119f3565b604051635d05f04960e01b81529091503090635d05f04990610602908e908e908690600401611b3d565b5f604051808303815f87803b158015610619575f80fd5b505af192505050801561062a575060015b61066c573d808015610657576040519150601f19603f3d011682016040523d82523d5f602084013e61065c565b606091505b50610666816111bf565b50610695565b507fbc197c81000000000000000000000000000000000000000000000000000000009350610697565b505b50505098975050505050505050565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106f5576040513360248201526106f59063d86ad9cf60e01b90604401610542565b828260e080821015610733576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b179052610733906111bf565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f1990920191018161076b57905050905089825f815181106107b3576107b3611ba4565b60209081029190910101526107ca87890189611bb8565b815f815181106107dc576107dc611ba4565b6020908102919091010152604051635d05f04960e01b81523090635d05f0499061080c9085908590600401611bf2565b5f604051808303815f87803b158015610823575f80fd5b505af1925050508015610834575060015b610876573d808015610861576040519150601f19603f3d011682016040523d82523d5f602084013e610866565b606091505b50610870816111bf565b506108a1565b507ff23a6e610000000000000000000000000000000000000000000000000000000094506108a49050565b50505b5050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b14806103205750610320826111d2565b7f00000000000000000000000000000000000000000000000000000000000000007f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae5f5b858110156111b6575f85858381811061093457610934611ba4565b90506020028101906109469190611c3f565b61094f90611c5d565b60208101519091506001600160a01b0316610996576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8888848181106109a9576109a9611ba4565b845180516020918201209102929092013592506109d1905085825f9182526020526040902090565b8214610a0c576040517fedec356900000000000000000000000000000000000000000000000000000000815260048101839052602401610344565b60608301516040517f0178fe3f000000000000000000000000000000000000000000000000000000008152600481018490525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015610a91573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab59190611c68565b9250925050610ac682600116151590565b15610fd9576040821615801590610b8657506040517f081812fc000000000000000000000000000000000000000000000000000000008152600481018690525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063081812fc90602401602060405180830381865afa158015610b56573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b7a9190611cc6565b6001600160a01b031614155b15610bc0576040517fa4f0771300000000000000000000000000000000000000000000000000000000815260048101869052602401610344565b600882165f03610c4a57604051630c4b7b8560e11b8152600481018690525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015610c2f575f80fd5b505af1158015610c41573d5f803e3d5ffd5b50505050610dc9565b6040517f0178b8bf000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178b8bf90602401602060405180830381865afa158015610cc6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cea9190611cc6565b92506001600160a01b03831615801590610da057506040517f1aedefda0000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301527f00000000000000000000000000000000000000000000000000000000000000001690631aedefda90602401602060405180830381865afa158015610d7c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610da091906117d9565b15610dc9577f000000000000000000000000000000000000000000000000000000000000000092505b6040517ff242432a0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526001606483015260a060848301525f60a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c4015f604051808303815f87803b158015610e83575f80fd5b505af1158015610e95573d5f803e3d5ffd5b505050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d84121a7f0000000000000000000000000000000000000000000000000000000000000000885f1c898e8c5f0151610efc8a611238565b604051602401610f0f9493929190611ce1565b60408051601f198184030181529181526020820180516001600160e01b03167f1542c01a00000000000000000000000000000000000000000000000000000000179052516001600160e01b031960e086901b168152610f7393929190600401611d19565b6020604051808303815f875af1158015610f8f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fb39190611cc6565b9050610fd2875f015188602001518387610fcc8861126d565b876112c4565b50506111a5565b620100006203000083160361117057604051630c4b7b8560e11b8152600481018690525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b15801561104d575f80fd5b505af115801561105f573d5f803e3d5ffd5b50506040517fd8c9921a000000000000000000000000000000000000000000000000000000008152600481018b9052602481018790526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660448301527f000000000000000000000000000000000000000000000000000000000000000016925063d8c9921a91506064015f604051808303815f87803b15801561110a575f80fd5b505af115801561111c573d5f803e3d5ffd5b507311100000000000000000000000000000011000009250505062040000831615611157577201000000000000000000000000000000010000175b610fd2875f0151886020015189604001518785876112c4565b6040517f1bfe8f0a00000000000000000000000000000000000000000000000000000000815260048101869052602401610344565b505050505050806001019050610919565b50505050505050565b6111c881611380565b9050805160208201fd5b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061032057507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610320565b5f602082168103611247576001175b6f11000000000000000000000000010000176002821661126857608081901b175b919050565b5f6204000082161561127f5762010000175b600882165f03611290576301000000175b6002821661129f57608081901b175b600482165f036112685773100000000000000000000000000000000000000017919050565b6040517f85f3e6430000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906385f3e64390611335908a908a908a908a908a908990600401611d49565b6020604051808303815f875af1158015611351573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113759190611d9c565b979650505050505050565b60605f82511180156113aa575062461bcd60e51b61139d83611db3565b6001600160e01b03191614155b156114435762461bcd60e51b7f577261707065644572726f723a3a3078000000000000000000000000000000006113e084611447565b6040516020016113f1929190611de6565b60408051601f198184030181529082905261140e9160240161165b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b805160609060011b8067ffffffffffffffff811115611468576114686117f8565b6040519080825280601f01601f191660200182016040528015611492576020820181803683370190505b50915060208381019083016114a88282856114b0565b505050919050565b8181015b8083101561039c5783516101005b82851080156114d057505f81115b156115065760031901600f82821c16600a81106114f057806057016114f5565b806030015b9050808653506001909401936114c2565b50506020840193506114b4565b5f60208284031215611523575f80fd5b81356001600160e01b03198116811461153a575f80fd5b9392505050565b5f8083601f840112611551575f80fd5b50813567ffffffffffffffff811115611568575f80fd5b6020830191508360208260051b8501011115611582575f80fd5b9250929050565b5f805f806040858703121561159c575f80fd5b843567ffffffffffffffff808211156115b3575f80fd5b6115bf88838901611541565b909650945060208701359150808211156115d7575f80fd5b506115e487828801611541565b95989497509550505050565b6001600160a01b0381168114611604575f80fd5b50565b8035611268816115f0565b5f60208284031215611622575f80fd5b813561153a816115f0565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61153a602083018461162d565b5f8083601f84011261167d575f80fd5b50813567ffffffffffffffff811115611694575f80fd5b602083019150836020828501011115611582575f80fd5b5f805f805f805f8060a0898b0312156116c2575f80fd5b88356116cd816115f0565b975060208901356116dd816115f0565b9650604089013567ffffffffffffffff808211156116f9575f80fd5b6117058c838d01611541565b909850965060608b013591508082111561171d575f80fd5b6117298c838d01611541565b909650945060808b0135915080821115611741575f80fd5b5061174e8b828c0161166d565b999c989b5096995094979396929594505050565b5f805f805f8060a08789031215611777575f80fd5b8635611782816115f0565b95506020870135611792816115f0565b94506040870135935060608701359250608087013567ffffffffffffffff8111156117bb575f80fd5b6117c789828a0161166d565b979a9699509497509295939492505050565b5f602082840312156117e9575f80fd5b8151801515811461153a575f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff8111828210171561182f5761182f6117f8565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561185e5761185e6117f8565b604052919050565b5f67ffffffffffffffff82111561187f5761187f6117f8565b50601f01601f191660200190565b5f6020828403121561189d575f80fd5b815167ffffffffffffffff8111156118b3575f80fd5b8201601f810184136118c3575f80fd5b80516118d66118d182611866565b611835565b8181528560208385010111156118ea575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761032057610320611907565b8082018082111561032057610320611907565b5f60808284031215611955575f80fd5b61195d61180c565b9050813567ffffffffffffffff811115611975575f80fd5b8201601f81018413611985575f80fd5b803560206119956118d183611866565b82815286828486010111156119a8575f80fd5b82828501838301375f81840183015284526119c4858201611607565b818501525050506119d760408301611607565b60408201526119e860608301611607565b606082015292915050565b5f6020808385031215611a04575f80fd5b823567ffffffffffffffff80821115611a1b575f80fd5b818501915085601f830112611a2e575f80fd5b813581811115611a4057611a406117f8565b8060051b611a4f858201611835565b9182528381018501918581019089841115611a68575f80fd5b86860192505b83831015611aa257823585811115611a84575f80fd5b611a928b89838a0101611945565b8352509186019190860190611a6e565b9998505050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b84811015611b3057601f19868403018952815160808151818652611af08287018261162d565b838801516001600160a01b03908116888a015260408086015182169089015260609485015116939096019290925250509783019790830190600101611aca565b5090979650505050505050565b604081528260408201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841115611b74575f80fd5b8360051b80866060850137820182810360609081016020850152611b9a90820185611aaf565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611bc8575f80fd5b813567ffffffffffffffff811115611bde575f80fd5b611bea84828501611945565b949350505050565b604080825283519082018190525f906020906060840190828701845b82811015611c2a57815184529284019290840190600101611c0e565b5050508381036020850152611b9a8186611aaf565b5f8235607e19833603018112611c53575f80fd5b9190910192915050565b5f6103203683611945565b5f805f60608486031215611c7a575f80fd5b8351611c85816115f0565b602085015190935063ffffffff81168114611c9e575f80fd5b604085015190925067ffffffffffffffff81168114611cbb575f80fd5b809150509250925092565b5f60208284031215611cd6575f80fd5b815161153a816115f0565b8481526001600160a01b0384166020820152608060408201525f611d08608083018561162d565b905082606083015295945050505050565b6001600160a01b0384168152826020820152606060408201525f611d40606083018461162d565b95945050505050565b60c081525f611d5b60c083018961162d565b6001600160a01b039788166020840152958716604083015250929094166060830152608082015267ffffffffffffffff90921660a090920191909152919050565b5f60208284031215611dac575f80fd5b5051919050565b5f815160208301516001600160e01b0319808216935060048310156114a85760049290920360031b82901b161692915050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000831681525f82518060208501601085015e5f9201601001918252509291505056fea2646970667358221220b11d7d3b35ad292473efbbcdf627897a9a7f7f2cfc7208ca444c76831b19f66964736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "25006": [ + { + "length": 32, + "start": 352 + }, + { + "length": 32, + "start": 1151 + }, + { + "length": 32, + "start": 1283 + }, + { + "length": 32, + "start": 1714 + }, + { + "length": 32, + "start": 2628 + }, + { + "length": 32, + "start": 2833 + }, + { + "length": 32, + "start": 3046 + }, + { + "length": 32, + "start": 3650 + }, + { + "length": 32, + "start": 4100 + }, + { + "length": 32, + "start": 4295 + } + ], + "25009": [ + { + "length": 32, + "start": 508 + }, + { + "length": 32, + "start": 3583 + }, + { + "length": 32, + "start": 4255 + } + ], + "25013": [ + { + "length": 32, + "start": 3193 + } + ], + "25915": [ + { + "length": 32, + "start": 391 + }, + { + "length": 32, + "start": 2263 + }, + { + "length": 32, + "start": 4854 + } + ], + "26063": [ + { + "length": 32, + "start": 289 + }, + { + "length": 32, + "start": 3740 + } + ], + "26066": [ + { + "length": 32, + "start": 469 + }, + { + "length": 32, + "start": 3787 + } + ], + "26070": [ + { + "length": 32, + "start": 717 + }, + { + "length": 32, + "start": 3383 + } + ], + "26073": [ + { + "length": 32, + "start": 756 + }, + { + "length": 32, + "start": 3495 + } + ], + "33410": [ + { + "length": 32, + "start": 430 + }, + { + "length": 32, + "start": 963 + } + ] + }, + "inputSourceName": "project/src/migration/LockedMigrationController.sol", + "devdoc": { + "errors": { + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "FrozenTokenApproval(uint256)": [ + { + "details": "Error selector: `0xa4f07713`" + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "NameDataMismatch(uint256)": [ + { + "details": "Error selector: `0xedec3569`" + } + ], + "NameNotLocked(uint256)": [ + { + "details": "Error selector: `0x1bfe8f0a`" + } + ], + "UnauthorizedCaller(address)": [ + { + "details": "Error selector: `0xd86ad9cf`", + "params": { + "caller": "The address that attempted the unauthorized operation" + } + } + ] + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "ethRegistry": "The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.", + "graveyard": "The ENSv1 `BaseRegistrar` token graveyard.", + "nameWrapper": "The ENSv1 `NameWrapper` contract.", + "publicResolver": "The replacement `PublicResolver`.", + "publicResolverSet": "The list of `PublicResolver` contracts that require replacement.", + "verifiableFactory": "The shared factory for verifiable deployments.", + "wrapperRegistryImpl": "The `WrapperRegistry` implementation contract." + } + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "details": "Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts", + "params": { + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated.", + "mds": "The migration parameters for each name, indexed in parallel with `ids`." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.", + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed" + } + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data` struct containing migration parameters.", + "id": "The NameWrapper token ID (namehash) of the name being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed" + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1554800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "ETH_REGISTRY()": "infinite", + "GRAVEYARD()": "infinite", + "NAME_WRAPPER()": "infinite", + "PUBLIC_RESOLVER()": "infinite", + "PUBLIC_RESOLVER_SET()": "infinite", + "VERIFIABLE_FACTORY()": "infinite", + "WRAPPER_REGISTRY_IMPL()": "infinite", + "finishERC1155Migration(uint256[],(string,address,address,address)[])": "infinite", + "getWrappedName()": "infinite", + "getWrappedNode()": "221", + "isContractNamer(address)": "infinite", + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": "infinite", + "onERC1155Received(address,address,uint256,uint256,bytes)": "infinite", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_getRegistry()": "infinite", + "_inject(string memory,address,contract IRegistry,address,uint256,uint64)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"graveyard\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry\",\"type\":\"address\"},{\"internalType\":\"contract VerifiableFactory\",\"name\":\"verifiableFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"wrapperRegistryImpl\",\"type\":\"address\"},{\"internalType\":\"contract IAddressSet\",\"name\":\"publicResolverSet\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"publicResolver\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"FrozenTokenApproval\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameNotLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GRAVEYARD\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PUBLIC_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PUBLIC_RESOLVER_SET\",\"outputs\":[{\"internalType\":\"contract IAddressSet\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERIFIABLE_FACTORY\",\"outputs\":[{\"internalType\":\"contract IVerifiableFactory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WRAPPER_REGISTRY_IMPL\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[]\",\"name\":\"mds\",\"type\":\"tuple[]\"}],\"name\":\"finishERC1155Migration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedName\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNode\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"FrozenTokenApproval(uint256)\":[{\"details\":\"Error selector: `0xa4f07713`\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"NameDataMismatch(uint256)\":[{\"details\":\"Error selector: `0xedec3569`\"}],\"NameNotLocked(uint256)\":[{\"details\":\"Error selector: `0x1bfe8f0a`\"}],\"UnauthorizedCaller(address)\":[{\"details\":\"Error selector: `0xd86ad9cf`\",\"params\":{\"caller\":\"The address that attempted the unauthorized operation\"}}]},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"ethRegistry\":\"The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\",\"graveyard\":\"The ENSv1 `BaseRegistrar` token graveyard.\",\"nameWrapper\":\"The ENSv1 `NameWrapper` contract.\",\"publicResolver\":\"The replacement `PublicResolver`.\",\"publicResolverSet\":\"The list of `PublicResolver` contracts that require replacement.\",\"verifiableFactory\":\"The shared factory for verifiable deployments.\",\"wrapperRegistryImpl\":\"The `WrapperRegistry` implementation contract.\"}},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"details\":\"Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts\",\"params\":{\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\",\"mds\":\"The migration parameters for each name, indexed in parallel with `ids`.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\",\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\"}},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data` struct containing migration parameters.\",\"id\":\"The NameWrapper token ID (namehash) of the name being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"FrozenTokenApproval(uint256)\":[{\"notice\":\"NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"NameDataMismatch(uint256)\":[{\"notice\":\"NameWrapper or BaseRegistrar token does not match supplied data.\"}],\"NameNotLocked(uint256)\":[{\"notice\":\"NameWrapper token is unlocked.\"}],\"UnauthorizedCaller(address)\":[{\"notice\":\"Thrown when a caller is not authorized to perform the requested operation\"}]},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"ETH_REGISTRY()\":{\"notice\":\"The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\"},\"GRAVEYARD()\":{\"notice\":\"The ENSv1 `BaseRegistrar` token graveyard.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\"},\"PUBLIC_RESOLVER()\":{\"notice\":\"The replacement `PublicResolver`.\"},\"PUBLIC_RESOLVER_SET()\":{\"notice\":\"The list of `PublicResolver` contracts that require replacement.\"},\"VERIFIABLE_FACTORY()\":{\"notice\":\"The shared factory for verifiable deployments.\"},\"WRAPPER_REGISTRY_IMPL()\":{\"notice\":\"The `WrapperRegistry` implementation contract.\"},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"notice\":\"Convert NameWrapper tokens to their equivalent ENSv2 form.\"},\"getWrappedName()\":{\"notice\":\"Returns the DNS-encoded name for this registry.\"},\"getWrappedNode()\":{\"notice\":\"Returns the DNS-encoded name for \\\"eth\\\".\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"notice\":\"Migrate one NameWrapper token via `safeTransferFrom()`.\"}},\"notice\":\"Migration controller for handling locked .eth names. Assumes premigration has `RESERVED` existing ENSv1 names. Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/migration/LockedMigrationController.sol\":\"LockedMigrationController\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n /*\\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n * 0xb0202a11 ===\\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n */\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @param data Additional data with no specified format, sent in call to `spender`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\",\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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 /**\\n * @dev An operation with an ERC-20 token failed.\\n */\\n error SafeERC20FailedOperation(address token);\\n\\n /**\\n * @dev Indicates a failed `decreaseAllowance` request.\\n */\\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n forceApprove(token, spender, oldAllowance + value);\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n * value, non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n unchecked {\\n uint256 currentAllowance = token.allowance(address(this), spender);\\n if (currentAllowance < requestedDecrease) {\\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n }\\n forceApprove(token, spender, currentAllowance - requestedDecrease);\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n *\\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n * set here.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n safeTransfer(token, to, value);\\n } else if (!token.transferAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferFromAndCallRelaxed(\\n IERC1363 token,\\n address from,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length == 0) {\\n safeTransferFrom(token, from, to, value);\\n } else if (!token.transferFromAndCall(from, to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n * once without retrying, and relies on the returned value to be true.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n forceApprove(token, to, value);\\n } else if (!token.approveAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n // bubble errors\\n if iszero(success) {\\n let ptr := mload(0x40)\\n returndatacopy(ptr, 0, returndatasize())\\n revert(ptr, returndatasize())\\n }\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n\\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\n }\\n}\\n\",\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\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 There's no code to deploy.\\n */\\n error Create2EmptyBytecode();\\n\\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(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n if (bytecode.length == 0) {\\n revert Create2EmptyBytecode();\\n }\\n assembly (\\\"memory-safe\\\") {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n // if no address was created, and returndata is not empty, bubble revert\\n if and(iszero(addr), not(iszero(returndatasize()))) {\\n let p := mload(0x40)\\n returndatacopy(p, 0, returndatasize())\\n revert(p, returndatasize())\\n }\\n }\\n if (addr == address(0)) {\\n revert Errors.FailedDeployment();\\n }\\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(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {\\n assembly (\\\"memory-safe\\\") {\\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 := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xbb7e8401583d26268ea9103013bcdcd90866a7718bd91105ebd21c9bf11f4f06\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/CloneProxyBytecode.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nlibrary CloneProxyBytecode {\\n // EIP-1167 minimal proxy creation/runtime code:\\n // https://eips.ethereum.org/EIPS/eip-1167\\n //\\n // Standard runtime is 45 bytes:\\n // 363d3d373d3d3d363d73<20-byte implementation>5af43d82803e903d91602b57fd5bf3\\n //\\n // We append a 32-byte salt to the runtime and make the creation stub return 77 bytes\\n // instead of the standard 45. The proxy still executes the same minimal-proxy logic;\\n // UUPSProxyLogic reads the appended salt with extcodecopy().\\n uint256 internal constant CREATION_CODE_LENGTH = 0x57;\\n\\n function creationCode(address logic, bytes32 salt) internal pure returns (bytes memory code) {\\n code = new bytes(CREATION_CODE_LENGTH);\\n\\n assembly (\\\"memory-safe\\\") {\\n let ptr := add(code, 0x20)\\n\\n // Creation stub plus runtime prefix. The creation stub returns 77 bytes:\\n // 45 bytes of EIP-1167 runtime plus our appended 32-byte salt.\\n mstore(ptr, 0x3d604d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n // Fill the EIP-1167 PUSH20 slot with the shared proxy logic address.\\n mstore(add(ptr, 0x14), shl(0x60, logic))\\n // Runtime suffix: delegatecall to `logic`, copy returndata, then return or revert.\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n // Append salt after the executable minimal-proxy runtime for extcodecopy().\\n mstore(add(ptr, 0x37), salt)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2973c5070195e3c2806b59f1dc7a9da5aa1efa4a30867d9715def848bd51780f\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IProxyAuthorization {\\n function canUpgradeFrom(address previousImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IUUPSProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IUUPSProxy {\\n /// @dev Error selector: `0x0760838f`\\n error ImplementationCannotBeZeroAddress();\\n\\n /// @dev Error selector: `0x0dc149f0`\\n error AlreadyInitialized();\\n\\n /// @dev Error selector: `0x40dde935`\\n error ImplementationNotSet();\\n\\n /// @dev Error selector: `0xca331687`\\n error InvalidUpgradeTarget(address currentImplementation, address newImplementation);\\n\\n /// @dev Error selector: `0x784cf700`\\n error UpgradeNotAllowedInContext();\\n\\n /// @dev Error selector: `0x2be61883`\\n error UnexpectedUpgrade();\\n\\n function initialize(address implementation, bytes calldata data) external payable;\\n\\n function getVerifiableProxyData() external view returns (bytes32 salt, address implementation);\\n\\n function verifiableProxyFactory() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5de1b176834f853b0aba3d6e6b188a158f4b0f75744c7ffebb01bf6f51518233\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IVerifiableFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IVerifiableFactory {\\n error VerificationFailed(address proxy);\\n\\n event ProxyDeployed(address indexed sender, address indexed proxyAddress, uint256 salt, address implementation);\\n\\n function deployProxy(address implementation, uint256 salt, bytes memory data) external returns (address);\\n\\n function verifyContract(address proxy) external view returns (address implementation);\\n}\\n\",\"keccak256\":\"0xe6c1b487e41bb6e89383f8f63942d6db67bd140539df2755b82d999624c6050a\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/UUPSProxyLogic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport {IProxyAuthorization} from \\\"./IProxyAuthorization.sol\\\";\\nimport {IUUPSProxy} from \\\"./IUUPSProxy.sol\\\";\\n\\ncontract UUPSProxyLogic is IUUPSProxy {\\n /// @dev `keccak256(bytes(\\\"eip1967.proxy.implementation\\\")) - 1`.\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ImplementationCannotBeZeroAddress()\\\")))`.\\n uint256 internal constant _IMPLEMENTATION_CANNOT_BE_ZERO_ADDRESS_ERROR_SELECTOR = 0x0760838f;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"AlreadyInitialized()\\\")))`.\\n uint256 internal constant _ALREADY_INITIALIZED_ERROR_SELECTOR = 0x0dc149f0;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"UpgradeNotAllowedInContext()\\\")))`.\\n uint256 internal constant _UPGRADE_NOT_ALLOWED_IN_CONTEXT_ERROR_SELECTOR = 0x784cf700;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"UnexpectedUpgrade()\\\")))`.\\n uint256 internal constant _UNEXPECTED_UPGRADE_ERROR_SELECTOR = 0x2be61883;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ERC1967InvalidImplementation(address)\\\")))`.\\n uint256 internal constant _ERC1967_INVALID_IMPLEMENTATION_ERROR_SELECTOR = 0x4c9c8ce3;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ERC1967NonPayable()\\\")))`.\\n uint256 internal constant _ERC1967_NON_PAYABLE_ERROR_SELECTOR = 0xb398979f;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"Upgraded(address)\\\")))`.\\n uint256 internal constant _UPGRADED_EVENT_SELECTOR =\\n 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;\\n\\n address public immutable verifiableProxyFactory;\\n\\n constructor() {\\n verifiableProxyFactory = msg.sender;\\n }\\n\\n function initialize(address implementation, bytes calldata data) external payable {\\n assembly {\\n if eq(implementation, 0) {\\n mstore(0, _IMPLEMENTATION_CANNOT_BE_ZERO_ADDRESS_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n if iszero(eq(sload(_IMPLEMENTATION_SLOT), 0)) {\\n mstore(0, _ALREADY_INITIALIZED_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n if iszero(extcodesize(implementation)) {\\n mstore(0, _ERC1967_INVALID_IMPLEMENTATION_ERROR_SELECTOR)\\n mstore(0x20, implementation)\\n revert(0x1c, 0x24)\\n }\\n sstore(_IMPLEMENTATION_SLOT, implementation)\\n log2(0, 0, _UPGRADED_EVENT_SELECTOR, implementation)\\n\\n let dlength := data.length\\n switch dlength\\n case 0 {\\n if callvalue() {\\n mstore(0, _ERC1967_NON_PAYABLE_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n }\\n default {\\n calldatacopy(0, data.offset, dlength)\\n let result := delegatecall(gas(), implementation, 0, dlength, 0, 0)\\n if iszero(result) {\\n returndatacopy(0, 0, returndatasize())\\n revert(0, returndatasize())\\n }\\n }\\n }\\n }\\n\\n function getVerifiableProxyData() public view returns (bytes32 salt, address implementation) {\\n assembly {\\n extcodecopy(address(), 0, sub(extcodesize(address()), 0x20), 0x20)\\n salt := mload(0)\\n implementation := sload(_IMPLEMENTATION_SLOT)\\n }\\n }\\n\\n function upgradeToAndCall(address newImplementation, bytes calldata) external payable {\\n if (newImplementation == address(0)) revert ImplementationCannotBeZeroAddress();\\n\\n address implementation = _implementation();\\n if (implementation == address(0)) revert ImplementationNotSet();\\n\\n IProxyAuthorization newImpl = IProxyAuthorization(newImplementation);\\n if (!newImpl.canUpgradeFrom(implementation)) {\\n revert InvalidUpgradeTarget(implementation, newImplementation);\\n }\\n\\n _delegateUpgrade(implementation, newImplementation);\\n }\\n\\n function _implementation() internal view returns (address impl) {\\n assembly {\\n impl := sload(_IMPLEMENTATION_SLOT)\\n }\\n }\\n\\n function _delegate(address implementation, bool checkImplementation) internal {\\n assembly {\\n calldatacopy(0, 0, calldatasize())\\n\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n if checkImplementation {\\n if iszero(eq(implementation, sload(_IMPLEMENTATION_SLOT))) {\\n mstore(0, _UPGRADE_NOT_ALLOWED_IN_CONTEXT_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n }\\n\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n function _delegateUpgrade(address implementation, address expectedImplementation) internal {\\n assembly {\\n calldatacopy(0, 0, calldatasize())\\n\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n if iszero(result) {\\n returndatacopy(0, 0, returndatasize())\\n revert(0, returndatasize())\\n }\\n\\n if iszero(eq(expectedImplementation, sload(_IMPLEMENTATION_SLOT))) {\\n mstore(0, _UNEXPECTED_UPGRADE_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n\\n returndatacopy(0, 0, returndatasize())\\n return(0, returndatasize())\\n }\\n }\\n\\n fallback() external payable {\\n _delegate(_implementation(), true);\\n }\\n}\\n\",\"keccak256\":\"0x980e42f28d79bc1d473593042c1fd2d17038f81344f13ac08a29c03f2cf20c54\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/VerifiableFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport {Create2} from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\nimport {CloneProxyBytecode} from \\\"./CloneProxyBytecode.sol\\\";\\nimport {UUPSProxyLogic} from \\\"./UUPSProxyLogic.sol\\\";\\nimport {IUUPSProxy} from \\\"./IUUPSProxy.sol\\\";\\nimport {IVerifiableFactory} from \\\"./IVerifiableFactory.sol\\\";\\n\\ncontract VerifiableFactory is IVerifiableFactory {\\n address public immutable proxyLogic;\\n\\n constructor() {\\n proxyLogic = address(new UUPSProxyLogic());\\n }\\n\\n /**\\n * @dev Deploys a new verifiable proxy clone at a deterministic address.\\n *\\n * The deployed proxy is an EIP-1167-style clone that delegates proxy mechanics to the\\n * factory's `proxyLogic` contract. The clone runtime also appends the derived salt so the\\n * factory can later verify the proxy's CREATE2 address.\\n *\\n * The CREATE2 salt is `keccak256(abi.encode(msg.sender, salt))`, so two callers can reuse\\n * the same user salt without colliding.\\n *\\n * @param implementation The address of the contract implementation the proxy will delegate calls to.\\n * @param salt A value provided by the caller to ensure uniqueness of the proxy address.\\n * @return proxy The address of the deployed proxy clone.\\n */\\n function deployProxy(address implementation, uint256 salt, bytes memory data) external returns (address proxy) {\\n bytes32 outerSalt = keccak256(abi.encode(msg.sender, salt));\\n bytes memory executableBytecode = _proxyCreationCode(outerSalt);\\n\\n assembly {\\n proxy := create2(0, add(executableBytecode, 0x20), mload(executableBytecode), outerSalt)\\n if iszero(proxy) {\\n revert(0, 0)\\n }\\n }\\n\\n IUUPSProxy(proxy).initialize(implementation, data);\\n\\n emit ProxyDeployed(msg.sender, proxy, salt, implementation);\\n }\\n\\n /**\\n * @dev Verifies a proxy contract and returns its current implementation.\\n *\\n * This function attempts to validate a proxy contract by retrieving its salt\\n * and reconstructing the address to ensure it was correctly deployed by the\\n * current factory.\\n *\\n * @param proxy The address of the proxy contract being verified.\\n * @return implementation The proxy's current implementation.\\n */\\n function verifyContract(address proxy) public view returns (address implementation) {\\n if (!isContract(proxy)) revert VerificationFailed(proxy);\\n\\n try IUUPSProxy(proxy).getVerifiableProxyData() returns (bytes32 salt, address actualImplementation) {\\n if (_verifyContract(proxy, salt)) return actualImplementation;\\n } catch {}\\n revert VerificationFailed(proxy);\\n }\\n\\n function _verifyContract(address proxy, bytes32 salt) private view returns (bool) {\\n bytes memory proxyBytecode = _proxyCreationCode(salt);\\n\\n address expectedProxyAddress = Create2.computeAddress(salt, keccak256(proxyBytecode), address(this));\\n\\n return expectedProxyAddress == proxy;\\n }\\n\\n function _proxyCreationCode(bytes32 salt) private view returns (bytes memory creationCode) {\\n creationCode = CloneProxyBytecode.creationCode(proxyLogic, salt);\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n}\\n\",\"keccak256\":\"0xb5d61f83d18f2a1e615ddc606f7277e1f8bc2eb13d8d452dc8c1f4a4603e72d2\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/migration/AbstractWrapperReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {IERC1155Receiver} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport {ERC165, IERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {UnauthorizedCaller} from \\\"../CommonErrors.sol\\\";\\nimport {WrappedErrorLib} from \\\"../utils/WrappedErrorLib.sol\\\";\\n\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title AbstractWrapperReceiver\\n/// @dev Abstract IERC1155Receiver which handles NameWrapper token migration via transfer.\\n///\\n/// NameWrapper only allows `Error(string)` exceptions during transfer and squelches typed errors.\\n/// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L317-L335\\n/// This contract, with the aid of WrappedErrorLib, embeds errors that occur during migration into `Error(string)`.\\n///\\n/// There are (2) AbstractWrapperReceiver implementations:\\n/// 1. UnlockedMigrationController accepts unlocked tokens.\\n/// 2. LockedWrapperReceiver accepts locked tokens.\\n///\\n/// `LibMigration.isLocked()` determines lock status.\\n///\\nabstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice The ENSv1 `BaseRegistrar` token graveyard.\\n address public immutable GRAVEYARD;\\n\\n /// @dev The ENSv1 `ENSRegistry` contract.\\n ENS internal immutable _REGISTRY_V1;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Restrict `msg.sender` to NameWrapper.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier onlyWrapper() {\\n if (msg.sender != address(NAME_WRAPPER)) {\\n WrappedErrorLib.wrapAndRevert(\\n abi.encodeWithSelector(UnauthorizedCaller.selector, msg.sender)\\n );\\n }\\n _;\\n }\\n\\n /// @dev Avoid `abi.decode()` failure for obviously invalid data.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier withData(bytes calldata data, uint256 minimumSize) {\\n if (data.length < minimumSize) {\\n WrappedErrorLib.wrapAndRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector));\\n }\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n constructor(INameWrapper nameWrapper, address graveyard) {\\n NAME_WRAPPER = nameWrapper;\\n GRAVEYARD = graveyard;\\n _REGISTRY_V1 = nameWrapper.ens();\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate one NameWrapper token via `safeTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param id The NameWrapper token ID (namehash) of the name being migrated.\\n /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters.\\n function onERC1155Received(\\n address /*operator*/,\\n address /*from*/,\\n uint256 id,\\n uint256 /*amount*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (amount != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L293\\n uint256[] memory ids = new uint256[](1);\\n LibMigration.Data[] memory mds = new LibMigration.Data[](1);\\n ids[0] = id;\\n mds[0] = abi.decode(data, (LibMigration.Data)); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155Received.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param data ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\\n function onERC1155BatchReceived(\\n address /*operator*/,\\n address /*from*/,\\n uint256[] calldata ids,\\n uint256[] calldata /*amounts*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, 64 + ids.length * LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (ids.length != amounts.length) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L162\\n // if (amounts[i] != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L182\\n LibMigration.Data[] memory mds = abi.decode(data, (LibMigration.Data[])); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155BatchReceived.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @notice Convert NameWrapper tokens to their equivalent ENSv2 form.\\n /// @dev Only callable by ourself and invoked by our `IERC1155Receiver` handlers.\\n ///\\n /// TODO: gas analysis and optimization\\n /// NOTE: converting this to an internal call requires catching many reverts\\n ///\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param mds The migration parameters for each name, indexed in parallel with `ids`.\\n function finishERC1155Migration(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n external\\n {\\n if (msg.sender != address(this)) {\\n revert UnauthorizedCaller(msg.sender);\\n }\\n if (ids.length != mds.length) {\\n revert IERC1155Errors.ERC1155InvalidArrayLength(ids.length, mds.length);\\n }\\n _migrateWrapped(ids, mds);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Migrate received NameWrapper tokens.\\n /// Token owner is this contract.\\n /// Token is not expired.\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n virtual;\\n}\\n\",\"keccak256\":\"0x0c15f9f657ba58bf5081cbff88c385c9e673ba87aed2032397ec2c5448d7fe1a\",\"license\":\"MIT\"},\"project/src/migration/LockedMigrationController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {VerifiableFactory} from \\\"@ensdomains/verifiable-factory/VerifiableFactory.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\nimport {IAddressSet} from \\\"../utils/interfaces/IAddressSet.sol\\\";\\n\\nimport {AbstractWrapperReceiver} from \\\"./AbstractWrapperReceiver.sol\\\";\\nimport {LockedWrapperReceiver} from \\\"./LockedWrapperReceiver.sol\\\";\\n\\n/// @notice Migration controller for handling locked .eth names.\\n///\\n/// Assumes premigration has `RESERVED` existing ENSv1 names.\\n/// Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration.\\n///\\ncontract LockedMigrationController is LockedWrapperReceiver, DelegatedContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n /// @param ethRegistry The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\\n /// @param verifiableFactory The shared factory for verifiable deployments.\\n /// @param wrapperRegistryImpl The `WrapperRegistry` implementation contract.\\n /// @param publicResolverSet The list of `PublicResolver` contracts that require replacement.\\n /// @param publicResolver The replacement `PublicResolver`.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n INameWrapper nameWrapper,\\n address graveyard,\\n IPermissionedRegistry ethRegistry,\\n VerifiableFactory verifiableFactory,\\n address wrapperRegistryImpl,\\n IAddressSet publicResolverSet,\\n address publicResolver,\\n IContractNamer contractNamer\\n )\\n LockedWrapperReceiver(\\n nameWrapper,\\n graveyard,\\n verifiableFactory,\\n wrapperRegistryImpl,\\n publicResolverSet,\\n publicResolver\\n )\\n DelegatedContractNamer(contractNamer)\\n {\\n ETH_REGISTRY = ethRegistry;\\n }\\n\\n /// @inheritdoc DelegatedContractNamer\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(AbstractWrapperReceiver, DelegatedContractNamer)\\n returns (bool)\\n {\\n return super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Returns the DNS-encoded name for \\\"eth\\\".\\n function getWrappedNode() public pure override returns (bytes32) {\\n return NameCoder.ETH_NODE;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Register `RESERVED` .eth token.\\n function _inject(\\n string memory label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 /*expiry*/\\n )\\n internal\\n override\\n returns (uint256 tokenId)\\n {\\n return\\n ETH_REGISTRY.register(\\n label,\\n owner,\\n subregistry,\\n resolver,\\n roleBitmap,\\n 0 // use reserved expiry\\n ); // reverts if not RESERVED\\n }\\n\\n /// @inheritdoc LockedWrapperReceiver\\n function _getRegistry() internal view override returns (IRegistry) {\\n return ETH_REGISTRY;\\n }\\n}\\n\",\"keccak256\":\"0xfeaf28aa17111f758e8957ee898ef7cc48c0410716b4bac412c0795543c6e664\",\"license\":\"MIT\"},\"project/src/migration/LockedWrapperReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {\\n INameWrapper,\\n CAN_EXTEND_EXPIRY,\\n CANNOT_APPROVE,\\n CANNOT_CREATE_SUBDOMAIN,\\n CANNOT_SET_RESOLVER,\\n CANNOT_TRANSFER\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IVerifiableFactory} from \\\"@ensdomains/verifiable-factory/IVerifiableFactory.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {REGISTRATION_ROLE_BITMAP} from \\\"../registrar/ETHRegistrar.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {IWrapperRegistry} from \\\"../registry/interfaces/IWrapperRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"../registry/libraries/RegistryRolesLib.sol\\\";\\nimport {IAddressSet} from \\\"../utils/interfaces/IAddressSet.sol\\\";\\n\\nimport {AbstractWrapperReceiver} from \\\"./AbstractWrapperReceiver.sol\\\";\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title LockedWrappedReceiver\\n/// @dev AbstractWrapperReceiver for locked NameWrapper tokens.\\n///\\n/// There are (2) LockedWrapperReceiver implementations:\\n/// 1. LockedMigrationController only accepts .eth 2LD tokens.\\n/// 2. WrapperRegistry only accepts emancipated (N+1)-LD children with a matching N-LD parent node.\\n///\\n/// eg. transfer(\\\"nick.eth\\\") => LockedMigrationController\\n/// \\u21aa ETHRegistry.subregistry(\\\"nick\\\") = WrapperRegistry(\\\"nick.eth\\\")\\n/// transfer(\\\"sub.nick.eth\\\") => WrapperRegistry(\\\"nick.eth\\\")\\n/// \\u21aa WrapperRegistry(\\\"nick.eth\\\").subregistry(\\\"sub\\\") = WrapperRegistry(\\\"sub.nick.eth\\\")\\n/// transfer(\\\"abc.sub.nick.eth\\\") => WrapperRegistry(\\\"sub.nick.eth\\\")\\n/// \\u21aa WrapperRegistry(\\\"sub.nick.eth\\\").subregistry(\\\"abc\\\") = WrapperRegistry(\\\"abc.sub.nick.eth\\\")\\n///\\n/// Upon successful migration:\\n/// * subregistry is bound to a WrapperRegistry (does not have `ROLE_SET_SUBREGISTRY`)\\n/// * subregistry is canonical (does not have `ROLE_SET_PARENT`) and knows its name\\n/// * subregistry migrates emancipated children with the same parent\\n///\\nabstract contract LockedWrapperReceiver is AbstractWrapperReceiver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The shared factory for verifiable deployments.\\n IVerifiableFactory public immutable VERIFIABLE_FACTORY;\\n\\n /// @notice The `WrapperRegistry` implementation contract.\\n address public immutable WRAPPER_REGISTRY_IMPL;\\n\\n /// @notice The list of `PublicResolver` contracts that require replacement.\\n IAddressSet public immutable PUBLIC_RESOLVER_SET;\\n\\n /// @notice The replacement `PublicResolver`.\\n address public immutable PUBLIC_RESOLVER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n /// @param verifiableFactory The shared factory for verifiable deployments.\\n /// @param wrapperRegistryImpl The `WrapperRegistry` implementation contract.\\n /// @param publicResolverSet The list of `PublicResolver` contracts that require replacement.\\n /// @param publicResolver The replacement `PublicResolver`.\\n constructor(\\n INameWrapper nameWrapper,\\n address graveyard,\\n IVerifiableFactory verifiableFactory,\\n address wrapperRegistryImpl,\\n IAddressSet publicResolverSet,\\n address publicResolver\\n )\\n AbstractWrapperReceiver(nameWrapper, graveyard)\\n {\\n VERIFIABLE_FACTORY = verifiableFactory;\\n WRAPPER_REGISTRY_IMPL = wrapperRegistryImpl;\\n PUBLIC_RESOLVER_SET = publicResolverSet;\\n PUBLIC_RESOLVER = publicResolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Returns the DNS-encoded name for this registry.\\n function getWrappedName() public view virtual returns (bytes memory) {\\n return NAME_WRAPPER.names(getWrappedNode());\\n }\\n\\n /// @notice Returns the NameWrapper node (namehash).\\n function getWrappedNode() public view virtual returns (bytes32);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc AbstractWrapperReceiver\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n override\\n {\\n IRegistry parentRegistry = _getRegistry();\\n bytes32 parentNode = getWrappedNode();\\n for (uint256 i; i < ids.length; ++i) {\\n LibMigration.Data memory md = mds[i];\\n if (md.owner == address(0)) {\\n revert InvalidOwner();\\n }\\n bytes32 node = bytes32(ids[i]);\\n bytes32 labelHash = keccak256(bytes(md.label));\\n if (node != NameCoder.namehash(parentNode, labelHash)) {\\n revert LibMigration.NameDataMismatch(uint256(node));\\n }\\n\\n // by construction: 1 <= length(label) <= 255\\n // same as NameCoder.assertLabelSize()\\n // see: V1Fixture.t.sol: `test_nameWrapper_labelTooShort()` and `test_nameWrapper_labelTooLong()`.\\n\\n address resolver = md.resolver;\\n (, uint32 fuses, uint64 expiry) = NAME_WRAPPER.getData(uint256(node));\\n if (LibMigration.isLocked(fuses)) {\\n if (\\n (fuses & CANNOT_APPROVE) != 0 &&\\n NAME_WRAPPER.getApproved(uint256(node)) != address(0)\\n ) {\\n revert LibMigration.FrozenTokenApproval(uint256(node));\\n }\\n\\n if ((fuses & CANNOT_SET_RESOLVER) == 0) {\\n NAME_WRAPPER.setResolver(node, address(0)); // clear ENSv1 resolver\\n } else {\\n resolver = _REGISTRY_V1.resolver(node); // replace with ENSv1 resolver\\n if (resolver != address(0) && PUBLIC_RESOLVER_SET.includes(resolver)) {\\n resolver = PUBLIC_RESOLVER; // replace with new PublicResolver\\n }\\n }\\n\\n NAME_WRAPPER.safeTransferFrom(address(this), GRAVEYARD, uint256(node), 1, \\\"\\\"); // transfer to graveyard\\n\\n // create subregistry\\n IRegistry subregistry =\\n IRegistry(\\n VERIFIABLE_FACTORY.deployProxy(\\n WRAPPER_REGISTRY_IMPL,\\n uint256(node),\\n abi.encodeCall(\\n IWrapperRegistry.initialize,\\n (\\n node,\\n parentRegistry,\\n md.label,\\n _subregistryRoleBitmapFromFuses(fuses)\\n )\\n )\\n )\\n );\\n\\n // add name to ENSv2\\n // PermissionedRegistry._register() => CannotSetPastExpiry :: see expiry check\\n // PermissionedRegistry._register() => LabelAlreadyRegistered :: only have ROLE_REGISTER_RESERVED\\n // ERC1155._safeTransferFrom() => ERC1155InvalidReceiver :: see owner check\\n _inject(\\n md.label,\\n md.owner,\\n subregistry,\\n resolver,\\n _tokenRoleBitmapFromFuses(fuses),\\n expiry\\n );\\n } else if (LibMigration.isEmancipatedChild(fuses)) {\\n NAME_WRAPPER.setResolver(node, address(0)); // clear ENSv1 resolver\\n NAME_WRAPPER.unwrap(parentNode, labelHash, GRAVEYARD); // unwrap and transfer to graveyard\\n\\n // add name to ENSv2 (same as UnlockedMigrationController, plus\\n // renewal rights when the name could extend its own expiry in v1)\\n uint256 roleBitmap = REGISTRATION_ROLE_BITMAP;\\n if ((fuses & CAN_EXTEND_EXPIRY) != 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_RENEW | RegistryRolesLib.ROLE_RENEW_ADMIN;\\n }\\n _inject(md.label, md.owner, md.subregistry, resolver, roleBitmap, expiry);\\n } else {\\n revert LibMigration.NameNotLocked(uint256(node));\\n }\\n }\\n }\\n\\n /// @dev Register a locked name.\\n function _inject(\\n string memory label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n internal\\n virtual\\n returns (uint256 tokenId);\\n\\n /// @dev The ENSv2 registry being migrated to.\\n function _getRegistry() internal view virtual returns (IRegistry);\\n\\n /// @dev Convert fuses to equivalent subregistry root roles.\\n function _subregistryRoleBitmapFromFuses(uint32 fuses)\\n internal\\n pure\\n returns (uint256 roleBitmap)\\n {\\n if ((fuses & CANNOT_CREATE_SUBDOMAIN) == 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_REGISTRAR;\\n }\\n roleBitmap |=\\n RegistryRolesLib.ROLE_RENEW |\\n RegistryRolesLib.ROLE_UPGRADE |\\n RegistryRolesLib.ROLE_CAN_NAME;\\n if (LibMigration.notFrozen(fuses)) {\\n roleBitmap |= roleBitmap << 128; // give admin\\n }\\n }\\n\\n /// @dev Convert fuses to equivalent token roles.\\n function _tokenRoleBitmapFromFuses(uint32 fuses) internal pure returns (uint256 roleBitmap) {\\n if ((fuses & CAN_EXTEND_EXPIRY) != 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_RENEW;\\n }\\n if ((fuses & CANNOT_SET_RESOLVER) == 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_SET_RESOLVER;\\n }\\n if (LibMigration.notFrozen(fuses)) {\\n roleBitmap |= roleBitmap << 128; // give admin\\n }\\n if ((fuses & CANNOT_TRANSFER) == 0) {\\n roleBitmap |= RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; // no user\\n }\\n }\\n}\\n\",\"keccak256\":\"0x73f231bff59f29d80527b5b385b5b9aa7878ec727cf4732da2a07a55c229f5cc\",\"license\":\"MIT\"},\"project/src/migration/libraries/LibMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n CANNOT_BURN_FUSES,\\n CANNOT_UNWRAP,\\n IS_DOT_ETH,\\n PARENT_CANNOT_CONTROL\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Primitives for migration.\\nlibrary LibMigration {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Typed arguments for migration via transfer payload.\\n struct Data {\\n /// @dev Subdomain being migrated.\\n string label;\\n /// @dev Address that will own the name in the v2 registry.\\n address owner;\\n /// @dev Address of the child registry.\\n /// Ignored by locked migration.\\n IRegistry subregistry;\\n /// @dev Resolver address to set for the migrated name.\\n /// Ignored if locked and `CANNOT_SET_RESOLVER`.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Minimum size of `abi.encode(Data({...}))`.\\n uint256 internal constant MIN_DATA_SIZE = 7 * 32;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be registered because unmigrated NameWrapper token exists.\\n /// @dev Error selector: `0x408fa1b8`\\n error NameRequiresMigration();\\n\\n /// @notice NameWrapper token is unlocked.\\n /// @dev Error selector: `0x1bfe8f0a`\\n error NameNotLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper token is locked.\\n /// @dev Error selector: `0xe7c290e2`\\n error NameIsLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper or BaseRegistrar token does not match supplied data.\\n /// @dev Error selector: `0xedec3569`\\n error NameDataMismatch(uint256 tokenId);\\n\\n /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\\n /// @dev Error selector: `0xa4f07713`\\n error FrozenTokenApproval(uint256 tokenId);\\n\\n /// @notice The encoded data is invalid.\\n /// @dev Error selector: `0x5cb045db`\\n error InvalidData();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns `true` if the NameWrapper token is locked.\\n function isLocked(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient\\n // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()`\\n return (fuses & CANNOT_UNWRAP) != 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token fuses are not frozen.\\n function notFrozen(uint32 fuses) internal pure returns (bool) {\\n return (fuses & CANNOT_BURN_FUSES) == 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth.\\n function isEmancipatedChild(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL must be set for the entire ancestory.\\n // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()`\\n return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL;\\n }\\n}\\n\",\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\"},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`.\\nabstract contract AbstractETHRegistrar is Ownable, ERC165, IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Minimum renew duration, in seconds.\\n uint64 public constant MIN_RENEW_DURATION = 1;\\n\\n /// @notice ENSv2 .eth `PermissionedRegistry`.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice Address that receives payments.\\n address public immutable BENEFICIARY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Oracle for registration and renewal costs.\\n IRentPriceOracle public rentPriceOracle;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `IRentPriceOracle` was replaced.\\n /// @param oracle The new `IRentPriceOracle` contract.\\n event RentPriceOracleUpdated(IRentPriceOracle oracle);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n constructor(\\n address owner_,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle\\n )\\n Ownable(owner_)\\n {\\n ETH_REGISTRY = ethRegistry;\\n BENEFICIARY = beneficiary;\\n\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Change the rent price oracle.\\n /// @param oracle The new `IRentPriceOracle` instance.\\n function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner {\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external\\n {\\n IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not\\n uint64 newExpiry = state.expiry + duration; // reverts if overflow\\n uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, amount); // reverts if payment failed\\n ETH_REGISTRY.renew(state.tokenId, newExpiry);\\n _onRenew(label, duration);\\n emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function isRenewable(string calldata label) external view returns (bool) {\\n return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n public\\n view\\n returns (uint256)\\n {\\n return\\n rentPriceOracle.getRenewPrice(\\n label,\\n _requireRenewable(label, duration).expiry,\\n duration,\\n paymentToken\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Callback for when a name is renewed.\\n function _onRenew(string calldata label, uint64 duration) internal virtual {}\\n\\n /// @dev Returns whether the name is renewable by this contract.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n virtual\\n returns (bool);\\n\\n /// @dev Ensure name is renewable.\\n function _requireRenewable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isRenewable(state)) {\\n revert NameNotRenewable(label);\\n }\\n if (duration < MIN_RENEW_DURATION) {\\n revert DurationTooShort(duration, MIN_RENEW_DURATION);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x03c6381eaa4b6f36c842a32396b8f9a5a573a4257d7a9d263e77c015486a9458\",\"license\":\"MIT\"},\"project/src/registrar/ETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"../registry/libraries/RegistryRolesLib.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {AbstractETHRegistrar} from \\\"./AbstractETHRegistrar.sol\\\";\\nimport {IETHRegistrar} from \\\"./interfaces/IETHRegistrar.sol\\\";\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Roles assigned to owners at registration. Includes set-subregistry, set-resolver, and can-transfer (with admin variants).\\nuint256 constant REGISTRATION_ROLE_BITMAP =\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY |\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN |\\n RegistryRolesLib.ROLE_SET_RESOLVER |\\n RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN |\\n RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN;\\n\\n/// @notice Commit-reveal registrar for .eth names. Registration requires two transactions: first\\n/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment\\n/// age but before the maximum commitment age has elapsed. The commitment hash binds all\\n/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer)\\n/// to prevent front-running.\\n///\\n/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed\\n/// set of roles (set subregistry, set resolver, and transfer \\u2014 each with their admin\\n/// counterpart).\\n///\\n/// Pricing and payment are delegated to a swappable `IRentPriceOracle`.\\n///\\ncontract ETHRegistrar is AbstractETHRegistrar, IETHRegistrar {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRenewer\\n uint64 public immutable GRACE_PERIOD;\\n\\n /// @notice Minimum seconds a commitment must age before registration can proceed.\\n /// @dev If zero, front-running protection is disabled.\\n uint64 public immutable MIN_COMMITMENT_AGE;\\n\\n /// @notice Maximum seconds a commitment remains valid; expired commitments are rejected.\\n uint64 public immutable MAX_COMMITMENT_AGE;\\n\\n /// @notice Minimum register duration, in seconds.\\n uint64 public immutable MIN_REGISTER_DURATION;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n mapping(bytes32 commitment => uint64 commitTime) public commitmentAt;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`.\\n /// @dev Error selector: `0x3e5aa838`\\n error MaxCommitmentAgeTooLow();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n /// @param gracePeriod Post-expiry period where still renewable and not available, in seconds.\\n /// @param minCommitmentAge Minimum seconds a commitment must age before registration can proceed.\\n /// @param maxCommitmentAge Maximum seconds a commitment remains valid; expired commitments are rejected.\\n /// @param minRegisterDuration Minimum register duration, in seconds.\\n constructor(\\n address owner_,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle,\\n uint64 gracePeriod,\\n uint64 minCommitmentAge,\\n uint64 maxCommitmentAge,\\n uint64 minRegisterDuration\\n )\\n AbstractETHRegistrar(owner_, ethRegistry, beneficiary, oracle)\\n {\\n if (maxCommitmentAge <= minCommitmentAge) {\\n revert MaxCommitmentAgeTooLow();\\n }\\n GRACE_PERIOD = gracePeriod;\\n MIN_COMMITMENT_AGE = minCommitmentAge;\\n MAX_COMMITMENT_AGE = maxCommitmentAge;\\n MIN_REGISTER_DURATION = minRegisterDuration;\\n }\\n\\n /// @inheritdoc AbstractETHRegistrar\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return\\n interfaceId == type(IETHRegistrar).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n function commit(bytes32 commitment) external {\\n if (commitmentAt[commitment] + MAX_COMMITMENT_AGE > block.timestamp) {\\n revert UnexpiredCommitmentExists(commitment);\\n }\\n commitmentAt[commitment] = uint64(block.timestamp);\\n emit CommitmentMade(commitment);\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function register(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256 tokenId)\\n {\\n if (owner == address(0)) {\\n revert InvalidOwner();\\n }\\n _consumeCommitment(\\n makeCommitment(label, owner, secret, subregistry, resolver, duration, referrer)\\n ); // reverts if no commitment\\n IPermissionedRegistry.State memory state = _requireAvailable(label, duration); // reverts if not\\n (uint256 base, uint256 premium) =\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(state.expiry),\\n duration,\\n paymentToken\\n ); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, base + premium); // reverts if payment failed\\n tokenId = ETH_REGISTRY.register(\\n label,\\n owner,\\n subregistry,\\n resolver,\\n REGISTRATION_ROLE_BITMAP,\\n uint64(block.timestamp) + duration // new expiry\\n ); // should not revert\\n emit NameRegistered(\\n tokenId,\\n label,\\n owner,\\n subregistry,\\n resolver,\\n duration,\\n paymentToken,\\n referrer,\\n base,\\n premium\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function isAvailable(string calldata label) external view returns (bool) {\\n return _isAvailable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium)\\n {\\n return\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(_requireAvailable(label, duration).expiry),\\n duration,\\n paymentToken\\n );\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n return\\n uint64(\\n _isRenewableGrace(state)\\n ? GRACE_PERIOD - (block.timestamp - state.expiry)\\n : 0\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n public\\n pure\\n override\\n returns (bytes32)\\n {\\n return\\n keccak256(abi.encode(label, owner, secret, subregistry, resolver, duration, referrer));\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates that the given `commitment` was recorded within the allowed time window\\n /// (between minimum and maximum commitment age), then deletes it so it cannot be reused.\\n /// @param commitment The commitment hash to validate and consume.\\n function _consumeCommitment(bytes32 commitment) internal {\\n uint64 t = uint64(block.timestamp);\\n uint64 t0 = commitmentAt[commitment];\\n uint64 tMin = t0 + MIN_COMMITMENT_AGE;\\n if (t < tMin) {\\n revert CommitmentTooNew(commitment, tMin, t);\\n }\\n uint64 tMax = t0 + MAX_COMMITMENT_AGE;\\n if (t >= tMax) {\\n revert CommitmentTooOld(commitment, tMax, t);\\n }\\n delete commitmentAt[commitment];\\n }\\n\\n /// @dev Ensure name is registerable.\\n function _requireAvailable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isAvailable(state)) {\\n revert NameNotAvailable(label);\\n }\\n if (duration < MIN_REGISTER_DURATION) {\\n revert DurationTooShort(duration, MIN_REGISTER_DURATION);\\n }\\n }\\n\\n /// @dev Determine if `AVAILABLE` and not in grace.\\n function _isAvailable(IPermissionedRegistry.State memory state) internal view returns (bool) {\\n return _checkGrace(state, false);\\n }\\n\\n /// @dev Determine if `REGISTERED` or in grace was `REGISTERED`.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n override\\n returns (bool)\\n {\\n return state.status == IPermissionedRegistry.Status.REGISTERED || _isRenewableGrace(state);\\n }\\n\\n /// @dev Determine if was `REGISTERED` and in grace.\\n function _isRenewableGrace(IPermissionedRegistry.State memory state)\\n internal\\n view\\n returns (bool)\\n {\\n return state.latestOwner != address(0) && _checkGrace(state, true);\\n }\\n\\n /// @dev Check if `AVAILABLE` and conditionally in grace.\\n function _checkGrace(IPermissionedRegistry.State memory state, bool grace)\\n internal\\n view\\n returns (bool)\\n {\\n return\\n state.status == IPermissionedRegistry.Status.AVAILABLE &&\\n (grace == (block.timestamp - state.expiry) < GRACE_PERIOD);\\n }\\n\\n /// @dev Determine duration name has been available.\\n function _availablePeriod(uint64 expiry) internal view returns (uint64) {\\n uint64 t = uint64(block.timestamp);\\n if (expiry == 0) {\\n return t; // never registered\\n }\\n expiry += GRACE_PERIOD;\\n return t > expiry ? t - expiry : 0;\\n }\\n}\\n\",\"keccak256\":\"0x601a5929b1b2eba60dd566dd6967c3dba1a471d6b24ffe292f4aa660af1cd5f1\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./IETHRenewer.sol\\\";\\n\\n/// @notice Interface for registering \\\".eth\\\" names.\\n/// @dev Interface selector: `0xc1401b80`\\ninterface IETHRegistrar is IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` was recorded onchain at `block.timestamp`.\\n /// @param commitment The commitment hash from `makeCommitment()`.\\n event CommitmentMade(bytes32 commitment);\\n\\n /// @notice A name was registered.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the registration.\\n /// @param owner The owner address.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param base The amount of `paymentToken` for the registration.\\n /// @param premium The amount of `paymentToken` due to premium.\\n event NameRegistered(\\n uint256 indexed tokenId,\\n string label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 base,\\n uint256 premium\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` is still usable for registration.\\n /// @dev Error selector: `0x0a059d71`\\n error UnexpiredCommitmentExists(bytes32 commitment);\\n\\n /// @notice `commitment` cannot be consumed yet.\\n /// @dev Error selector: `0x6be614e3`\\n error CommitmentTooNew(bytes32 commitment, uint64 validFrom, uint64 blockTimestamp);\\n\\n /// @notice `commitment` has expired.\\n /// @dev Error selector: `0x0cb9df3f`\\n error CommitmentTooOld(bytes32 commitment, uint64 validTo, uint64 blockTimestamp);\\n\\n /// @notice `label` cannot be registered.\\n /// @dev Error selector: `0x477707e8`\\n error NameNotAvailable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registration step #1: record intent to register without revealing any information.\\n /// @dev Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.\\n /// @param commitment The commitment hash.\\n function commit(bytes32 commitment) external;\\n\\n /// @notice Register a name.\\n /// @param label The name from commitment.\\n /// @param owner The owner from commitment.\\n /// @param secret The secret from commitment.\\n /// @param subregistry The registry from commitment.\\n /// @param resolver The resolver from commitment.\\n /// @param duration The registration from commitment.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @return The registered token ID.\\n function register(\\n string memory label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256);\\n\\n /// @notice Get timestamp of a prior commitment.\\n /// @param commitment The commitment hash.\\n /// @return The commitment time, in seconds, or 0 if unknown.\\n function commitmentAt(bytes32 commitment) external view returns (uint64);\\n\\n /// @notice Determine register price for a name.\\n /// @param label The name to register.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Check if name is available.\\n /// @param label The name to check.\\n /// @return `true` if registerable.\\n function isAvailable(string memory label) external view returns (bool);\\n\\n /// @notice Compute hash of registration parameters.\\n /// @param label The name to register.\\n /// @param owner The owner address.\\n /// @param secret The secret for the registration.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param referrer The referrer hash.\\n /// @return The commitment hash.\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n external\\n pure\\n returns (bytes32);\\n}\\n\",\"keccak256\":\"0x7e824c5019f8eb7d7a283451700234716353e01d649c811b5ced5cf58b476289\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for renewing \\\".eth\\\" names.\\n/// @dev Interface selector: `0x06aaeb32`\\ninterface IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A name was extended by `duration`.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the renewal.\\n /// @param duration The duration extension, in seconds.\\n /// @param newExpiry The new expiry, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param amount The amount of `paymentToken`.\\n event NameRenewed(\\n uint256 indexed tokenId,\\n string label,\\n uint64 duration,\\n uint64 newExpiry,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 amount\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `duration` less than `minDuration`.\\n /// @dev Error selector: `0xa096b844`\\n error DurationTooShort(uint64 duration, uint64 minDuration);\\n\\n /// @notice `label` cannot be renewed.\\n /// @dev Error selector: `0x1caefaa0`\\n error NameNotRenewable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Renew a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external;\\n\\n /// @notice Determine renew price for a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice Check if name is renewable.\\n /// @param label The name to check.\\n /// @return `true` if renewable.\\n function isRenewable(string calldata label) external view returns (bool);\\n\\n /// @notice Determine remaining grace period.\\n /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`.\\n /// @param label The name to check.\\n /// @return The remaining grace period, in seconds.\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64);\\n\\n /// @notice Post-expiry period where still renewable and not available, in seconds.\\n function GRACE_PERIOD() external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IWrapperRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IPermissionedRegistry} from \\\"./IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Interface for a registry that manages a locked NameWrapper name.\\n/// @dev Interface selector: `0xe01aaa11`\\ninterface IWrapperRegistry is IPermissionedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Upgrade target is not approved for `WrapperRegistry` proxies.\\n /// @dev Error selector: `0xf74d7dd0`\\n /// @param implementation The disallowed implementation address.\\n error UpgradeTargetNotApproved(address implementation);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Initializes WrapperRegistry.\\n /// @param node Namehash of this registry.\\n /// @param parentRegistry The parent of this registry.\\n /// @param childLabel The subdomain for this registry.\\n /// @param roleBitmap The role bitmap granted to the virtual admin.\\n function initialize(\\n bytes32 node,\\n IRegistry parentRegistry,\\n string calldata childLabel,\\n uint256 roleBitmap\\n )\\n external;\\n\\n /// @notice Returns the DNS-encoded name for this registry.\\n function getWrappedName() external view returns (bytes memory);\\n\\n /// @notice Returns the NameWrapper node (namehash).\\n function getWrappedNode() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xe3e62e3df99cfaa38a4684c6369a31b41b3c89e02f851698e28954475bdb9775\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 39: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 62: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x01771816c1c5b16c10f29b33083dbd1cc2eb64dbfec60fb45a1a1969cec06624\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/WrappedErrorLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {HexUtils} from \\\"@ens/contracts/utils/HexUtils.sol\\\";\\n\\n/// @dev Library to wrap and unwrap typed error data inside of `Error(string)`.\\n/// Uses hex to embed arbitrary data and avoid invalid unicode.\\nlibrary WrappedErrorLib {\\n /// @dev Error selector for `Error(string)`.\\n bytes4 internal constant ERROR_STRING_SELECTOR = 0x08c379a0;\\n\\n /// @dev The detectable human-readable error prefix.\\n /// Must be exactly 16 bytes.\\n bytes16 internal constant WRAPPED_ERROR_PREFIX = \\\"WrappedError::0x\\\";\\n\\n /// @dev Wrap an error and then revert.\\n function wrapAndRevert(bytes memory err) internal pure {\\n err = wrap(err);\\n assembly {\\n revert(add(err, 32), mload(err))\\n }\\n }\\n\\n /// @dev Embed a typed error into `Error(string)`.\\n /// Does nothing if already `Error(string)`.\\n /// For detection, `WRAPPED_ERROR_PREFIX` is leading bytes the error string.\\n function wrap(bytes memory err) internal pure returns (bytes memory) {\\n if (err.length > 0 && bytes4(err) != ERROR_STRING_SELECTOR) {\\n // assert((err.length & 31) == 4);\\n err = abi.encodeWithSelector(\\n ERROR_STRING_SELECTOR,\\n abi.encodePacked(WRAPPED_ERROR_PREFIX, HexUtils.bytesToHex(err))\\n );\\n }\\n return err;\\n }\\n\\n /// @dev Unwrap a typed error from `Error(string)`.\\n /// Does nothing if detection and extracton fails.\\n /// @param err The error data to unwrap.\\n /// @return The unwrapped error data, or unmodified if not wrapped.\\n function unwrap(bytes memory err) internal pure returns (bytes memory) {\\n if (bytes4(err) == ERROR_STRING_SELECTOR) {\\n bytes memory v;\\n assembly {\\n v := add(err, 4) // skip selector\\n }\\n v = abi.decode(v, (bytes));\\n if (bytes16(v) == WRAPPED_ERROR_PREFIX) {\\n (bytes memory inner, bool ok) = HexUtils.hexToBytes(v, 16, v.length);\\n if (ok) {\\n return inner;\\n }\\n }\\n }\\n return err;\\n }\\n}\\n\",\"keccak256\":\"0xf92862b6509cf553bd542925617318a2509bfdc6457e8b5d102c8e9658c610e4\",\"license\":\"MIT\"},\"project/src/utils/interfaces/IAddressSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x1aedefda`\\ninterface IAddressSet {\\n /// @notice Check if `addr` is included in the set.\\n /// @param addr The address to check.\\n /// @return `true` if included.\\n function includes(address addr) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcb4f9c6364c1cf8a737591088f488ede7a7c6bc9d7d87f2dbdac731b492bd862\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "FrozenTokenApproval(uint256)": [ + { + "notice": "NameWrapper token has existing approval and burned `CANNOT_APPROVE`." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "NameDataMismatch(uint256)": [ + { + "notice": "NameWrapper or BaseRegistrar token does not match supplied data." + } + ], + "NameNotLocked(uint256)": [ + { + "notice": "NameWrapper token is unlocked." + } + ], + "UnauthorizedCaller(address)": [ + { + "notice": "Thrown when a caller is not authorized to perform the requested operation" + } + ] + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "ETH_REGISTRY()": { + "notice": "The ENSv2 .eth `PermissionedRegistry` where migrated names are registered." + }, + "GRAVEYARD()": { + "notice": "The ENSv1 `BaseRegistrar` token graveyard." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens." + }, + "PUBLIC_RESOLVER()": { + "notice": "The replacement `PublicResolver`." + }, + "PUBLIC_RESOLVER_SET()": { + "notice": "The list of `PublicResolver` contracts that require replacement." + }, + "VERIFIABLE_FACTORY()": { + "notice": "The shared factory for verifiable deployments." + }, + "WRAPPER_REGISTRY_IMPL()": { + "notice": "The `WrapperRegistry` implementation contract." + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "notice": "Convert NameWrapper tokens to their equivalent ENSv2 form." + }, + "getWrappedName()": { + "notice": "Returns the DNS-encoded name for this registry." + }, + "getWrappedNode()": { + "notice": "Returns the DNS-encoded name for \"eth\"." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "notice": "Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "notice": "Migrate one NameWrapper token via `safeTransferFrom()`." + } + }, + "notice": "Migration controller for handling locked .eth names. Assumes premigration has `RESERVED` existing ENSv1 names. Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce80000000000000000000000006f4bf58ac55e0018589b2d9734ed8bb82740124d00000000000000000000000067b728a792e789a8978b30cf1b3b641f19354b43000000000000000000000000118bc31a50d559f7015a8da26d54b3b030cdb70f000000000000000000000000cf9f4863a1b44216cfc0be65f4e47b2b9a04392400000000000000000000000024be557df149980a52241dd78a376d78f73689a5000000000000000000000000d25f66dd4ff61486c2c5c1e6201a23576698d3df00000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0xcca560843be7912376a56638a3535b3d433ad36e3762c3cf34762dd59b9112ee", + "nonce": "0x61", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x275ffda3c3f5bfd0b4505bd1d1ab793306010bc2b2f44b5abbd43d3592db964b", + "blockNumber": "0xaa5715", + "transactionIndex": "0x34" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ManagedUniversalResolverProxy.json b/contracts/deployments/sepolia/ManagedUniversalResolverProxy.json new file mode 100644 index 000000000..9bfa1bad4 --- /dev/null +++ b/contracts/deployments/sepolia/ManagedUniversalResolverProxy.json @@ -0,0 +1,7245 @@ +{ + "address": "0x6d80F2172CFdEc5730fE683860C33d26fC42e6F1", + "argsData": "0x", + "contractName": "UpgradableUniversalResolverProxy", + "sourceName": "src/universalResolver/UpgradableUniversalResolverProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidImplementation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [], + "name": "SameImplementation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "AdminRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f80fd5b50604051610c26380380610c2683398101604081905261002e9161019b565b6100378161006e565b5f80516020610c0683398151915280546001600160a01b0319166001600160a01b038316179055610067826100e6565b50506101cc565b6001600160a01b038116158061008c57506001600160a01b0381163b155b156100aa5760405163340aafcd60e11b815260040160405180910390fd5b6001600160a01b0381166100bc61014d565b6001600160a01b0316036100e357604051634c3b76bf60e01b815260040160405180910390fd5b50565b5f6100ef61016c565b9050815f80516020610be683398151915280546001600160a01b0319166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b5f5f80516020610c068339815191525b546001600160a01b0316919050565b5f5f80516020610be683398151915261015d565b80516001600160a01b0381168114610196575f80fd5b919050565b5f80604083850312156101ac575f80fd5b6101b583610180565b91506101c360208401610180565b90509250929050565b610a0d806101d95f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f806100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610693565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106da565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079a565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107b5565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610889565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109c4565b6105a4565b6104308361041d83856109c4565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b5f815160208301516001600160e01b0319808216935060048310156106775780818460040360031b1b83161693505b505050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106a6576106a661067f565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a015f5b8281101561073f5760bf1988870301845261072d8683516106ac565b95509284019290840190600101610711565b5050505050828103604084015261075681876106ac565b6001600160e01b0319861660608501529050828103608084015261077a81856106ac565b98975050505050505050565b6001600160a01b038116811461051a575f80fd5b5f602082840312156107aa575f80fd5b813561024481610786565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f2576107f26107b5565b604052919050565b5f67ffffffffffffffff831115610813576108136107b5565b610826601f8401601f19166020016107c9565b9050828152838383011115610839575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261085e575f80fd5b610244838351602085016107fa565b80516001600160e01b031981168114610884575f80fd5b919050565b5f805f805f60a0868803121561089d575f80fd5b85516108a881610786565b8095505060208087015167ffffffffffffffff808211156108c7575f80fd5b818901915089601f8301126108da575f80fd5b8151818111156108ec576108ec6107b5565b8060051b6108fb8582016107c9565b918252838101850191858101908d841115610914575f80fd5b86860192505b8383101561096157825185811115610930575f80fd5b8601603f81018f13610940575f80fd5b6109518f89830151604084016107fa565b835250918601919086019061091a565b60408d0151909a5095505050508083111561097a575f80fd5b6109868a848b0161084f565b955061099460608a0161086d565b945060808901519250808311156109a9575f80fd5b50506109b78882890161084f565b9150509295509295909350565b808201808211156106a6576106a661067f56fea2646970667358221220b497e606fddd22fd3bdcf262866dcd9d2d07fa9e7b15191a16b45ee0405c434e64736f6c63430008190033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f806100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610693565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106da565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079a565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107b5565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610889565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109c4565b6105a4565b6104308361041d83856109c4565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b5f815160208301516001600160e01b0319808216935060048310156106775780818460040360031b1b83161693505b505050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106a6576106a661067f565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a015f5b8281101561073f5760bf1988870301845261072d8683516106ac565b95509284019290840190600101610711565b5050505050828103604084015261075681876106ac565b6001600160e01b0319861660608501529050828103608084015261077a81856106ac565b98975050505050505050565b6001600160a01b038116811461051a575f80fd5b5f602082840312156107aa575f80fd5b813561024481610786565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f2576107f26107b5565b604052919050565b5f67ffffffffffffffff831115610813576108136107b5565b610826601f8401601f19166020016107c9565b9050828152838383011115610839575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261085e575f80fd5b610244838351602085016107fa565b80516001600160e01b031981168114610884575f80fd5b919050565b5f805f805f60a0868803121561089d575f80fd5b85516108a881610786565b8095505060208087015167ffffffffffffffff808211156108c7575f80fd5b818901915089601f8301126108da575f80fd5b8151818111156108ec576108ec6107b5565b8060051b6108fb8582016107c9565b918252838101850191858101908d841115610914575f80fd5b86860192505b8383101561096157825185811115610930575f80fd5b8601603f81018f13610940575f80fd5b6109518f89830151604084016107fa565b835250918601919086019061091a565b60408d0151909a5095505050508083111561097a575f80fd5b6109868a848b0161084f565b955061099460608a0161086d565b945060808901519250808311156109a9575f80fd5b50506109b78882890161084f565b9150509295509295909350565b808201808211156106a6576106a661067f56fea2646970667358221220b497e606fddd22fd3bdcf262866dcd9d2d07fa9e7b15191a16b45ee0405c434e64736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/src/universalResolver/UpgradableUniversalResolverProxy.sol", + "devdoc": { + "errors": { + "CallerNotAdmin()": [ + { + "details": "Error selector: `0x06d919f2`" + } + ], + "InvalidImplementation()": [ + { + "details": "Error selector: `0x68155f9a`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "SameImplementation()": [ + { + "details": "Error selector: `0x4c3b76bf`" + } + ] + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new admin address", + "previousAdmin": "The previous admin address" + } + }, + "AdminRemoved(address)": { + "params": { + "admin": "The admin address that was removed" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The new implementation address" + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "admin_": "The address of the admin", + "implementation_": "The address of the implementation" + } + }, + "upgradeTo(address)": { + "params": { + "newImplementation": "Address of the new implementation" + } + } + }, + "stateVariables": { + "_ADMIN_SLOT": { + "details": "Storage slot for admin (EIP-1967 compatible)" + }, + "_IMPLEMENTATION_SLOT": { + "details": "Storage slot for implementation address (EIP-1967 compatible)" + } + }, + "title": "UpgradableUniversalResolverProxy", + "version": 1 + }, + "evm": { + "bytecode": { + "functionDebugData": { + "@_74300": { + "entryPoint": null, + "id": 74300, + "parameterSlots": 2, + "returnSlots": 0 + }, + "@_getAdmin_74497": { + "entryPoint": 364, + "id": 74497, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_getImplementation_74484": { + "entryPoint": 333, + "id": 74484, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_setAdmin_74539": { + "entryPoint": 230, + "id": 74539, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_setImplementation_74513": { + "entryPoint": null, + "id": 74513, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_validateImplementation_74471": { + "entryPoint": 110, + "id": 74471, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@getAddressSlot_44365": { + "entryPoint": null, + "id": 44365, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_address_fromMemory": { + "entryPoint": 384, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_tuple_t_addresst_address_fromMemory": { + "entryPoint": 411, + "id": null, + "parameterSlots": 2, + "returnSlots": 2 + } + }, + "generatedSources": [ + { + "ast": { + "nativeSrc": "0:491:381", + "nodeType": "YulBlock", + "src": "0:491:381", + "statements": [ + { + "nativeSrc": "6:3:381", + "nodeType": "YulBlock", + "src": "6:3:381", + "statements": [] + }, + { + "body": { + "nativeSrc": "74:117:381", + "nodeType": "YulBlock", + "src": "74:117:381", + "statements": [ + { + "nativeSrc": "84:22:381", + "nodeType": "YulAssignment", + "src": "84:22:381", + "value": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "99:6:381", + "nodeType": "YulIdentifier", + "src": "99:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "93:5:381", + "nodeType": "YulIdentifier", + "src": "93:5:381" + }, + "nativeSrc": "93:13:381", + "nodeType": "YulFunctionCall", + "src": "93:13:381" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "84:5:381", + "nodeType": "YulIdentifier", + "src": "84:5:381" + } + ] + }, + { + "body": { + "nativeSrc": "169:16:381", + "nodeType": "YulBlock", + "src": "169:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "178:1:381", + "nodeType": "YulLiteral", + "src": "178:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "181:1:381", + "nodeType": "YulLiteral", + "src": "181:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "171:6:381", + "nodeType": "YulIdentifier", + "src": "171:6:381" + }, + "nativeSrc": "171:12:381", + "nodeType": "YulFunctionCall", + "src": "171:12:381" + }, + "nativeSrc": "171:12:381", + "nodeType": "YulExpressionStatement", + "src": "171:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "128:5:381", + "nodeType": "YulIdentifier", + "src": "128:5:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "139:5:381", + "nodeType": "YulIdentifier", + "src": "139:5:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "154:3:381", + "nodeType": "YulLiteral", + "src": "154:3:381", + "type": "", + "value": "160" + }, + { + "kind": "number", + "nativeSrc": "159:1:381", + "nodeType": "YulLiteral", + "src": "159:1:381", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "150:3:381", + "nodeType": "YulIdentifier", + "src": "150:3:381" + }, + "nativeSrc": "150:11:381", + "nodeType": "YulFunctionCall", + "src": "150:11:381" + }, + { + "kind": "number", + "nativeSrc": "163:1:381", + "nodeType": "YulLiteral", + "src": "163:1:381", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "146:3:381", + "nodeType": "YulIdentifier", + "src": "146:3:381" + }, + "nativeSrc": "146:19:381", + "nodeType": "YulFunctionCall", + "src": "146:19:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "135:3:381", + "nodeType": "YulIdentifier", + "src": "135:3:381" + }, + "nativeSrc": "135:31:381", + "nodeType": "YulFunctionCall", + "src": "135:31:381" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "125:2:381", + "nodeType": "YulIdentifier", + "src": "125:2:381" + }, + "nativeSrc": "125:42:381", + "nodeType": "YulFunctionCall", + "src": "125:42:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "118:6:381", + "nodeType": "YulIdentifier", + "src": "118:6:381" + }, + "nativeSrc": "118:50:381", + "nodeType": "YulFunctionCall", + "src": "118:50:381" + }, + "nativeSrc": "115:70:381", + "nodeType": "YulIf", + "src": "115:70:381" + } + ] + }, + "name": "abi_decode_address_fromMemory", + "nativeSrc": "14:177:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "53:6:381", + "nodeType": "YulTypedName", + "src": "53:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "64:5:381", + "nodeType": "YulTypedName", + "src": "64:5:381", + "type": "" + } + ], + "src": "14:177:381" + }, + { + "body": { + "nativeSrc": "294:195:381", + "nodeType": "YulBlock", + "src": "294:195:381", + "statements": [ + { + "body": { + "nativeSrc": "340:16:381", + "nodeType": "YulBlock", + "src": "340:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "349:1:381", + "nodeType": "YulLiteral", + "src": "349:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "352:1:381", + "nodeType": "YulLiteral", + "src": "352:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "342:6:381", + "nodeType": "YulIdentifier", + "src": "342:6:381" + }, + "nativeSrc": "342:12:381", + "nodeType": "YulFunctionCall", + "src": "342:12:381" + }, + "nativeSrc": "342:12:381", + "nodeType": "YulExpressionStatement", + "src": "342:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "315:7:381", + "nodeType": "YulIdentifier", + "src": "315:7:381" + }, + { + "name": "headStart", + "nativeSrc": "324:9:381", + "nodeType": "YulIdentifier", + "src": "324:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "311:3:381", + "nodeType": "YulIdentifier", + "src": "311:3:381" + }, + "nativeSrc": "311:23:381", + "nodeType": "YulFunctionCall", + "src": "311:23:381" + }, + { + "kind": "number", + "nativeSrc": "336:2:381", + "nodeType": "YulLiteral", + "src": "336:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "307:3:381", + "nodeType": "YulIdentifier", + "src": "307:3:381" + }, + "nativeSrc": "307:32:381", + "nodeType": "YulFunctionCall", + "src": "307:32:381" + }, + "nativeSrc": "304:52:381", + "nodeType": "YulIf", + "src": "304:52:381" + }, + { + "nativeSrc": "365:50:381", + "nodeType": "YulAssignment", + "src": "365:50:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "405:9:381", + "nodeType": "YulIdentifier", + "src": "405:9:381" + } + ], + "functionName": { + "name": "abi_decode_address_fromMemory", + "nativeSrc": "375:29:381", + "nodeType": "YulIdentifier", + "src": "375:29:381" + }, + "nativeSrc": "375:40:381", + "nodeType": "YulFunctionCall", + "src": "375:40:381" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "365:6:381", + "nodeType": "YulIdentifier", + "src": "365:6:381" + } + ] + }, + { + "nativeSrc": "424:59:381", + "nodeType": "YulAssignment", + "src": "424:59:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "468:9:381", + "nodeType": "YulIdentifier", + "src": "468:9:381" + }, + { + "kind": "number", + "nativeSrc": "479:2:381", + "nodeType": "YulLiteral", + "src": "479:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "464:3:381", + "nodeType": "YulIdentifier", + "src": "464:3:381" + }, + "nativeSrc": "464:18:381", + "nodeType": "YulFunctionCall", + "src": "464:18:381" + } + ], + "functionName": { + "name": "abi_decode_address_fromMemory", + "nativeSrc": "434:29:381", + "nodeType": "YulIdentifier", + "src": "434:29:381" + }, + "nativeSrc": "434:49:381", + "nodeType": "YulFunctionCall", + "src": "434:49:381" + }, + "variableNames": [ + { + "name": "value1", + "nativeSrc": "424:6:381", + "nodeType": "YulIdentifier", + "src": "424:6:381" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_addresst_address_fromMemory", + "nativeSrc": "196:293:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "252:9:381", + "nodeType": "YulTypedName", + "src": "252:9:381", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "263:7:381", + "nodeType": "YulTypedName", + "src": "263:7:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "275:6:381", + "nodeType": "YulTypedName", + "src": "275:6:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "283:6:381", + "nodeType": "YulTypedName", + "src": "283:6:381", + "type": "" + } + ], + "src": "196:293:381" + } + ] + }, + "contents": "{\n { }\n function abi_decode_address_fromMemory(offset) -> value\n {\n value := mload(offset)\n if iszero(eq(value, and(value, sub(shl(160, 1), 1)))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_addresst_address_fromMemory(headStart, dataEnd) -> value0, value1\n {\n if slt(sub(dataEnd, headStart), 64) { revert(0, 0) }\n value0 := abi_decode_address_fromMemory(headStart)\n value1 := abi_decode_address_fromMemory(add(headStart, 32))\n }\n}", + "id": 381, + "language": "Yul", + "name": "#utility.yul" + } + ], + "linkReferences": {}, + "object": "608060405234801561000f575f80fd5b50604051610c26380380610c2683398101604081905261002e9161019b565b6100378161006e565b5f80516020610c0683398151915280546001600160a01b0319166001600160a01b038316179055610067826100e6565b50506101cc565b6001600160a01b038116158061008c57506001600160a01b0381163b155b156100aa5760405163340aafcd60e11b815260040160405180910390fd5b6001600160a01b0381166100bc61014d565b6001600160a01b0316036100e357604051634c3b76bf60e01b815260040160405180910390fd5b50565b5f6100ef61016c565b9050815f80516020610be683398151915280546001600160a01b0319166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b5f5f80516020610c068339815191525b546001600160a01b0316919050565b5f5f80516020610be683398151915261015d565b80516001600160a01b0381168114610196575f80fd5b919050565b5f80604083850312156101ac575f80fd5b6101b583610180565b91506101c360208401610180565b90509250929050565b610a0d806101d95f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f806100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610693565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106da565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079a565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107b5565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610889565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109c4565b6105a4565b6104308361041d83856109c4565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b5f815160208301516001600160e01b0319808216935060048310156106775780818460040360031b1b83161693505b505050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106a6576106a661067f565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a015f5b8281101561073f5760bf1988870301845261072d8683516106ac565b95509284019290840190600101610711565b5050505050828103604084015261075681876106ac565b6001600160e01b0319861660608501529050828103608084015261077a81856106ac565b98975050505050505050565b6001600160a01b038116811461051a575f80fd5b5f602082840312156107aa575f80fd5b813561024481610786565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f2576107f26107b5565b604052919050565b5f67ffffffffffffffff831115610813576108136107b5565b610826601f8401601f19166020016107c9565b9050828152838383011115610839575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261085e575f80fd5b610244838351602085016107fa565b80516001600160e01b031981168114610884575f80fd5b919050565b5f805f805f60a0868803121561089d575f80fd5b85516108a881610786565b8095505060208087015167ffffffffffffffff808211156108c7575f80fd5b818901915089601f8301126108da575f80fd5b8151818111156108ec576108ec6107b5565b8060051b6108fb8582016107c9565b918252838101850191858101908d841115610914575f80fd5b86860192505b8383101561096157825185811115610930575f80fd5b8601603f81018f13610940575f80fd5b6109518f89830151604084016107fa565b835250918601919086019061091a565b60408d0151909a5095505050508083111561097a575f80fd5b6109868a848b0161084f565b955061099460608a0161086d565b945060808901519250808311156109a9575f80fd5b50506109b78882890161084f565b9150509295509295909350565b808201808211156106a6576106a661067f56fea2646970667358221220b497e606fddd22fd3bdcf262866dcd9d2d07fa9e7b15191a16b45ee0405c434e64736f6c63430008190033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH2 0xC26 CODESIZE SUB DUP1 PUSH2 0xC26 DUP4 CODECOPY DUP2 ADD PUSH1 0x40 DUP2 SWAP1 MSTORE PUSH2 0x2E SWAP2 PUSH2 0x19B JUMP JUMPDEST PUSH2 0x37 DUP2 PUSH2 0x6E JUMP JUMPDEST PUSH0 DUP1 MLOAD PUSH1 0x20 PUSH2 0xC06 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP1 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH2 0x67 DUP3 PUSH2 0xE6 JUMP JUMPDEST POP POP PUSH2 0x1CC JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x8C JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0xAA JUMPI PUSH1 0x40 MLOAD PUSH4 0x340AAFCD PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND PUSH2 0xBC PUSH2 0x14D JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0xE3 JUMPI PUSH1 0x40 MLOAD PUSH4 0x4C3B76BF PUSH1 0xE0 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0xEF PUSH2 0x16C JUMP JUMPDEST SWAP1 POP DUP2 PUSH0 DUP1 MLOAD PUSH1 0x20 PUSH2 0xBE6 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP1 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST PUSH0 PUSH0 DUP1 MLOAD PUSH1 0x20 PUSH2 0xC06 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH0 DUP1 MLOAD PUSH1 0x20 PUSH2 0xBE6 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE PUSH2 0x15D JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x196 JUMPI PUSH0 DUP1 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1AC JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x1B5 DUP4 PUSH2 0x180 JUMP JUMPDEST SWAP2 POP PUSH2 0x1C3 PUSH1 0x20 DUP5 ADD PUSH2 0x180 JUMP JUMPDEST SWAP1 POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH2 0xA0D DUP1 PUSH2 0x1D9 PUSH0 CODECOPY PUSH0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4A JUMPI PUSH0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x3659CFE6 EQ PUSH2 0x176 JUMPI DUP1 PUSH4 0x5C60DA1B EQ PUSH2 0x189 JUMPI DUP1 PUSH4 0x8BAD0C0A EQ PUSH2 0x1AD JUMPI DUP1 PUSH4 0xF851A440 EQ PUSH2 0x1B5 JUMPI JUMPDEST PUSH0 DUP1 PUSH2 0x54 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH0 CALLDATASIZE PUSH1 0x40 MLOAD PUSH2 0x6D SWAP3 SWAP2 SWAP1 PUSH2 0x639 JUMP JUMPDEST PUSH0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 GAS STATICCALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH0 DUP2 EQ PUSH2 0xA5 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0xAA JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 ISZERO DUP1 ISZERO PUSH2 0xD5 JUMPI POP PUSH4 0x556F183 PUSH1 0xE4 SHL PUSH2 0xC9 DUP3 PUSH2 0x648 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND EQ JUMPDEST ISZERO PUSH2 0x15E JUMPI PUSH0 PUSH2 0xFB PUSH2 0xF6 DUP4 PUSH1 0x4 DUP1 DUP7 MLOAD PUSH2 0xF1 SWAP2 SWAP1 PUSH2 0x693 JUMP JUMPDEST PUSH2 0x1EF JUMP JUMPDEST PUSH2 0x24B JUMP JUMPDEST SWAP1 POP PUSH2 0x105 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 PUSH0 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x15C JUMPI ADDRESS DUP2 PUSH1 0x20 ADD MLOAD DUP3 PUSH1 0x40 ADD MLOAD DUP4 PUSH1 0x60 ADD MLOAD DUP5 PUSH1 0x80 ADD MLOAD PUSH1 0x40 MLOAD PUSH4 0x556F183 PUSH1 0xE4 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x153 SWAP6 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x6DA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMPDEST DUP2 ISZERO PUSH2 0x16C JUMPI DUP1 MLOAD PUSH1 0x20 DUP3 ADD RETURN JUMPDEST DUP1 MLOAD PUSH1 0x20 DUP3 ADD REVERT JUMPDEST STOP JUMPDEST PUSH2 0x174 PUSH2 0x184 CALLDATASIZE PUSH1 0x4 PUSH2 0x79A JUMP JUMPDEST PUSH2 0x2B6 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x375 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x174 PUSH2 0x383 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x406 JUMP JUMPDEST PUSH0 PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 DUP2 PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x20A JUMPI PUSH2 0x20A PUSH2 0x7B5 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x1F ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x234 JUMPI PUSH1 0x20 DUP3 ADD DUP2 DUP1 CALLDATASIZE DUP4 CALLDATACOPY ADD SWAP1 POP JUMPDEST POP SWAP1 POP PUSH2 0x244 DUP5 DUP5 DUP4 PUSH0 DUP7 PUSH2 0x40F JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0xA0 DUP2 ADD DUP3 MSTORE PUSH0 DUP1 DUP3 MSTORE PUSH1 0x60 PUSH1 0x20 DUP4 ADD DUP2 SWAP1 MSTORE SWAP3 DUP3 ADD DUP4 SWAP1 MSTORE DUP3 DUP3 ADD MSTORE PUSH1 0x80 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP2 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD DUP2 ADD SWAP1 PUSH2 0x288 SWAP2 SWAP1 PUSH2 0x889 JUMP JUMPDEST PUSH1 0x80 DUP7 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND PUSH1 0x60 DUP6 ADD MSTORE PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x20 DUP4 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x2BE PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x2EF JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0x2F8 DUP2 PUSH2 0x473 JUMP JUMPDEST PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xBC7CD75A20EE27FD9ADEBAB32041F755214DBC6BFFA90CC0225B39DA2E5C2D3B SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x1BD JUMP JUMPDEST SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x38B PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x3BC JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH0 PUSH2 0x3C5 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP PUSH2 0x3D0 PUSH0 PUSH2 0x51D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xA3B62BC36326052D97EA62D63C3D60308ED4C3EA8AC079DD8499F1E9C4F80C0F SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x44C JUMP JUMPDEST PUSH2 0x422 DUP6 PUSH2 0x41D DUP4 DUP8 PUSH2 0x9C4 JUMP JUMPDEST PUSH2 0x5A4 JUMP JUMPDEST PUSH2 0x430 DUP4 PUSH2 0x41D DUP4 DUP6 PUSH2 0x9C4 JUMP JUMPDEST PUSH2 0x445 DUP3 PUSH1 0x20 DUP6 ADD ADD DUP6 PUSH1 0x20 DUP9 ADD ADD DUP4 PUSH2 0x5F0 JUMP JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH0 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 PUSH2 0x1E0 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x491 JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0x4C8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x68155F9A00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH2 0x4DA PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x51A JUMPI PUSH1 0x40 MLOAD PUSH32 0x4C3B76BF00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0x526 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP DUP2 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST DUP2 MLOAD DUP2 GT ISZERO PUSH2 0x5EC JUMPI DUP2 MLOAD PUSH1 0x40 MLOAD PUSH32 0x8A3C1CFB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x153 SWAP2 DUP4 SWAP2 PUSH1 0x4 ADD SWAP2 DUP3 MSTORE PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST POP POP JUMP JUMPDEST JUMPDEST PUSH1 0x1F DUP2 GT ISZERO PUSH2 0x611 JUMPI DUP2 MLOAD DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1F NOT ADD PUSH2 0x5F1 JUMP JUMPDEST DUP1 ISZERO PUSH2 0x634 JUMPI DUP2 MLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0x20 DUP5 SWAP1 SUB PUSH1 0x3 SHL SHL PUSH0 NOT ADD DUP1 NOT SWAP1 SWAP3 AND SWAP2 AND OR DUP4 MSTORE JUMPDEST POP POP POP JUMP JUMPDEST DUP2 DUP4 DUP3 CALLDATACOPY PUSH0 SWAP2 ADD SWAP1 DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP2 MLOAD PUSH1 0x20 DUP4 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP1 DUP3 AND SWAP4 POP PUSH1 0x4 DUP4 LT ISZERO PUSH2 0x677 JUMPI DUP1 DUP2 DUP5 PUSH1 0x4 SUB PUSH1 0x3 SHL SHL DUP4 AND AND SWAP4 POP JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x11 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST DUP2 DUP2 SUB DUP2 DUP2 GT ISZERO PUSH2 0x6A6 JUMPI PUSH2 0x6A6 PUSH2 0x67F JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 DUP2 MLOAD DUP1 DUP5 MSTORE DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP7 ADD MCOPY PUSH0 PUSH1 0x20 DUP3 DUP7 ADD ADD MSTORE PUSH1 0x20 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 PUSH1 0xA0 DUP3 ADD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP9 AND DUP4 MSTORE PUSH1 0x20 PUSH1 0xA0 PUSH1 0x20 DUP6 ADD MSTORE DUP2 DUP9 MLOAD DUP1 DUP5 MSTORE PUSH1 0xC0 DUP7 ADD SWAP2 POP PUSH1 0xC0 DUP2 PUSH1 0x5 SHL DUP8 ADD ADD SWAP4 POP PUSH1 0x20 DUP11 ADD PUSH0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x73F JUMPI PUSH1 0xBF NOT DUP9 DUP8 SUB ADD DUP5 MSTORE PUSH2 0x72D DUP7 DUP4 MLOAD PUSH2 0x6AC JUMP JUMPDEST SWAP6 POP SWAP3 DUP5 ADD SWAP3 SWAP1 DUP5 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x711 JUMP JUMPDEST POP POP POP POP POP DUP3 DUP2 SUB PUSH1 0x40 DUP5 ADD MSTORE PUSH2 0x756 DUP2 DUP8 PUSH2 0x6AC JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP7 AND PUSH1 0x60 DUP6 ADD MSTORE SWAP1 POP DUP3 DUP2 SUB PUSH1 0x80 DUP5 ADD MSTORE PUSH2 0x77A DUP2 DUP6 PUSH2 0x6AC JUMP JUMPDEST SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x51A JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x7AA JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x244 DUP2 PUSH2 0x786 JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x41 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1F DUP3 ADD PUSH1 0x1F NOT AND DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x7F2 JUMPI PUSH2 0x7F2 PUSH2 0x7B5 JUMP JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH8 0xFFFFFFFFFFFFFFFF DUP4 GT ISZERO PUSH2 0x813 JUMPI PUSH2 0x813 PUSH2 0x7B5 JUMP JUMPDEST PUSH2 0x826 PUSH1 0x1F DUP5 ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD PUSH2 0x7C9 JUMP JUMPDEST SWAP1 POP DUP3 DUP2 MSTORE DUP4 DUP4 DUP4 ADD GT ISZERO PUSH2 0x839 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP3 DUP3 PUSH1 0x20 DUP4 ADD MCOPY PUSH0 PUSH1 0x20 DUP5 DUP4 ADD ADD MSTORE SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x85E JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x244 DUP4 DUP4 MLOAD PUSH1 0x20 DUP6 ADD PUSH2 0x7FA JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP2 AND DUP2 EQ PUSH2 0x884 JUMPI PUSH0 DUP1 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP1 PUSH0 DUP1 PUSH0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0x89D JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP6 MLOAD PUSH2 0x8A8 DUP2 PUSH2 0x786 JUMP JUMPDEST DUP1 SWAP6 POP POP PUSH1 0x20 DUP1 DUP8 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x8C7 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 DUP10 ADD SWAP2 POP DUP10 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x8DA JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 MLOAD DUP2 DUP2 GT ISZERO PUSH2 0x8EC JUMPI PUSH2 0x8EC PUSH2 0x7B5 JUMP JUMPDEST DUP1 PUSH1 0x5 SHL PUSH2 0x8FB DUP6 DUP3 ADD PUSH2 0x7C9 JUMP JUMPDEST SWAP2 DUP3 MSTORE DUP4 DUP2 ADD DUP6 ADD SWAP2 DUP6 DUP2 ADD SWAP1 DUP14 DUP5 GT ISZERO PUSH2 0x914 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP7 DUP7 ADD SWAP3 POP JUMPDEST DUP4 DUP4 LT ISZERO PUSH2 0x961 JUMPI DUP3 MLOAD DUP6 DUP2 GT ISZERO PUSH2 0x930 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP7 ADD PUSH1 0x3F DUP2 ADD DUP16 SGT PUSH2 0x940 JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x951 DUP16 DUP10 DUP4 ADD MLOAD PUSH1 0x40 DUP5 ADD PUSH2 0x7FA JUMP JUMPDEST DUP4 MSTORE POP SWAP2 DUP7 ADD SWAP2 SWAP1 DUP7 ADD SWAP1 PUSH2 0x91A JUMP JUMPDEST PUSH1 0x40 DUP14 ADD MLOAD SWAP1 SWAP11 POP SWAP6 POP POP POP POP DUP1 DUP4 GT ISZERO PUSH2 0x97A JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x986 DUP11 DUP5 DUP12 ADD PUSH2 0x84F JUMP JUMPDEST SWAP6 POP PUSH2 0x994 PUSH1 0x60 DUP11 ADD PUSH2 0x86D JUMP JUMPDEST SWAP5 POP PUSH1 0x80 DUP10 ADD MLOAD SWAP3 POP DUP1 DUP4 GT ISZERO PUSH2 0x9A9 JUMPI PUSH0 DUP1 REVERT JUMPDEST POP POP PUSH2 0x9B7 DUP9 DUP3 DUP10 ADD PUSH2 0x84F JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 POP SWAP3 SWAP6 SWAP1 SWAP4 POP JUMP JUMPDEST DUP1 DUP3 ADD DUP1 DUP3 GT ISZERO PUSH2 0x6A6 JUMPI PUSH2 0x6A6 PUSH2 0x67F JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0xB4 SWAP8 0xE6 MOD REVERT 0xDD 0x22 REVERT EXTCODESIZE 0xDC CALLCODE PUSH3 0x866DCD SWAP14 0x2D SMOD STATICCALL SWAP15 PUSH28 0x15191A16B45EE0405C434E64736F6C63430008190033B53127684A56 DUP12 BALANCE PUSH20 0xAE13B9F8A6016E243E63B6E8EE1178D6A717850B TSTORE PUSH2 0x336 ADDMOD SWAP5 LOG1 EXTCODESIZE LOG1 LOG3 0x21 MOD PUSH8 0xC828492DB98DCA3E KECCAK256 PUSH23 0xCC3735A920A3CA505D382BBC0000000000000000000000 ", + "sourceMap": "490:6212:360:-:0;;;2878:182;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2941:40;2965:15;2941:23;:40::i;:::-;-1:-1:-1;;;;;;;;;;;6350:74:360;;-1:-1:-1;;;;;;6350:74:360;-1:-1:-1;;;;;6350:74:360;;;;;3036:17;3046:6;3036:9;:17::i;:::-;2878:182;;490:6212;;5307:328;-1:-1:-1;;;;;5395:31:360;;;;:69;;-1:-1:-1;;;;;;5430:29:360;;;:34;5395:69;5391:130;;;5487:23;;-1:-1:-1;;;5487:23:360;;;;;;;;;;;5391:130;-1:-1:-1;;;;;5534:41:360;;:20;:18;:20::i;:::-;-1:-1:-1;;;;;5534:41:360;;5530:99;;5598:20;;-1:-1:-1;;;5598:20:360;;;;;;;;;;;5530:99;5307:328;:::o;6485:215::-;6540:21;6564:11;:9;:11::i;:::-;6540:35;-1:-1:-1;6633:8:360;-1:-1:-1;;;;;;;;;;;6585:56:360;;-1:-1:-1;;;;;;6585:56:360;-1:-1:-1;;;;;6585:56:360;;;;;;6656:37;;;;;;;;;;;-1:-1:-1;;6656:37:360;6530:170;6485:215;:::o;5708:140::-;5761:7;-1:-1:-1;;;;;;;;;;;5787:48:360;:54;-1:-1:-1;;;;;5787:54:360;;5708:140;-1:-1:-1;5708:140:360:o;5912:122::-;5956:7;-1:-1:-1;;;;;;;;;;;5982:39:360;1899:163:257;14:177:381;93:13;;-1:-1:-1;;;;;135:31:381;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:293::-;275:6;283;336:2;324:9;315:7;311:23;307:32;304:52;;;352:1;349;342:12;304:52;375:40;405:9;375:40;:::i;:::-;365:50;;434:49;479:2;468:9;464:18;434:49;:::i;:::-;424:59;;196:293;;;;;:::o;:::-;490:6212:360;;;;;;" + }, + "deployedBytecode": { + "functionDebugData": { + "@_74374": { + "entryPoint": null, + "id": 74374, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@_checkBound_20014": { + "entryPoint": 1444, + "id": 20014, + "parameterSlots": 2, + "returnSlots": 0 + }, + "@_getAdmin_74497": { + "entryPoint": 1100, + "id": 74497, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_getImplementation_74484": { + "entryPoint": 445, + "id": 74484, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_setAdmin_74539": { + "entryPoint": 1309, + "id": 74539, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_setImplementation_74513": { + "entryPoint": null, + "id": 74513, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_validateImplementation_74471": { + "entryPoint": 1139, + "id": 74471, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@admin_74438": { + "entryPoint": 1030, + "id": 74438, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@copyBytes_20513": { + "entryPoint": 1039, + "id": 20513, + "parameterSlots": 5, + "returnSlots": 0 + }, + "@copy_21720": { + "entryPoint": 1520, + "id": 21720, + "parameterSlots": 3, + "returnSlots": 0 + }, + "@decode_1541": { + "entryPoint": 587, + "id": 1541, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@getAddressSlot_44365": { + "entryPoint": null, + "id": 44365, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@implementation_74428": { + "entryPoint": 885, + "id": 74428, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@ptr_21730": { + "entryPoint": null, + "id": 21730, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@renounceAdmin_74418": { + "entryPoint": 899, + "id": 74418, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@substring_20541": { + "entryPoint": 495, + "id": 20541, + "parameterSlots": 3, + "returnSlots": 1 + }, + "@upgradeTo_74395": { + "entryPoint": 694, + "id": 74395, + "parameterSlots": 1, + "returnSlots": 0 + }, + "abi_decode_available_length_string_fromMemory": { + "entryPoint": 2042, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "abi_decode_bytes4_fromMemory": { + "entryPoint": 2157, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_bytes_fromMemory": { + "entryPoint": 2127, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_decode_tuple_t_address": { + "entryPoint": 1946, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory": { + "entryPoint": 2185, + "id": null, + "parameterSlots": 2, + "returnSlots": 5 + }, + "abi_encode_bytes4": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 0 + }, + "abi_encode_string": { + "entryPoint": 1708, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed": { + "entryPoint": 1593, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "abi_encode_tuple_t_address__to_t_address__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed": { + "entryPoint": 1754, + "id": null, + "parameterSlots": 6, + "returnSlots": 1 + }, + "abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "allocate_memory": { + "entryPoint": 1993, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "checked_add_t_uint256": { + "entryPoint": 2500, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "checked_sub_t_uint256": { + "entryPoint": 1683, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4": { + "entryPoint": 1608, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "panic_error_0x11": { + "entryPoint": 1663, + "id": null, + "parameterSlots": 0, + "returnSlots": 0 + }, + "panic_error_0x41": { + "entryPoint": 1973, + "id": null, + "parameterSlots": 0, + "returnSlots": 0 + }, + "validator_revert_address": { + "entryPoint": 1926, + "id": null, + "parameterSlots": 1, + "returnSlots": 0 + } + }, + "generatedSources": [ + { + "ast": { + "nativeSrc": "0:7012:381", + "nodeType": "YulBlock", + "src": "0:7012:381", + "statements": [ + { + "nativeSrc": "6:3:381", + "nodeType": "YulBlock", + "src": "6:3:381", + "statements": [] + }, + { + "body": { + "nativeSrc": "161:124:381", + "nodeType": "YulBlock", + "src": "161:124:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "184:3:381", + "nodeType": "YulIdentifier", + "src": "184:3:381" + }, + { + "name": "value0", + "nativeSrc": "189:6:381", + "nodeType": "YulIdentifier", + "src": "189:6:381" + }, + { + "name": "value1", + "nativeSrc": "197:6:381", + "nodeType": "YulIdentifier", + "src": "197:6:381" + } + ], + "functionName": { + "name": "calldatacopy", + "nativeSrc": "171:12:381", + "nodeType": "YulIdentifier", + "src": "171:12:381" + }, + "nativeSrc": "171:33:381", + "nodeType": "YulFunctionCall", + "src": "171:33:381" + }, + "nativeSrc": "171:33:381", + "nodeType": "YulExpressionStatement", + "src": "171:33:381" + }, + { + "nativeSrc": "213:26:381", + "nodeType": "YulVariableDeclaration", + "src": "213:26:381", + "value": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "227:3:381", + "nodeType": "YulIdentifier", + "src": "227:3:381" + }, + { + "name": "value1", + "nativeSrc": "232:6:381", + "nodeType": "YulIdentifier", + "src": "232:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "223:3:381", + "nodeType": "YulIdentifier", + "src": "223:3:381" + }, + "nativeSrc": "223:16:381", + "nodeType": "YulFunctionCall", + "src": "223:16:381" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "217:2:381", + "nodeType": "YulTypedName", + "src": "217:2:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "255:2:381", + "nodeType": "YulIdentifier", + "src": "255:2:381" + }, + { + "kind": "number", + "nativeSrc": "259:1:381", + "nodeType": "YulLiteral", + "src": "259:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "248:6:381", + "nodeType": "YulIdentifier", + "src": "248:6:381" + }, + "nativeSrc": "248:13:381", + "nodeType": "YulFunctionCall", + "src": "248:13:381" + }, + "nativeSrc": "248:13:381", + "nodeType": "YulExpressionStatement", + "src": "248:13:381" + }, + { + "nativeSrc": "270:9:381", + "nodeType": "YulAssignment", + "src": "270:9:381", + "value": { + "name": "_1", + "nativeSrc": "277:2:381", + "nodeType": "YulIdentifier", + "src": "277:2:381" + }, + "variableNames": [ + { + "name": "end", + "nativeSrc": "270:3:381", + "nodeType": "YulIdentifier", + "src": "270:3:381" + } + ] + } + ] + }, + "name": "abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed", + "nativeSrc": "14:271:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "pos", + "nativeSrc": "129:3:381", + "nodeType": "YulTypedName", + "src": "129:3:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "134:6:381", + "nodeType": "YulTypedName", + "src": "134:6:381", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "142:6:381", + "nodeType": "YulTypedName", + "src": "142:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "end", + "nativeSrc": "153:3:381", + "nodeType": "YulTypedName", + "src": "153:3:381", + "type": "" + } + ], + "src": "14:271:381" + }, + { + "body": { + "nativeSrc": "383:314:381", + "nodeType": "YulBlock", + "src": "383:314:381", + "statements": [ + { + "nativeSrc": "393:26:381", + "nodeType": "YulVariableDeclaration", + "src": "393:26:381", + "value": { + "arguments": [ + { + "name": "array", + "nativeSrc": "413:5:381", + "nodeType": "YulIdentifier", + "src": "413:5:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "407:5:381", + "nodeType": "YulIdentifier", + "src": "407:5:381" + }, + "nativeSrc": "407:12:381", + "nodeType": "YulFunctionCall", + "src": "407:12:381" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "397:6:381", + "nodeType": "YulTypedName", + "src": "397:6:381", + "type": "" + } + ] + }, + { + "nativeSrc": "428:33:381", + "nodeType": "YulVariableDeclaration", + "src": "428:33:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "448:5:381", + "nodeType": "YulIdentifier", + "src": "448:5:381" + }, + { + "kind": "number", + "nativeSrc": "455:4:381", + "nodeType": "YulLiteral", + "src": "455:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "444:3:381", + "nodeType": "YulIdentifier", + "src": "444:3:381" + }, + "nativeSrc": "444:16:381", + "nodeType": "YulFunctionCall", + "src": "444:16:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "438:5:381", + "nodeType": "YulIdentifier", + "src": "438:5:381" + }, + "nativeSrc": "438:23:381", + "nodeType": "YulFunctionCall", + "src": "438:23:381" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "432:2:381", + "nodeType": "YulTypedName", + "src": "432:2:381", + "type": "" + } + ] + }, + { + "nativeSrc": "470:76:381", + "nodeType": "YulVariableDeclaration", + "src": "470:76:381", + "value": { + "kind": "number", + "nativeSrc": "480:66:381", + "nodeType": "YulLiteral", + "src": "480:66:381", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + }, + "variables": [ + { + "name": "_2", + "nativeSrc": "474:2:381", + "nodeType": "YulTypedName", + "src": "474:2:381", + "type": "" + } + ] + }, + { + "nativeSrc": "555:20:381", + "nodeType": "YulAssignment", + "src": "555:20:381", + "value": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "568:2:381", + "nodeType": "YulIdentifier", + "src": "568:2:381" + }, + { + "name": "_2", + "nativeSrc": "572:2:381", + "nodeType": "YulIdentifier", + "src": "572:2:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "564:3:381", + "nodeType": "YulIdentifier", + "src": "564:3:381" + }, + "nativeSrc": "564:11:381", + "nodeType": "YulFunctionCall", + "src": "564:11:381" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "555:5:381", + "nodeType": "YulIdentifier", + "src": "555:5:381" + } + ] + }, + { + "body": { + "nativeSrc": "609:82:381", + "nodeType": "YulBlock", + "src": "609:82:381", + "statements": [ + { + "nativeSrc": "623:58:381", + "nodeType": "YulAssignment", + "src": "623:58:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_1", + "nativeSrc": "640:2:381", + "nodeType": "YulIdentifier", + "src": "640:2:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "652:1:381", + "nodeType": "YulLiteral", + "src": "652:1:381", + "type": "", + "value": "3" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "659:1:381", + "nodeType": "YulLiteral", + "src": "659:1:381", + "type": "", + "value": "4" + }, + { + "name": "length", + "nativeSrc": "662:6:381", + "nodeType": "YulIdentifier", + "src": "662:6:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "655:3:381", + "nodeType": "YulIdentifier", + "src": "655:3:381" + }, + "nativeSrc": "655:14:381", + "nodeType": "YulFunctionCall", + "src": "655:14:381" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "648:3:381", + "nodeType": "YulIdentifier", + "src": "648:3:381" + }, + "nativeSrc": "648:22:381", + "nodeType": "YulFunctionCall", + "src": "648:22:381" + }, + { + "name": "_2", + "nativeSrc": "672:2:381", + "nodeType": "YulIdentifier", + "src": "672:2:381" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "644:3:381", + "nodeType": "YulIdentifier", + "src": "644:3:381" + }, + "nativeSrc": "644:31:381", + "nodeType": "YulFunctionCall", + "src": "644:31:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "636:3:381", + "nodeType": "YulIdentifier", + "src": "636:3:381" + }, + "nativeSrc": "636:40:381", + "nodeType": "YulFunctionCall", + "src": "636:40:381" + }, + { + "name": "_2", + "nativeSrc": "678:2:381", + "nodeType": "YulIdentifier", + "src": "678:2:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "632:3:381", + "nodeType": "YulIdentifier", + "src": "632:3:381" + }, + "nativeSrc": "632:49:381", + "nodeType": "YulFunctionCall", + "src": "632:49:381" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "623:5:381", + "nodeType": "YulIdentifier", + "src": "623:5:381" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "length", + "nativeSrc": "590:6:381", + "nodeType": "YulIdentifier", + "src": "590:6:381" + }, + { + "kind": "number", + "nativeSrc": "598:1:381", + "nodeType": "YulLiteral", + "src": "598:1:381", + "type": "", + "value": "4" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "587:2:381", + "nodeType": "YulIdentifier", + "src": "587:2:381" + }, + "nativeSrc": "587:13:381", + "nodeType": "YulFunctionCall", + "src": "587:13:381" + }, + "nativeSrc": "584:107:381", + "nodeType": "YulIf", + "src": "584:107:381" + } + ] + }, + "name": "convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4", + "nativeSrc": "290:407:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "array", + "nativeSrc": "363:5:381", + "nodeType": "YulTypedName", + "src": "363:5:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "373:5:381", + "nodeType": "YulTypedName", + "src": "373:5:381", + "type": "" + } + ], + "src": "290:407:381" + }, + { + "body": { + "nativeSrc": "734:152:381", + "nodeType": "YulBlock", + "src": "734:152:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "751:1:381", + "nodeType": "YulLiteral", + "src": "751:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "754:77:381", + "nodeType": "YulLiteral", + "src": "754:77:381", + "type": "", + "value": "35408467139433450592217433187231851964531694900788300625387963629091585785856" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "744:6:381", + "nodeType": "YulIdentifier", + "src": "744:6:381" + }, + "nativeSrc": "744:88:381", + "nodeType": "YulFunctionCall", + "src": "744:88:381" + }, + "nativeSrc": "744:88:381", + "nodeType": "YulExpressionStatement", + "src": "744:88:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "848:1:381", + "nodeType": "YulLiteral", + "src": "848:1:381", + "type": "", + "value": "4" + }, + { + "kind": "number", + "nativeSrc": "851:4:381", + "nodeType": "YulLiteral", + "src": "851:4:381", + "type": "", + "value": "0x11" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "841:6:381", + "nodeType": "YulIdentifier", + "src": "841:6:381" + }, + "nativeSrc": "841:15:381", + "nodeType": "YulFunctionCall", + "src": "841:15:381" + }, + "nativeSrc": "841:15:381", + "nodeType": "YulExpressionStatement", + "src": "841:15:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "872:1:381", + "nodeType": "YulLiteral", + "src": "872:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "875:4:381", + "nodeType": "YulLiteral", + "src": "875:4:381", + "type": "", + "value": "0x24" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "865:6:381", + "nodeType": "YulIdentifier", + "src": "865:6:381" + }, + "nativeSrc": "865:15:381", + "nodeType": "YulFunctionCall", + "src": "865:15:381" + }, + "nativeSrc": "865:15:381", + "nodeType": "YulExpressionStatement", + "src": "865:15:381" + } + ] + }, + "name": "panic_error_0x11", + "nativeSrc": "702:184:381", + "nodeType": "YulFunctionDefinition", + "src": "702:184:381" + }, + { + "body": { + "nativeSrc": "940:79:381", + "nodeType": "YulBlock", + "src": "940:79:381", + "statements": [ + { + "nativeSrc": "950:17:381", + "nodeType": "YulAssignment", + "src": "950:17:381", + "value": { + "arguments": [ + { + "name": "x", + "nativeSrc": "962:1:381", + "nodeType": "YulIdentifier", + "src": "962:1:381" + }, + { + "name": "y", + "nativeSrc": "965:1:381", + "nodeType": "YulIdentifier", + "src": "965:1:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "958:3:381", + "nodeType": "YulIdentifier", + "src": "958:3:381" + }, + "nativeSrc": "958:9:381", + "nodeType": "YulFunctionCall", + "src": "958:9:381" + }, + "variableNames": [ + { + "name": "diff", + "nativeSrc": "950:4:381", + "nodeType": "YulIdentifier", + "src": "950:4:381" + } + ] + }, + { + "body": { + "nativeSrc": "991:22:381", + "nodeType": "YulBlock", + "src": "991:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x11", + "nativeSrc": "993:16:381", + "nodeType": "YulIdentifier", + "src": "993:16:381" + }, + "nativeSrc": "993:18:381", + "nodeType": "YulFunctionCall", + "src": "993:18:381" + }, + "nativeSrc": "993:18:381", + "nodeType": "YulExpressionStatement", + "src": "993:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "diff", + "nativeSrc": "982:4:381", + "nodeType": "YulIdentifier", + "src": "982:4:381" + }, + { + "name": "x", + "nativeSrc": "988:1:381", + "nodeType": "YulIdentifier", + "src": "988:1:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "979:2:381", + "nodeType": "YulIdentifier", + "src": "979:2:381" + }, + "nativeSrc": "979:11:381", + "nodeType": "YulFunctionCall", + "src": "979:11:381" + }, + "nativeSrc": "976:37:381", + "nodeType": "YulIf", + "src": "976:37:381" + } + ] + }, + "name": "checked_sub_t_uint256", + "nativeSrc": "891:128:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "x", + "nativeSrc": "922:1:381", + "nodeType": "YulTypedName", + "src": "922:1:381", + "type": "" + }, + { + "name": "y", + "nativeSrc": "925:1:381", + "nodeType": "YulTypedName", + "src": "925:1:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "diff", + "nativeSrc": "931:4:381", + "nodeType": "YulTypedName", + "src": "931:4:381", + "type": "" + } + ], + "src": "891:128:381" + }, + { + "body": { + "nativeSrc": "1074:239:381", + "nodeType": "YulBlock", + "src": "1074:239:381", + "statements": [ + { + "nativeSrc": "1084:26:381", + "nodeType": "YulVariableDeclaration", + "src": "1084:26:381", + "value": { + "arguments": [ + { + "name": "value", + "nativeSrc": "1104:5:381", + "nodeType": "YulIdentifier", + "src": "1104:5:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "1098:5:381", + "nodeType": "YulIdentifier", + "src": "1098:5:381" + }, + "nativeSrc": "1098:12:381", + "nodeType": "YulFunctionCall", + "src": "1098:12:381" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "1088:6:381", + "nodeType": "YulTypedName", + "src": "1088:6:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1126:3:381", + "nodeType": "YulIdentifier", + "src": "1126:3:381" + }, + { + "name": "length", + "nativeSrc": "1131:6:381", + "nodeType": "YulIdentifier", + "src": "1131:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1119:6:381", + "nodeType": "YulIdentifier", + "src": "1119:6:381" + }, + "nativeSrc": "1119:19:381", + "nodeType": "YulFunctionCall", + "src": "1119:19:381" + }, + "nativeSrc": "1119:19:381", + "nodeType": "YulExpressionStatement", + "src": "1119:19:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1157:3:381", + "nodeType": "YulIdentifier", + "src": "1157:3:381" + }, + { + "kind": "number", + "nativeSrc": "1162:4:381", + "nodeType": "YulLiteral", + "src": "1162:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1153:3:381", + "nodeType": "YulIdentifier", + "src": "1153:3:381" + }, + "nativeSrc": "1153:14:381", + "nodeType": "YulFunctionCall", + "src": "1153:14:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "1173:5:381", + "nodeType": "YulIdentifier", + "src": "1173:5:381" + }, + { + "kind": "number", + "nativeSrc": "1180:4:381", + "nodeType": "YulLiteral", + "src": "1180:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1169:3:381", + "nodeType": "YulIdentifier", + "src": "1169:3:381" + }, + "nativeSrc": "1169:16:381", + "nodeType": "YulFunctionCall", + "src": "1169:16:381" + }, + { + "name": "length", + "nativeSrc": "1187:6:381", + "nodeType": "YulIdentifier", + "src": "1187:6:381" + } + ], + "functionName": { + "name": "mcopy", + "nativeSrc": "1147:5:381", + "nodeType": "YulIdentifier", + "src": "1147:5:381" + }, + "nativeSrc": "1147:47:381", + "nodeType": "YulFunctionCall", + "src": "1147:47:381" + }, + "nativeSrc": "1147:47:381", + "nodeType": "YulExpressionStatement", + "src": "1147:47:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1218:3:381", + "nodeType": "YulIdentifier", + "src": "1218:3:381" + }, + { + "name": "length", + "nativeSrc": "1223:6:381", + "nodeType": "YulIdentifier", + "src": "1223:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1214:3:381", + "nodeType": "YulIdentifier", + "src": "1214:3:381" + }, + "nativeSrc": "1214:16:381", + "nodeType": "YulFunctionCall", + "src": "1214:16:381" + }, + { + "kind": "number", + "nativeSrc": "1232:4:381", + "nodeType": "YulLiteral", + "src": "1232:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1210:3:381", + "nodeType": "YulIdentifier", + "src": "1210:3:381" + }, + "nativeSrc": "1210:27:381", + "nodeType": "YulFunctionCall", + "src": "1210:27:381" + }, + { + "kind": "number", + "nativeSrc": "1239:1:381", + "nodeType": "YulLiteral", + "src": "1239:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1203:6:381", + "nodeType": "YulIdentifier", + "src": "1203:6:381" + }, + "nativeSrc": "1203:38:381", + "nodeType": "YulFunctionCall", + "src": "1203:38:381" + }, + "nativeSrc": "1203:38:381", + "nodeType": "YulExpressionStatement", + "src": "1203:38:381" + }, + { + "nativeSrc": "1250:57:381", + "nodeType": "YulAssignment", + "src": "1250:57:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1265:3:381", + "nodeType": "YulIdentifier", + "src": "1265:3:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "length", + "nativeSrc": "1278:6:381", + "nodeType": "YulIdentifier", + "src": "1278:6:381" + }, + { + "kind": "number", + "nativeSrc": "1286:2:381", + "nodeType": "YulLiteral", + "src": "1286:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1274:3:381", + "nodeType": "YulIdentifier", + "src": "1274:3:381" + }, + "nativeSrc": "1274:15:381", + "nodeType": "YulFunctionCall", + "src": "1274:15:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "1295:2:381", + "nodeType": "YulLiteral", + "src": "1295:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "1291:3:381", + "nodeType": "YulIdentifier", + "src": "1291:3:381" + }, + "nativeSrc": "1291:7:381", + "nodeType": "YulFunctionCall", + "src": "1291:7:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1270:3:381", + "nodeType": "YulIdentifier", + "src": "1270:3:381" + }, + "nativeSrc": "1270:29:381", + "nodeType": "YulFunctionCall", + "src": "1270:29:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1261:3:381", + "nodeType": "YulIdentifier", + "src": "1261:3:381" + }, + "nativeSrc": "1261:39:381", + "nodeType": "YulFunctionCall", + "src": "1261:39:381" + }, + { + "kind": "number", + "nativeSrc": "1302:4:381", + "nodeType": "YulLiteral", + "src": "1302:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1257:3:381", + "nodeType": "YulIdentifier", + "src": "1257:3:381" + }, + "nativeSrc": "1257:50:381", + "nodeType": "YulFunctionCall", + "src": "1257:50:381" + }, + "variableNames": [ + { + "name": "end", + "nativeSrc": "1250:3:381", + "nodeType": "YulIdentifier", + "src": "1250:3:381" + } + ] + } + ] + }, + "name": "abi_encode_string", + "nativeSrc": "1024:289:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "1051:5:381", + "nodeType": "YulTypedName", + "src": "1051:5:381", + "type": "" + }, + { + "name": "pos", + "nativeSrc": "1058:3:381", + "nodeType": "YulTypedName", + "src": "1058:3:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "end", + "nativeSrc": "1066:3:381", + "nodeType": "YulTypedName", + "src": "1066:3:381", + "type": "" + } + ], + "src": "1024:289:381" + }, + { + "body": { + "nativeSrc": "1361:107:381", + "nodeType": "YulBlock", + "src": "1361:107:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1378:3:381", + "nodeType": "YulIdentifier", + "src": "1378:3:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "1387:5:381", + "nodeType": "YulIdentifier", + "src": "1387:5:381" + }, + { + "kind": "number", + "nativeSrc": "1394:66:381", + "nodeType": "YulLiteral", + "src": "1394:66:381", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1383:3:381", + "nodeType": "YulIdentifier", + "src": "1383:3:381" + }, + "nativeSrc": "1383:78:381", + "nodeType": "YulFunctionCall", + "src": "1383:78:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1371:6:381", + "nodeType": "YulIdentifier", + "src": "1371:6:381" + }, + "nativeSrc": "1371:91:381", + "nodeType": "YulFunctionCall", + "src": "1371:91:381" + }, + "nativeSrc": "1371:91:381", + "nodeType": "YulExpressionStatement", + "src": "1371:91:381" + } + ] + }, + "name": "abi_encode_bytes4", + "nativeSrc": "1318:150:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "1345:5:381", + "nodeType": "YulTypedName", + "src": "1345:5:381", + "type": "" + }, + { + "name": "pos", + "nativeSrc": "1352:3:381", + "nodeType": "YulTypedName", + "src": "1352:3:381", + "type": "" + } + ], + "src": "1318:150:381" + }, + { + "body": { + "nativeSrc": "1790:985:381", + "nodeType": "YulBlock", + "src": "1790:985:381", + "statements": [ + { + "nativeSrc": "1800:33:381", + "nodeType": "YulVariableDeclaration", + "src": "1800:33:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "1818:9:381", + "nodeType": "YulIdentifier", + "src": "1818:9:381" + }, + { + "kind": "number", + "nativeSrc": "1829:3:381", + "nodeType": "YulLiteral", + "src": "1829:3:381", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1814:3:381", + "nodeType": "YulIdentifier", + "src": "1814:3:381" + }, + "nativeSrc": "1814:19:381", + "nodeType": "YulFunctionCall", + "src": "1814:19:381" + }, + "variables": [ + { + "name": "tail_1", + "nativeSrc": "1804:6:381", + "nodeType": "YulTypedName", + "src": "1804:6:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "1849:9:381", + "nodeType": "YulIdentifier", + "src": "1849:9:381" + }, + { + "arguments": [ + { + "name": "value0", + "nativeSrc": "1864:6:381", + "nodeType": "YulIdentifier", + "src": "1864:6:381" + }, + { + "kind": "number", + "nativeSrc": "1872:42:381", + "nodeType": "YulLiteral", + "src": "1872:42:381", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1860:3:381", + "nodeType": "YulIdentifier", + "src": "1860:3:381" + }, + "nativeSrc": "1860:55:381", + "nodeType": "YulFunctionCall", + "src": "1860:55:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1842:6:381", + "nodeType": "YulIdentifier", + "src": "1842:6:381" + }, + "nativeSrc": "1842:74:381", + "nodeType": "YulFunctionCall", + "src": "1842:74:381" + }, + "nativeSrc": "1842:74:381", + "nodeType": "YulExpressionStatement", + "src": "1842:74:381" + }, + { + "nativeSrc": "1925:12:381", + "nodeType": "YulVariableDeclaration", + "src": "1925:12:381", + "value": { + "kind": "number", + "nativeSrc": "1935:2:381", + "nodeType": "YulLiteral", + "src": "1935:2:381", + "type": "", + "value": "32" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "1929:2:381", + "nodeType": "YulTypedName", + "src": "1929:2:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "1957:9:381", + "nodeType": "YulIdentifier", + "src": "1957:9:381" + }, + { + "kind": "number", + "nativeSrc": "1968:2:381", + "nodeType": "YulLiteral", + "src": "1968:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1953:3:381", + "nodeType": "YulIdentifier", + "src": "1953:3:381" + }, + "nativeSrc": "1953:18:381", + "nodeType": "YulFunctionCall", + "src": "1953:18:381" + }, + { + "kind": "number", + "nativeSrc": "1973:3:381", + "nodeType": "YulLiteral", + "src": "1973:3:381", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1946:6:381", + "nodeType": "YulIdentifier", + "src": "1946:6:381" + }, + "nativeSrc": "1946:31:381", + "nodeType": "YulFunctionCall", + "src": "1946:31:381" + }, + "nativeSrc": "1946:31:381", + "nodeType": "YulExpressionStatement", + "src": "1946:31:381" + }, + { + "nativeSrc": "1986:17:381", + "nodeType": "YulVariableDeclaration", + "src": "1986:17:381", + "value": { + "name": "tail_1", + "nativeSrc": "1997:6:381", + "nodeType": "YulIdentifier", + "src": "1997:6:381" + }, + "variables": [ + { + "name": "pos", + "nativeSrc": "1990:3:381", + "nodeType": "YulTypedName", + "src": "1990:3:381", + "type": "" + } + ] + }, + { + "nativeSrc": "2012:27:381", + "nodeType": "YulVariableDeclaration", + "src": "2012:27:381", + "value": { + "arguments": [ + { + "name": "value1", + "nativeSrc": "2032:6:381", + "nodeType": "YulIdentifier", + "src": "2032:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "2026:5:381", + "nodeType": "YulIdentifier", + "src": "2026:5:381" + }, + "nativeSrc": "2026:13:381", + "nodeType": "YulFunctionCall", + "src": "2026:13:381" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "2016:6:381", + "nodeType": "YulTypedName", + "src": "2016:6:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "tail_1", + "nativeSrc": "2055:6:381", + "nodeType": "YulIdentifier", + "src": "2055:6:381" + }, + { + "name": "length", + "nativeSrc": "2063:6:381", + "nodeType": "YulIdentifier", + "src": "2063:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2048:6:381", + "nodeType": "YulIdentifier", + "src": "2048:6:381" + }, + "nativeSrc": "2048:22:381", + "nodeType": "YulFunctionCall", + "src": "2048:22:381" + }, + "nativeSrc": "2048:22:381", + "nodeType": "YulExpressionStatement", + "src": "2048:22:381" + }, + { + "nativeSrc": "2079:26:381", + "nodeType": "YulAssignment", + "src": "2079:26:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2090:9:381", + "nodeType": "YulIdentifier", + "src": "2090:9:381" + }, + { + "kind": "number", + "nativeSrc": "2101:3:381", + "nodeType": "YulLiteral", + "src": "2101:3:381", + "type": "", + "value": "192" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2086:3:381", + "nodeType": "YulIdentifier", + "src": "2086:3:381" + }, + "nativeSrc": "2086:19:381", + "nodeType": "YulFunctionCall", + "src": "2086:19:381" + }, + "variableNames": [ + { + "name": "pos", + "nativeSrc": "2079:3:381", + "nodeType": "YulIdentifier", + "src": "2079:3:381" + } + ] + }, + { + "nativeSrc": "2114:54:381", + "nodeType": "YulVariableDeclaration", + "src": "2114:54:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2136:9:381", + "nodeType": "YulIdentifier", + "src": "2136:9:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "2151:1:381", + "nodeType": "YulLiteral", + "src": "2151:1:381", + "type": "", + "value": "5" + }, + { + "name": "length", + "nativeSrc": "2154:6:381", + "nodeType": "YulIdentifier", + "src": "2154:6:381" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "2147:3:381", + "nodeType": "YulIdentifier", + "src": "2147:3:381" + }, + "nativeSrc": "2147:14:381", + "nodeType": "YulFunctionCall", + "src": "2147:14:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2132:3:381", + "nodeType": "YulIdentifier", + "src": "2132:3:381" + }, + "nativeSrc": "2132:30:381", + "nodeType": "YulFunctionCall", + "src": "2132:30:381" + }, + { + "kind": "number", + "nativeSrc": "2164:3:381", + "nodeType": "YulLiteral", + "src": "2164:3:381", + "type": "", + "value": "192" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2128:3:381", + "nodeType": "YulIdentifier", + "src": "2128:3:381" + }, + "nativeSrc": "2128:40:381", + "nodeType": "YulFunctionCall", + "src": "2128:40:381" + }, + "variables": [ + { + "name": "tail_2", + "nativeSrc": "2118:6:381", + "nodeType": "YulTypedName", + "src": "2118:6:381", + "type": "" + } + ] + }, + { + "nativeSrc": "2177:29:381", + "nodeType": "YulVariableDeclaration", + "src": "2177:29:381", + "value": { + "arguments": [ + { + "name": "value1", + "nativeSrc": "2195:6:381", + "nodeType": "YulIdentifier", + "src": "2195:6:381" + }, + { + "kind": "number", + "nativeSrc": "2203:2:381", + "nodeType": "YulLiteral", + "src": "2203:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2191:3:381", + "nodeType": "YulIdentifier", + "src": "2191:3:381" + }, + "nativeSrc": "2191:15:381", + "nodeType": "YulFunctionCall", + "src": "2191:15:381" + }, + "variables": [ + { + "name": "srcPtr", + "nativeSrc": "2181:6:381", + "nodeType": "YulTypedName", + "src": "2181:6:381", + "type": "" + } + ] + }, + { + "nativeSrc": "2215:10:381", + "nodeType": "YulVariableDeclaration", + "src": "2215:10:381", + "value": { + "kind": "number", + "nativeSrc": "2224:1:381", + "nodeType": "YulLiteral", + "src": "2224:1:381", + "type": "", + "value": "0" + }, + "variables": [ + { + "name": "i", + "nativeSrc": "2219:1:381", + "nodeType": "YulTypedName", + "src": "2219:1:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "2283:207:381", + "nodeType": "YulBlock", + "src": "2283:207:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "2304:3:381", + "nodeType": "YulIdentifier", + "src": "2304:3:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "tail_2", + "nativeSrc": "2317:6:381", + "nodeType": "YulIdentifier", + "src": "2317:6:381" + }, + { + "name": "headStart", + "nativeSrc": "2325:9:381", + "nodeType": "YulIdentifier", + "src": "2325:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2313:3:381", + "nodeType": "YulIdentifier", + "src": "2313:3:381" + }, + "nativeSrc": "2313:22:381", + "nodeType": "YulFunctionCall", + "src": "2313:22:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "2341:3:381", + "nodeType": "YulLiteral", + "src": "2341:3:381", + "type": "", + "value": "191" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "2337:3:381", + "nodeType": "YulIdentifier", + "src": "2337:3:381" + }, + "nativeSrc": "2337:8:381", + "nodeType": "YulFunctionCall", + "src": "2337:8:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2309:3:381", + "nodeType": "YulIdentifier", + "src": "2309:3:381" + }, + "nativeSrc": "2309:37:381", + "nodeType": "YulFunctionCall", + "src": "2309:37:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2297:6:381", + "nodeType": "YulIdentifier", + "src": "2297:6:381" + }, + "nativeSrc": "2297:50:381", + "nodeType": "YulFunctionCall", + "src": "2297:50:381" + }, + "nativeSrc": "2297:50:381", + "nodeType": "YulExpressionStatement", + "src": "2297:50:381" + }, + { + "nativeSrc": "2360:50:381", + "nodeType": "YulAssignment", + "src": "2360:50:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "srcPtr", + "nativeSrc": "2394:6:381", + "nodeType": "YulIdentifier", + "src": "2394:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "2388:5:381", + "nodeType": "YulIdentifier", + "src": "2388:5:381" + }, + "nativeSrc": "2388:13:381", + "nodeType": "YulFunctionCall", + "src": "2388:13:381" + }, + { + "name": "tail_2", + "nativeSrc": "2403:6:381", + "nodeType": "YulIdentifier", + "src": "2403:6:381" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2370:17:381", + "nodeType": "YulIdentifier", + "src": "2370:17:381" + }, + "nativeSrc": "2370:40:381", + "nodeType": "YulFunctionCall", + "src": "2370:40:381" + }, + "variableNames": [ + { + "name": "tail_2", + "nativeSrc": "2360:6:381", + "nodeType": "YulIdentifier", + "src": "2360:6:381" + } + ] + }, + { + "nativeSrc": "2423:25:381", + "nodeType": "YulAssignment", + "src": "2423:25:381", + "value": { + "arguments": [ + { + "name": "srcPtr", + "nativeSrc": "2437:6:381", + "nodeType": "YulIdentifier", + "src": "2437:6:381" + }, + { + "name": "_1", + "nativeSrc": "2445:2:381", + "nodeType": "YulIdentifier", + "src": "2445:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2433:3:381", + "nodeType": "YulIdentifier", + "src": "2433:3:381" + }, + "nativeSrc": "2433:15:381", + "nodeType": "YulFunctionCall", + "src": "2433:15:381" + }, + "variableNames": [ + { + "name": "srcPtr", + "nativeSrc": "2423:6:381", + "nodeType": "YulIdentifier", + "src": "2423:6:381" + } + ] + }, + { + "nativeSrc": "2461:19:381", + "nodeType": "YulAssignment", + "src": "2461:19:381", + "value": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "2472:3:381", + "nodeType": "YulIdentifier", + "src": "2472:3:381" + }, + { + "name": "_1", + "nativeSrc": "2477:2:381", + "nodeType": "YulIdentifier", + "src": "2477:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2468:3:381", + "nodeType": "YulIdentifier", + "src": "2468:3:381" + }, + "nativeSrc": "2468:12:381", + "nodeType": "YulFunctionCall", + "src": "2468:12:381" + }, + "variableNames": [ + { + "name": "pos", + "nativeSrc": "2461:3:381", + "nodeType": "YulIdentifier", + "src": "2461:3:381" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "i", + "nativeSrc": "2245:1:381", + "nodeType": "YulIdentifier", + "src": "2245:1:381" + }, + { + "name": "length", + "nativeSrc": "2248:6:381", + "nodeType": "YulIdentifier", + "src": "2248:6:381" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "2242:2:381", + "nodeType": "YulIdentifier", + "src": "2242:2:381" + }, + "nativeSrc": "2242:13:381", + "nodeType": "YulFunctionCall", + "src": "2242:13:381" + }, + "nativeSrc": "2234:256:381", + "nodeType": "YulForLoop", + "post": { + "nativeSrc": "2256:18:381", + "nodeType": "YulBlock", + "src": "2256:18:381", + "statements": [ + { + "nativeSrc": "2258:14:381", + "nodeType": "YulAssignment", + "src": "2258:14:381", + "value": { + "arguments": [ + { + "name": "i", + "nativeSrc": "2267:1:381", + "nodeType": "YulIdentifier", + "src": "2267:1:381" + }, + { + "kind": "number", + "nativeSrc": "2270:1:381", + "nodeType": "YulLiteral", + "src": "2270:1:381", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2263:3:381", + "nodeType": "YulIdentifier", + "src": "2263:3:381" + }, + "nativeSrc": "2263:9:381", + "nodeType": "YulFunctionCall", + "src": "2263:9:381" + }, + "variableNames": [ + { + "name": "i", + "nativeSrc": "2258:1:381", + "nodeType": "YulIdentifier", + "src": "2258:1:381" + } + ] + } + ] + }, + "pre": { + "nativeSrc": "2238:3:381", + "nodeType": "YulBlock", + "src": "2238:3:381", + "statements": [] + }, + "src": "2234:256:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2510:9:381", + "nodeType": "YulIdentifier", + "src": "2510:9:381" + }, + { + "kind": "number", + "nativeSrc": "2521:2:381", + "nodeType": "YulLiteral", + "src": "2521:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2506:3:381", + "nodeType": "YulIdentifier", + "src": "2506:3:381" + }, + "nativeSrc": "2506:18:381", + "nodeType": "YulFunctionCall", + "src": "2506:18:381" + }, + { + "arguments": [ + { + "name": "tail_2", + "nativeSrc": "2530:6:381", + "nodeType": "YulIdentifier", + "src": "2530:6:381" + }, + { + "name": "headStart", + "nativeSrc": "2538:9:381", + "nodeType": "YulIdentifier", + "src": "2538:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2526:3:381", + "nodeType": "YulIdentifier", + "src": "2526:3:381" + }, + "nativeSrc": "2526:22:381", + "nodeType": "YulFunctionCall", + "src": "2526:22:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2499:6:381", + "nodeType": "YulIdentifier", + "src": "2499:6:381" + }, + "nativeSrc": "2499:50:381", + "nodeType": "YulFunctionCall", + "src": "2499:50:381" + }, + "nativeSrc": "2499:50:381", + "nodeType": "YulExpressionStatement", + "src": "2499:50:381" + }, + { + "nativeSrc": "2558:47:381", + "nodeType": "YulVariableDeclaration", + "src": "2558:47:381", + "value": { + "arguments": [ + { + "name": "value2", + "nativeSrc": "2590:6:381", + "nodeType": "YulIdentifier", + "src": "2590:6:381" + }, + { + "name": "tail_2", + "nativeSrc": "2598:6:381", + "nodeType": "YulIdentifier", + "src": "2598:6:381" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2572:17:381", + "nodeType": "YulIdentifier", + "src": "2572:17:381" + }, + "nativeSrc": "2572:33:381", + "nodeType": "YulFunctionCall", + "src": "2572:33:381" + }, + "variables": [ + { + "name": "tail_3", + "nativeSrc": "2562:6:381", + "nodeType": "YulTypedName", + "src": "2562:6:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value3", + "nativeSrc": "2632:6:381", + "nodeType": "YulIdentifier", + "src": "2632:6:381" + }, + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2644:9:381", + "nodeType": "YulIdentifier", + "src": "2644:9:381" + }, + { + "kind": "number", + "nativeSrc": "2655:2:381", + "nodeType": "YulLiteral", + "src": "2655:2:381", + "type": "", + "value": "96" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2640:3:381", + "nodeType": "YulIdentifier", + "src": "2640:3:381" + }, + "nativeSrc": "2640:18:381", + "nodeType": "YulFunctionCall", + "src": "2640:18:381" + } + ], + "functionName": { + "name": "abi_encode_bytes4", + "nativeSrc": "2614:17:381", + "nodeType": "YulIdentifier", + "src": "2614:17:381" + }, + "nativeSrc": "2614:45:381", + "nodeType": "YulFunctionCall", + "src": "2614:45:381" + }, + "nativeSrc": "2614:45:381", + "nodeType": "YulExpressionStatement", + "src": "2614:45:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2679:9:381", + "nodeType": "YulIdentifier", + "src": "2679:9:381" + }, + { + "kind": "number", + "nativeSrc": "2690:3:381", + "nodeType": "YulLiteral", + "src": "2690:3:381", + "type": "", + "value": "128" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2675:3:381", + "nodeType": "YulIdentifier", + "src": "2675:3:381" + }, + "nativeSrc": "2675:19:381", + "nodeType": "YulFunctionCall", + "src": "2675:19:381" + }, + { + "arguments": [ + { + "name": "tail_3", + "nativeSrc": "2700:6:381", + "nodeType": "YulIdentifier", + "src": "2700:6:381" + }, + { + "name": "headStart", + "nativeSrc": "2708:9:381", + "nodeType": "YulIdentifier", + "src": "2708:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2696:3:381", + "nodeType": "YulIdentifier", + "src": "2696:3:381" + }, + "nativeSrc": "2696:22:381", + "nodeType": "YulFunctionCall", + "src": "2696:22:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2668:6:381", + "nodeType": "YulIdentifier", + "src": "2668:6:381" + }, + "nativeSrc": "2668:51:381", + "nodeType": "YulFunctionCall", + "src": "2668:51:381" + }, + "nativeSrc": "2668:51:381", + "nodeType": "YulExpressionStatement", + "src": "2668:51:381" + }, + { + "nativeSrc": "2728:41:381", + "nodeType": "YulAssignment", + "src": "2728:41:381", + "value": { + "arguments": [ + { + "name": "value4", + "nativeSrc": "2754:6:381", + "nodeType": "YulIdentifier", + "src": "2754:6:381" + }, + { + "name": "tail_3", + "nativeSrc": "2762:6:381", + "nodeType": "YulIdentifier", + "src": "2762:6:381" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2736:17:381", + "nodeType": "YulIdentifier", + "src": "2736:17:381" + }, + "nativeSrc": "2736:33:381", + "nodeType": "YulFunctionCall", + "src": "2736:33:381" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "2728:4:381", + "nodeType": "YulIdentifier", + "src": "2728:4:381" + } + ] + } + ] + }, + "name": "abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed", + "nativeSrc": "1473:1302:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "1727:9:381", + "nodeType": "YulTypedName", + "src": "1727:9:381", + "type": "" + }, + { + "name": "value4", + "nativeSrc": "1738:6:381", + "nodeType": "YulTypedName", + "src": "1738:6:381", + "type": "" + }, + { + "name": "value3", + "nativeSrc": "1746:6:381", + "nodeType": "YulTypedName", + "src": "1746:6:381", + "type": "" + }, + { + "name": "value2", + "nativeSrc": "1754:6:381", + "nodeType": "YulTypedName", + "src": "1754:6:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "1762:6:381", + "nodeType": "YulTypedName", + "src": "1762:6:381", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "1770:6:381", + "nodeType": "YulTypedName", + "src": "1770:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "1781:4:381", + "nodeType": "YulTypedName", + "src": "1781:4:381", + "type": "" + } + ], + "src": "1473:1302:381" + }, + { + "body": { + "nativeSrc": "2825:109:381", + "nodeType": "YulBlock", + "src": "2825:109:381", + "statements": [ + { + "body": { + "nativeSrc": "2912:16:381", + "nodeType": "YulBlock", + "src": "2912:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "2921:1:381", + "nodeType": "YulLiteral", + "src": "2921:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "2924:1:381", + "nodeType": "YulLiteral", + "src": "2924:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "2914:6:381", + "nodeType": "YulIdentifier", + "src": "2914:6:381" + }, + "nativeSrc": "2914:12:381", + "nodeType": "YulFunctionCall", + "src": "2914:12:381" + }, + "nativeSrc": "2914:12:381", + "nodeType": "YulExpressionStatement", + "src": "2914:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "2848:5:381", + "nodeType": "YulIdentifier", + "src": "2848:5:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "2859:5:381", + "nodeType": "YulIdentifier", + "src": "2859:5:381" + }, + { + "kind": "number", + "nativeSrc": "2866:42:381", + "nodeType": "YulLiteral", + "src": "2866:42:381", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "2855:3:381", + "nodeType": "YulIdentifier", + "src": "2855:3:381" + }, + "nativeSrc": "2855:54:381", + "nodeType": "YulFunctionCall", + "src": "2855:54:381" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "2845:2:381", + "nodeType": "YulIdentifier", + "src": "2845:2:381" + }, + "nativeSrc": "2845:65:381", + "nodeType": "YulFunctionCall", + "src": "2845:65:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "2838:6:381", + "nodeType": "YulIdentifier", + "src": "2838:6:381" + }, + "nativeSrc": "2838:73:381", + "nodeType": "YulFunctionCall", + "src": "2838:73:381" + }, + "nativeSrc": "2835:93:381", + "nodeType": "YulIf", + "src": "2835:93:381" + } + ] + }, + "name": "validator_revert_address", + "nativeSrc": "2780:154:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "2814:5:381", + "nodeType": "YulTypedName", + "src": "2814:5:381", + "type": "" + } + ], + "src": "2780:154:381" + }, + { + "body": { + "nativeSrc": "3009:177:381", + "nodeType": "YulBlock", + "src": "3009:177:381", + "statements": [ + { + "body": { + "nativeSrc": "3055:16:381", + "nodeType": "YulBlock", + "src": "3055:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3064:1:381", + "nodeType": "YulLiteral", + "src": "3064:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3067:1:381", + "nodeType": "YulLiteral", + "src": "3067:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "3057:6:381", + "nodeType": "YulIdentifier", + "src": "3057:6:381" + }, + "nativeSrc": "3057:12:381", + "nodeType": "YulFunctionCall", + "src": "3057:12:381" + }, + "nativeSrc": "3057:12:381", + "nodeType": "YulExpressionStatement", + "src": "3057:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "3030:7:381", + "nodeType": "YulIdentifier", + "src": "3030:7:381" + }, + { + "name": "headStart", + "nativeSrc": "3039:9:381", + "nodeType": "YulIdentifier", + "src": "3039:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "3026:3:381", + "nodeType": "YulIdentifier", + "src": "3026:3:381" + }, + "nativeSrc": "3026:23:381", + "nodeType": "YulFunctionCall", + "src": "3026:23:381" + }, + { + "kind": "number", + "nativeSrc": "3051:2:381", + "nodeType": "YulLiteral", + "src": "3051:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "3022:3:381", + "nodeType": "YulIdentifier", + "src": "3022:3:381" + }, + "nativeSrc": "3022:32:381", + "nodeType": "YulFunctionCall", + "src": "3022:32:381" + }, + "nativeSrc": "3019:52:381", + "nodeType": "YulIf", + "src": "3019:52:381" + }, + { + "nativeSrc": "3080:36:381", + "nodeType": "YulVariableDeclaration", + "src": "3080:36:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3106:9:381", + "nodeType": "YulIdentifier", + "src": "3106:9:381" + } + ], + "functionName": { + "name": "calldataload", + "nativeSrc": "3093:12:381", + "nodeType": "YulIdentifier", + "src": "3093:12:381" + }, + "nativeSrc": "3093:23:381", + "nodeType": "YulFunctionCall", + "src": "3093:23:381" + }, + "variables": [ + { + "name": "value", + "nativeSrc": "3084:5:381", + "nodeType": "YulTypedName", + "src": "3084:5:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value", + "nativeSrc": "3150:5:381", + "nodeType": "YulIdentifier", + "src": "3150:5:381" + } + ], + "functionName": { + "name": "validator_revert_address", + "nativeSrc": "3125:24:381", + "nodeType": "YulIdentifier", + "src": "3125:24:381" + }, + "nativeSrc": "3125:31:381", + "nodeType": "YulFunctionCall", + "src": "3125:31:381" + }, + "nativeSrc": "3125:31:381", + "nodeType": "YulExpressionStatement", + "src": "3125:31:381" + }, + { + "nativeSrc": "3165:15:381", + "nodeType": "YulAssignment", + "src": "3165:15:381", + "value": { + "name": "value", + "nativeSrc": "3175:5:381", + "nodeType": "YulIdentifier", + "src": "3175:5:381" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "3165:6:381", + "nodeType": "YulIdentifier", + "src": "3165:6:381" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_address", + "nativeSrc": "2939:247:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "2975:9:381", + "nodeType": "YulTypedName", + "src": "2975:9:381", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "2986:7:381", + "nodeType": "YulTypedName", + "src": "2986:7:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "2998:6:381", + "nodeType": "YulTypedName", + "src": "2998:6:381", + "type": "" + } + ], + "src": "2939:247:381" + }, + { + "body": { + "nativeSrc": "3292:125:381", + "nodeType": "YulBlock", + "src": "3292:125:381", + "statements": [ + { + "nativeSrc": "3302:26:381", + "nodeType": "YulAssignment", + "src": "3302:26:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3314:9:381", + "nodeType": "YulIdentifier", + "src": "3314:9:381" + }, + { + "kind": "number", + "nativeSrc": "3325:2:381", + "nodeType": "YulLiteral", + "src": "3325:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3310:3:381", + "nodeType": "YulIdentifier", + "src": "3310:3:381" + }, + "nativeSrc": "3310:18:381", + "nodeType": "YulFunctionCall", + "src": "3310:18:381" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "3302:4:381", + "nodeType": "YulIdentifier", + "src": "3302:4:381" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3344:9:381", + "nodeType": "YulIdentifier", + "src": "3344:9:381" + }, + { + "arguments": [ + { + "name": "value0", + "nativeSrc": "3359:6:381", + "nodeType": "YulIdentifier", + "src": "3359:6:381" + }, + { + "kind": "number", + "nativeSrc": "3367:42:381", + "nodeType": "YulLiteral", + "src": "3367:42:381", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "3355:3:381", + "nodeType": "YulIdentifier", + "src": "3355:3:381" + }, + "nativeSrc": "3355:55:381", + "nodeType": "YulFunctionCall", + "src": "3355:55:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3337:6:381", + "nodeType": "YulIdentifier", + "src": "3337:6:381" + }, + "nativeSrc": "3337:74:381", + "nodeType": "YulFunctionCall", + "src": "3337:74:381" + }, + "nativeSrc": "3337:74:381", + "nodeType": "YulExpressionStatement", + "src": "3337:74:381" + } + ] + }, + "name": "abi_encode_tuple_t_address__to_t_address__fromStack_reversed", + "nativeSrc": "3191:226:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "3261:9:381", + "nodeType": "YulTypedName", + "src": "3261:9:381", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "3272:6:381", + "nodeType": "YulTypedName", + "src": "3272:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "3283:4:381", + "nodeType": "YulTypedName", + "src": "3283:4:381", + "type": "" + } + ], + "src": "3191:226:381" + }, + { + "body": { + "nativeSrc": "3454:152:381", + "nodeType": "YulBlock", + "src": "3454:152:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3471:1:381", + "nodeType": "YulLiteral", + "src": "3471:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3474:77:381", + "nodeType": "YulLiteral", + "src": "3474:77:381", + "type": "", + "value": "35408467139433450592217433187231851964531694900788300625387963629091585785856" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3464:6:381", + "nodeType": "YulIdentifier", + "src": "3464:6:381" + }, + "nativeSrc": "3464:88:381", + "nodeType": "YulFunctionCall", + "src": "3464:88:381" + }, + "nativeSrc": "3464:88:381", + "nodeType": "YulExpressionStatement", + "src": "3464:88:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3568:1:381", + "nodeType": "YulLiteral", + "src": "3568:1:381", + "type": "", + "value": "4" + }, + { + "kind": "number", + "nativeSrc": "3571:4:381", + "nodeType": "YulLiteral", + "src": "3571:4:381", + "type": "", + "value": "0x41" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3561:6:381", + "nodeType": "YulIdentifier", + "src": "3561:6:381" + }, + "nativeSrc": "3561:15:381", + "nodeType": "YulFunctionCall", + "src": "3561:15:381" + }, + "nativeSrc": "3561:15:381", + "nodeType": "YulExpressionStatement", + "src": "3561:15:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3592:1:381", + "nodeType": "YulLiteral", + "src": "3592:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3595:4:381", + "nodeType": "YulLiteral", + "src": "3595:4:381", + "type": "", + "value": "0x24" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "3585:6:381", + "nodeType": "YulIdentifier", + "src": "3585:6:381" + }, + "nativeSrc": "3585:15:381", + "nodeType": "YulFunctionCall", + "src": "3585:15:381" + }, + "nativeSrc": "3585:15:381", + "nodeType": "YulExpressionStatement", + "src": "3585:15:381" + } + ] + }, + "name": "panic_error_0x41", + "nativeSrc": "3422:184:381", + "nodeType": "YulFunctionDefinition", + "src": "3422:184:381" + }, + { + "body": { + "nativeSrc": "3656:230:381", + "nodeType": "YulBlock", + "src": "3656:230:381", + "statements": [ + { + "nativeSrc": "3666:19:381", + "nodeType": "YulAssignment", + "src": "3666:19:381", + "value": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3682:2:381", + "nodeType": "YulLiteral", + "src": "3682:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "3676:5:381", + "nodeType": "YulIdentifier", + "src": "3676:5:381" + }, + "nativeSrc": "3676:9:381", + "nodeType": "YulFunctionCall", + "src": "3676:9:381" + }, + "variableNames": [ + { + "name": "memPtr", + "nativeSrc": "3666:6:381", + "nodeType": "YulIdentifier", + "src": "3666:6:381" + } + ] + }, + { + "nativeSrc": "3694:58:381", + "nodeType": "YulVariableDeclaration", + "src": "3694:58:381", + "value": { + "arguments": [ + { + "name": "memPtr", + "nativeSrc": "3716:6:381", + "nodeType": "YulIdentifier", + "src": "3716:6:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "size", + "nativeSrc": "3732:4:381", + "nodeType": "YulIdentifier", + "src": "3732:4:381" + }, + { + "kind": "number", + "nativeSrc": "3738:2:381", + "nodeType": "YulLiteral", + "src": "3738:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3728:3:381", + "nodeType": "YulIdentifier", + "src": "3728:3:381" + }, + "nativeSrc": "3728:13:381", + "nodeType": "YulFunctionCall", + "src": "3728:13:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3747:2:381", + "nodeType": "YulLiteral", + "src": "3747:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "3743:3:381", + "nodeType": "YulIdentifier", + "src": "3743:3:381" + }, + "nativeSrc": "3743:7:381", + "nodeType": "YulFunctionCall", + "src": "3743:7:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "3724:3:381", + "nodeType": "YulIdentifier", + "src": "3724:3:381" + }, + "nativeSrc": "3724:27:381", + "nodeType": "YulFunctionCall", + "src": "3724:27:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3712:3:381", + "nodeType": "YulIdentifier", + "src": "3712:3:381" + }, + "nativeSrc": "3712:40:381", + "nodeType": "YulFunctionCall", + "src": "3712:40:381" + }, + "variables": [ + { + "name": "newFreePtr", + "nativeSrc": "3698:10:381", + "nodeType": "YulTypedName", + "src": "3698:10:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "3827:22:381", + "nodeType": "YulBlock", + "src": "3827:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "3829:16:381", + "nodeType": "YulIdentifier", + "src": "3829:16:381" + }, + "nativeSrc": "3829:18:381", + "nodeType": "YulFunctionCall", + "src": "3829:18:381" + }, + "nativeSrc": "3829:18:381", + "nodeType": "YulExpressionStatement", + "src": "3829:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "newFreePtr", + "nativeSrc": "3770:10:381", + "nodeType": "YulIdentifier", + "src": "3770:10:381" + }, + { + "kind": "number", + "nativeSrc": "3782:18:381", + "nodeType": "YulLiteral", + "src": "3782:18:381", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "3767:2:381", + "nodeType": "YulIdentifier", + "src": "3767:2:381" + }, + "nativeSrc": "3767:34:381", + "nodeType": "YulFunctionCall", + "src": "3767:34:381" + }, + { + "arguments": [ + { + "name": "newFreePtr", + "nativeSrc": "3806:10:381", + "nodeType": "YulIdentifier", + "src": "3806:10:381" + }, + { + "name": "memPtr", + "nativeSrc": "3818:6:381", + "nodeType": "YulIdentifier", + "src": "3818:6:381" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "3803:2:381", + "nodeType": "YulIdentifier", + "src": "3803:2:381" + }, + "nativeSrc": "3803:22:381", + "nodeType": "YulFunctionCall", + "src": "3803:22:381" + } + ], + "functionName": { + "name": "or", + "nativeSrc": "3764:2:381", + "nodeType": "YulIdentifier", + "src": "3764:2:381" + }, + "nativeSrc": "3764:62:381", + "nodeType": "YulFunctionCall", + "src": "3764:62:381" + }, + "nativeSrc": "3761:88:381", + "nodeType": "YulIf", + "src": "3761:88:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3865:2:381", + "nodeType": "YulLiteral", + "src": "3865:2:381", + "type": "", + "value": "64" + }, + { + "name": "newFreePtr", + "nativeSrc": "3869:10:381", + "nodeType": "YulIdentifier", + "src": "3869:10:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3858:6:381", + "nodeType": "YulIdentifier", + "src": "3858:6:381" + }, + "nativeSrc": "3858:22:381", + "nodeType": "YulFunctionCall", + "src": "3858:22:381" + }, + "nativeSrc": "3858:22:381", + "nodeType": "YulExpressionStatement", + "src": "3858:22:381" + } + ] + }, + "name": "allocate_memory", + "nativeSrc": "3611:275:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "size", + "nativeSrc": "3636:4:381", + "nodeType": "YulTypedName", + "src": "3636:4:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "memPtr", + "nativeSrc": "3645:6:381", + "nodeType": "YulTypedName", + "src": "3645:6:381", + "type": "" + } + ], + "src": "3611:275:381" + }, + { + "body": { + "nativeSrc": "3977:325:381", + "nodeType": "YulBlock", + "src": "3977:325:381", + "statements": [ + { + "body": { + "nativeSrc": "4021:22:381", + "nodeType": "YulBlock", + "src": "4021:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "4023:16:381", + "nodeType": "YulIdentifier", + "src": "4023:16:381" + }, + "nativeSrc": "4023:18:381", + "nodeType": "YulFunctionCall", + "src": "4023:18:381" + }, + "nativeSrc": "4023:18:381", + "nodeType": "YulExpressionStatement", + "src": "4023:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "length", + "nativeSrc": "3993:6:381", + "nodeType": "YulIdentifier", + "src": "3993:6:381" + }, + { + "kind": "number", + "nativeSrc": "4001:18:381", + "nodeType": "YulLiteral", + "src": "4001:18:381", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "3990:2:381", + "nodeType": "YulIdentifier", + "src": "3990:2:381" + }, + "nativeSrc": "3990:30:381", + "nodeType": "YulFunctionCall", + "src": "3990:30:381" + }, + "nativeSrc": "3987:56:381", + "nodeType": "YulIf", + "src": "3987:56:381" + }, + { + "nativeSrc": "4052:66:381", + "nodeType": "YulAssignment", + "src": "4052:66:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "length", + "nativeSrc": "4089:6:381", + "nodeType": "YulIdentifier", + "src": "4089:6:381" + }, + { + "kind": "number", + "nativeSrc": "4097:2:381", + "nodeType": "YulLiteral", + "src": "4097:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4085:3:381", + "nodeType": "YulIdentifier", + "src": "4085:3:381" + }, + "nativeSrc": "4085:15:381", + "nodeType": "YulFunctionCall", + "src": "4085:15:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4106:2:381", + "nodeType": "YulLiteral", + "src": "4106:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "4102:3:381", + "nodeType": "YulIdentifier", + "src": "4102:3:381" + }, + "nativeSrc": "4102:7:381", + "nodeType": "YulFunctionCall", + "src": "4102:7:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "4081:3:381", + "nodeType": "YulIdentifier", + "src": "4081:3:381" + }, + "nativeSrc": "4081:29:381", + "nodeType": "YulFunctionCall", + "src": "4081:29:381" + }, + { + "kind": "number", + "nativeSrc": "4112:4:381", + "nodeType": "YulLiteral", + "src": "4112:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4077:3:381", + "nodeType": "YulIdentifier", + "src": "4077:3:381" + }, + "nativeSrc": "4077:40:381", + "nodeType": "YulFunctionCall", + "src": "4077:40:381" + } + ], + "functionName": { + "name": "allocate_memory", + "nativeSrc": "4061:15:381", + "nodeType": "YulIdentifier", + "src": "4061:15:381" + }, + "nativeSrc": "4061:57:381", + "nodeType": "YulFunctionCall", + "src": "4061:57:381" + }, + "variableNames": [ + { + "name": "array", + "nativeSrc": "4052:5:381", + "nodeType": "YulIdentifier", + "src": "4052:5:381" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "array", + "nativeSrc": "4134:5:381", + "nodeType": "YulIdentifier", + "src": "4134:5:381" + }, + { + "name": "length", + "nativeSrc": "4141:6:381", + "nodeType": "YulIdentifier", + "src": "4141:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "4127:6:381", + "nodeType": "YulIdentifier", + "src": "4127:6:381" + }, + "nativeSrc": "4127:21:381", + "nodeType": "YulFunctionCall", + "src": "4127:21:381" + }, + "nativeSrc": "4127:21:381", + "nodeType": "YulExpressionStatement", + "src": "4127:21:381" + }, + { + "body": { + "nativeSrc": "4186:16:381", + "nodeType": "YulBlock", + "src": "4186:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4195:1:381", + "nodeType": "YulLiteral", + "src": "4195:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4198:1:381", + "nodeType": "YulLiteral", + "src": "4198:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4188:6:381", + "nodeType": "YulIdentifier", + "src": "4188:6:381" + }, + "nativeSrc": "4188:12:381", + "nodeType": "YulFunctionCall", + "src": "4188:12:381" + }, + "nativeSrc": "4188:12:381", + "nodeType": "YulExpressionStatement", + "src": "4188:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "src", + "nativeSrc": "4167:3:381", + "nodeType": "YulIdentifier", + "src": "4167:3:381" + }, + { + "name": "length", + "nativeSrc": "4172:6:381", + "nodeType": "YulIdentifier", + "src": "4172:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4163:3:381", + "nodeType": "YulIdentifier", + "src": "4163:3:381" + }, + "nativeSrc": "4163:16:381", + "nodeType": "YulFunctionCall", + "src": "4163:16:381" + }, + { + "name": "end", + "nativeSrc": "4181:3:381", + "nodeType": "YulIdentifier", + "src": "4181:3:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "4160:2:381", + "nodeType": "YulIdentifier", + "src": "4160:2:381" + }, + "nativeSrc": "4160:25:381", + "nodeType": "YulFunctionCall", + "src": "4160:25:381" + }, + "nativeSrc": "4157:45:381", + "nodeType": "YulIf", + "src": "4157:45:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "4221:5:381", + "nodeType": "YulIdentifier", + "src": "4221:5:381" + }, + { + "kind": "number", + "nativeSrc": "4228:4:381", + "nodeType": "YulLiteral", + "src": "4228:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4217:3:381", + "nodeType": "YulIdentifier", + "src": "4217:3:381" + }, + "nativeSrc": "4217:16:381", + "nodeType": "YulFunctionCall", + "src": "4217:16:381" + }, + { + "name": "src", + "nativeSrc": "4235:3:381", + "nodeType": "YulIdentifier", + "src": "4235:3:381" + }, + { + "name": "length", + "nativeSrc": "4240:6:381", + "nodeType": "YulIdentifier", + "src": "4240:6:381" + } + ], + "functionName": { + "name": "mcopy", + "nativeSrc": "4211:5:381", + "nodeType": "YulIdentifier", + "src": "4211:5:381" + }, + "nativeSrc": "4211:36:381", + "nodeType": "YulFunctionCall", + "src": "4211:36:381" + }, + "nativeSrc": "4211:36:381", + "nodeType": "YulExpressionStatement", + "src": "4211:36:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "4271:5:381", + "nodeType": "YulIdentifier", + "src": "4271:5:381" + }, + { + "name": "length", + "nativeSrc": "4278:6:381", + "nodeType": "YulIdentifier", + "src": "4278:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4267:3:381", + "nodeType": "YulIdentifier", + "src": "4267:3:381" + }, + "nativeSrc": "4267:18:381", + "nodeType": "YulFunctionCall", + "src": "4267:18:381" + }, + { + "kind": "number", + "nativeSrc": "4287:4:381", + "nodeType": "YulLiteral", + "src": "4287:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4263:3:381", + "nodeType": "YulIdentifier", + "src": "4263:3:381" + }, + "nativeSrc": "4263:29:381", + "nodeType": "YulFunctionCall", + "src": "4263:29:381" + }, + { + "kind": "number", + "nativeSrc": "4294:1:381", + "nodeType": "YulLiteral", + "src": "4294:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "4256:6:381", + "nodeType": "YulIdentifier", + "src": "4256:6:381" + }, + "nativeSrc": "4256:40:381", + "nodeType": "YulFunctionCall", + "src": "4256:40:381" + }, + "nativeSrc": "4256:40:381", + "nodeType": "YulExpressionStatement", + "src": "4256:40:381" + } + ] + }, + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "3891:411:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "src", + "nativeSrc": "3946:3:381", + "nodeType": "YulTypedName", + "src": "3946:3:381", + "type": "" + }, + { + "name": "length", + "nativeSrc": "3951:6:381", + "nodeType": "YulTypedName", + "src": "3951:6:381", + "type": "" + }, + { + "name": "end", + "nativeSrc": "3959:3:381", + "nodeType": "YulTypedName", + "src": "3959:3:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "array", + "nativeSrc": "3967:5:381", + "nodeType": "YulTypedName", + "src": "3967:5:381", + "type": "" + } + ], + "src": "3891:411:381" + }, + { + "body": { + "nativeSrc": "4370:173:381", + "nodeType": "YulBlock", + "src": "4370:173:381", + "statements": [ + { + "body": { + "nativeSrc": "4419:16:381", + "nodeType": "YulBlock", + "src": "4419:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4428:1:381", + "nodeType": "YulLiteral", + "src": "4428:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4431:1:381", + "nodeType": "YulLiteral", + "src": "4431:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4421:6:381", + "nodeType": "YulIdentifier", + "src": "4421:6:381" + }, + "nativeSrc": "4421:12:381", + "nodeType": "YulFunctionCall", + "src": "4421:12:381" + }, + "nativeSrc": "4421:12:381", + "nodeType": "YulExpressionStatement", + "src": "4421:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4398:6:381", + "nodeType": "YulIdentifier", + "src": "4398:6:381" + }, + { + "kind": "number", + "nativeSrc": "4406:4:381", + "nodeType": "YulLiteral", + "src": "4406:4:381", + "type": "", + "value": "0x1f" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4394:3:381", + "nodeType": "YulIdentifier", + "src": "4394:3:381" + }, + "nativeSrc": "4394:17:381", + "nodeType": "YulFunctionCall", + "src": "4394:17:381" + }, + { + "name": "end", + "nativeSrc": "4413:3:381", + "nodeType": "YulIdentifier", + "src": "4413:3:381" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "4390:3:381", + "nodeType": "YulIdentifier", + "src": "4390:3:381" + }, + "nativeSrc": "4390:27:381", + "nodeType": "YulFunctionCall", + "src": "4390:27:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "4383:6:381", + "nodeType": "YulIdentifier", + "src": "4383:6:381" + }, + "nativeSrc": "4383:35:381", + "nodeType": "YulFunctionCall", + "src": "4383:35:381" + }, + "nativeSrc": "4380:55:381", + "nodeType": "YulIf", + "src": "4380:55:381" + }, + { + "nativeSrc": "4444:93:381", + "nodeType": "YulAssignment", + "src": "4444:93:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4503:6:381", + "nodeType": "YulIdentifier", + "src": "4503:6:381" + }, + { + "kind": "number", + "nativeSrc": "4511:4:381", + "nodeType": "YulLiteral", + "src": "4511:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4499:3:381", + "nodeType": "YulIdentifier", + "src": "4499:3:381" + }, + "nativeSrc": "4499:17:381", + "nodeType": "YulFunctionCall", + "src": "4499:17:381" + }, + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4524:6:381", + "nodeType": "YulIdentifier", + "src": "4524:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "4518:5:381", + "nodeType": "YulIdentifier", + "src": "4518:5:381" + }, + "nativeSrc": "4518:13:381", + "nodeType": "YulFunctionCall", + "src": "4518:13:381" + }, + { + "name": "end", + "nativeSrc": "4533:3:381", + "nodeType": "YulIdentifier", + "src": "4533:3:381" + } + ], + "functionName": { + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "4453:45:381", + "nodeType": "YulIdentifier", + "src": "4453:45:381" + }, + "nativeSrc": "4453:84:381", + "nodeType": "YulFunctionCall", + "src": "4453:84:381" + }, + "variableNames": [ + { + "name": "array", + "nativeSrc": "4444:5:381", + "nodeType": "YulIdentifier", + "src": "4444:5:381" + } + ] + } + ] + }, + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "4307:236:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "4344:6:381", + "nodeType": "YulTypedName", + "src": "4344:6:381", + "type": "" + }, + { + "name": "end", + "nativeSrc": "4352:3:381", + "nodeType": "YulTypedName", + "src": "4352:3:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "array", + "nativeSrc": "4360:5:381", + "nodeType": "YulTypedName", + "src": "4360:5:381", + "type": "" + } + ], + "src": "4307:236:381" + }, + { + "body": { + "nativeSrc": "4607:164:381", + "nodeType": "YulBlock", + "src": "4607:164:381", + "statements": [ + { + "nativeSrc": "4617:22:381", + "nodeType": "YulAssignment", + "src": "4617:22:381", + "value": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4632:6:381", + "nodeType": "YulIdentifier", + "src": "4632:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "4626:5:381", + "nodeType": "YulIdentifier", + "src": "4626:5:381" + }, + "nativeSrc": "4626:13:381", + "nodeType": "YulFunctionCall", + "src": "4626:13:381" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "4617:5:381", + "nodeType": "YulIdentifier", + "src": "4617:5:381" + } + ] + }, + { + "body": { + "nativeSrc": "4749:16:381", + "nodeType": "YulBlock", + "src": "4749:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4758:1:381", + "nodeType": "YulLiteral", + "src": "4758:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4761:1:381", + "nodeType": "YulLiteral", + "src": "4761:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4751:6:381", + "nodeType": "YulIdentifier", + "src": "4751:6:381" + }, + "nativeSrc": "4751:12:381", + "nodeType": "YulFunctionCall", + "src": "4751:12:381" + }, + "nativeSrc": "4751:12:381", + "nodeType": "YulExpressionStatement", + "src": "4751:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "4661:5:381", + "nodeType": "YulIdentifier", + "src": "4661:5:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "4672:5:381", + "nodeType": "YulIdentifier", + "src": "4672:5:381" + }, + { + "kind": "number", + "nativeSrc": "4679:66:381", + "nodeType": "YulLiteral", + "src": "4679:66:381", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "4668:3:381", + "nodeType": "YulIdentifier", + "src": "4668:3:381" + }, + "nativeSrc": "4668:78:381", + "nodeType": "YulFunctionCall", + "src": "4668:78:381" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "4658:2:381", + "nodeType": "YulIdentifier", + "src": "4658:2:381" + }, + "nativeSrc": "4658:89:381", + "nodeType": "YulFunctionCall", + "src": "4658:89:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "4651:6:381", + "nodeType": "YulIdentifier", + "src": "4651:6:381" + }, + "nativeSrc": "4651:97:381", + "nodeType": "YulFunctionCall", + "src": "4651:97:381" + }, + "nativeSrc": "4648:117:381", + "nodeType": "YulIf", + "src": "4648:117:381" + } + ] + }, + "name": "abi_decode_bytes4_fromMemory", + "nativeSrc": "4548:223:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "4586:6:381", + "nodeType": "YulTypedName", + "src": "4586:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "4597:5:381", + "nodeType": "YulTypedName", + "src": "4597:5:381", + "type": "" + } + ], + "src": "4548:223:381" + }, + { + "body": { + "nativeSrc": "4985:1642:381", + "nodeType": "YulBlock", + "src": "4985:1642:381", + "statements": [ + { + "body": { + "nativeSrc": "5032:16:381", + "nodeType": "YulBlock", + "src": "5032:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5041:1:381", + "nodeType": "YulLiteral", + "src": "5041:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5044:1:381", + "nodeType": "YulLiteral", + "src": "5044:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5034:6:381", + "nodeType": "YulIdentifier", + "src": "5034:6:381" + }, + "nativeSrc": "5034:12:381", + "nodeType": "YulFunctionCall", + "src": "5034:12:381" + }, + "nativeSrc": "5034:12:381", + "nodeType": "YulExpressionStatement", + "src": "5034:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "5006:7:381", + "nodeType": "YulIdentifier", + "src": "5006:7:381" + }, + { + "name": "headStart", + "nativeSrc": "5015:9:381", + "nodeType": "YulIdentifier", + "src": "5015:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "5002:3:381", + "nodeType": "YulIdentifier", + "src": "5002:3:381" + }, + "nativeSrc": "5002:23:381", + "nodeType": "YulFunctionCall", + "src": "5002:23:381" + }, + { + "kind": "number", + "nativeSrc": "5027:3:381", + "nodeType": "YulLiteral", + "src": "5027:3:381", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "4998:3:381", + "nodeType": "YulIdentifier", + "src": "4998:3:381" + }, + "nativeSrc": "4998:33:381", + "nodeType": "YulFunctionCall", + "src": "4998:33:381" + }, + "nativeSrc": "4995:53:381", + "nodeType": "YulIf", + "src": "4995:53:381" + }, + { + "nativeSrc": "5057:29:381", + "nodeType": "YulVariableDeclaration", + "src": "5057:29:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5076:9:381", + "nodeType": "YulIdentifier", + "src": "5076:9:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5070:5:381", + "nodeType": "YulIdentifier", + "src": "5070:5:381" + }, + "nativeSrc": "5070:16:381", + "nodeType": "YulFunctionCall", + "src": "5070:16:381" + }, + "variables": [ + { + "name": "value", + "nativeSrc": "5061:5:381", + "nodeType": "YulTypedName", + "src": "5061:5:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value", + "nativeSrc": "5120:5:381", + "nodeType": "YulIdentifier", + "src": "5120:5:381" + } + ], + "functionName": { + "name": "validator_revert_address", + "nativeSrc": "5095:24:381", + "nodeType": "YulIdentifier", + "src": "5095:24:381" + }, + "nativeSrc": "5095:31:381", + "nodeType": "YulFunctionCall", + "src": "5095:31:381" + }, + "nativeSrc": "5095:31:381", + "nodeType": "YulExpressionStatement", + "src": "5095:31:381" + }, + { + "nativeSrc": "5135:15:381", + "nodeType": "YulAssignment", + "src": "5135:15:381", + "value": { + "name": "value", + "nativeSrc": "5145:5:381", + "nodeType": "YulIdentifier", + "src": "5145:5:381" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "5135:6:381", + "nodeType": "YulIdentifier", + "src": "5135:6:381" + } + ] + }, + { + "nativeSrc": "5159:12:381", + "nodeType": "YulVariableDeclaration", + "src": "5159:12:381", + "value": { + "kind": "number", + "nativeSrc": "5169:2:381", + "nodeType": "YulLiteral", + "src": "5169:2:381", + "type": "", + "value": "32" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "5163:2:381", + "nodeType": "YulTypedName", + "src": "5163:2:381", + "type": "" + } + ] + }, + { + "nativeSrc": "5180:39:381", + "nodeType": "YulVariableDeclaration", + "src": "5180:39:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5204:9:381", + "nodeType": "YulIdentifier", + "src": "5204:9:381" + }, + { + "name": "_1", + "nativeSrc": "5215:2:381", + "nodeType": "YulIdentifier", + "src": "5215:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5200:3:381", + "nodeType": "YulIdentifier", + "src": "5200:3:381" + }, + "nativeSrc": "5200:18:381", + "nodeType": "YulFunctionCall", + "src": "5200:18:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5194:5:381", + "nodeType": "YulIdentifier", + "src": "5194:5:381" + }, + "nativeSrc": "5194:25:381", + "nodeType": "YulFunctionCall", + "src": "5194:25:381" + }, + "variables": [ + { + "name": "offset", + "nativeSrc": "5184:6:381", + "nodeType": "YulTypedName", + "src": "5184:6:381", + "type": "" + } + ] + }, + { + "nativeSrc": "5228:28:381", + "nodeType": "YulVariableDeclaration", + "src": "5228:28:381", + "value": { + "kind": "number", + "nativeSrc": "5238:18:381", + "nodeType": "YulLiteral", + "src": "5238:18:381", + "type": "", + "value": "0xffffffffffffffff" + }, + "variables": [ + { + "name": "_2", + "nativeSrc": "5232:2:381", + "nodeType": "YulTypedName", + "src": "5232:2:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5283:16:381", + "nodeType": "YulBlock", + "src": "5283:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5292:1:381", + "nodeType": "YulLiteral", + "src": "5292:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5295:1:381", + "nodeType": "YulLiteral", + "src": "5295:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5285:6:381", + "nodeType": "YulIdentifier", + "src": "5285:6:381" + }, + "nativeSrc": "5285:12:381", + "nodeType": "YulFunctionCall", + "src": "5285:12:381" + }, + "nativeSrc": "5285:12:381", + "nodeType": "YulExpressionStatement", + "src": "5285:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "5271:6:381", + "nodeType": "YulIdentifier", + "src": "5271:6:381" + }, + { + "name": "_2", + "nativeSrc": "5279:2:381", + "nodeType": "YulIdentifier", + "src": "5279:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5268:2:381", + "nodeType": "YulIdentifier", + "src": "5268:2:381" + }, + "nativeSrc": "5268:14:381", + "nodeType": "YulFunctionCall", + "src": "5268:14:381" + }, + "nativeSrc": "5265:34:381", + "nodeType": "YulIf", + "src": "5265:34:381" + }, + { + "nativeSrc": "5308:32:381", + "nodeType": "YulVariableDeclaration", + "src": "5308:32:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5322:9:381", + "nodeType": "YulIdentifier", + "src": "5322:9:381" + }, + { + "name": "offset", + "nativeSrc": "5333:6:381", + "nodeType": "YulIdentifier", + "src": "5333:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5318:3:381", + "nodeType": "YulIdentifier", + "src": "5318:3:381" + }, + "nativeSrc": "5318:22:381", + "nodeType": "YulFunctionCall", + "src": "5318:22:381" + }, + "variables": [ + { + "name": "_3", + "nativeSrc": "5312:2:381", + "nodeType": "YulTypedName", + "src": "5312:2:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5388:16:381", + "nodeType": "YulBlock", + "src": "5388:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5397:1:381", + "nodeType": "YulLiteral", + "src": "5397:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5400:1:381", + "nodeType": "YulLiteral", + "src": "5400:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5390:6:381", + "nodeType": "YulIdentifier", + "src": "5390:6:381" + }, + "nativeSrc": "5390:12:381", + "nodeType": "YulFunctionCall", + "src": "5390:12:381" + }, + "nativeSrc": "5390:12:381", + "nodeType": "YulExpressionStatement", + "src": "5390:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5367:2:381", + "nodeType": "YulIdentifier", + "src": "5367:2:381" + }, + { + "kind": "number", + "nativeSrc": "5371:4:381", + "nodeType": "YulLiteral", + "src": "5371:4:381", + "type": "", + "value": "0x1f" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5363:3:381", + "nodeType": "YulIdentifier", + "src": "5363:3:381" + }, + "nativeSrc": "5363:13:381", + "nodeType": "YulFunctionCall", + "src": "5363:13:381" + }, + { + "name": "dataEnd", + "nativeSrc": "5378:7:381", + "nodeType": "YulIdentifier", + "src": "5378:7:381" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "5359:3:381", + "nodeType": "YulIdentifier", + "src": "5359:3:381" + }, + "nativeSrc": "5359:27:381", + "nodeType": "YulFunctionCall", + "src": "5359:27:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "5352:6:381", + "nodeType": "YulIdentifier", + "src": "5352:6:381" + }, + "nativeSrc": "5352:35:381", + "nodeType": "YulFunctionCall", + "src": "5352:35:381" + }, + "nativeSrc": "5349:55:381", + "nodeType": "YulIf", + "src": "5349:55:381" + }, + { + "nativeSrc": "5413:19:381", + "nodeType": "YulVariableDeclaration", + "src": "5413:19:381", + "value": { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5429:2:381", + "nodeType": "YulIdentifier", + "src": "5429:2:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5423:5:381", + "nodeType": "YulIdentifier", + "src": "5423:5:381" + }, + "nativeSrc": "5423:9:381", + "nodeType": "YulFunctionCall", + "src": "5423:9:381" + }, + "variables": [ + { + "name": "_4", + "nativeSrc": "5417:2:381", + "nodeType": "YulTypedName", + "src": "5417:2:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5455:22:381", + "nodeType": "YulBlock", + "src": "5455:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "5457:16:381", + "nodeType": "YulIdentifier", + "src": "5457:16:381" + }, + "nativeSrc": "5457:18:381", + "nodeType": "YulFunctionCall", + "src": "5457:18:381" + }, + "nativeSrc": "5457:18:381", + "nodeType": "YulExpressionStatement", + "src": "5457:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "_4", + "nativeSrc": "5447:2:381", + "nodeType": "YulIdentifier", + "src": "5447:2:381" + }, + { + "name": "_2", + "nativeSrc": "5451:2:381", + "nodeType": "YulIdentifier", + "src": "5451:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5444:2:381", + "nodeType": "YulIdentifier", + "src": "5444:2:381" + }, + "nativeSrc": "5444:10:381", + "nodeType": "YulFunctionCall", + "src": "5444:10:381" + }, + "nativeSrc": "5441:36:381", + "nodeType": "YulIf", + "src": "5441:36:381" + }, + { + "nativeSrc": "5486:20:381", + "nodeType": "YulVariableDeclaration", + "src": "5486:20:381", + "value": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5500:1:381", + "nodeType": "YulLiteral", + "src": "5500:1:381", + "type": "", + "value": "5" + }, + { + "name": "_4", + "nativeSrc": "5503:2:381", + "nodeType": "YulIdentifier", + "src": "5503:2:381" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "5496:3:381", + "nodeType": "YulIdentifier", + "src": "5496:3:381" + }, + "nativeSrc": "5496:10:381", + "nodeType": "YulFunctionCall", + "src": "5496:10:381" + }, + "variables": [ + { + "name": "_5", + "nativeSrc": "5490:2:381", + "nodeType": "YulTypedName", + "src": "5490:2:381", + "type": "" + } + ] + }, + { + "nativeSrc": "5515:39:381", + "nodeType": "YulVariableDeclaration", + "src": "5515:39:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_5", + "nativeSrc": "5546:2:381", + "nodeType": "YulIdentifier", + "src": "5546:2:381" + }, + { + "name": "_1", + "nativeSrc": "5550:2:381", + "nodeType": "YulIdentifier", + "src": "5550:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5542:3:381", + "nodeType": "YulIdentifier", + "src": "5542:3:381" + }, + "nativeSrc": "5542:11:381", + "nodeType": "YulFunctionCall", + "src": "5542:11:381" + } + ], + "functionName": { + "name": "allocate_memory", + "nativeSrc": "5526:15:381", + "nodeType": "YulIdentifier", + "src": "5526:15:381" + }, + "nativeSrc": "5526:28:381", + "nodeType": "YulFunctionCall", + "src": "5526:28:381" + }, + "variables": [ + { + "name": "dst", + "nativeSrc": "5519:3:381", + "nodeType": "YulTypedName", + "src": "5519:3:381", + "type": "" + } + ] + }, + { + "nativeSrc": "5563:16:381", + "nodeType": "YulVariableDeclaration", + "src": "5563:16:381", + "value": { + "name": "dst", + "nativeSrc": "5576:3:381", + "nodeType": "YulIdentifier", + "src": "5576:3:381" + }, + "variables": [ + { + "name": "dst_1", + "nativeSrc": "5567:5:381", + "nodeType": "YulTypedName", + "src": "5567:5:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "5595:3:381", + "nodeType": "YulIdentifier", + "src": "5595:3:381" + }, + { + "name": "_4", + "nativeSrc": "5600:2:381", + "nodeType": "YulIdentifier", + "src": "5600:2:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "5588:6:381", + "nodeType": "YulIdentifier", + "src": "5588:6:381" + }, + "nativeSrc": "5588:15:381", + "nodeType": "YulFunctionCall", + "src": "5588:15:381" + }, + "nativeSrc": "5588:15:381", + "nodeType": "YulExpressionStatement", + "src": "5588:15:381" + }, + { + "nativeSrc": "5612:19:381", + "nodeType": "YulAssignment", + "src": "5612:19:381", + "value": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "5623:3:381", + "nodeType": "YulIdentifier", + "src": "5623:3:381" + }, + { + "name": "_1", + "nativeSrc": "5628:2:381", + "nodeType": "YulIdentifier", + "src": "5628:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5619:3:381", + "nodeType": "YulIdentifier", + "src": "5619:3:381" + }, + "nativeSrc": "5619:12:381", + "nodeType": "YulFunctionCall", + "src": "5619:12:381" + }, + "variableNames": [ + { + "name": "dst", + "nativeSrc": "5612:3:381", + "nodeType": "YulIdentifier", + "src": "5612:3:381" + } + ] + }, + { + "nativeSrc": "5640:34:381", + "nodeType": "YulVariableDeclaration", + "src": "5640:34:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5662:2:381", + "nodeType": "YulIdentifier", + "src": "5662:2:381" + }, + { + "name": "_5", + "nativeSrc": "5666:2:381", + "nodeType": "YulIdentifier", + "src": "5666:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5658:3:381", + "nodeType": "YulIdentifier", + "src": "5658:3:381" + }, + "nativeSrc": "5658:11:381", + "nodeType": "YulFunctionCall", + "src": "5658:11:381" + }, + { + "name": "_1", + "nativeSrc": "5671:2:381", + "nodeType": "YulIdentifier", + "src": "5671:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5654:3:381", + "nodeType": "YulIdentifier", + "src": "5654:3:381" + }, + "nativeSrc": "5654:20:381", + "nodeType": "YulFunctionCall", + "src": "5654:20:381" + }, + "variables": [ + { + "name": "srcEnd", + "nativeSrc": "5644:6:381", + "nodeType": "YulTypedName", + "src": "5644:6:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5706:16:381", + "nodeType": "YulBlock", + "src": "5706:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5715:1:381", + "nodeType": "YulLiteral", + "src": "5715:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5718:1:381", + "nodeType": "YulLiteral", + "src": "5718:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5708:6:381", + "nodeType": "YulIdentifier", + "src": "5708:6:381" + }, + "nativeSrc": "5708:12:381", + "nodeType": "YulFunctionCall", + "src": "5708:12:381" + }, + "nativeSrc": "5708:12:381", + "nodeType": "YulExpressionStatement", + "src": "5708:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "srcEnd", + "nativeSrc": "5689:6:381", + "nodeType": "YulIdentifier", + "src": "5689:6:381" + }, + { + "name": "dataEnd", + "nativeSrc": "5697:7:381", + "nodeType": "YulIdentifier", + "src": "5697:7:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5686:2:381", + "nodeType": "YulIdentifier", + "src": "5686:2:381" + }, + "nativeSrc": "5686:19:381", + "nodeType": "YulFunctionCall", + "src": "5686:19:381" + }, + "nativeSrc": "5683:39:381", + "nodeType": "YulIf", + "src": "5683:39:381" + }, + { + "nativeSrc": "5731:22:381", + "nodeType": "YulVariableDeclaration", + "src": "5731:22:381", + "value": { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5746:2:381", + "nodeType": "YulIdentifier", + "src": "5746:2:381" + }, + { + "name": "_1", + "nativeSrc": "5750:2:381", + "nodeType": "YulIdentifier", + "src": "5750:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5742:3:381", + "nodeType": "YulIdentifier", + "src": "5742:3:381" + }, + "nativeSrc": "5742:11:381", + "nodeType": "YulFunctionCall", + "src": "5742:11:381" + }, + "variables": [ + { + "name": "src", + "nativeSrc": "5735:3:381", + "nodeType": "YulTypedName", + "src": "5735:3:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5818:359:381", + "nodeType": "YulBlock", + "src": "5818:359:381", + "statements": [ + { + "nativeSrc": "5832:29:381", + "nodeType": "YulVariableDeclaration", + "src": "5832:29:381", + "value": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5857:3:381", + "nodeType": "YulIdentifier", + "src": "5857:3:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5851:5:381", + "nodeType": "YulIdentifier", + "src": "5851:5:381" + }, + "nativeSrc": "5851:10:381", + "nodeType": "YulFunctionCall", + "src": "5851:10:381" + }, + "variables": [ + { + "name": "innerOffset", + "nativeSrc": "5836:11:381", + "nodeType": "YulTypedName", + "src": "5836:11:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5897:16:381", + "nodeType": "YulBlock", + "src": "5897:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5906:1:381", + "nodeType": "YulLiteral", + "src": "5906:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5909:1:381", + "nodeType": "YulLiteral", + "src": "5909:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5899:6:381", + "nodeType": "YulIdentifier", + "src": "5899:6:381" + }, + "nativeSrc": "5899:12:381", + "nodeType": "YulFunctionCall", + "src": "5899:12:381" + }, + "nativeSrc": "5899:12:381", + "nodeType": "YulExpressionStatement", + "src": "5899:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "innerOffset", + "nativeSrc": "5880:11:381", + "nodeType": "YulIdentifier", + "src": "5880:11:381" + }, + { + "name": "_2", + "nativeSrc": "5893:2:381", + "nodeType": "YulIdentifier", + "src": "5893:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5877:2:381", + "nodeType": "YulIdentifier", + "src": "5877:2:381" + }, + "nativeSrc": "5877:19:381", + "nodeType": "YulFunctionCall", + "src": "5877:19:381" + }, + "nativeSrc": "5874:39:381", + "nodeType": "YulIf", + "src": "5874:39:381" + }, + { + "nativeSrc": "5926:30:381", + "nodeType": "YulVariableDeclaration", + "src": "5926:30:381", + "value": { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5940:2:381", + "nodeType": "YulIdentifier", + "src": "5940:2:381" + }, + { + "name": "innerOffset", + "nativeSrc": "5944:11:381", + "nodeType": "YulIdentifier", + "src": "5944:11:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5936:3:381", + "nodeType": "YulIdentifier", + "src": "5936:3:381" + }, + "nativeSrc": "5936:20:381", + "nodeType": "YulFunctionCall", + "src": "5936:20:381" + }, + "variables": [ + { + "name": "_6", + "nativeSrc": "5930:2:381", + "nodeType": "YulTypedName", + "src": "5930:2:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6006:16:381", + "nodeType": "YulBlock", + "src": "6006:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6015:1:381", + "nodeType": "YulLiteral", + "src": "6015:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6018:1:381", + "nodeType": "YulLiteral", + "src": "6018:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6008:6:381", + "nodeType": "YulIdentifier", + "src": "6008:6:381" + }, + "nativeSrc": "6008:12:381", + "nodeType": "YulFunctionCall", + "src": "6008:12:381" + }, + "nativeSrc": "6008:12:381", + "nodeType": "YulExpressionStatement", + "src": "6008:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "_6", + "nativeSrc": "5987:2:381", + "nodeType": "YulIdentifier", + "src": "5987:2:381" + }, + { + "kind": "number", + "nativeSrc": "5991:2:381", + "nodeType": "YulLiteral", + "src": "5991:2:381", + "type": "", + "value": "63" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5983:3:381", + "nodeType": "YulIdentifier", + "src": "5983:3:381" + }, + "nativeSrc": "5983:11:381", + "nodeType": "YulFunctionCall", + "src": "5983:11:381" + }, + { + "name": "dataEnd", + "nativeSrc": "5996:7:381", + "nodeType": "YulIdentifier", + "src": "5996:7:381" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "5979:3:381", + "nodeType": "YulIdentifier", + "src": "5979:3:381" + }, + "nativeSrc": "5979:25:381", + "nodeType": "YulFunctionCall", + "src": "5979:25:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "5972:6:381", + "nodeType": "YulIdentifier", + "src": "5972:6:381" + }, + "nativeSrc": "5972:33:381", + "nodeType": "YulFunctionCall", + "src": "5972:33:381" + }, + "nativeSrc": "5969:53:381", + "nodeType": "YulIf", + "src": "5969:53:381" + }, + { + "expression": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "6042:3:381", + "nodeType": "YulIdentifier", + "src": "6042:3:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "_6", + "nativeSrc": "6097:2:381", + "nodeType": "YulIdentifier", + "src": "6097:2:381" + }, + { + "kind": "number", + "nativeSrc": "6101:2:381", + "nodeType": "YulLiteral", + "src": "6101:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6093:3:381", + "nodeType": "YulIdentifier", + "src": "6093:3:381" + }, + "nativeSrc": "6093:11:381", + "nodeType": "YulFunctionCall", + "src": "6093:11:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "_6", + "nativeSrc": "6116:2:381", + "nodeType": "YulIdentifier", + "src": "6116:2:381" + }, + { + "name": "_1", + "nativeSrc": "6120:2:381", + "nodeType": "YulIdentifier", + "src": "6120:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6112:3:381", + "nodeType": "YulIdentifier", + "src": "6112:3:381" + }, + "nativeSrc": "6112:11:381", + "nodeType": "YulFunctionCall", + "src": "6112:11:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6106:5:381", + "nodeType": "YulIdentifier", + "src": "6106:5:381" + }, + "nativeSrc": "6106:18:381", + "nodeType": "YulFunctionCall", + "src": "6106:18:381" + }, + { + "name": "dataEnd", + "nativeSrc": "6126:7:381", + "nodeType": "YulIdentifier", + "src": "6126:7:381" + } + ], + "functionName": { + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "6047:45:381", + "nodeType": "YulIdentifier", + "src": "6047:45:381" + }, + "nativeSrc": "6047:87:381", + "nodeType": "YulFunctionCall", + "src": "6047:87:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "6035:6:381", + "nodeType": "YulIdentifier", + "src": "6035:6:381" + }, + "nativeSrc": "6035:100:381", + "nodeType": "YulFunctionCall", + "src": "6035:100:381" + }, + "nativeSrc": "6035:100:381", + "nodeType": "YulExpressionStatement", + "src": "6035:100:381" + }, + { + "nativeSrc": "6148:19:381", + "nodeType": "YulAssignment", + "src": "6148:19:381", + "value": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "6159:3:381", + "nodeType": "YulIdentifier", + "src": "6159:3:381" + }, + { + "name": "_1", + "nativeSrc": "6164:2:381", + "nodeType": "YulIdentifier", + "src": "6164:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6155:3:381", + "nodeType": "YulIdentifier", + "src": "6155:3:381" + }, + "nativeSrc": "6155:12:381", + "nodeType": "YulFunctionCall", + "src": "6155:12:381" + }, + "variableNames": [ + { + "name": "dst", + "nativeSrc": "6148:3:381", + "nodeType": "YulIdentifier", + "src": "6148:3:381" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5773:3:381", + "nodeType": "YulIdentifier", + "src": "5773:3:381" + }, + { + "name": "srcEnd", + "nativeSrc": "5778:6:381", + "nodeType": "YulIdentifier", + "src": "5778:6:381" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "5770:2:381", + "nodeType": "YulIdentifier", + "src": "5770:2:381" + }, + "nativeSrc": "5770:15:381", + "nodeType": "YulFunctionCall", + "src": "5770:15:381" + }, + "nativeSrc": "5762:415:381", + "nodeType": "YulForLoop", + "post": { + "nativeSrc": "5786:23:381", + "nodeType": "YulBlock", + "src": "5786:23:381", + "statements": [ + { + "nativeSrc": "5788:19:381", + "nodeType": "YulAssignment", + "src": "5788:19:381", + "value": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5799:3:381", + "nodeType": "YulIdentifier", + "src": "5799:3:381" + }, + { + "name": "_1", + "nativeSrc": "5804:2:381", + "nodeType": "YulIdentifier", + "src": "5804:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5795:3:381", + "nodeType": "YulIdentifier", + "src": "5795:3:381" + }, + "nativeSrc": "5795:12:381", + "nodeType": "YulFunctionCall", + "src": "5795:12:381" + }, + "variableNames": [ + { + "name": "src", + "nativeSrc": "5788:3:381", + "nodeType": "YulIdentifier", + "src": "5788:3:381" + } + ] + } + ] + }, + "pre": { + "nativeSrc": "5766:3:381", + "nodeType": "YulBlock", + "src": "5766:3:381", + "statements": [] + }, + "src": "5762:415:381" + }, + { + "nativeSrc": "6186:15:381", + "nodeType": "YulAssignment", + "src": "6186:15:381", + "value": { + "name": "dst_1", + "nativeSrc": "6196:5:381", + "nodeType": "YulIdentifier", + "src": "6196:5:381" + }, + "variableNames": [ + { + "name": "value1", + "nativeSrc": "6186:6:381", + "nodeType": "YulIdentifier", + "src": "6186:6:381" + } + ] + }, + { + "nativeSrc": "6210:41:381", + "nodeType": "YulVariableDeclaration", + "src": "6210:41:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6236:9:381", + "nodeType": "YulIdentifier", + "src": "6236:9:381" + }, + { + "kind": "number", + "nativeSrc": "6247:2:381", + "nodeType": "YulLiteral", + "src": "6247:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6232:3:381", + "nodeType": "YulIdentifier", + "src": "6232:3:381" + }, + "nativeSrc": "6232:18:381", + "nodeType": "YulFunctionCall", + "src": "6232:18:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6226:5:381", + "nodeType": "YulIdentifier", + "src": "6226:5:381" + }, + "nativeSrc": "6226:25:381", + "nodeType": "YulFunctionCall", + "src": "6226:25:381" + }, + "variables": [ + { + "name": "offset_1", + "nativeSrc": "6214:8:381", + "nodeType": "YulTypedName", + "src": "6214:8:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6280:16:381", + "nodeType": "YulBlock", + "src": "6280:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6289:1:381", + "nodeType": "YulLiteral", + "src": "6289:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6292:1:381", + "nodeType": "YulLiteral", + "src": "6292:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6282:6:381", + "nodeType": "YulIdentifier", + "src": "6282:6:381" + }, + "nativeSrc": "6282:12:381", + "nodeType": "YulFunctionCall", + "src": "6282:12:381" + }, + "nativeSrc": "6282:12:381", + "nodeType": "YulExpressionStatement", + "src": "6282:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset_1", + "nativeSrc": "6266:8:381", + "nodeType": "YulIdentifier", + "src": "6266:8:381" + }, + { + "name": "_2", + "nativeSrc": "6276:2:381", + "nodeType": "YulIdentifier", + "src": "6276:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6263:2:381", + "nodeType": "YulIdentifier", + "src": "6263:2:381" + }, + "nativeSrc": "6263:16:381", + "nodeType": "YulFunctionCall", + "src": "6263:16:381" + }, + "nativeSrc": "6260:36:381", + "nodeType": "YulIf", + "src": "6260:36:381" + }, + { + "nativeSrc": "6305:72:381", + "nodeType": "YulAssignment", + "src": "6305:72:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6347:9:381", + "nodeType": "YulIdentifier", + "src": "6347:9:381" + }, + { + "name": "offset_1", + "nativeSrc": "6358:8:381", + "nodeType": "YulIdentifier", + "src": "6358:8:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6343:3:381", + "nodeType": "YulIdentifier", + "src": "6343:3:381" + }, + "nativeSrc": "6343:24:381", + "nodeType": "YulFunctionCall", + "src": "6343:24:381" + }, + { + "name": "dataEnd", + "nativeSrc": "6369:7:381", + "nodeType": "YulIdentifier", + "src": "6369:7:381" + } + ], + "functionName": { + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "6315:27:381", + "nodeType": "YulIdentifier", + "src": "6315:27:381" + }, + "nativeSrc": "6315:62:381", + "nodeType": "YulFunctionCall", + "src": "6315:62:381" + }, + "variableNames": [ + { + "name": "value2", + "nativeSrc": "6305:6:381", + "nodeType": "YulIdentifier", + "src": "6305:6:381" + } + ] + }, + { + "nativeSrc": "6386:58:381", + "nodeType": "YulAssignment", + "src": "6386:58:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6429:9:381", + "nodeType": "YulIdentifier", + "src": "6429:9:381" + }, + { + "kind": "number", + "nativeSrc": "6440:2:381", + "nodeType": "YulLiteral", + "src": "6440:2:381", + "type": "", + "value": "96" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6425:3:381", + "nodeType": "YulIdentifier", + "src": "6425:3:381" + }, + "nativeSrc": "6425:18:381", + "nodeType": "YulFunctionCall", + "src": "6425:18:381" + } + ], + "functionName": { + "name": "abi_decode_bytes4_fromMemory", + "nativeSrc": "6396:28:381", + "nodeType": "YulIdentifier", + "src": "6396:28:381" + }, + "nativeSrc": "6396:48:381", + "nodeType": "YulFunctionCall", + "src": "6396:48:381" + }, + "variableNames": [ + { + "name": "value3", + "nativeSrc": "6386:6:381", + "nodeType": "YulIdentifier", + "src": "6386:6:381" + } + ] + }, + { + "nativeSrc": "6453:42:381", + "nodeType": "YulVariableDeclaration", + "src": "6453:42:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6479:9:381", + "nodeType": "YulIdentifier", + "src": "6479:9:381" + }, + { + "kind": "number", + "nativeSrc": "6490:3:381", + "nodeType": "YulLiteral", + "src": "6490:3:381", + "type": "", + "value": "128" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6475:3:381", + "nodeType": "YulIdentifier", + "src": "6475:3:381" + }, + "nativeSrc": "6475:19:381", + "nodeType": "YulFunctionCall", + "src": "6475:19:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6469:5:381", + "nodeType": "YulIdentifier", + "src": "6469:5:381" + }, + "nativeSrc": "6469:26:381", + "nodeType": "YulFunctionCall", + "src": "6469:26:381" + }, + "variables": [ + { + "name": "offset_2", + "nativeSrc": "6457:8:381", + "nodeType": "YulTypedName", + "src": "6457:8:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6524:16:381", + "nodeType": "YulBlock", + "src": "6524:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6533:1:381", + "nodeType": "YulLiteral", + "src": "6533:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6536:1:381", + "nodeType": "YulLiteral", + "src": "6536:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6526:6:381", + "nodeType": "YulIdentifier", + "src": "6526:6:381" + }, + "nativeSrc": "6526:12:381", + "nodeType": "YulFunctionCall", + "src": "6526:12:381" + }, + "nativeSrc": "6526:12:381", + "nodeType": "YulExpressionStatement", + "src": "6526:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset_2", + "nativeSrc": "6510:8:381", + "nodeType": "YulIdentifier", + "src": "6510:8:381" + }, + { + "name": "_2", + "nativeSrc": "6520:2:381", + "nodeType": "YulIdentifier", + "src": "6520:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6507:2:381", + "nodeType": "YulIdentifier", + "src": "6507:2:381" + }, + "nativeSrc": "6507:16:381", + "nodeType": "YulFunctionCall", + "src": "6507:16:381" + }, + "nativeSrc": "6504:36:381", + "nodeType": "YulIf", + "src": "6504:36:381" + }, + { + "nativeSrc": "6549:72:381", + "nodeType": "YulAssignment", + "src": "6549:72:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6591:9:381", + "nodeType": "YulIdentifier", + "src": "6591:9:381" + }, + { + "name": "offset_2", + "nativeSrc": "6602:8:381", + "nodeType": "YulIdentifier", + "src": "6602:8:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6587:3:381", + "nodeType": "YulIdentifier", + "src": "6587:3:381" + }, + "nativeSrc": "6587:24:381", + "nodeType": "YulFunctionCall", + "src": "6587:24:381" + }, + { + "name": "dataEnd", + "nativeSrc": "6613:7:381", + "nodeType": "YulIdentifier", + "src": "6613:7:381" + } + ], + "functionName": { + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "6559:27:381", + "nodeType": "YulIdentifier", + "src": "6559:27:381" + }, + "nativeSrc": "6559:62:381", + "nodeType": "YulFunctionCall", + "src": "6559:62:381" + }, + "variableNames": [ + { + "name": "value4", + "nativeSrc": "6549:6:381", + "nodeType": "YulIdentifier", + "src": "6549:6:381" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory", + "nativeSrc": "4776:1851:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "4919:9:381", + "nodeType": "YulTypedName", + "src": "4919:9:381", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "4930:7:381", + "nodeType": "YulTypedName", + "src": "4930:7:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "4942:6:381", + "nodeType": "YulTypedName", + "src": "4942:6:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "4950:6:381", + "nodeType": "YulTypedName", + "src": "4950:6:381", + "type": "" + }, + { + "name": "value2", + "nativeSrc": "4958:6:381", + "nodeType": "YulTypedName", + "src": "4958:6:381", + "type": "" + }, + { + "name": "value3", + "nativeSrc": "4966:6:381", + "nodeType": "YulTypedName", + "src": "4966:6:381", + "type": "" + }, + { + "name": "value4", + "nativeSrc": "4974:6:381", + "nodeType": "YulTypedName", + "src": "4974:6:381", + "type": "" + } + ], + "src": "4776:1851:381" + }, + { + "body": { + "nativeSrc": "6680:77:381", + "nodeType": "YulBlock", + "src": "6680:77:381", + "statements": [ + { + "nativeSrc": "6690:16:381", + "nodeType": "YulAssignment", + "src": "6690:16:381", + "value": { + "arguments": [ + { + "name": "x", + "nativeSrc": "6701:1:381", + "nodeType": "YulIdentifier", + "src": "6701:1:381" + }, + { + "name": "y", + "nativeSrc": "6704:1:381", + "nodeType": "YulIdentifier", + "src": "6704:1:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6697:3:381", + "nodeType": "YulIdentifier", + "src": "6697:3:381" + }, + "nativeSrc": "6697:9:381", + "nodeType": "YulFunctionCall", + "src": "6697:9:381" + }, + "variableNames": [ + { + "name": "sum", + "nativeSrc": "6690:3:381", + "nodeType": "YulIdentifier", + "src": "6690:3:381" + } + ] + }, + { + "body": { + "nativeSrc": "6729:22:381", + "nodeType": "YulBlock", + "src": "6729:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x11", + "nativeSrc": "6731:16:381", + "nodeType": "YulIdentifier", + "src": "6731:16:381" + }, + "nativeSrc": "6731:18:381", + "nodeType": "YulFunctionCall", + "src": "6731:18:381" + }, + "nativeSrc": "6731:18:381", + "nodeType": "YulExpressionStatement", + "src": "6731:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "x", + "nativeSrc": "6721:1:381", + "nodeType": "YulIdentifier", + "src": "6721:1:381" + }, + { + "name": "sum", + "nativeSrc": "6724:3:381", + "nodeType": "YulIdentifier", + "src": "6724:3:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6718:2:381", + "nodeType": "YulIdentifier", + "src": "6718:2:381" + }, + "nativeSrc": "6718:10:381", + "nodeType": "YulFunctionCall", + "src": "6718:10:381" + }, + "nativeSrc": "6715:36:381", + "nodeType": "YulIf", + "src": "6715:36:381" + } + ] + }, + "name": "checked_add_t_uint256", + "nativeSrc": "6632:125:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "x", + "nativeSrc": "6663:1:381", + "nodeType": "YulTypedName", + "src": "6663:1:381", + "type": "" + }, + { + "name": "y", + "nativeSrc": "6666:1:381", + "nodeType": "YulTypedName", + "src": "6666:1:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "sum", + "nativeSrc": "6672:3:381", + "nodeType": "YulTypedName", + "src": "6672:3:381", + "type": "" + } + ], + "src": "6632:125:381" + }, + { + "body": { + "nativeSrc": "6891:119:381", + "nodeType": "YulBlock", + "src": "6891:119:381", + "statements": [ + { + "nativeSrc": "6901:26:381", + "nodeType": "YulAssignment", + "src": "6901:26:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6913:9:381", + "nodeType": "YulIdentifier", + "src": "6913:9:381" + }, + { + "kind": "number", + "nativeSrc": "6924:2:381", + "nodeType": "YulLiteral", + "src": "6924:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6909:3:381", + "nodeType": "YulIdentifier", + "src": "6909:3:381" + }, + "nativeSrc": "6909:18:381", + "nodeType": "YulFunctionCall", + "src": "6909:18:381" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "6901:4:381", + "nodeType": "YulIdentifier", + "src": "6901:4:381" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6943:9:381", + "nodeType": "YulIdentifier", + "src": "6943:9:381" + }, + { + "name": "value0", + "nativeSrc": "6954:6:381", + "nodeType": "YulIdentifier", + "src": "6954:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "6936:6:381", + "nodeType": "YulIdentifier", + "src": "6936:6:381" + }, + "nativeSrc": "6936:25:381", + "nodeType": "YulFunctionCall", + "src": "6936:25:381" + }, + "nativeSrc": "6936:25:381", + "nodeType": "YulExpressionStatement", + "src": "6936:25:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6981:9:381", + "nodeType": "YulIdentifier", + "src": "6981:9:381" + }, + { + "kind": "number", + "nativeSrc": "6992:2:381", + "nodeType": "YulLiteral", + "src": "6992:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6977:3:381", + "nodeType": "YulIdentifier", + "src": "6977:3:381" + }, + "nativeSrc": "6977:18:381", + "nodeType": "YulFunctionCall", + "src": "6977:18:381" + }, + { + "name": "value1", + "nativeSrc": "6997:6:381", + "nodeType": "YulIdentifier", + "src": "6997:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "6970:6:381", + "nodeType": "YulIdentifier", + "src": "6970:6:381" + }, + "nativeSrc": "6970:34:381", + "nodeType": "YulFunctionCall", + "src": "6970:34:381" + }, + "nativeSrc": "6970:34:381", + "nodeType": "YulExpressionStatement", + "src": "6970:34:381" + } + ] + }, + "name": "abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed", + "nativeSrc": "6762:248:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "6852:9:381", + "nodeType": "YulTypedName", + "src": "6852:9:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "6863:6:381", + "nodeType": "YulTypedName", + "src": "6863:6:381", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "6871:6:381", + "nodeType": "YulTypedName", + "src": "6871:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "6882:4:381", + "nodeType": "YulTypedName", + "src": "6882:4:381", + "type": "" + } + ], + "src": "6762:248:381" + } + ] + }, + "contents": "{\n { }\n function abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed(pos, value1, value0) -> end\n {\n calldatacopy(pos, value0, value1)\n let _1 := add(pos, value1)\n mstore(_1, 0)\n end := _1\n }\n function convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4(array) -> value\n {\n let length := mload(array)\n let _1 := mload(add(array, 0x20))\n let _2 := 0xffffffff00000000000000000000000000000000000000000000000000000000\n value := and(_1, _2)\n if lt(length, 4)\n {\n value := and(and(_1, shl(shl(3, sub(4, length)), _2)), _2)\n }\n }\n function panic_error_0x11()\n {\n mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)\n mstore(4, 0x11)\n revert(0, 0x24)\n }\n function checked_sub_t_uint256(x, y) -> diff\n {\n diff := sub(x, y)\n if gt(diff, x) { panic_error_0x11() }\n }\n function abi_encode_string(value, pos) -> end\n {\n let length := mload(value)\n mstore(pos, length)\n mcopy(add(pos, 0x20), add(value, 0x20), length)\n mstore(add(add(pos, length), 0x20), 0)\n end := add(add(pos, and(add(length, 31), not(31))), 0x20)\n }\n function abi_encode_bytes4(value, pos)\n {\n mstore(pos, and(value, 0xffffffff00000000000000000000000000000000000000000000000000000000))\n }\n function abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed(headStart, value4, value3, value2, value1, value0) -> tail\n {\n let tail_1 := add(headStart, 160)\n mstore(headStart, and(value0, 0xffffffffffffffffffffffffffffffffffffffff))\n let _1 := 32\n mstore(add(headStart, 32), 160)\n let pos := tail_1\n let length := mload(value1)\n mstore(tail_1, length)\n pos := add(headStart, 192)\n let tail_2 := add(add(headStart, shl(5, length)), 192)\n let srcPtr := add(value1, 32)\n let i := 0\n for { } lt(i, length) { i := add(i, 1) }\n {\n mstore(pos, add(sub(tail_2, headStart), not(191)))\n tail_2 := abi_encode_string(mload(srcPtr), tail_2)\n srcPtr := add(srcPtr, _1)\n pos := add(pos, _1)\n }\n mstore(add(headStart, 64), sub(tail_2, headStart))\n let tail_3 := abi_encode_string(value2, tail_2)\n abi_encode_bytes4(value3, add(headStart, 96))\n mstore(add(headStart, 128), sub(tail_3, headStart))\n tail := abi_encode_string(value4, tail_3)\n }\n function validator_revert_address(value)\n {\n if iszero(eq(value, and(value, 0xffffffffffffffffffffffffffffffffffffffff))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_address(headStart, dataEnd) -> value0\n {\n if slt(sub(dataEnd, headStart), 32) { revert(0, 0) }\n let value := calldataload(headStart)\n validator_revert_address(value)\n value0 := value\n }\n function abi_encode_tuple_t_address__to_t_address__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, and(value0, 0xffffffffffffffffffffffffffffffffffffffff))\n }\n function panic_error_0x41()\n {\n mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)\n mstore(4, 0x41)\n revert(0, 0x24)\n }\n function allocate_memory(size) -> memPtr\n {\n memPtr := mload(64)\n let newFreePtr := add(memPtr, and(add(size, 31), not(31)))\n if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }\n mstore(64, newFreePtr)\n }\n function abi_decode_available_length_string_fromMemory(src, length, end) -> array\n {\n if gt(length, 0xffffffffffffffff) { panic_error_0x41() }\n array := allocate_memory(add(and(add(length, 31), not(31)), 0x20))\n mstore(array, length)\n if gt(add(src, length), end) { revert(0, 0) }\n mcopy(add(array, 0x20), src, length)\n mstore(add(add(array, length), 0x20), 0)\n }\n function abi_decode_bytes_fromMemory(offset, end) -> array\n {\n if iszero(slt(add(offset, 0x1f), end)) { revert(0, 0) }\n array := abi_decode_available_length_string_fromMemory(add(offset, 0x20), mload(offset), end)\n }\n function abi_decode_bytes4_fromMemory(offset) -> value\n {\n value := mload(offset)\n if iszero(eq(value, and(value, 0xffffffff00000000000000000000000000000000000000000000000000000000))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory(headStart, dataEnd) -> value0, value1, value2, value3, value4\n {\n if slt(sub(dataEnd, headStart), 160) { revert(0, 0) }\n let value := mload(headStart)\n validator_revert_address(value)\n value0 := value\n let _1 := 32\n let offset := mload(add(headStart, _1))\n let _2 := 0xffffffffffffffff\n if gt(offset, _2) { revert(0, 0) }\n let _3 := add(headStart, offset)\n if iszero(slt(add(_3, 0x1f), dataEnd)) { revert(0, 0) }\n let _4 := mload(_3)\n if gt(_4, _2) { panic_error_0x41() }\n let _5 := shl(5, _4)\n let dst := allocate_memory(add(_5, _1))\n let dst_1 := dst\n mstore(dst, _4)\n dst := add(dst, _1)\n let srcEnd := add(add(_3, _5), _1)\n if gt(srcEnd, dataEnd) { revert(0, 0) }\n let src := add(_3, _1)\n for { } lt(src, srcEnd) { src := add(src, _1) }\n {\n let innerOffset := mload(src)\n if gt(innerOffset, _2) { revert(0, 0) }\n let _6 := add(_3, innerOffset)\n if iszero(slt(add(_6, 63), dataEnd)) { revert(0, 0) }\n mstore(dst, abi_decode_available_length_string_fromMemory(add(_6, 64), mload(add(_6, _1)), dataEnd))\n dst := add(dst, _1)\n }\n value1 := dst_1\n let offset_1 := mload(add(headStart, 64))\n if gt(offset_1, _2) { revert(0, 0) }\n value2 := abi_decode_bytes_fromMemory(add(headStart, offset_1), dataEnd)\n value3 := abi_decode_bytes4_fromMemory(add(headStart, 96))\n let offset_2 := mload(add(headStart, 128))\n if gt(offset_2, _2) { revert(0, 0) }\n value4 := abi_decode_bytes_fromMemory(add(headStart, offset_2), dataEnd)\n }\n function checked_add_t_uint256(x, y) -> sum\n {\n sum := add(x, y)\n if gt(x, sum) { panic_error_0x11() }\n }\n function abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed(headStart, value1, value0) -> tail\n {\n tail := add(headStart, 64)\n mstore(headStart, value0)\n mstore(add(headStart, 32), value1)\n }\n}", + "id": 381, + "language": "Yul", + "name": "#utility.yul" + } + ], + "immutableReferences": {}, + "linkReferences": {}, + "object": "608060405234801561000f575f80fd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f806100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610693565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106da565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079a565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107b5565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610889565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109c4565b6105a4565b6104308361041d83856109c4565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b5f815160208301516001600160e01b0319808216935060048310156106775780818460040360031b1b83161693505b505050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106a6576106a661067f565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a015f5b8281101561073f5760bf1988870301845261072d8683516106ac565b95509284019290840190600101610711565b5050505050828103604084015261075681876106ac565b6001600160e01b0319861660608501529050828103608084015261077a81856106ac565b98975050505050505050565b6001600160a01b038116811461051a575f80fd5b5f602082840312156107aa575f80fd5b813561024481610786565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f2576107f26107b5565b604052919050565b5f67ffffffffffffffff831115610813576108136107b5565b610826601f8401601f19166020016107c9565b9050828152838383011115610839575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261085e575f80fd5b610244838351602085016107fa565b80516001600160e01b031981168114610884575f80fd5b919050565b5f805f805f60a0868803121561089d575f80fd5b85516108a881610786565b8095505060208087015167ffffffffffffffff808211156108c7575f80fd5b818901915089601f8301126108da575f80fd5b8151818111156108ec576108ec6107b5565b8060051b6108fb8582016107c9565b918252838101850191858101908d841115610914575f80fd5b86860192505b8383101561096157825185811115610930575f80fd5b8601603f81018f13610940575f80fd5b6109518f89830151604084016107fa565b835250918601919086019061091a565b60408d0151909a5095505050508083111561097a575f80fd5b6109868a848b0161084f565b955061099460608a0161086d565b945060808901519250808311156109a9575f80fd5b50506109b78882890161084f565b9150509295509295909350565b808201808211156106a6576106a661067f56fea2646970667358221220b497e606fddd22fd3bdcf262866dcd9d2d07fa9e7b15191a16b45ee0405c434e64736f6c63430008190033", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4A JUMPI PUSH0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x3659CFE6 EQ PUSH2 0x176 JUMPI DUP1 PUSH4 0x5C60DA1B EQ PUSH2 0x189 JUMPI DUP1 PUSH4 0x8BAD0C0A EQ PUSH2 0x1AD JUMPI DUP1 PUSH4 0xF851A440 EQ PUSH2 0x1B5 JUMPI JUMPDEST PUSH0 DUP1 PUSH2 0x54 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH0 CALLDATASIZE PUSH1 0x40 MLOAD PUSH2 0x6D SWAP3 SWAP2 SWAP1 PUSH2 0x639 JUMP JUMPDEST PUSH0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 GAS STATICCALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH0 DUP2 EQ PUSH2 0xA5 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0xAA JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 ISZERO DUP1 ISZERO PUSH2 0xD5 JUMPI POP PUSH4 0x556F183 PUSH1 0xE4 SHL PUSH2 0xC9 DUP3 PUSH2 0x648 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND EQ JUMPDEST ISZERO PUSH2 0x15E JUMPI PUSH0 PUSH2 0xFB PUSH2 0xF6 DUP4 PUSH1 0x4 DUP1 DUP7 MLOAD PUSH2 0xF1 SWAP2 SWAP1 PUSH2 0x693 JUMP JUMPDEST PUSH2 0x1EF JUMP JUMPDEST PUSH2 0x24B JUMP JUMPDEST SWAP1 POP PUSH2 0x105 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 PUSH0 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x15C JUMPI ADDRESS DUP2 PUSH1 0x20 ADD MLOAD DUP3 PUSH1 0x40 ADD MLOAD DUP4 PUSH1 0x60 ADD MLOAD DUP5 PUSH1 0x80 ADD MLOAD PUSH1 0x40 MLOAD PUSH4 0x556F183 PUSH1 0xE4 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x153 SWAP6 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x6DA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMPDEST DUP2 ISZERO PUSH2 0x16C JUMPI DUP1 MLOAD PUSH1 0x20 DUP3 ADD RETURN JUMPDEST DUP1 MLOAD PUSH1 0x20 DUP3 ADD REVERT JUMPDEST STOP JUMPDEST PUSH2 0x174 PUSH2 0x184 CALLDATASIZE PUSH1 0x4 PUSH2 0x79A JUMP JUMPDEST PUSH2 0x2B6 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x375 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x174 PUSH2 0x383 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x406 JUMP JUMPDEST PUSH0 PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 DUP2 PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x20A JUMPI PUSH2 0x20A PUSH2 0x7B5 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x1F ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x234 JUMPI PUSH1 0x20 DUP3 ADD DUP2 DUP1 CALLDATASIZE DUP4 CALLDATACOPY ADD SWAP1 POP JUMPDEST POP SWAP1 POP PUSH2 0x244 DUP5 DUP5 DUP4 PUSH0 DUP7 PUSH2 0x40F JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0xA0 DUP2 ADD DUP3 MSTORE PUSH0 DUP1 DUP3 MSTORE PUSH1 0x60 PUSH1 0x20 DUP4 ADD DUP2 SWAP1 MSTORE SWAP3 DUP3 ADD DUP4 SWAP1 MSTORE DUP3 DUP3 ADD MSTORE PUSH1 0x80 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP2 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD DUP2 ADD SWAP1 PUSH2 0x288 SWAP2 SWAP1 PUSH2 0x889 JUMP JUMPDEST PUSH1 0x80 DUP7 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND PUSH1 0x60 DUP6 ADD MSTORE PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x20 DUP4 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x2BE PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x2EF JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0x2F8 DUP2 PUSH2 0x473 JUMP JUMPDEST PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xBC7CD75A20EE27FD9ADEBAB32041F755214DBC6BFFA90CC0225B39DA2E5C2D3B SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x1BD JUMP JUMPDEST SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x38B PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x3BC JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH0 PUSH2 0x3C5 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP PUSH2 0x3D0 PUSH0 PUSH2 0x51D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xA3B62BC36326052D97EA62D63C3D60308ED4C3EA8AC079DD8499F1E9C4F80C0F SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x44C JUMP JUMPDEST PUSH2 0x422 DUP6 PUSH2 0x41D DUP4 DUP8 PUSH2 0x9C4 JUMP JUMPDEST PUSH2 0x5A4 JUMP JUMPDEST PUSH2 0x430 DUP4 PUSH2 0x41D DUP4 DUP6 PUSH2 0x9C4 JUMP JUMPDEST PUSH2 0x445 DUP3 PUSH1 0x20 DUP6 ADD ADD DUP6 PUSH1 0x20 DUP9 ADD ADD DUP4 PUSH2 0x5F0 JUMP JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH0 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 PUSH2 0x1E0 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x491 JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0x4C8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x68155F9A00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH2 0x4DA PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x51A JUMPI PUSH1 0x40 MLOAD PUSH32 0x4C3B76BF00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0x526 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP DUP2 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST DUP2 MLOAD DUP2 GT ISZERO PUSH2 0x5EC JUMPI DUP2 MLOAD PUSH1 0x40 MLOAD PUSH32 0x8A3C1CFB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x153 SWAP2 DUP4 SWAP2 PUSH1 0x4 ADD SWAP2 DUP3 MSTORE PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST POP POP JUMP JUMPDEST JUMPDEST PUSH1 0x1F DUP2 GT ISZERO PUSH2 0x611 JUMPI DUP2 MLOAD DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1F NOT ADD PUSH2 0x5F1 JUMP JUMPDEST DUP1 ISZERO PUSH2 0x634 JUMPI DUP2 MLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0x20 DUP5 SWAP1 SUB PUSH1 0x3 SHL SHL PUSH0 NOT ADD DUP1 NOT SWAP1 SWAP3 AND SWAP2 AND OR DUP4 MSTORE JUMPDEST POP POP POP JUMP JUMPDEST DUP2 DUP4 DUP3 CALLDATACOPY PUSH0 SWAP2 ADD SWAP1 DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP2 MLOAD PUSH1 0x20 DUP4 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP1 DUP3 AND SWAP4 POP PUSH1 0x4 DUP4 LT ISZERO PUSH2 0x677 JUMPI DUP1 DUP2 DUP5 PUSH1 0x4 SUB PUSH1 0x3 SHL SHL DUP4 AND AND SWAP4 POP JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x11 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST DUP2 DUP2 SUB DUP2 DUP2 GT ISZERO PUSH2 0x6A6 JUMPI PUSH2 0x6A6 PUSH2 0x67F JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 DUP2 MLOAD DUP1 DUP5 MSTORE DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP7 ADD MCOPY PUSH0 PUSH1 0x20 DUP3 DUP7 ADD ADD MSTORE PUSH1 0x20 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 PUSH1 0xA0 DUP3 ADD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP9 AND DUP4 MSTORE PUSH1 0x20 PUSH1 0xA0 PUSH1 0x20 DUP6 ADD MSTORE DUP2 DUP9 MLOAD DUP1 DUP5 MSTORE PUSH1 0xC0 DUP7 ADD SWAP2 POP PUSH1 0xC0 DUP2 PUSH1 0x5 SHL DUP8 ADD ADD SWAP4 POP PUSH1 0x20 DUP11 ADD PUSH0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x73F JUMPI PUSH1 0xBF NOT DUP9 DUP8 SUB ADD DUP5 MSTORE PUSH2 0x72D DUP7 DUP4 MLOAD PUSH2 0x6AC JUMP JUMPDEST SWAP6 POP SWAP3 DUP5 ADD SWAP3 SWAP1 DUP5 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x711 JUMP JUMPDEST POP POP POP POP POP DUP3 DUP2 SUB PUSH1 0x40 DUP5 ADD MSTORE PUSH2 0x756 DUP2 DUP8 PUSH2 0x6AC JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP7 AND PUSH1 0x60 DUP6 ADD MSTORE SWAP1 POP DUP3 DUP2 SUB PUSH1 0x80 DUP5 ADD MSTORE PUSH2 0x77A DUP2 DUP6 PUSH2 0x6AC JUMP JUMPDEST SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x51A JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x7AA JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x244 DUP2 PUSH2 0x786 JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x41 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1F DUP3 ADD PUSH1 0x1F NOT AND DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x7F2 JUMPI PUSH2 0x7F2 PUSH2 0x7B5 JUMP JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH8 0xFFFFFFFFFFFFFFFF DUP4 GT ISZERO PUSH2 0x813 JUMPI PUSH2 0x813 PUSH2 0x7B5 JUMP JUMPDEST PUSH2 0x826 PUSH1 0x1F DUP5 ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD PUSH2 0x7C9 JUMP JUMPDEST SWAP1 POP DUP3 DUP2 MSTORE DUP4 DUP4 DUP4 ADD GT ISZERO PUSH2 0x839 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP3 DUP3 PUSH1 0x20 DUP4 ADD MCOPY PUSH0 PUSH1 0x20 DUP5 DUP4 ADD ADD MSTORE SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x85E JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x244 DUP4 DUP4 MLOAD PUSH1 0x20 DUP6 ADD PUSH2 0x7FA JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP2 AND DUP2 EQ PUSH2 0x884 JUMPI PUSH0 DUP1 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP1 PUSH0 DUP1 PUSH0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0x89D JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP6 MLOAD PUSH2 0x8A8 DUP2 PUSH2 0x786 JUMP JUMPDEST DUP1 SWAP6 POP POP PUSH1 0x20 DUP1 DUP8 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x8C7 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 DUP10 ADD SWAP2 POP DUP10 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x8DA JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 MLOAD DUP2 DUP2 GT ISZERO PUSH2 0x8EC JUMPI PUSH2 0x8EC PUSH2 0x7B5 JUMP JUMPDEST DUP1 PUSH1 0x5 SHL PUSH2 0x8FB DUP6 DUP3 ADD PUSH2 0x7C9 JUMP JUMPDEST SWAP2 DUP3 MSTORE DUP4 DUP2 ADD DUP6 ADD SWAP2 DUP6 DUP2 ADD SWAP1 DUP14 DUP5 GT ISZERO PUSH2 0x914 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP7 DUP7 ADD SWAP3 POP JUMPDEST DUP4 DUP4 LT ISZERO PUSH2 0x961 JUMPI DUP3 MLOAD DUP6 DUP2 GT ISZERO PUSH2 0x930 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP7 ADD PUSH1 0x3F DUP2 ADD DUP16 SGT PUSH2 0x940 JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x951 DUP16 DUP10 DUP4 ADD MLOAD PUSH1 0x40 DUP5 ADD PUSH2 0x7FA JUMP JUMPDEST DUP4 MSTORE POP SWAP2 DUP7 ADD SWAP2 SWAP1 DUP7 ADD SWAP1 PUSH2 0x91A JUMP JUMPDEST PUSH1 0x40 DUP14 ADD MLOAD SWAP1 SWAP11 POP SWAP6 POP POP POP POP DUP1 DUP4 GT ISZERO PUSH2 0x97A JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x986 DUP11 DUP5 DUP12 ADD PUSH2 0x84F JUMP JUMPDEST SWAP6 POP PUSH2 0x994 PUSH1 0x60 DUP11 ADD PUSH2 0x86D JUMP JUMPDEST SWAP5 POP PUSH1 0x80 DUP10 ADD MLOAD SWAP3 POP DUP1 DUP4 GT ISZERO PUSH2 0x9A9 JUMPI PUSH0 DUP1 REVERT JUMPDEST POP POP PUSH2 0x9B7 DUP9 DUP3 DUP10 ADD PUSH2 0x84F JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 POP SWAP3 SWAP6 SWAP1 SWAP4 POP JUMP JUMPDEST DUP1 DUP3 ADD DUP1 DUP3 GT ISZERO PUSH2 0x6A6 JUMPI PUSH2 0x6A6 PUSH2 0x67F JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0xB4 SWAP8 0xE6 MOD REVERT 0xDD 0x22 REVERT EXTCODESIZE 0xDC CALLCODE PUSH3 0x866DCD SWAP14 0x2D SMOD STATICCALL SWAP15 PUSH28 0x15191A16B45EE0405C434E64736F6C63430008190033000000000000 ", + "sourceMap": "490:6212:360:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3416:7;3425:14;3443:20;:18;:20::i;:::-;-1:-1:-1;;;;;3443:31:360;3475:8;;3443:41;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3415:69;;;;3499:2;3498:3;:43;;;;-1:-1:-1;;;;3505:9:360;3512:1;3505:9;:::i;:::-;-1:-1:-1;;;;;;3505:36:360;;3498:43;3494:447;;;3557:23;3583:56;3598:40;3619:1;3622;3636;3625;:8;:12;;;;:::i;:::-;3598:20;:40::i;:::-;3583:14;:56::i;:::-;3557:82;;3669:20;:18;:20::i;:::-;-1:-1:-1;;;;;3657:32:360;:1;:8;;;-1:-1:-1;;;;;3657:32:360;;3653:278;;3760:4;3787:1;:6;;;3815:1;:10;;;3847:1;:18;;;3887:1;:11;;;3716:200;;-1:-1:-1;;;3716:200:360;;;;;;;;;;;;:::i;:::-;;;;;;;;3653:278;3543:398;3494:447;3955:2;3951:200;;;4025:1;4019:8;4014:2;4011:1;4007:10;4000:28;3951:200;4124:1;4118:8;4113:2;4110:1;4106:10;4099:28;3951:200;3405:752;4280:213;;;;;;:::i;:::-;;:::i;4822:102::-;;;:::i;:::-;;;-1:-1:-1;;;;;3355:55:381;;;3337:74;;3325:2;3310:18;4822:102:360;;;;;;;4589:167;;;:::i;4981:84::-;;;:::i;5708:140::-;5761:7;841:66;5787:48;:54;-1:-1:-1;;;;;5787:54:360;;5708:140;-1:-1:-1;5708:140:360:o;8960:218:130:-;9077:17;9123:3;9113:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9113:14:130;;9106:21;;9137:34;9147:4;9153:3;9158:4;9164:1;9167:3;9137:9;:34::i;:::-;8960:218;;;;;:::o;752:224:3:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;924:1:3;900:69;;;;;;;;;;;;:::i;:::-;885:11;;;834:135;-1:-1:-1;;;;;;834:135:3;865:18;;;834:135;853:10;;;834:135;845:6;;;834:135;-1:-1:-1;;;;;834:135:3;;;835:1;752:224;-1:-1:-1;752:224:3:o;4280:213:360:-;2517:11;:9;:11::i;:::-;-1:-1:-1;;;;;2503:25:360;:10;-1:-1:-1;;;;;2503:25:360;;2499:66;;2549:16;;-1:-1:-1;;;2549:16:360;;;;;;;;;;;2499:66;4355:42:::1;4379:17;4355:23;:42::i;:::-;841:66:::0;6350:74;;-1:-1:-1;;6350:74:360;-1:-1:-1;;;;;6350:74:360;;;;;4459:27:::1;::::0;-1:-1:-1;;;;;4459:27:360;::::1;::::0;::::1;::::0;;;::::1;4280:213:::0;:::o;4822:102::-;4871:7;4897:20;:18;:20::i;:::-;4890:27;;4822:102;:::o;4589:167::-;2517:11;:9;:11::i;:::-;-1:-1:-1;;;;;2503:25:360;:10;-1:-1:-1;;;;;2503:25:360;;2499:66;;2549:16;;-1:-1:-1;;;2549:16:360;;;;;;;;;;;2499:66;4643:20:::1;4666:11;:9;:11::i;:::-;4643:34;;4687:21;4705:1;4687:9;:21::i;:::-;4723:26;::::0;-1:-1:-1;;;;;4723:26:360;::::1;::::0;::::1;::::0;;;::::1;4633:123;4589:167::o:0;4981:84::-;5021:7;5047:11;:9;:11::i;8279:427:130:-;8451:31;8463:4;8469:12;8478:3;8469:6;:12;:::i;:::-;8451:11;:31::i;:::-;8492;8504:4;8510:12;8519:3;8510:6;:12;:::i;8492:31::-;8557:132;8605:6;1271:2:137;1264:10;;8586:25:130;8648:6;1271:2:137;1264:10;;8629:25:130;8672:3;8557:11;:132::i;:::-;8279:427;;;;;:::o;5912:122:360:-;5956:7;1019:66;5982:39;1899:163:257;5307:328:360;-1:-1:-1;;;;;5395:31:360;;;;:69;;-1:-1:-1;;;;;;5430:29:360;;;:34;5395:69;5391:130;;;5487:23;;;;;;;;;;;;;;5391:130;5558:17;-1:-1:-1;;;;;5534:41:360;:20;:18;:20::i;:::-;-1:-1:-1;;;;;5534:41:360;;5530:99;;5598:20;;;;;;;;;;;;;;5530:99;5307:328;:::o;6485:215::-;6540:21;6564:11;:9;:11::i;:::-;6540:35;-1:-1:-1;6633:8:360;1019:66;6585:56;;-1:-1:-1;;6585:56:360;-1:-1:-1;;;;;6585:56:360;;;;;;6656:37;;;;;;;;;;;-1:-1:-1;;6656:37:360;6530:170;6485:215;:::o;338:169:130:-;422:1;:8;416:3;:14;412:89;;;481:8;;453:37;;;;;;;476:3;;453:37;;6936:25:381;;;6992:2;6977:18;;6970:34;6924:2;6909:18;;6762:248;412:89:130;338:169;;:::o;327:671:137:-;512:185;527:2;522:3;519:11;512:185;;;564:10;;552:23;;608:2;599:12;;;;635;;;;-1:-1:-1;;671:12:137;512:185;;;749:3;746:236;;;852:10;;907;;817:1;802:2;798:12;;;795:1;791:20;787:28;-1:-1:-1;;783:36:137;864:9;;848:26;;;903:21;;953:14;941:27;;746:236;327:671;;;:::o;14:271:381:-;197:6;189;184:3;171:33;153:3;223:16;;248:13;;;223:16;14:271;-1:-1:-1;14:271:381:o;290:407::-;373:5;413;407:12;455:4;448:5;444:16;438:23;-1:-1:-1;;;;;;572:2:381;568;564:11;555:20;;598:1;590:6;587:13;584:107;;;678:2;672;662:6;659:1;655:14;652:1;648:22;644:31;640:2;636:40;632:49;623:58;;584:107;;;;290:407;;;:::o;702:184::-;-1:-1:-1;;;751:1:381;744:88;851:4;848:1;841:15;875:4;872:1;865:15;891:128;958:9;;;979:11;;;976:37;;;993:18;;:::i;:::-;891:128;;;;:::o;1024:289::-;1066:3;1104:5;1098:12;1131:6;1126:3;1119:19;1187:6;1180:4;1173:5;1169:16;1162:4;1157:3;1153:14;1147:47;1239:1;1232:4;1223:6;1218:3;1214:16;1210:27;1203:38;1302:4;1295:2;1291:7;1286:2;1278:6;1274:15;1270:29;1265:3;1261:39;1257:50;1250:57;;;1024:289;;;;:::o;1473:1302::-;1781:4;1829:3;1818:9;1814:19;-1:-1:-1;;;;;1864:6:381;1860:55;1849:9;1842:74;1935:2;1973:3;1968:2;1957:9;1953:18;1946:31;1997:6;2032;2026:13;2063:6;2055;2048:22;2101:3;2090:9;2086:19;2079:26;;2164:3;2154:6;2151:1;2147:14;2136:9;2132:30;2128:40;2114:54;;2203:2;2195:6;2191:15;2224:1;2234:256;2248:6;2245:1;2242:13;2234:256;;;2341:3;2337:8;2325:9;2317:6;2313:22;2309:37;2304:3;2297:50;2370:40;2403:6;2394;2388:13;2370:40;:::i;:::-;2360:50;-1:-1:-1;2468:12:381;;;;2433:15;;;;2270:1;2263:9;2234:256;;;2238:3;;;;;2538:9;2530:6;2526:22;2521:2;2510:9;2506:18;2499:50;2572:33;2598:6;2590;2572:33;:::i;:::-;-1:-1:-1;;;;;;1383:78:381;;2655:2;2640:18;;1371:91;2558:47;-1:-1:-1;2708:9:381;2700:6;2696:22;2690:3;2679:9;2675:19;2668:51;2736:33;2762:6;2754;2736:33;:::i;:::-;2728:41;1473:1302;-1:-1:-1;;;;;;;;1473:1302:381:o;2780:154::-;-1:-1:-1;;;;;2859:5:381;2855:54;2848:5;2845:65;2835:93;;2924:1;2921;2914:12;2939:247;2998:6;3051:2;3039:9;3030:7;3026:23;3022:32;3019:52;;;3067:1;3064;3057:12;3019:52;3106:9;3093:23;3125:31;3150:5;3125:31;:::i;3422:184::-;-1:-1:-1;;;3471:1:381;3464:88;3571:4;3568:1;3561:15;3595:4;3592:1;3585:15;3611:275;3682:2;3676:9;3747:2;3728:13;;-1:-1:-1;;3724:27:381;3712:40;;3782:18;3767:34;;3803:22;;;3764:62;3761:88;;;3829:18;;:::i;:::-;3865:2;3858:22;3611:275;;-1:-1:-1;3611:275:381:o;3891:411::-;3967:5;4001:18;3993:6;3990:30;3987:56;;;4023:18;;:::i;:::-;4061:57;4106:2;4085:15;;-1:-1:-1;;4081:29:381;4112:4;4077:40;4061:57;:::i;:::-;4052:66;;4141:6;4134:5;4127:21;4181:3;4172:6;4167:3;4163:16;4160:25;4157:45;;;4198:1;4195;4188:12;4157:45;4240:6;4235:3;4228:4;4221:5;4217:16;4211:36;4294:1;4287:4;4278:6;4271:5;4267:18;4263:29;4256:40;3891:411;;;;;:::o;4307:236::-;4360:5;4413:3;4406:4;4398:6;4394:17;4390:27;4380:55;;4431:1;4428;4421:12;4380:55;4453:84;4533:3;4524:6;4518:13;4511:4;4503:6;4499:17;4453:84;:::i;4548:223::-;4626:13;;-1:-1:-1;;;;;;4668:78:381;;4658:89;;4648:117;;4761:1;4758;4751:12;4648:117;4548:223;;;:::o;4776:1851::-;4942:6;4950;4958;4966;4974;5027:3;5015:9;5006:7;5002:23;4998:33;4995:53;;;5044:1;5041;5034:12;4995:53;5076:9;5070:16;5095:31;5120:5;5095:31;:::i;:::-;5145:5;5135:15;;;5169:2;5215;5204:9;5200:18;5194:25;5238:18;5279:2;5271:6;5268:14;5265:34;;;5295:1;5292;5285:12;5265:34;5333:6;5322:9;5318:22;5308:32;;5378:7;5371:4;5367:2;5363:13;5359:27;5349:55;;5400:1;5397;5390:12;5349:55;5429:2;5423:9;5451:2;5447;5444:10;5441:36;;;5457:18;;:::i;:::-;5503:2;5500:1;5496:10;5526:28;5550:2;5546;5542:11;5526:28;:::i;:::-;5588:15;;;5658:11;;;5654:20;;;5619:12;;;;5686:19;;;5683:39;;;5718:1;5715;5708:12;5683:39;5750:2;5746;5742:11;5731:22;;5762:415;5778:6;5773:3;5770:15;5762:415;;;5857:3;5851:10;5893:2;5880:11;5877:19;5874:39;;;5909:1;5906;5899:12;5874:39;5936:20;;5991:2;5983:11;;5979:25;-1:-1:-1;5969:53:381;;6018:1;6015;6008:12;5969:53;6047:87;6126:7;6120:2;6116;6112:11;6106:18;6101:2;6097;6093:11;6047:87;:::i;:::-;6035:100;;-1:-1:-1;5795:12:381;;;;6155;;;;5762:415;;;6247:2;6232:18;;6226:25;6196:5;;-1:-1:-1;6226:25:381;-1:-1:-1;;;;6263:16:381;;;6260:36;;;6292:1;6289;6282:12;6260:36;6315:62;6369:7;6358:8;6347:9;6343:24;6315:62;:::i;:::-;6305:72;;6396:48;6440:2;6429:9;6425:18;6396:48;:::i;:::-;6386:58;;6490:3;6479:9;6475:19;6469:26;6453:42;;6520:2;6510:8;6507:16;6504:36;;;6536:1;6533;6526:12;6504:36;;;6559:62;6613:7;6602:8;6591:9;6587:24;6559:62;:::i;:::-;6549:72;;;4776:1851;;;;;;;;:::o;6632:125::-;6697:9;;;6718:10;;;6715:36;;;6731:18;;:::i" + }, + "gasEstimates": { + "creation": { + "codeDepositCost": "514600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "": "infinite", + "admin()": "2430", + "implementation()": "2375", + "renounceAdmin()": "infinite", + "upgradeTo(address)": "infinite" + }, + "internal": { + "_getAdmin()": "2152", + "_getImplementation()": "2141", + "_setAdmin(address)": "27982", + "_setImplementation(address)": "infinite", + "_validateImplementation(address)": "infinite" + } + }, + "methodIdentifiers": { + "admin()": "f851a440", + "implementation()": "5c60da1b", + "renounceAdmin()": "8bad0c0a", + "upgradeTo(address)": "3659cfe6" + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CallerNotAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SameImplementation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"AdminRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CallerNotAdmin()\":[{\"details\":\"Error selector: `0x06d919f2`\"}],\"InvalidImplementation()\":[{\"details\":\"Error selector: `0x68155f9a`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"SameImplementation()\":[{\"details\":\"Error selector: `0x4c3b76bf`\"}]},\"events\":{\"AdminChanged(address,address)\":{\"params\":{\"newAdmin\":\"The new admin address\",\"previousAdmin\":\"The previous admin address\"}},\"AdminRemoved(address)\":{\"params\":{\"admin\":\"The admin address that was removed\"}},\"Upgraded(address)\":{\"params\":{\"implementation\":\"The new implementation address\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"admin_\":\"The address of the admin\",\"implementation_\":\"The address of the implementation\"}},\"upgradeTo(address)\":{\"params\":{\"newImplementation\":\"Address of the new implementation\"}}},\"stateVariables\":{\"_ADMIN_SLOT\":{\"details\":\"Storage slot for admin (EIP-1967 compatible)\"},\"_IMPLEMENTATION_SLOT\":{\"details\":\"Storage slot for implementation address (EIP-1967 compatible)\"}},\"title\":\"UpgradableUniversalResolverProxy\",\"version\":1},\"userdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"notice\":\"Event emitted when the admin is changed.\"},\"AdminRemoved(address)\":{\"notice\":\"Event emitted when the admin is removed.\"},\"Upgraded(address)\":{\"notice\":\"Event emitted when the implementation is upgraded.\"}},\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Returns the current admin address.\"},\"implementation()\":{\"notice\":\"Returns the current implementation address.\"},\"renounceAdmin()\":{\"notice\":\"Allows admin to revoke their admin rights by setting admin to address(0).\"},\"upgradeTo(address)\":{\"notice\":\"Upgrades to a new implementation.\"}},\"notice\":\"A specialized proxy for UniversalResolver that forwards method calls and properly handles CCIP-Read reverts. Admin can upgrade the implementation.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/universalResolver/UpgradableUniversalResolverProxy.sol\":\"UpgradableUniversalResolverProxy\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/src/universalResolver/UpgradableUniversalResolverProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EIP3668, OffchainLookup} from \\\"@ens/contracts/ccipRead/EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"@ens/contracts/utils/BytesUtils.sol\\\";\\nimport {StorageSlot} from \\\"@openzeppelin/contracts/utils/StorageSlot.sol\\\";\\n\\n/// @title UpgradableUniversalResolverProxy\\n/// @notice A specialized proxy for UniversalResolver that forwards method calls\\n/// and properly handles CCIP-Read reverts. Admin can upgrade the implementation.\\ncontract UpgradableUniversalResolverProxy {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Storage slot for implementation address (EIP-1967 compatible)\\n bytes32 private constant _IMPLEMENTATION_SLOT =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @dev Storage slot for admin (EIP-1967 compatible)\\n bytes32 private constant _ADMIN_SLOT =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Event emitted when the implementation is upgraded.\\n /// @param implementation The new implementation address\\n event Upgraded(address indexed implementation);\\n\\n /// @notice Event emitted when the admin is changed.\\n /// @param previousAdmin The previous admin address\\n /// @param newAdmin The new admin address\\n event AdminChanged(address indexed previousAdmin, address indexed newAdmin);\\n\\n /// @notice Event emitted when the admin is removed.\\n /// @param admin The admin address that was removed\\n event AdminRemoved(address indexed admin);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x06d919f2`\\n error CallerNotAdmin();\\n\\n /// @dev Error selector: `0x68155f9a`\\n error InvalidImplementation();\\n\\n /// @dev Error selector: `0x4c3b76bf`\\n error SameImplementation();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier restricting a function to the admin.\\n modifier onlyAdmin() {\\n if (msg.sender != _getAdmin())\\n revert CallerNotAdmin();\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param admin_ The address of the admin\\n /// @param implementation_ The address of the implementation\\n constructor(address admin_, address implementation_) {\\n _validateImplementation(implementation_);\\n _setImplementation(implementation_);\\n _setAdmin(admin_);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Fallback function that handles forwarding calls to the implementation\\n /// and properly manages CCIP-Read reverts.\\n fallback() external {\\n (bool ok, bytes memory v) = _getImplementation().staticcall(msg.data);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n EIP3668.Params memory p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n if (p.sender == _getImplementation()) {\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n p.callbackFunction,\\n p.extraData\\n );\\n }\\n }\\n\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @notice Upgrades to a new implementation.\\n /// @param newImplementation Address of the new implementation\\n function upgradeTo(address newImplementation) external onlyAdmin {\\n _validateImplementation(newImplementation);\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /// @notice Allows admin to revoke their admin rights by setting admin to address(0).\\n function renounceAdmin() external onlyAdmin {\\n address currentAdmin = _getAdmin();\\n _setAdmin(address(0));\\n emit AdminRemoved(currentAdmin);\\n }\\n\\n /// @notice Returns the current implementation address.\\n function implementation() external view returns (address) {\\n return _getImplementation();\\n }\\n\\n /// @notice Returns the current admin address.\\n function admin() external view returns (address) {\\n return _getAdmin();\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates if the implementation is valid.\\n function _validateImplementation(address newImplementation) internal view {\\n if (newImplementation == address(0) || newImplementation.code.length == 0) {\\n revert InvalidImplementation();\\n }\\n if (_getImplementation() == newImplementation) {\\n revert SameImplementation();\\n }\\n }\\n\\n /// @dev Gets the current implementation address from storage.\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /// @dev Gets the current admin address from storage.\\n function _getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Sets the implementation address in storage.\\n function _setImplementation(address newImplementation) private {\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /// @dev Sets the admin address in storage.\\n function _setAdmin(address newAdmin) private {\\n address previousAdmin = _getAdmin();\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n emit AdminChanged(previousAdmin, newAdmin);\\n }\\n}\\n\",\"keccak256\":\"0x12df288b00cb10a4e94697b04af4203300f5592cf32ab27735d0682078fb6110\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "events": { + "AdminChanged(address,address)": { + "notice": "Event emitted when the admin is changed." + }, + "AdminRemoved(address)": { + "notice": "Event emitted when the admin is removed." + }, + "Upgraded(address)": { + "notice": "Event emitted when the implementation is upgraded." + } + }, + "kind": "user", + "methods": { + "admin()": { + "notice": "Returns the current admin address." + }, + "implementation()": { + "notice": "Returns the current implementation address." + }, + "renounceAdmin()": { + "notice": "Allows admin to revoke their admin rights by setting admin to address(0)." + }, + "upgradeTo(address)": { + "notice": "Upgrades to a new implementation." + } + }, + "notice": "A specialized proxy for UniversalResolver that forwards method calls and properly handles CCIP-Read reverts. Admin can upgrade the implementation.", + "version": 1 + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/MigrationHelper.json b/contracts/deployments/sepolia/MigrationHelper.json new file mode 100644 index 000000000..ef4922f3d --- /dev/null +++ b/contracts/deployments/sepolia/MigrationHelper.json @@ -0,0 +1,545 @@ +{ + "address": "0xd54a53c1567b26f9653c8565dccc39bceb6ab327", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "rootRegistry", + "type": "address" + }, + { + "internalType": "contract AbstractWrapperReceiver", + "name": "unlockedController", + "type": "address" + }, + { + "internalType": "contract AbstractWrapperReceiver", + "name": "lockedController", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "nft", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "NotApprovedOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "ParentNotMigrated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "WrappedOwnerMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LOCKED_CONTROLLER", + "outputs": [ + { + "internalType": "contract AbstractWrapperReceiver", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_REGISTRY", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNLOCKED_CONTROLLER", + "outputs": [ + { + "internalType": "contract AbstractWrapperReceiver", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[]", + "name": "unwrapped", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[][]", + "name": "unlockedGroups", + "type": "tuple[][]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[][]", + "name": "lockedGroups", + "type": "tuple[][]" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "parentName", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[][]", + "name": "groups", + "type": "tuple[][]" + } + ], + "internalType": "struct LockedChildren[]", + "name": "lockedChildrenGroups", + "type": "tuple[]" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "MigrationHelper", + "sourceName": "src/migration/MigrationHelper.sol", + "bytecode": "0x610140604052348015610010575f80fd5b506040516118a33803806118a383398101604081905261002f91610148565b6001600160a01b0380821660805284811660a05283811660c081905290831660e0526040805163192cf07d60e01b8152905163192cf07d916004808201926020929091908290030181865afa15801561008a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100ae91906101a4565b6001600160a01b031661010081905260408051632b20e39760e01b81529051632b20e397916004808201926020929091908290030181865afa1580156100f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061011a91906101a4565b6001600160a01b031661012052506101c692505050565b6001600160a01b0381168114610145575f80fd5b50565b5f805f806080858703121561015b575f80fd5b845161016681610131565b602086015190945061017781610131565b604086015190935061018881610131565b606086015190925061019981610131565b939692955090935050565b5f602082840312156101b4575f80fd5b81516101bf81610131565b9392505050565b60805160a05160c05160e051610100516101205161164b6102585f395f81816102b70152818161032f015261035701525f818160f5015281816109d501528181610a4f01528181610b0a0152610c5a01525f818160b6015261049601525f818161015801528181610387015261044901525f818161019201526104f301525f81816101310152610640015261164b5ff3fe608060405234801561000f575f80fd5b5060043610610085575f3560e01c806348ee1bcc1161005857806348ee1bcc1461012c5780634ee4a142146101535780636f3ff7261461017a578063c92cc49a1461018d575f80fd5b806301ffc9a714610089578063141b1a4c146100b1578063192cf07d146100f0578063476e8b7114610117575b5f80fd5b61009c610097366004610e7b565b6101b4565b60405190151581526020015b60405180910390f35b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a8565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b61012a610125366004610efb565b610233565b005b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b61009c610188366004610fdd565b61061f565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b5f7fffffffff00000000000000000000000000000000000000000000000000000000821663379ffb9360e11b148061022d57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b335f5b8881101561042157368a8a8381811061025157610251610ff8565b9050602002810190610263919061100c565b90505f610270828061102a565b60405161027e92919061106d565b6040519081900381207f6352211e0000000000000000000000000000000000000000000000000000000082526004820181905291505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610304573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610328919061107c565b90506103557f000000000000000000000000000000000000000000000000000000000000000082876106ab565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b88d4fde827f000000000000000000000000000000000000000000000000000000000000000085876040516020016103b891906110bf565b6040516020818303038152906040526040518563ffffffff1660e01b81526004016103e694939291906111a4565b5f604051808303815f87803b1580156103fd575f80fd5b505af115801561040f573d5f803e3d5ffd5b50505050505050806001019050610236565b5061046f817f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae7f00000000000000000000000000000000000000000000000000000000000000008a8a6107a2565b6104bc817f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae7f000000000000000000000000000000000000000000000000000000000000000088886107a2565b5f5b8281101561061357368484838181106104d9576104d9610ff8565b90506020028101906104eb91906111df565b90505f6105557f000000000000000000000000000000000000000000000000000000000000000061051c848061102a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506107f4915050565b90506001600160a01b0381166105ac5761056f828061102a565b6040517f83d435f10000000000000000000000000000000000000000000000000000000081526004016105a39291906111f3565b60405180910390fd5b610609846105f66105bd858061102a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506108d4915050565b83610604602087018761120e565b6107a2565b50506001016104be565b50505050505050505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610687573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022d9190611254565b806001600160a01b0316826001600160a01b03161415801561075357506040517fe985e9c50000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152828116602483015284169063e985e9c590604401602060405180830381865afa15801561072d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107519190611254565b155b1561079d576040517f1cf8fdfe0000000000000000000000000000000000000000000000000000000081526001600160a01b038085166004830152831660248201526044016105a3565b505050565b5f5b818110156107ec576107e48686868686868181106107c4576107c4610ff8565b90506020028101906107d6919061120e565b6107df916112e1565b610905565b6001016107a4565b505050505050565b5f805f6108018585610d04565b9092509050816108155785925050506108cd565b5f6108218787846107f4565b90506001600160a01b038116156108c9575f61083d8787610d31565b506040517f35af62160000000000000000000000000000000000000000000000000000000081529091506001600160a01b038316906335af621690610886908490600401611409565b602060405180830381865afa1580156108a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c5919061107c565b9450505b5050505b9392505050565b5f6108df8383610d04565b92509050801561022d576108cd6108f684846108d4565b825f9182526020526040902090565b80515f8190036109155750610cfe565b5f808267ffffffffffffffff81111561093057610930611273565b604051908082528060200260200182016040528015610959578160200160208202803683370190505b5090505f5b83811015610aff575f85828151811061097957610979610ff8565b602002602001015190505f6109a189835f0151805190602001205f9182526020526040902090565b6040517f0178fe3f000000000000000000000000000000000000000000000000000000008152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015610a22573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a46919061141b565b50509050610a757f0000000000000000000000000000000000000000000000000000000000000000828d6106ab565b835f03610a8457809550610ad2565b806001600160a01b0316866001600160a01b031614610ad2576040517fd04374c0000000000000000000000000000000000000000000000000000000008152600481018390526024016105a3565b81858581518110610ae557610ae5610ff8565b60200260200101818152505050505080600101905061095e565b5082600103610be0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f242432a8387845f81518110610b4b57610b4b610ff8565b60200260200101516001895f81518110610b6757610b67610ff8565b6020026020010151604051602001610b7f91906114c8565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610bae9594939291906114da565b5f604051808303815f87803b158015610bc5575f80fd5b505af1158015610bd7573d5f803e3d5ffd5b50505050610cfa565b5f8367ffffffffffffffff811115610bfa57610bfa611273565b604051908082528060200260200182016040528015610c23578160200160208202803683370190505b5090505f5b84811015610c57576001828281518110610c4457610c44610ff8565b6020908102919091010152600101610c28565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632eb2c2d6848885858a604051602001610c9c919061151c565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610ccb9594939291906115b8565b5f604051808303815f87803b158015610ce2575f80fd5b505af1158015610cf4573d5f803e3d5ffd5b50505050505b5050505b50505050565b5f805f610d118585610dae565b9250905060ff811615610d2957806021858701012092505b509250929050565b60605f80610d3f8585610dae565b925090505f60ff821667ffffffffffffffff811115610d6057610d60611273565b6040519080825280601f01601f191660200182016040528015610d8a576020820181803683370190505b509050610da36020820160218888010160ff8516610e32565b959194509092505050565b5f8083518310610dd3578360405163ba4adc2360e01b81526004016105a39190611409565b838381518110610de557610de5610ff8565b016020015160f81c91505081810160010181610e05578351811415610e0b565b83518110155b15610e2b578360405163ba4adc2360e01b81526004016105a39190611409565b9250929050565b5b601f811115610e53578151835260209283019290910190601f1901610e33565b801561079d5790518251600160209390930360031b9290921b5f190180199091169116179052565b5f60208284031215610e8b575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108cd575f80fd5b5f8083601f840112610eca575f80fd5b50813567ffffffffffffffff811115610ee1575f80fd5b6020830191508360208260051b8501011115610e2b575f80fd5b5f805f805f805f806080898b031215610f12575f80fd5b883567ffffffffffffffff80821115610f29575f80fd5b610f358c838d01610eba565b909a50985060208b0135915080821115610f4d575f80fd5b610f598c838d01610eba565b909850965060408b0135915080821115610f71575f80fd5b610f7d8c838d01610eba565b909650945060608b0135915080821115610f95575f80fd5b50610fa28b828c01610eba565b999c989b5096995094979396929594505050565b6001600160a01b0381168114610fca575f80fd5b50565b8035610fd881610fb6565b919050565b5f60208284031215610fed575f80fd5b81356108cd81610fb6565b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112611020575f80fd5b9190910192915050565b5f808335601e1984360301811261103f575f80fd5b83018035915067ffffffffffffffff821115611059575f80fd5b602001915036819003821315610e2b575f80fd5b818382375f9101908152919050565b5f6020828403121561108c575f80fd5b81516108cd81610fb6565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f8235601e198436030181126110d7575f80fd5b830160208101903567ffffffffffffffff8111156110f3575f80fd5b803603821315611101575f80fd5b6080602085015261111660a085018284611097565b915050602084013561112781610fb6565b6001600160a01b03811660408501525061114360408501610fcd565b6001600160a01b03811660608501525061115f60608501610fcd565b6001600160a01b0381166080850152509392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f6001600160a01b038087168352808616602084015250836040830152608060608301526111d56080830184611176565b9695505050505050565b5f8235603e19833603018112611020575f80fd5b602081525f611206602083018486611097565b949350505050565b5f808335601e19843603018112611223575f80fd5b83018035915067ffffffffffffffff82111561123d575f80fd5b6020019150600581901b3603821315610e2b575f80fd5b5f60208284031215611264575f80fd5b815180151581146108cd575f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff811182821017156112aa576112aa611273565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156112d9576112d9611273565b604052919050565b5f67ffffffffffffffff808411156112fb576112fb611273565b8360051b602061130c8183016112b0565b868152918501918181019036841115611323575f80fd5b865b848110156113fd5780358681111561133b575f80fd5b8801608036829003121561134d575f80fd5b611355611287565b813588811115611363575f80fd5b8201601f3681830112611374575f80fd5b81358a81111561138657611386611273565b611397818301601f19168a016112b0565b915080825236898285010111156113ac575f80fd5b808984018a8401375f9082018901528252506113c9828701610fcd565b8682015260406113da818401610fcd565b9082015260606113eb838201610fcd565b90820152845250918301918301611325565b50979650505050505050565b602081525f6108cd6020830184611176565b5f805f6060848603121561142d575f80fd5b835161143881610fb6565b602085015190935063ffffffff81168114611451575f80fd5b604085015190925067ffffffffffffffff8116811461146e575f80fd5b809150509250925092565b5f81516080845261148d6080850182611176565b905060208301516001600160a01b03808216602087015280604086015116604087015280606086015116606087015250508091505092915050565b602081525f6108cd6020830184611479565b5f6001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261151160a0830184611176565b979650505050505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b8281101561157157603f1988860301845261155f858351611479565b94509285019290850190600101611543565b5092979650505050505050565b5f815180845260208085019450602084015f5b838110156115ad57815187529582019590820190600101611591565b509495945050505050565b5f6001600160a01b03808816835280871660208401525060a060408301526115e360a083018661157e565b82810360608401526115f5818661157e565b905082810360808401526116098185611176565b9897505050505050505056fea264697066735822122030c6d4157a071ce51d1eb807225105801c8d042ce07bc750ef917813f92e39b764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610085575f3560e01c806348ee1bcc1161005857806348ee1bcc1461012c5780634ee4a142146101535780636f3ff7261461017a578063c92cc49a1461018d575f80fd5b806301ffc9a714610089578063141b1a4c146100b1578063192cf07d146100f0578063476e8b7114610117575b5f80fd5b61009c610097366004610e7b565b6101b4565b60405190151581526020015b60405180910390f35b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100a8565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b61012a610125366004610efb565b610233565b005b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b61009c610188366004610fdd565b61061f565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b5f7fffffffff00000000000000000000000000000000000000000000000000000000821663379ffb9360e11b148061022d57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b335f5b8881101561042157368a8a8381811061025157610251610ff8565b9050602002810190610263919061100c565b90505f610270828061102a565b60405161027e92919061106d565b6040519081900381207f6352211e0000000000000000000000000000000000000000000000000000000082526004820181905291505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610304573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610328919061107c565b90506103557f000000000000000000000000000000000000000000000000000000000000000082876106ab565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b88d4fde827f000000000000000000000000000000000000000000000000000000000000000085876040516020016103b891906110bf565b6040516020818303038152906040526040518563ffffffff1660e01b81526004016103e694939291906111a4565b5f604051808303815f87803b1580156103fd575f80fd5b505af115801561040f573d5f803e3d5ffd5b50505050505050806001019050610236565b5061046f817f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae7f00000000000000000000000000000000000000000000000000000000000000008a8a6107a2565b6104bc817f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae7f000000000000000000000000000000000000000000000000000000000000000088886107a2565b5f5b8281101561061357368484838181106104d9576104d9610ff8565b90506020028101906104eb91906111df565b90505f6105557f000000000000000000000000000000000000000000000000000000000000000061051c848061102a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506107f4915050565b90506001600160a01b0381166105ac5761056f828061102a565b6040517f83d435f10000000000000000000000000000000000000000000000000000000081526004016105a39291906111f3565b60405180910390fd5b610609846105f66105bd858061102a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506108d4915050565b83610604602087018761120e565b6107a2565b50506001016104be565b50505050505050505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610687573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022d9190611254565b806001600160a01b0316826001600160a01b03161415801561075357506040517fe985e9c50000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152828116602483015284169063e985e9c590604401602060405180830381865afa15801561072d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107519190611254565b155b1561079d576040517f1cf8fdfe0000000000000000000000000000000000000000000000000000000081526001600160a01b038085166004830152831660248201526044016105a3565b505050565b5f5b818110156107ec576107e48686868686868181106107c4576107c4610ff8565b90506020028101906107d6919061120e565b6107df916112e1565b610905565b6001016107a4565b505050505050565b5f805f6108018585610d04565b9092509050816108155785925050506108cd565b5f6108218787846107f4565b90506001600160a01b038116156108c9575f61083d8787610d31565b506040517f35af62160000000000000000000000000000000000000000000000000000000081529091506001600160a01b038316906335af621690610886908490600401611409565b602060405180830381865afa1580156108a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c5919061107c565b9450505b5050505b9392505050565b5f6108df8383610d04565b92509050801561022d576108cd6108f684846108d4565b825f9182526020526040902090565b80515f8190036109155750610cfe565b5f808267ffffffffffffffff81111561093057610930611273565b604051908082528060200260200182016040528015610959578160200160208202803683370190505b5090505f5b83811015610aff575f85828151811061097957610979610ff8565b602002602001015190505f6109a189835f0151805190602001205f9182526020526040902090565b6040517f0178fe3f000000000000000000000000000000000000000000000000000000008152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015610a22573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a46919061141b565b50509050610a757f0000000000000000000000000000000000000000000000000000000000000000828d6106ab565b835f03610a8457809550610ad2565b806001600160a01b0316866001600160a01b031614610ad2576040517fd04374c0000000000000000000000000000000000000000000000000000000008152600481018390526024016105a3565b81858581518110610ae557610ae5610ff8565b60200260200101818152505050505080600101905061095e565b5082600103610be0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f242432a8387845f81518110610b4b57610b4b610ff8565b60200260200101516001895f81518110610b6757610b67610ff8565b6020026020010151604051602001610b7f91906114c8565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610bae9594939291906114da565b5f604051808303815f87803b158015610bc5575f80fd5b505af1158015610bd7573d5f803e3d5ffd5b50505050610cfa565b5f8367ffffffffffffffff811115610bfa57610bfa611273565b604051908082528060200260200182016040528015610c23578160200160208202803683370190505b5090505f5b84811015610c57576001828281518110610c4457610c44610ff8565b6020908102919091010152600101610c28565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632eb2c2d6848885858a604051602001610c9c919061151c565b6040516020818303038152906040526040518663ffffffff1660e01b8152600401610ccb9594939291906115b8565b5f604051808303815f87803b158015610ce2575f80fd5b505af1158015610cf4573d5f803e3d5ffd5b50505050505b5050505b50505050565b5f805f610d118585610dae565b9250905060ff811615610d2957806021858701012092505b509250929050565b60605f80610d3f8585610dae565b925090505f60ff821667ffffffffffffffff811115610d6057610d60611273565b6040519080825280601f01601f191660200182016040528015610d8a576020820181803683370190505b509050610da36020820160218888010160ff8516610e32565b959194509092505050565b5f8083518310610dd3578360405163ba4adc2360e01b81526004016105a39190611409565b838381518110610de557610de5610ff8565b016020015160f81c91505081810160010181610e05578351811415610e0b565b83518110155b15610e2b578360405163ba4adc2360e01b81526004016105a39190611409565b9250929050565b5b601f811115610e53578151835260209283019290910190601f1901610e33565b801561079d5790518251600160209390930360031b9290921b5f190180199091169116179052565b5f60208284031215610e8b575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108cd575f80fd5b5f8083601f840112610eca575f80fd5b50813567ffffffffffffffff811115610ee1575f80fd5b6020830191508360208260051b8501011115610e2b575f80fd5b5f805f805f805f806080898b031215610f12575f80fd5b883567ffffffffffffffff80821115610f29575f80fd5b610f358c838d01610eba565b909a50985060208b0135915080821115610f4d575f80fd5b610f598c838d01610eba565b909850965060408b0135915080821115610f71575f80fd5b610f7d8c838d01610eba565b909650945060608b0135915080821115610f95575f80fd5b50610fa28b828c01610eba565b999c989b5096995094979396929594505050565b6001600160a01b0381168114610fca575f80fd5b50565b8035610fd881610fb6565b919050565b5f60208284031215610fed575f80fd5b81356108cd81610fb6565b634e487b7160e01b5f52603260045260245ffd5b5f8235607e19833603018112611020575f80fd5b9190910192915050565b5f808335601e1984360301811261103f575f80fd5b83018035915067ffffffffffffffff821115611059575f80fd5b602001915036819003821315610e2b575f80fd5b818382375f9101908152919050565b5f6020828403121561108c575f80fd5b81516108cd81610fb6565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f8235601e198436030181126110d7575f80fd5b830160208101903567ffffffffffffffff8111156110f3575f80fd5b803603821315611101575f80fd5b6080602085015261111660a085018284611097565b915050602084013561112781610fb6565b6001600160a01b03811660408501525061114360408501610fcd565b6001600160a01b03811660608501525061115f60608501610fcd565b6001600160a01b0381166080850152509392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f6001600160a01b038087168352808616602084015250836040830152608060608301526111d56080830184611176565b9695505050505050565b5f8235603e19833603018112611020575f80fd5b602081525f611206602083018486611097565b949350505050565b5f808335601e19843603018112611223575f80fd5b83018035915067ffffffffffffffff82111561123d575f80fd5b6020019150600581901b3603821315610e2b575f80fd5b5f60208284031215611264575f80fd5b815180151581146108cd575f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff811182821017156112aa576112aa611273565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156112d9576112d9611273565b604052919050565b5f67ffffffffffffffff808411156112fb576112fb611273565b8360051b602061130c8183016112b0565b868152918501918181019036841115611323575f80fd5b865b848110156113fd5780358681111561133b575f80fd5b8801608036829003121561134d575f80fd5b611355611287565b813588811115611363575f80fd5b8201601f3681830112611374575f80fd5b81358a81111561138657611386611273565b611397818301601f19168a016112b0565b915080825236898285010111156113ac575f80fd5b808984018a8401375f9082018901528252506113c9828701610fcd565b8682015260406113da818401610fcd565b9082015260606113eb838201610fcd565b90820152845250918301918301611325565b50979650505050505050565b602081525f6108cd6020830184611176565b5f805f6060848603121561142d575f80fd5b835161143881610fb6565b602085015190935063ffffffff81168114611451575f80fd5b604085015190925067ffffffffffffffff8116811461146e575f80fd5b809150509250925092565b5f81516080845261148d6080850182611176565b905060208301516001600160a01b03808216602087015280604086015116604087015280606086015116606087015250508091505092915050565b602081525f6108cd6020830184611479565b5f6001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261151160a0830184611176565b979650505050505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b8281101561157157603f1988860301845261155f858351611479565b94509285019290850190600101611543565b5092979650505050505050565b5f815180845260208085019450602084015f5b838110156115ad57815187529582019590820190600101611591565b509495945050505050565b5f6001600160a01b03808816835280871660208401525060a060408301526115e360a083018661157e565b82810360608401526115f5818661157e565b905082810360808401526116098185611176565b9897505050505050505056fea264697066735822122030c6d4157a071ce51d1eb807225105801c8d042ce07bc750ef917813f92e39b764736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "62687": [ + { + "length": 32, + "start": 402 + }, + { + "length": 32, + "start": 1267 + } + ], + "62691": [ + { + "length": 32, + "start": 344 + }, + { + "length": 32, + "start": 903 + }, + { + "length": 32, + "start": 1097 + } + ], + "62695": [ + { + "length": 32, + "start": 182 + }, + { + "length": 32, + "start": 1174 + } + ], + "62699": [ + { + "length": 32, + "start": 245 + }, + { + "length": 32, + "start": 2517 + }, + { + "length": 32, + "start": 2639 + }, + { + "length": 32, + "start": 2826 + }, + { + "length": 32, + "start": 3162 + } + ], + "62703": [ + { + "length": 32, + "start": 695 + }, + { + "length": 32, + "start": 815 + }, + { + "length": 32, + "start": 855 + } + ], + "75299": [ + { + "length": 32, + "start": 305 + }, + { + "length": 32, + "start": 1600 + } + ] + }, + "inputSourceName": "project/src/migration/MigrationHelper.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "NotApprovedOperator(address,address)": [ + { + "details": "Error selector: `0x1cf8fdfe`" + } + ], + "ParentNotMigrated(bytes)": [ + { + "details": "Error selector: `0x83d435f1`" + } + ], + "WrappedOwnerMismatch(uint256)": [ + { + "details": "Error selector: `0xd04374c0`" + } + ] + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "lockedController": "The ENSv2 `LockedMigrationController`.", + "rootRegistry": "The root registry.", + "unlockedController": "The ENSv2 `UnlockedMigrationController`." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])": { + "params": { + "lockedChildrenGroups": "Array of `LockedChildren` for 3LD+ tokens.", + "lockedGroups": "Array of Groups of `LibMigration.Data` for locked 2LD tokens with a common owner.", + "unlockedGroups": "Array of Groups of `LibMigration.Data` for unlocked 2LD tokens with a common owner.", + "unwrapped": "Array of `LibMigration.Data` for unwrapped tokens." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "stateVariables": { + "_BASE_REGISTRAR": { + "details": "The ENSv1 `BaseRegistrar` contract." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1141400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "LOCKED_CONTROLLER()": "infinite", + "NAME_WRAPPER()": "infinite", + "ROOT_REGISTRY()": "infinite", + "UNLOCKED_CONTROLLER()": "infinite", + "isContractNamer(address)": "infinite", + "migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])": "infinite", + "supportsInterface(bytes4)": "373" + }, + "internal": { + "_requireOperatorApproval(address,address,address)": "infinite", + "_transferWrapped(address,bytes32,address,struct LibMigration.Data memory[] memory)": "infinite", + "_transferWrappedGroups(address,bytes32,address,struct LibMigration.Data calldata[] calldata[] calldata)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"rootRegistry\",\"type\":\"address\"},{\"internalType\":\"contract AbstractWrapperReceiver\",\"name\":\"unlockedController\",\"type\":\"address\"},{\"internalType\":\"contract AbstractWrapperReceiver\",\"name\":\"lockedController\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"nft\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NotApprovedOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"ParentNotMigrated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"WrappedOwnerMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LOCKED_CONTROLLER\",\"outputs\":[{\"internalType\":\"contract AbstractWrapperReceiver\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UNLOCKED_CONTROLLER\",\"outputs\":[{\"internalType\":\"contract AbstractWrapperReceiver\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[]\",\"name\":\"unwrapped\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[][]\",\"name\":\"unlockedGroups\",\"type\":\"tuple[][]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[][]\",\"name\":\"lockedGroups\",\"type\":\"tuple[][]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"parentName\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[][]\",\"name\":\"groups\",\"type\":\"tuple[][]\"}],\"internalType\":\"struct LockedChildren[]\",\"name\":\"lockedChildrenGroups\",\"type\":\"tuple[]\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"NotApprovedOperator(address,address)\":[{\"details\":\"Error selector: `0x1cf8fdfe`\"}],\"ParentNotMigrated(bytes)\":[{\"details\":\"Error selector: `0x83d435f1`\"}],\"WrappedOwnerMismatch(uint256)\":[{\"details\":\"Error selector: `0xd04374c0`\"}]},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"lockedController\":\"The ENSv2 `LockedMigrationController`.\",\"rootRegistry\":\"The root registry.\",\"unlockedController\":\"The ENSv2 `UnlockedMigrationController`.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])\":{\"params\":{\"lockedChildrenGroups\":\"Array of `LockedChildren` for 3LD+ tokens.\",\"lockedGroups\":\"Array of Groups of `LibMigration.Data` for locked 2LD tokens with a common owner.\",\"unlockedGroups\":\"Array of Groups of `LibMigration.Data` for unlocked 2LD tokens with a common owner.\",\"unwrapped\":\"Array of `LibMigration.Data` for unwrapped tokens.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"_BASE_REGISTRAR\":{\"details\":\"The ENSv1 `BaseRegistrar` contract.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"NotApprovedOperator(address,address)\":[{\"notice\":\"Caller is not an approved operator by `owner` on `nft`.\"}],\"ParentNotMigrated(bytes)\":[{\"notice\":\"A parent has not been migrated yet.\"}],\"WrappedOwnerMismatch(uint256)\":[{\"notice\":\"A group has multiple owners.\"}]},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"LOCKED_CONTROLLER()\":{\"notice\":\"The ENSv2 `LockedMigrationController` contract.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract.\"},\"ROOT_REGISTRY()\":{\"notice\":\"The ENSv2 root registry.\"},\"UNLOCKED_CONTROLLER()\":{\"notice\":\"The ENSv2 `UnlockedMigrationController` contract.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])\":{\"notice\":\"Optimized batch migration helper.\"}},\"notice\":\"Migration helper for mixed (ERC-721 and ERC-1155) batch migration using approval.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/migration/MigrationHelper.sol\":\"MigrationHelper\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/migration/AbstractWrapperReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {IERC1155Receiver} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport {ERC165, IERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {UnauthorizedCaller} from \\\"../CommonErrors.sol\\\";\\nimport {WrappedErrorLib} from \\\"../utils/WrappedErrorLib.sol\\\";\\n\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title AbstractWrapperReceiver\\n/// @dev Abstract IERC1155Receiver which handles NameWrapper token migration via transfer.\\n///\\n/// NameWrapper only allows `Error(string)` exceptions during transfer and squelches typed errors.\\n/// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L317-L335\\n/// This contract, with the aid of WrappedErrorLib, embeds errors that occur during migration into `Error(string)`.\\n///\\n/// There are (2) AbstractWrapperReceiver implementations:\\n/// 1. UnlockedMigrationController accepts unlocked tokens.\\n/// 2. LockedWrapperReceiver accepts locked tokens.\\n///\\n/// `LibMigration.isLocked()` determines lock status.\\n///\\nabstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice The ENSv1 `BaseRegistrar` token graveyard.\\n address public immutable GRAVEYARD;\\n\\n /// @dev The ENSv1 `ENSRegistry` contract.\\n ENS internal immutable _REGISTRY_V1;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Restrict `msg.sender` to NameWrapper.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier onlyWrapper() {\\n if (msg.sender != address(NAME_WRAPPER)) {\\n WrappedErrorLib.wrapAndRevert(\\n abi.encodeWithSelector(UnauthorizedCaller.selector, msg.sender)\\n );\\n }\\n _;\\n }\\n\\n /// @dev Avoid `abi.decode()` failure for obviously invalid data.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier withData(bytes calldata data, uint256 minimumSize) {\\n if (data.length < minimumSize) {\\n WrappedErrorLib.wrapAndRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector));\\n }\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n constructor(INameWrapper nameWrapper, address graveyard) {\\n NAME_WRAPPER = nameWrapper;\\n GRAVEYARD = graveyard;\\n _REGISTRY_V1 = nameWrapper.ens();\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate one NameWrapper token via `safeTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param id The NameWrapper token ID (namehash) of the name being migrated.\\n /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters.\\n function onERC1155Received(\\n address /*operator*/,\\n address /*from*/,\\n uint256 id,\\n uint256 /*amount*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (amount != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L293\\n uint256[] memory ids = new uint256[](1);\\n LibMigration.Data[] memory mds = new LibMigration.Data[](1);\\n ids[0] = id;\\n mds[0] = abi.decode(data, (LibMigration.Data)); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155Received.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param data ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\\n function onERC1155BatchReceived(\\n address /*operator*/,\\n address /*from*/,\\n uint256[] calldata ids,\\n uint256[] calldata /*amounts*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, 64 + ids.length * LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (ids.length != amounts.length) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L162\\n // if (amounts[i] != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L182\\n LibMigration.Data[] memory mds = abi.decode(data, (LibMigration.Data[])); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155BatchReceived.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @notice Convert NameWrapper tokens to their equivalent ENSv2 form.\\n /// @dev Only callable by ourself and invoked by our `IERC1155Receiver` handlers.\\n ///\\n /// TODO: gas analysis and optimization\\n /// NOTE: converting this to an internal call requires catching many reverts\\n ///\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param mds The migration parameters for each name, indexed in parallel with `ids`.\\n function finishERC1155Migration(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n external\\n {\\n if (msg.sender != address(this)) {\\n revert UnauthorizedCaller(msg.sender);\\n }\\n if (ids.length != mds.length) {\\n revert IERC1155Errors.ERC1155InvalidArrayLength(ids.length, mds.length);\\n }\\n _migrateWrapped(ids, mds);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Migrate received NameWrapper tokens.\\n /// Token owner is this contract.\\n /// Token is not expired.\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n virtual;\\n}\\n\",\"keccak256\":\"0x0c15f9f657ba58bf5081cbff88c385c9e673ba87aed2032397ec2c5448d7fe1a\",\"license\":\"MIT\"},\"project/src/migration/MigrationHelper.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IBaseRegistrar} from \\\"@ens/contracts/ethregistrar/IBaseRegistrar.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {LibRegistry} from \\\"../universalResolver/libraries/LibRegistry.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {AbstractWrapperReceiver} from \\\"./AbstractWrapperReceiver.sol\\\";\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @dev Struct for migrating locked 3LD+ tokens.\\nstruct LockedChildren {\\n /// @param parentName The parent name.\\n bytes parentName;\\n /// @param groups Array of Groups of `LibMigration.Data` for locked tokens with a common owner.\\n LibMigration.Data[][] groups;\\n}\\n\\n/// @notice Migration helper for mixed (ERC-721 and ERC-1155) batch migration using approval.\\ncontract MigrationHelper is DelegatedContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 root registry.\\n IRegistry public immutable ROOT_REGISTRY;\\n\\n /// @notice The ENSv2 `UnlockedMigrationController` contract.\\n AbstractWrapperReceiver public immutable UNLOCKED_CONTROLLER;\\n\\n /// @notice The ENSv2 `LockedMigrationController` contract.\\n AbstractWrapperReceiver public immutable LOCKED_CONTROLLER;\\n\\n /// @notice The ENSv1 `NameWrapper` contract.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @dev The ENSv1 `BaseRegistrar` contract.\\n IBaseRegistrar internal immutable _BASE_REGISTRAR;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A group has multiple owners.\\n /// @dev Error selector: `0xd04374c0`\\n error WrappedOwnerMismatch(uint256 tokenId);\\n\\n /// @notice A parent has not been migrated yet.\\n /// @dev Error selector: `0x83d435f1`\\n error ParentNotMigrated(bytes name);\\n\\n /// @notice Caller is not an approved operator by `owner` on `nft`.\\n /// @dev Error selector: `0x1cf8fdfe`\\n error NotApprovedOperator(address nft, address owner);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param rootRegistry The root registry.\\n /// @param unlockedController The ENSv2 `UnlockedMigrationController`.\\n /// @param lockedController The ENSv2 `LockedMigrationController`.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n IRegistry rootRegistry,\\n AbstractWrapperReceiver unlockedController,\\n AbstractWrapperReceiver lockedController,\\n IContractNamer contractNamer\\n )\\n DelegatedContractNamer(contractNamer)\\n {\\n ROOT_REGISTRY = rootRegistry;\\n UNLOCKED_CONTROLLER = unlockedController;\\n LOCKED_CONTROLLER = lockedController;\\n\\n NAME_WRAPPER = unlockedController.NAME_WRAPPER();\\n _BASE_REGISTRAR = NAME_WRAPPER.registrar();\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Optimized batch migration helper.\\n /// @param unwrapped Array of `LibMigration.Data` for unwrapped tokens.\\n /// @param unlockedGroups Array of Groups of `LibMigration.Data` for unlocked 2LD tokens with a common owner.\\n /// @param lockedGroups Array of Groups of `LibMigration.Data` for locked 2LD tokens with a common owner.\\n /// @param lockedChildrenGroups Array of `LockedChildren` for 3LD+ tokens.\\n function migrate(\\n LibMigration.Data[] calldata unwrapped,\\n LibMigration.Data[][] calldata unlockedGroups,\\n LibMigration.Data[][] calldata lockedGroups,\\n LockedChildren[] calldata lockedChildrenGroups\\n )\\n external\\n {\\n address sender = msg.sender;\\n for (uint256 i; i < unwrapped.length; ++i) {\\n LibMigration.Data calldata md = unwrapped[i];\\n uint256 tokenId = uint256(keccak256(bytes(md.label)));\\n address owner = _BASE_REGISTRAR.ownerOf(tokenId);\\n _requireOperatorApproval(address(_BASE_REGISTRAR), owner, sender);\\n _BASE_REGISTRAR.safeTransferFrom(\\n owner,\\n address(UNLOCKED_CONTROLLER),\\n tokenId,\\n abi.encode(md)\\n );\\n }\\n _transferWrappedGroups(\\n sender,\\n NameCoder.ETH_NODE,\\n address(UNLOCKED_CONTROLLER),\\n unlockedGroups\\n );\\n _transferWrappedGroups(sender, NameCoder.ETH_NODE, address(LOCKED_CONTROLLER), lockedGroups);\\n for (uint256 j; j < lockedChildrenGroups.length; ++j) {\\n LockedChildren calldata lc = lockedChildrenGroups[j];\\n IRegistry registry = LibRegistry.findExactRegistry(ROOT_REGISTRY, lc.parentName, 0);\\n if (address(registry) == address(0)) {\\n revert ParentNotMigrated(lc.parentName);\\n }\\n _transferWrappedGroups(\\n sender,\\n NameCoder.namehash(lc.parentName, 0),\\n address(registry),\\n lc.groups\\n );\\n }\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Batch transfer groups of NameWrapper tokens.\\n function _transferWrappedGroups(\\n address sender,\\n bytes32 parentNode,\\n address receiver,\\n LibMigration.Data[][] calldata groups\\n )\\n internal\\n {\\n for (uint256 i; i < groups.length; ++i) {\\n _transferWrapped(sender, parentNode, receiver, groups[i]);\\n }\\n }\\n\\n /// @dev Batch transfer NameWrapper tokens.\\n function _transferWrapped(\\n address sender,\\n bytes32 parentNode,\\n address receiver,\\n LibMigration.Data[] memory mds\\n )\\n internal\\n {\\n uint256 n = mds.length;\\n if (n == 0) {\\n return;\\n }\\n address from;\\n uint256[] memory ids = new uint256[](n);\\n for (uint256 i; i < n; ++i) {\\n LibMigration.Data memory md = mds[i];\\n uint256 id = uint256(NameCoder.namehash(parentNode, keccak256(bytes(md.label))));\\n (address owner, , ) = NAME_WRAPPER.getData(id);\\n _requireOperatorApproval(address(NAME_WRAPPER), owner, sender);\\n if (i == 0) {\\n from = owner;\\n } else if (from != owner) {\\n revert WrappedOwnerMismatch(id);\\n }\\n ids[i] = id;\\n }\\n if (n == 1) {\\n NAME_WRAPPER.safeTransferFrom(from, receiver, ids[0], 1, abi.encode(mds[0]));\\n } else {\\n uint256[] memory amounts = new uint256[](n);\\n for (uint256 i; i < n; ++i) {\\n amounts[i] = 1;\\n }\\n NAME_WRAPPER.safeBatchTransferFrom(from, receiver, ids, amounts, abi.encode(mds));\\n }\\n }\\n\\n /// @dev Ensure operator is owner or approved by owner.\\n function _requireOperatorApproval(address nft, address owner, address operator) internal view {\\n // transfer() will check if from is approved by this contract\\n // note: both IBaseRegistrar and INameWrapper implement isApprovedForAll()\\n if (owner != operator && !INameWrapper(nft).isApprovedForAll(owner, operator)) {\\n revert NotApprovedOperator(nft, owner);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe9dbe2b44baea99546038f656728e03d79bbdbe34eeccdb4fabc0c294e11ecec\",\"license\":\"MIT\"},\"project/src/migration/libraries/LibMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n CANNOT_BURN_FUSES,\\n CANNOT_UNWRAP,\\n IS_DOT_ETH,\\n PARENT_CANNOT_CONTROL\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Primitives for migration.\\nlibrary LibMigration {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Typed arguments for migration via transfer payload.\\n struct Data {\\n /// @dev Subdomain being migrated.\\n string label;\\n /// @dev Address that will own the name in the v2 registry.\\n address owner;\\n /// @dev Address of the child registry.\\n /// Ignored by locked migration.\\n IRegistry subregistry;\\n /// @dev Resolver address to set for the migrated name.\\n /// Ignored if locked and `CANNOT_SET_RESOLVER`.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Minimum size of `abi.encode(Data({...}))`.\\n uint256 internal constant MIN_DATA_SIZE = 7 * 32;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be registered because unmigrated NameWrapper token exists.\\n /// @dev Error selector: `0x408fa1b8`\\n error NameRequiresMigration();\\n\\n /// @notice NameWrapper token is unlocked.\\n /// @dev Error selector: `0x1bfe8f0a`\\n error NameNotLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper token is locked.\\n /// @dev Error selector: `0xe7c290e2`\\n error NameIsLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper or BaseRegistrar token does not match supplied data.\\n /// @dev Error selector: `0xedec3569`\\n error NameDataMismatch(uint256 tokenId);\\n\\n /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\\n /// @dev Error selector: `0xa4f07713`\\n error FrozenTokenApproval(uint256 tokenId);\\n\\n /// @notice The encoded data is invalid.\\n /// @dev Error selector: `0x5cb045db`\\n error InvalidData();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns `true` if the NameWrapper token is locked.\\n function isLocked(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient\\n // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()`\\n return (fuses & CANNOT_UNWRAP) != 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token fuses are not frozen.\\n function notFrozen(uint32 fuses) internal pure returns (bool) {\\n return (fuses & CANNOT_BURN_FUSES) == 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth.\\n function isEmancipatedChild(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL must be set for the entire ancestory.\\n // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()`\\n return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL;\\n }\\n}\\n\",\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/universalResolver/libraries/LibRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"../../registry/interfaces/IOwnedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Recursive traversal helpers for the namechain registry tree \\u2014 resolver lookup, registry\\n/// discovery, canonical name construction, and ancestry enumeration.\\nlibrary LibRegistry {\\n /// @dev Find the resolver address for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return exactRegistry The exact registry or null if not exact.\\n /// @return resolver The resolver or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n // supply if end of name\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return (rootRegistry, address(0), bytes32(0), offset);\\n }\\n // lookup parent name\\n (exactRegistry, resolver, node, resolverOffset) = findResolver(rootRegistry, name, next);\\n // if there was a parent registry...\\n if (address(exactRegistry) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n // remember the resolver (if it exists)\\n address res = exactRegistry.getResolver(label);\\n if (res != address(0)) {\\n resolver = res;\\n resolverOffset = offset;\\n }\\n exactRegistry = exactRegistry.getSubregistry(label);\\n }\\n node = NameCoder.namehash(node, labelHash); // update namehash\\n }\\n\\n /// @dev Find the owner for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return owner The owner address or null if unowned or not found.\\n function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (address owner)\\n {\\n IRegistry registry = findParentRegistry(rootRegistry, name, offset);\\n if (\\n address(registry) != address(0) &&\\n ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId)\\n ) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n owner = IOwnedRegistry(address(registry)).findOwner(label);\\n }\\n }\\n\\n /// @dev Construct the canonical name for `registry`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param registry The registry to name.\\n /// @return name The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry rootRegistry, IRegistry registry)\\n internal\\n view\\n returns (bytes memory name)\\n {\\n if (address(registry) == address(0)) {\\n return \\\"\\\";\\n }\\n for (;;) {\\n if (address(registry) == address(rootRegistry)) {\\n return abi.encodePacked(name, uint8(0)); // add terminator\\n }\\n (IRegistry parent, string memory label) = registry.getParent();\\n if (address(parent) == address(0)) {\\n return \\\"\\\"; // no canonical parent\\n }\\n IRegistry child = parent.getSubregistry(label);\\n if (address(child) != address(registry)) {\\n return \\\"\\\"; // wrong canonical child\\n }\\n name = abi.encodePacked(name, NameCoder.assertLabelSize(label), label); // reverts if invalid label\\n registry = parent;\\n }\\n }\\n\\n /// @dev Find the registry for `name` and return it iff it is canonical for that name.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name)\\n internal\\n view\\n returns (IRegistry)\\n {\\n IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0);\\n return\\n address(registry) != address(0) &&\\n keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) ==\\n keccak256(name)\\n ? registry\\n : IRegistry(address(0));\\n }\\n\\n /// @dev Find the exact registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return exactRegistry The exact registry or null if not found.\\n function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return rootRegistry;\\n }\\n IRegistry parent = findExactRegistry(rootRegistry, name, next);\\n if (address(parent) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n exactRegistry = parent.getSubregistry(label);\\n }\\n }\\n\\n /// @dev Find the parent registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return parentRegistry The parent registry or null if not found.\\n function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry parentRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n parentRegistry = findExactRegistry(rootRegistry, name, next);\\n }\\n }\\n\\n /// @dev Find all registries in the ancestry of `name`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return registries Array of registries in label-order.\\n function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry[] memory registries)\\n {\\n registries = new IRegistry[](1 + NameCoder.countLabels(name, offset));\\n registries[registries.length - 1] = rootRegistry;\\n _findRegistries(name, offset, registries, 0);\\n }\\n\\n /// @dev Recursive function for building ancestry.\\n function _findRegistries(\\n bytes memory name,\\n uint256 offset,\\n IRegistry[] memory registries,\\n uint256 index\\n )\\n private\\n view\\n returns (IRegistry registry)\\n {\\n (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset);\\n if (bytes(label).length == 0) {\\n return registries[registries.length - 1];\\n }\\n registry = _findRegistries(name, nextOffset, registries, index + 1);\\n if (address(registry) != address(0)) {\\n registry = registry.getSubregistry(label);\\n registries[index] = registry;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0b5f34bcc76ee3e49d300444fbcbe1ed152faee49a91c87eaea5f6d61ce6fb0b\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"},\"project/src/utils/WrappedErrorLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {HexUtils} from \\\"@ens/contracts/utils/HexUtils.sol\\\";\\n\\n/// @dev Library to wrap and unwrap typed error data inside of `Error(string)`.\\n/// Uses hex to embed arbitrary data and avoid invalid unicode.\\nlibrary WrappedErrorLib {\\n /// @dev Error selector for `Error(string)`.\\n bytes4 internal constant ERROR_STRING_SELECTOR = 0x08c379a0;\\n\\n /// @dev The detectable human-readable error prefix.\\n /// Must be exactly 16 bytes.\\n bytes16 internal constant WRAPPED_ERROR_PREFIX = \\\"WrappedError::0x\\\";\\n\\n /// @dev Wrap an error and then revert.\\n function wrapAndRevert(bytes memory err) internal pure {\\n err = wrap(err);\\n assembly {\\n revert(add(err, 32), mload(err))\\n }\\n }\\n\\n /// @dev Embed a typed error into `Error(string)`.\\n /// Does nothing if already `Error(string)`.\\n /// For detection, `WRAPPED_ERROR_PREFIX` is leading bytes the error string.\\n function wrap(bytes memory err) internal pure returns (bytes memory) {\\n if (err.length > 0 && bytes4(err) != ERROR_STRING_SELECTOR) {\\n // assert((err.length & 31) == 4);\\n err = abi.encodeWithSelector(\\n ERROR_STRING_SELECTOR,\\n abi.encodePacked(WRAPPED_ERROR_PREFIX, HexUtils.bytesToHex(err))\\n );\\n }\\n return err;\\n }\\n\\n /// @dev Unwrap a typed error from `Error(string)`.\\n /// Does nothing if detection and extracton fails.\\n /// @param err The error data to unwrap.\\n /// @return The unwrapped error data, or unmodified if not wrapped.\\n function unwrap(bytes memory err) internal pure returns (bytes memory) {\\n if (bytes4(err) == ERROR_STRING_SELECTOR) {\\n bytes memory v;\\n assembly {\\n v := add(err, 4) // skip selector\\n }\\n v = abi.decode(v, (bytes));\\n if (bytes16(v) == WRAPPED_ERROR_PREFIX) {\\n (bytes memory inner, bool ok) = HexUtils.hexToBytes(v, 16, v.length);\\n if (ok) {\\n return inner;\\n }\\n }\\n }\\n return err;\\n }\\n}\\n\",\"keccak256\":\"0xf92862b6509cf553bd542925617318a2509bfdc6457e8b5d102c8e9658c610e4\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "NotApprovedOperator(address,address)": [ + { + "notice": "Caller is not an approved operator by `owner` on `nft`." + } + ], + "ParentNotMigrated(bytes)": [ + { + "notice": "A parent has not been migrated yet." + } + ], + "WrappedOwnerMismatch(uint256)": [ + { + "notice": "A group has multiple owners." + } + ] + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "LOCKED_CONTROLLER()": { + "notice": "The ENSv2 `LockedMigrationController` contract." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract." + }, + "ROOT_REGISTRY()": { + "notice": "The ENSv2 root registry." + }, + "UNLOCKED_CONTROLLER()": { + "notice": "The ENSv2 `UnlockedMigrationController` contract." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "migrate((string,address,address,address)[],(string,address,address,address)[][],(string,address,address,address)[][],(bytes,(string,address,address,address)[][])[])": { + "notice": "Optimized batch migration helper." + } + }, + "notice": "Migration helper for mixed (ERC-721 and ERC-1155) batch migration using approval.", + "version": 1 + }, + "argsData": "0x00000000000000000000000011b5bfbe9078d826b1edbdd1cfc12f5828d9f50c000000000000000000000000d021a69db7f9e276a59cbbccf06e7f1e5434215c000000000000000000000000681802eff57b83edce99d688c023ab128449517600000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0xf0525dabfdd5d62246c2a80c89f3759e33b1907d0367b4d2a0569043ca1265db", + "nonce": "0x63", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xf2f7060154554e1245016988f36968a91ce3f99621d6e8bbf8ed02d53dc3e4e9", + "blockNumber": "0xaa5717", + "transactionIndex": "0xc9" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/MockDAI.json b/contracts/deployments/sepolia/MockDAI.json new file mode 100644 index 000000000..3e8a37968 --- /dev/null +++ b/contracts/deployments/sepolia/MockDAI.json @@ -0,0 +1,916 @@ +{ + "address": "0xe33a01a41ee4a68616b5278183aa88808326ed8e", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "ERC2612ExpiredSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC2612InvalidSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nuke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "MockERC20", + "sourceName": "test/mocks/MockERC20.sol", + "bytecode": "0x610160604052348015610010575f80fd5b5060405161155238038061155283398101604081905261002f916101d6565b6040805180820190915260018152603160f81b602082015282908190818060036100598282610315565b5060046100668282610315565b5061007691508390506005610135565b61012052610085816006610135565b61014052815160208084019190912060e052815190820120610100524660a05261011160e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c052506008805460ff191660ff929092169190911790555061042c565b5f6020835110156101505761014983610167565b9050610161565b8161015b8482610315565b5060ff90505b92915050565b5f80829050601f8151111561019a578260405163305a27a960e01b815260040161019191906103d4565b60405180910390fd5b80516101a582610409565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b805160ff811681146101d1575f80fd5b919050565b5f80604083850312156101e7575f80fd5b82516001600160401b03808211156101fd575f80fd5b818501915085601f830112610210575f80fd5b815181811115610222576102226101ad565b604051601f8201601f19908116603f0116810190838211818310171561024a5761024a6101ad565b81604052828152886020848701011115610262575f80fd5b8260208601602083015e5f602084830101528096505050505050610288602084016101c1565b90509250929050565b600181811c908216806102a557607f821691505b6020821081036102c357634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561031057805f5260205f20601f840160051c810160208510156102ee5750805b601f840160051c820191505b8181101561030d575f81556001016102fa565b50505b505050565b81516001600160401b0381111561032e5761032e6101ad565b6103428161033c8454610291565b846102c9565b602080601f831160018114610375575f841561035e5750858301515b5f19600386901b1c1916600185901b1785556103cc565b5f85815260208120601f198616915b828110156103a357888601518255948401946001909101908401610384565b50858210156103c057878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b805160208083015191908110156102c3575f1960209190910360031b1b16919050565b60805160a05160c05160e0516101005161012051610140516110d561047d5f395f61080601525f6107d901525f61074e01525f61072601525f61068101525f6106ab01525f6106d501526110d55ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806370a0823111610093578063a9059cbb11610063578063a9059cbb146101ea578063cade97aa146101fd578063d505accf14610210578063dd62ed3e14610223575f80fd5b806370a082311461018c5780637ecebe00146101b457806384b0196e146101c757806395d89b41146101e2575f80fd5b806323b872dd116100ce57806323b872dd14610147578063313ce5671461015a5780633644e5151461016f57806340c10f1914610177575f80fd5b806306fdde03146100f4578063095ea7b31461011257806318160ddd14610135575b5f80fd5b6100fc61025b565b6040516101099190610e35565b60405180910390f35b610125610120366004610e69565b6102eb565b6040519015158152602001610109565b6002545b604051908152602001610109565b610125610155366004610e91565b610304565b60085460405160ff9091168152602001610109565b610139610327565b61018a610185366004610e69565b610335565b005b61013961019a366004610eca565b6001600160a01b03165f9081526020819052604090205490565b6101396101c2366004610eca565b610343565b6101cf610360565b6040516101099796959493929190610ee3565b6100fc6103be565b6101256101f8366004610e69565b6103cd565b61018a61020b366004610eca565b6103da565b61018a61021e366004610f96565b610404565b610139610231366004611003565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b60606003805461026a90611034565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611034565b80156102e15780601f106102b8576101008083540402835291602001916102e1565b820191905f5260205f20905b8154815290600101906020018083116102c457829003601f168201915b5050505050905090565b5f336102f8818585610571565b60019150505b92915050565b5f33610311858285610583565b61031c858585610618565b506001949350505050565b5f610330610675565b905090565b61033f828261079e565b5050565b6001600160a01b0381165f908152600760205260408120546102fe565b5f6060805f805f60606103716107d2565b6103796107ff565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b60606004805461026a90611034565b5f336102f8818585610618565b610401816103fc836001600160a01b03165f9081526020819052604090205490565b61082c565b50565b83421115610446576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886104918c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f6104eb82610860565b90505f6104fa828787876108a7565b9050896001600160a01b0316816001600160a01b03161461055a576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b16602482015260440161043d565b6105658a8a8a610571565b50505050505050505050565b61057e83838360016108d3565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106125781811015610604576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044810183905260640161043d565b61061284848484035f6108d3565b50505050565b6001600160a01b03831661064157604051634b637e8f60e11b81525f600482015260240161043d565b6001600160a01b03821661066a5760405163ec442f0560e01b81525f600482015260240161043d565b61057e8383836109d7565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156106cd57507f000000000000000000000000000000000000000000000000000000000000000046145b156106f757507f000000000000000000000000000000000000000000000000000000000000000090565b610330604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166107c75760405163ec442f0560e01b81525f600482015260240161043d565b61033f5f83836109d7565b60606103307f00000000000000000000000000000000000000000000000000000000000000006005610b16565b60606103307f00000000000000000000000000000000000000000000000000000000000000006006610b16565b6001600160a01b03821661085557604051634b637e8f60e11b81525f600482015260240161043d565b61033f825f836109d7565b5f6102fe61086c610675565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f805f806108b788888888610bbf565b9250925092506108c78282610c87565b50909695505050505050565b6001600160a01b038416610915576040517fe602df050000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038316610957576040517f94280d620000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561061257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109c991815260200190565b60405180910390a350505050565b6001600160a01b038316610a01578060025f8282546109f6919061106c565b90915550610a8a9050565b6001600160a01b0383165f9081526020819052604090205481811015610a6c576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602481018290526044810183905260640161043d565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610aa657600280548290039055610ac4565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610b0991815260200190565b60405180910390a3505050565b606060ff8314610b3057610b2983610d8a565b90506102fe565b818054610b3c90611034565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6890611034565b8015610bb35780601f10610b8a57610100808354040283529160200191610bb3565b820191905f5260205f20905b815481529060010190602001808311610b9657829003601f168201915b505050505090506102fe565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610bf857505f91506003905082610c7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610c49573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610c7457505f925060019150829050610c7d565b92505f91508190505b9450945094915050565b5f826003811115610c9a57610c9a61108b565b03610ca3575050565b6001826003811115610cb757610cb761108b565b03610cee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610d0257610d0261108b565b03610d3c576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b6003826003811115610d5057610d5061108b565b0361033f576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b60605f610d9683610dc7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f8111156102fe576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e476020830184610e07565b9392505050565b80356001600160a01b0381168114610e64575f80fd5b919050565b5f8060408385031215610e7a575f80fd5b610e8383610e4e565b946020939093013593505050565b5f805f60608486031215610ea3575f80fd5b610eac84610e4e565b9250610eba60208501610e4e565b9150604084013590509250925092565b5f60208284031215610eda575f80fd5b610e4782610e4e565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e06020840152610f1f60e084018a610e07565b8381036040850152610f31818a610e07565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b81811015610f8457835183529284019291840191600101610f68565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a031215610fac575f80fd5b610fb588610e4e565b9650610fc360208901610e4e565b95506040880135945060608801359350608088013560ff81168114610fe6575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611014575f80fd5b61101d83610e4e565b915061102b60208401610e4e565b90509250929050565b600181811c9082168061104857607f821691505b60208210810361106657634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102fe57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220cdc2566732702bdfff4697695617b2f6b1e00e79e3174e5aaad85856d16daf8764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806370a0823111610093578063a9059cbb11610063578063a9059cbb146101ea578063cade97aa146101fd578063d505accf14610210578063dd62ed3e14610223575f80fd5b806370a082311461018c5780637ecebe00146101b457806384b0196e146101c757806395d89b41146101e2575f80fd5b806323b872dd116100ce57806323b872dd14610147578063313ce5671461015a5780633644e5151461016f57806340c10f1914610177575f80fd5b806306fdde03146100f4578063095ea7b31461011257806318160ddd14610135575b5f80fd5b6100fc61025b565b6040516101099190610e35565b60405180910390f35b610125610120366004610e69565b6102eb565b6040519015158152602001610109565b6002545b604051908152602001610109565b610125610155366004610e91565b610304565b60085460405160ff9091168152602001610109565b610139610327565b61018a610185366004610e69565b610335565b005b61013961019a366004610eca565b6001600160a01b03165f9081526020819052604090205490565b6101396101c2366004610eca565b610343565b6101cf610360565b6040516101099796959493929190610ee3565b6100fc6103be565b6101256101f8366004610e69565b6103cd565b61018a61020b366004610eca565b6103da565b61018a61021e366004610f96565b610404565b610139610231366004611003565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b60606003805461026a90611034565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611034565b80156102e15780601f106102b8576101008083540402835291602001916102e1565b820191905f5260205f20905b8154815290600101906020018083116102c457829003601f168201915b5050505050905090565b5f336102f8818585610571565b60019150505b92915050565b5f33610311858285610583565b61031c858585610618565b506001949350505050565b5f610330610675565b905090565b61033f828261079e565b5050565b6001600160a01b0381165f908152600760205260408120546102fe565b5f6060805f805f60606103716107d2565b6103796107ff565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b60606004805461026a90611034565b5f336102f8818585610618565b610401816103fc836001600160a01b03165f9081526020819052604090205490565b61082c565b50565b83421115610446576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886104918c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f6104eb82610860565b90505f6104fa828787876108a7565b9050896001600160a01b0316816001600160a01b03161461055a576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b16602482015260440161043d565b6105658a8a8a610571565b50505050505050505050565b61057e83838360016108d3565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106125781811015610604576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044810183905260640161043d565b61061284848484035f6108d3565b50505050565b6001600160a01b03831661064157604051634b637e8f60e11b81525f600482015260240161043d565b6001600160a01b03821661066a5760405163ec442f0560e01b81525f600482015260240161043d565b61057e8383836109d7565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156106cd57507f000000000000000000000000000000000000000000000000000000000000000046145b156106f757507f000000000000000000000000000000000000000000000000000000000000000090565b610330604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166107c75760405163ec442f0560e01b81525f600482015260240161043d565b61033f5f83836109d7565b60606103307f00000000000000000000000000000000000000000000000000000000000000006005610b16565b60606103307f00000000000000000000000000000000000000000000000000000000000000006006610b16565b6001600160a01b03821661085557604051634b637e8f60e11b81525f600482015260240161043d565b61033f825f836109d7565b5f6102fe61086c610675565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f805f806108b788888888610bbf565b9250925092506108c78282610c87565b50909695505050505050565b6001600160a01b038416610915576040517fe602df050000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038316610957576040517f94280d620000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561061257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109c991815260200190565b60405180910390a350505050565b6001600160a01b038316610a01578060025f8282546109f6919061106c565b90915550610a8a9050565b6001600160a01b0383165f9081526020819052604090205481811015610a6c576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602481018290526044810183905260640161043d565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610aa657600280548290039055610ac4565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610b0991815260200190565b60405180910390a3505050565b606060ff8314610b3057610b2983610d8a565b90506102fe565b818054610b3c90611034565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6890611034565b8015610bb35780601f10610b8a57610100808354040283529160200191610bb3565b820191905f5260205f20905b815481529060010190602001808311610b9657829003601f168201915b505050505090506102fe565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610bf857505f91506003905082610c7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610c49573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610c7457505f925060019150829050610c7d565b92505f91508190505b9450945094915050565b5f826003811115610c9a57610c9a61108b565b03610ca3575050565b6001826003811115610cb757610cb761108b565b03610cee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610d0257610d0261108b565b03610d3c576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b6003826003811115610d5057610d5061108b565b0361033f576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b60605f610d9683610dc7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f8111156102fe576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e476020830184610e07565b9392505050565b80356001600160a01b0381168114610e64575f80fd5b919050565b5f8060408385031215610e7a575f80fd5b610e8383610e4e565b946020939093013593505050565b5f805f60608486031215610ea3575f80fd5b610eac84610e4e565b9250610eba60208501610e4e565b9150604084013590509250925092565b5f60208284031215610eda575f80fd5b610e4782610e4e565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e06020840152610f1f60e084018a610e07565b8381036040850152610f31818a610e07565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b81811015610f8457835183529284019291840191600101610f68565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a031215610fac575f80fd5b610fb588610e4e565b9650610fc360208901610e4e565b95506040880135945060608801359350608088013560ff81168114610fe6575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611014575f80fd5b61101d83610e4e565b915061102b60208401610e4e565b90509250929050565b600181811c9082168061104857607f821691505b60208210810361106657634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102fe57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220cdc2566732702bdfff4697695617b2f6b1e00e79e3174e5aaad85856d16daf8764736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "46225": [ + { + "length": 32, + "start": 1749 + } + ], + "46227": [ + { + "length": 32, + "start": 1707 + } + ], + "46229": [ + { + "length": 32, + "start": 1665 + } + ], + "46231": [ + { + "length": 32, + "start": 1830 + } + ], + "46233": [ + { + "length": 32, + "start": 1870 + } + ], + "46236": [ + { + "length": 32, + "start": 2009 + } + ], + "46239": [ + { + "length": 32, + "start": 2054 + } + ] + }, + "inputSourceName": "project/test/mocks/MockERC20.sol", + "devdoc": { + "errors": { + "ECDSAInvalidSignature()": [ + { + "details": "The signature derives the `address(0)`." + } + ], + "ECDSAInvalidSignatureLength(uint256)": [ + { + "details": "The signature has an invalid length." + } + ], + "ECDSAInvalidSignatureS(bytes32)": [ + { + "details": "The signature has an S value that is in the upper half order." + } + ], + "ERC20InsufficientAllowance(address,uint256,uint256)": [ + { + "details": "Indicates a failure with the `spender`’s `allowance`. Used in transfers.", + "params": { + "allowance": "Amount of tokens a `spender` is allowed to operate with.", + "needed": "Minimum amount required to perform a transfer.", + "spender": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC20InsufficientBalance(address,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC20InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC20InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC20InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC20InvalidSpender(address)": [ + { + "details": "Indicates a failure with the `spender` to be approved. Used in approvals.", + "params": { + "spender": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC2612ExpiredSignature(uint256)": [ + { + "details": "Permit deadline has expired." + } + ], + "ERC2612InvalidSigner(address,address)": [ + { + "details": "Mismatched signature." + } + ], + "InvalidAccountNonce(address,uint256)": [ + { + "details": "The nonce used for an `account` is not the expected current nonce." + } + ] + }, + "events": { + "Approval(address,address,uint256)": { + "details": "Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance." + }, + "EIP712DomainChanged()": { + "details": "MAY be emitted to signal that the domain could have changed." + }, + "Transfer(address,address,uint256)": { + "details": "Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero." + } + }, + "kind": "dev", + "methods": { + "DOMAIN_SEPARATOR()": { + "details": "Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}." + }, + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "eip712Domain()": { + "details": "returns the fields and values that describe the domain separator used by this contract for EIP-712 signature." + }, + "name()": { + "details": "Returns the name of the token." + }, + "nonces(address)": { + "details": "Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times." + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "861800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "DOMAIN_SEPARATOR()": "infinite", + "allowance(address,address)": "infinite", + "approve(address,uint256)": "24758", + "balanceOf(address)": "2560", + "decimals()": "2333", + "eip712Domain()": "infinite", + "mint(address,uint256)": "infinite", + "name()": "infinite", + "nonces(address)": "2613", + "nuke(address)": "53133", + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": "infinite", + "symbol()": "infinite", + "totalSupply()": "2348", + "transfer(address,uint256)": "51238", + "transferFrom(address,address,uint256)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"allowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSpender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"ERC2612ExpiredSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC2612InvalidSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentNonce\",\"type\":\"uint256\"}],\"name\":\"InvalidAccountNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortString\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"str\",\"type\":\"string\"}],\"name\":\"StringTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EIP712DomainChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eip712Domain\",\"outputs\":[{\"internalType\":\"bytes1\",\"name\":\"fields\",\"type\":\"bytes1\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"verifyingContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"extensions\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nuke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ECDSAInvalidSignature()\":[{\"details\":\"The signature derives the `address(0)`.\"}],\"ECDSAInvalidSignatureLength(uint256)\":[{\"details\":\"The signature has an invalid length.\"}],\"ECDSAInvalidSignatureS(bytes32)\":[{\"details\":\"The signature has an S value that is in the upper half order.\"}],\"ERC20InsufficientAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\",\"params\":{\"allowance\":\"Amount of tokens a `spender` is allowed to operate with.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC20InsufficientBalance(address,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC20InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC20InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidSpender(address)\":[{\"details\":\"Indicates a failure with the `spender` to be approved. Used in approvals.\",\"params\":{\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC2612ExpiredSignature(uint256)\":[{\"details\":\"Permit deadline has expired.\"}],\"ERC2612InvalidSigner(address,address)\":[{\"details\":\"Mismatched signature.\"}],\"InvalidAccountNonce(address,uint256)\":[{\"details\":\"The nonce used for an `account` is not the expected current nonce.\"}]},\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"EIP712DomainChanged()\":{\"details\":\"MAY be emitted to signal that the domain could have changed.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"eip712Domain()\":{\"details\":\"returns the fields and values that describe the domain separator used by this contract for EIP-712 signature.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/test/mocks/MockERC20.sol\":\"MockERC20\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)\\n\\npragma solidity ^0.8.20;\\n\\ninterface IERC5267 {\\n /**\\n * @dev MAY be emitted to signal that the domain could have changed.\\n */\\n event EIP712DomainChanged();\\n\\n /**\\n * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\\n * signature.\\n */\\n function eip712Domain()\\n external\\n view\\n returns (\\n bytes1 fields,\\n string memory name,\\n string memory version,\\n uint256 chainId,\\n address verifyingContract,\\n bytes32 salt,\\n uint256[] memory extensions\\n );\\n}\\n\",\"keccak256\":\"0x92aa1df62dc3d33f1656d63bede0923e0df0b706ad4137c8b10b0a8fe549fd92\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC20Metadata} from \\\"./extensions/IERC20Metadata.sol\\\";\\nimport {Context} from \\\"../../utils/Context.sol\\\";\\nimport {IERC20Errors} from \\\"../../interfaces/draft-IERC6093.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 *\\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 * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\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 ERC-20\\n * applications.\\n */\\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\\n mapping(address account => uint256) private _balances;\\n\\n mapping(address account => mapping(address spender => 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 * Both values are immutable: they can only be set once during 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 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 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 default value returned by this function, unless\\n * it's 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 returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual 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 `value`.\\n */\\n function transfer(address to, uint256 value) public virtual returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, value);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `value` 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 value) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, value);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Skips emitting an {Approval} event indicating an allowance update. This is not\\n * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\\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 `value`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `value`.\\n */\\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, value);\\n _transfer(from, to, value);\\n return true;\\n }\\n\\n /**\\n * @dev Moves a `value` 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 * NOTE: This function is not virtual, {_update} should be overridden instead.\\n */\\n function _transfer(address from, address to, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC20InvalidSender(address(0));\\n }\\n if (to == address(0)) {\\n revert ERC20InvalidReceiver(address(0));\\n }\\n _update(from, to, value);\\n }\\n\\n /**\\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\\n * this function.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _update(address from, address to, uint256 value) internal virtual {\\n if (from == address(0)) {\\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\\n _totalSupply += value;\\n } else {\\n uint256 fromBalance = _balances[from];\\n if (fromBalance < value) {\\n revert ERC20InsufficientBalance(from, fromBalance, value);\\n }\\n unchecked {\\n // Overflow not possible: value <= fromBalance <= totalSupply.\\n _balances[from] = fromBalance - value;\\n }\\n }\\n\\n if (to == address(0)) {\\n unchecked {\\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\\n _totalSupply -= value;\\n }\\n } else {\\n unchecked {\\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\\n _balances[to] += value;\\n }\\n }\\n\\n emit Transfer(from, to, value);\\n }\\n\\n /**\\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\\n * Relies on the `_update` mechanism\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * NOTE: This function is not virtual, {_update} should be overridden instead.\\n */\\n function _mint(address account, uint256 value) internal {\\n if (account == address(0)) {\\n revert ERC20InvalidReceiver(address(0));\\n }\\n _update(address(0), account, value);\\n }\\n\\n /**\\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\\n * Relies on the `_update` mechanism.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * NOTE: This function is not virtual, {_update} should be overridden instead\\n */\\n function _burn(address account, uint256 value) internal {\\n if (account == address(0)) {\\n revert ERC20InvalidSender(address(0));\\n }\\n _update(account, address(0), value);\\n }\\n\\n /**\\n * @dev Sets `value` 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 * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\\n */\\n function _approve(address owner, address spender, uint256 value) internal {\\n _approve(owner, spender, value, true);\\n }\\n\\n /**\\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\\n *\\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\\n * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\\n * `Approval` event during `transferFrom` operations.\\n *\\n * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\\n * true using the following override:\\n *\\n * ```solidity\\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\\n * super._approve(owner, spender, value, true);\\n * }\\n * ```\\n *\\n * Requirements are the same as {_approve}.\\n */\\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\\n if (owner == address(0)) {\\n revert ERC20InvalidApprover(address(0));\\n }\\n if (spender == address(0)) {\\n revert ERC20InvalidSpender(address(0));\\n }\\n _allowances[owner][spender] = value;\\n if (emitEvent) {\\n emit Approval(owner, spender, value);\\n }\\n }\\n\\n /**\\n * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\\n *\\n * Does not update the allowance value in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Does not emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance < type(uint256).max) {\\n if (currentAllowance < value) {\\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\\n }\\n unchecked {\\n _approve(owner, spender, currentAllowance - value, false);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x41f6b3b9e030561e7896dbef372b499cc8d418a80c3884a4d65a68f2fdc7493a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Permit.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20Permit} from \\\"./IERC20Permit.sol\\\";\\nimport {ERC20} from \\\"../ERC20.sol\\\";\\nimport {ECDSA} from \\\"../../../utils/cryptography/ECDSA.sol\\\";\\nimport {EIP712} from \\\"../../../utils/cryptography/EIP712.sol\\\";\\nimport {Nonces} from \\\"../../../utils/Nonces.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC-20 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 */\\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {\\n bytes32 private constant PERMIT_TYPEHASH =\\n keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n /**\\n * @dev Permit deadline has expired.\\n */\\n error ERC2612ExpiredSignature(uint256 deadline);\\n\\n /**\\n * @dev Mismatched signature.\\n */\\n error ERC2612InvalidSigner(address signer, address owner);\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC-20 token name.\\n */\\n constructor(string memory name) EIP712(name, \\\"1\\\") {}\\n\\n /**\\n * @inheritdoc IERC20Permit\\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 ) public virtual {\\n if (block.timestamp > deadline) {\\n revert ERC2612ExpiredSignature(deadline);\\n }\\n\\n bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSA.recover(hash, v, r, s);\\n if (signer != owner) {\\n revert ERC2612InvalidSigner(signer, owner);\\n }\\n\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @inheritdoc IERC20Permit\\n */\\n function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) {\\n return super.nonces(owner);\\n }\\n\\n /**\\n * @inheritdoc IERC20Permit\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n}\\n\",\"keccak256\":\"0xaa7f0646f49ebe2606eeca169f85c56451bbaeeeb06265fa076a03369a25d1d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\\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\",\"keccak256\":\"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC-20 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 *\\n * ==== Security Considerations\\n *\\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\\n * generally recommended is:\\n *\\n * ```solidity\\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\\n * doThing(..., value);\\n * }\\n *\\n * function doThing(..., uint256 value) public {\\n * token.safeTransferFrom(msg.sender, address(this), value);\\n * ...\\n * }\\n * ```\\n *\\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\\n * {SafeERC20-safeTransferFrom}).\\n *\\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\\n * contracts should have entry points that don't rely on permit.\\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 * CAUTION: See Security Considerations above.\\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\",\"keccak256\":\"0x27dbc90e5136ffe46c04f7596fc2dbcc3acebd8d504da3d93fdb8496e6de04f6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Nonces.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides tracking nonces for addresses. Nonces will only increment.\\n */\\nabstract contract Nonces {\\n /**\\n * @dev The nonce used for an `account` is not the expected current nonce.\\n */\\n error InvalidAccountNonce(address account, uint256 currentNonce);\\n\\n mapping(address account => uint256) private _nonces;\\n\\n /**\\n * @dev Returns the next unused nonce for an address.\\n */\\n function nonces(address owner) public view virtual returns (uint256) {\\n return _nonces[owner];\\n }\\n\\n /**\\n * @dev Consumes a nonce.\\n *\\n * Returns the current value and increments nonce.\\n */\\n function _useNonce(address owner) internal virtual returns (uint256) {\\n // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be\\n // decremented or reset. This guarantees that the nonce never overflows.\\n unchecked {\\n // It is important to do x++ and not ++x here.\\n return _nonces[owner]++;\\n }\\n }\\n\\n /**\\n * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.\\n */\\n function _useCheckedNonce(address owner, uint256 nonce) internal virtual {\\n uint256 current = _useNonce(owner);\\n if (nonce != current) {\\n revert InvalidAccountNonce(owner, current);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0082767004fca261c332e9ad100868327a863a88ef724e844857128845ab350f\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\n\\n// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |\\n// | length | 0x BB |\\ntype ShortString is bytes32;\\n\\n/**\\n * @dev This library provides functions to convert short memory strings\\n * into a `ShortString` type that can be used as an immutable variable.\\n *\\n * Strings of arbitrary length can be optimized using this library if\\n * they are short enough (up to 31 bytes) by packing them with their\\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\\n * fallback mechanism can be used for every other case.\\n *\\n * Usage example:\\n *\\n * ```solidity\\n * contract Named {\\n * using ShortStrings for *;\\n *\\n * ShortString private immutable _name;\\n * string private _nameFallback;\\n *\\n * constructor(string memory contractName) {\\n * _name = contractName.toShortStringWithFallback(_nameFallback);\\n * }\\n *\\n * function name() external view returns (string memory) {\\n * return _name.toStringWithFallback(_nameFallback);\\n * }\\n * }\\n * ```\\n */\\nlibrary ShortStrings {\\n // Used as an identifier for strings longer than 31 bytes.\\n bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\\n\\n error StringTooLong(string str);\\n error InvalidShortString();\\n\\n /**\\n * @dev Encode a string of at most 31 chars into a `ShortString`.\\n *\\n * This will trigger a `StringTooLong` error is the input string is too long.\\n */\\n function toShortString(string memory str) internal pure returns (ShortString) {\\n bytes memory bstr = bytes(str);\\n if (bstr.length > 31) {\\n revert StringTooLong(str);\\n }\\n return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\\n }\\n\\n /**\\n * @dev Decode a `ShortString` back to a \\\"normal\\\" string.\\n */\\n function toString(ShortString sstr) internal pure returns (string memory) {\\n uint256 len = byteLength(sstr);\\n // using `new string(len)` would work locally but is not memory safe.\\n string memory str = new string(32);\\n assembly (\\\"memory-safe\\\") {\\n mstore(str, len)\\n mstore(add(str, 0x20), sstr)\\n }\\n return str;\\n }\\n\\n /**\\n * @dev Return the length of a `ShortString`.\\n */\\n function byteLength(ShortString sstr) internal pure returns (uint256) {\\n uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\\n if (result > 31) {\\n revert InvalidShortString();\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\\n */\\n function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\\n if (bytes(value).length < 32) {\\n return toShortString(value);\\n } else {\\n StorageSlot.getStringSlot(store).value = value;\\n return ShortString.wrap(FALLBACK_SENTINEL);\\n }\\n }\\n\\n /**\\n * @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}.\\n */\\n function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\\n return toString(value);\\n } else {\\n return store;\\n }\\n }\\n\\n /**\\n * @dev Return the length of a string that was encoded to `ShortString` or written to storage using\\n * {toShortStringWithFallback}.\\n *\\n * WARNING: This will return the \\\"byte length\\\" of the string. This may not reflect the actual length in terms of\\n * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\\n */\\n function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\\n return byteLength(value);\\n } else {\\n return bytes(store).length;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1fcf8cceb1a67e6c8512267e780933c4a3f63ef44756e6c818fda79be51c8402\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Math} from \\\"./math/Math.sol\\\";\\nimport {SafeCast} from \\\"./math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n using SafeCast for *;\\n\\n bytes16 private constant HEX_DIGITS = \\\"0123456789abcdef\\\";\\n uint8 private constant ADDRESS_LENGTH = 20;\\n uint256 private constant SPECIAL_CHARS_LOOKUP =\\n (1 << 0x08) | // backspace\\n (1 << 0x09) | // tab\\n (1 << 0x0a) | // newline\\n (1 << 0x0c) | // form feed\\n (1 << 0x0d) | // carriage return\\n (1 << 0x22) | // double quote\\n (1 << 0x5c); // backslash\\n\\n /**\\n * @dev The `value` string doesn't fit in the specified `length`.\\n */\\n error StringsInsufficientHexLength(uint256 value, uint256 length);\\n\\n /**\\n * @dev The string being parsed contains characters that are not in scope of the given base.\\n */\\n error StringsInvalidChar();\\n\\n /**\\n * @dev The string being parsed is not a properly formatted address.\\n */\\n error StringsInvalidAddressFormat();\\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 assembly (\\\"memory-safe\\\") {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n assembly (\\\"memory-safe\\\") {\\n mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toStringSigned(int256 value) internal pure returns (string memory) {\\n return string.concat(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value)));\\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 uint256 localValue = value;\\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] = HEX_DIGITS[localValue & 0xf];\\n localValue >>= 4;\\n }\\n if (localValue != 0) {\\n revert StringsInsufficientHexLength(value, length);\\n }\\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\\n * representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\\n * representation, according to EIP-55.\\n */\\n function toChecksumHexString(address addr) internal pure returns (string memory) {\\n bytes memory buffer = bytes(toHexString(addr));\\n\\n // hash the hex part of buffer (skip length + 2 bytes, length 40)\\n uint256 hashValue;\\n assembly (\\\"memory-safe\\\") {\\n hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\\n }\\n\\n for (uint256 i = 41; i > 1; --i) {\\n // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\\n if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\\n // case shift by xoring with 0x20\\n buffer[i] ^= 0x20;\\n }\\n hashValue >>= 4;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input) internal pure returns (uint256) {\\n return parseUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n uint256 result = 0;\\n for (uint256 i = begin; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 9) return (false, 0);\\n result *= 10;\\n result += chr;\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `int256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input) internal pure returns (int256) {\\n return parseInt(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\\n (bool success, int256 value) = tryParseInt(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\\n * the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\\n return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n uint256 private constant ABS_MIN_INT256 = 2 ** 255;\\n\\n /**\\n * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character or if the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, int256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseIntUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseIntUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, int256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // Check presence of a negative sign.\\n bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n bool positiveSign = sign == bytes1(\\\"+\\\");\\n bool negativeSign = sign == bytes1(\\\"-\\\");\\n uint256 offset = (positiveSign || negativeSign).toUint();\\n\\n (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\\n\\n if (absSuccess && absValue < ABS_MIN_INT256) {\\n return (true, negativeSign ? -int256(absValue) : int256(absValue));\\n } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\\n return (true, type(int256).min);\\n } else return (false, 0);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input) internal pure returns (uint256) {\\n return parseHexUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseHexUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\\n * invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseHexUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseHexUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // skip 0x prefix if present\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 offset = hasPrefix.toUint() * 2;\\n\\n uint256 result = 0;\\n for (uint256 i = begin + offset; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 15) return (false, 0);\\n result *= 16;\\n unchecked {\\n // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\\n // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.\\n result += chr;\\n }\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as an `address`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input) internal pure returns (address) {\\n return parseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\\n (bool success, address value) = tryParseAddress(input, begin, end);\\n if (!success) revert StringsInvalidAddressFormat();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\\n * formatted address. See {parseAddress-string} requirements.\\n */\\n function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\\n return tryParseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\\n * formatted address. See {parseAddress-string-uint256-uint256} requirements.\\n */\\n function tryParseAddress(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, address value) {\\n if (end > bytes(input).length || begin > end) return (false, address(0));\\n\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\\n\\n // check that input is the correct length\\n if (end - begin == expectedLength) {\\n // length guarantees that this does not overflow, and value is at most type(uint160).max\\n (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\\n return (s, address(uint160(v)));\\n } else {\\n return (false, address(0));\\n }\\n }\\n\\n function _tryParseChr(bytes1 chr) private pure returns (uint8) {\\n uint8 value = uint8(chr);\\n\\n // Try to parse `chr`:\\n // - Case 1: [0-9]\\n // - Case 2: [a-f]\\n // - Case 3: [A-F]\\n // - otherwise not supported\\n unchecked {\\n if (value > 47 && value < 58) value -= 48;\\n else if (value > 96 && value < 103) value -= 87;\\n else if (value > 64 && value < 71) value -= 55;\\n else return type(uint8).max;\\n }\\n\\n return value;\\n }\\n\\n /**\\n * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.\\n *\\n * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.\\n *\\n * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of\\n * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode\\n * characters that are not in this range, but other tooling may provide different results.\\n */\\n function escapeJSON(string memory input) internal pure returns (string memory) {\\n bytes memory buffer = bytes(input);\\n bytes memory output = new bytes(2 * buffer.length); // worst case scenario\\n uint256 outputLength = 0;\\n\\n for (uint256 i; i < buffer.length; ++i) {\\n bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));\\n if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {\\n output[outputLength++] = \\\"\\\\\\\\\\\";\\n if (char == 0x08) output[outputLength++] = \\\"b\\\";\\n else if (char == 0x09) output[outputLength++] = \\\"t\\\";\\n else if (char == 0x0a) output[outputLength++] = \\\"n\\\";\\n else if (char == 0x0c) output[outputLength++] = \\\"f\\\";\\n else if (char == 0x0d) output[outputLength++] = \\\"r\\\";\\n else if (char == 0x5c) output[outputLength++] = \\\"\\\\\\\\\\\";\\n else if (char == 0x22) {\\n // solhint-disable-next-line quotes\\n output[outputLength++] = '\\\"';\\n }\\n } else {\\n output[outputLength++] = char;\\n }\\n }\\n // write the actual length and deallocate unused memory\\n assembly (\\\"memory-safe\\\") {\\n mstore(output, outputLength)\\n mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))\\n }\\n\\n return string(output);\\n }\\n\\n /**\\n * @dev Reads a bytes32 from a bytes array without bounds checking.\\n *\\n * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\\n * assembly block as such would prevent some optimizations.\\n */\\n function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\\n // This is not memory safe in the general case, but all calls to this private function are within bounds.\\n assembly (\\\"memory-safe\\\") {\\n value := mload(add(buffer, add(0x20, offset)))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x81c274a60a7ae232ae3dc9ff3a4011b4849a853c13b0832cd3351bb1bb2f0dae\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.20;\\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 }\\n\\n /**\\n * @dev The signature derives the `address(0)`.\\n */\\n error ECDSAInvalidSignature();\\n\\n /**\\n * @dev The signature has an invalid length.\\n */\\n error ECDSAInvalidSignatureLength(uint256 length);\\n\\n /**\\n * @dev The signature has an S value that is in the upper half order.\\n */\\n error ECDSAInvalidSignatureS(bytes32 s);\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\\n * return address(0) without also returning an error description. Errors are documented using an enum (error type)\\n * and a bytes32 providing additional information about the error.\\n *\\n * If no error is returned, then the address can be used for verification purposes.\\n *\\n * The `ecrecover` EVM precompile 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 {MessageHashUtils-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 function tryRecover(\\n bytes32 hash,\\n bytes memory signature\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\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 assembly (\\\"memory-safe\\\") {\\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, bytes32(signature.length));\\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 precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\\n _throwError(error, errorArg);\\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[ERC-2098 short signatures]\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n unchecked {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n // We do not check for an overflow here since the shift operation results in 0 or 1.\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\\n _throwError(error, errorArg);\\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 function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\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, s);\\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, bytes32(0));\\n }\\n\\n return (signer, RecoverError.NoError, bytes32(0));\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\\n */\\n function _throwError(RecoverError error, bytes32 errorArg) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert ECDSAInvalidSignature();\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert ECDSAInvalidSignatureLength(uint256(errorArg));\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert ECDSAInvalidSignatureS(errorArg);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x69f54c02b7d81d505910ec198c11ed4c6a728418a868b906b4a0cf29946fda84\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {MessageHashUtils} from \\\"./MessageHashUtils.sol\\\";\\nimport {ShortStrings, ShortString} from \\\"../ShortStrings.sol\\\";\\nimport {IERC5267} from \\\"../../interfaces/IERC5267.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose\\n * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract\\n * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to\\n * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\\n * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the\\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\\n *\\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n */\\nabstract contract EIP712 is IERC5267 {\\n using ShortStrings for *;\\n\\n bytes32 private constant TYPE_HASH =\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _cachedDomainSeparator;\\n uint256 private immutable _cachedChainId;\\n address private immutable _cachedThis;\\n\\n bytes32 private immutable _hashedName;\\n bytes32 private immutable _hashedVersion;\\n\\n ShortString private immutable _name;\\n ShortString private immutable _version;\\n // slither-disable-next-line constable-states\\n string private _nameFallback;\\n // slither-disable-next-line constable-states\\n string private _versionFallback;\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n _name = name.toShortStringWithFallback(_nameFallback);\\n _version = version.toShortStringWithFallback(_versionFallback);\\n _hashedName = keccak256(bytes(name));\\n _hashedVersion = keccak256(bytes(version));\\n\\n _cachedChainId = block.chainid;\\n _cachedDomainSeparator = _buildDomainSeparator();\\n _cachedThis = address(this);\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\\n return _cachedDomainSeparator;\\n } else {\\n return _buildDomainSeparator();\\n }\\n }\\n\\n function _buildDomainSeparator() private view returns (bytes32) {\\n return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n\\n /**\\n * @inheritdoc IERC5267\\n */\\n function eip712Domain()\\n public\\n view\\n virtual\\n returns (\\n bytes1 fields,\\n string memory name,\\n string memory version,\\n uint256 chainId,\\n address verifyingContract,\\n bytes32 salt,\\n uint256[] memory extensions\\n )\\n {\\n return (\\n hex\\\"0f\\\", // 01111\\n _EIP712Name(),\\n _EIP712Version(),\\n block.chainid,\\n address(this),\\n bytes32(0),\\n new uint256[](0)\\n );\\n }\\n\\n /**\\n * @dev The name parameter for the EIP712 domain.\\n *\\n * NOTE: By default this function reads _name which is an immutable value.\\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function _EIP712Name() internal view returns (string memory) {\\n return _name.toStringWithFallback(_nameFallback);\\n }\\n\\n /**\\n * @dev The version parameter for the EIP712 domain.\\n *\\n * NOTE: By default this function reads _version which is an immutable value.\\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function _EIP712Version() internal view returns (string memory) {\\n return _version.toStringWithFallback(_versionFallback);\\n }\\n}\\n\",\"keccak256\":\"0x0c60057e7351874f086db8dc9291b7ada9ad62cb7725befd2991430d04a74572\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Strings} from \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\\n *\\n * The library provides methods for generating a hash of a message that conforms to the\\n * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\\n * specifications.\\n */\\nlibrary MessageHashUtils {\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x45` (`personal_sign` messages).\\n *\\n * The digest is calculated by prefixing a bytes32 `messageHash` with\\n * `\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\"` and hashing the result. It corresponds with the\\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\\n *\\n * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\\n * keccak256, although any bytes32 value can be safely used because the final digest will\\n * be re-hashed.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\") // 32 is the bytes-length of messageHash\\n mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\\n digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\\n }\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x45` (`personal_sign` messages).\\n *\\n * The digest is calculated by prefixing an arbitrary `message` with\\n * `\\\"\\\\x19Ethereum Signed Message:\\\\n\\\" + len(message)` and hashing the result. It corresponds with the\\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\\n return\\n keccak256(bytes.concat(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", bytes(Strings.toString(message.length)), message));\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x00` (data with intended validator).\\n *\\n * The digest is calculated by prefixing an arbitrary `data` with `\\\"\\\\x19\\\\x00\\\"` and the intended\\n * `validator` address. Then hashing the result.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(hex\\\"19_00\\\", validator, data));\\n }\\n\\n /**\\n * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.\\n */\\n function toDataWithIntendedValidatorHash(\\n address validator,\\n bytes32 messageHash\\n ) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, hex\\\"19_00\\\")\\n mstore(0x02, shl(96, validator))\\n mstore(0x16, messageHash)\\n digest := keccak256(0x00, 0x36)\\n }\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).\\n *\\n * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\\n * `\\\\x19\\\\x01` and hashing the result. It corresponds to the hash signed by the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n mstore(ptr, hex\\\"19_01\\\")\\n mstore(add(ptr, 0x02), domainSeparator)\\n mstore(add(ptr, 0x22), structHash)\\n digest := keccak256(ptr, 0x42)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x26670fef37d4adf55570ba78815eec5f31cb017e708f61886add4fc4da665631\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\\n }\\n }\\n\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a > b, a, b);\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a < b, a, b);\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // Formula from the \\\"Bit Twiddling Hacks\\\" by Sean Eron Anderson.\\n // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\\n // taking advantage of the most significant (or \\\"sign\\\" bit) in two's complement representation.\\n // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\\n // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\\n int256 mask = n >> 255;\\n\\n // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\\n return uint256((n + mask) ^ mask);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\"},\"project/test/mocks/MockERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {ERC20Permit} from \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol\\\";\\n\\ncontract MockERC20 is ERC20Permit {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n uint8 private _decimals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor(string memory symbol, uint8 decimals_) ERC20(symbol, symbol) ERC20Permit(symbol) {\\n _decimals = decimals_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function mint(address to, uint256 amount) external {\\n _mint(to, amount);\\n }\\n\\n function nuke(address owner) external {\\n _burn(owner, balanceOf(owner));\\n }\\n\\n function decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\\n\\ncontract MockERC20Blacklist is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n mapping(address account => bool isBlacklisted) public isBlacklisted;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n error Blacklisted(address);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"BLACK\\\", 6) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function setBlacklisted(address account, bool blacklisted) external {\\n isBlacklisted[account] = blacklisted;\\n }\\n\\n function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\\n _checkBlacklist(from);\\n _checkBlacklist(to);\\n return super.transferFrom(from, to, amount);\\n }\\n\\n function _checkBlacklist(address addr) internal view {\\n if (isBlacklisted[addr]) {\\n revert Blacklisted(addr);\\n }\\n }\\n}\\n\\n\\ncontract MockERC20VoidReturn is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"VOID\\\", 11) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\\n super.transferFrom(from, to, amount);\\n assembly {\\n return(0, 0) // return void\\n }\\n }\\n}\\n\\n\\ncontract MockERC20FalseReturn is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"FALSE\\\", 13) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function transferFrom(address, address, uint256) public pure override returns (bool) {\\n return false; // return false instead of revert\\n }\\n}\\n\",\"keccak256\":\"0xf418c9e3b57c817e2ae0085dacf3b79d531ff5e4c5d51634c09d0981d834472b\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 38520, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 38526, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 38528, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 38530, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 38532, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + }, + { + "astId": 46241, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_nameFallback", + "offset": 0, + "slot": "5", + "type": "t_string_storage" + }, + { + "astId": 46243, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_versionFallback", + "offset": 0, + "slot": "6", + "type": "t_string_storage" + }, + { + "astId": 43769, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_nonces", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 76079, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_decimals", + "offset": 0, + "slot": "8", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "argsData": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000034441490000000000000000000000000000000000000000000000000000000000", + "transaction": { + "hash": "0xa7e918b75d383112b139bc59286381d09f38be7dabbdaedc449ff09e0b2f7271", + "nonce": "0x12", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x518b91964408f02a8db777444c0294b1e1f38fa5705c964163582eb2d09d0e0e", + "blockNumber": "0xaa56bb", + "transactionIndex": "0x5c" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/MockUSDC.json b/contracts/deployments/sepolia/MockUSDC.json new file mode 100644 index 000000000..53b2a9b52 --- /dev/null +++ b/contracts/deployments/sepolia/MockUSDC.json @@ -0,0 +1,916 @@ +{ + "address": "0xd3322b29a7bdee707d1684676f149bf41aa3422f", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "ERC2612ExpiredSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC2612InvalidSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + } + ], + "name": "InvalidAccountNonce", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nuke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "MockERC20", + "sourceName": "test/mocks/MockERC20.sol", + "bytecode": "0x610160604052348015610010575f80fd5b5060405161155238038061155283398101604081905261002f916101d6565b6040805180820190915260018152603160f81b602082015282908190818060036100598282610315565b5060046100668282610315565b5061007691508390506005610135565b61012052610085816006610135565b61014052815160208084019190912060e052815190820120610100524660a05261011160e05161010051604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201529081019290925260608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b60805250503060c052506008805460ff191660ff929092169190911790555061042c565b5f6020835110156101505761014983610167565b9050610161565b8161015b8482610315565b5060ff90505b92915050565b5f80829050601f8151111561019a578260405163305a27a960e01b815260040161019191906103d4565b60405180910390fd5b80516101a582610409565b179392505050565b634e487b7160e01b5f52604160045260245ffd5b805160ff811681146101d1575f80fd5b919050565b5f80604083850312156101e7575f80fd5b82516001600160401b03808211156101fd575f80fd5b818501915085601f830112610210575f80fd5b815181811115610222576102226101ad565b604051601f8201601f19908116603f0116810190838211818310171561024a5761024a6101ad565b81604052828152886020848701011115610262575f80fd5b8260208601602083015e5f602084830101528096505050505050610288602084016101c1565b90509250929050565b600181811c908216806102a557607f821691505b6020821081036102c357634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561031057805f5260205f20601f840160051c810160208510156102ee5750805b601f840160051c820191505b8181101561030d575f81556001016102fa565b50505b505050565b81516001600160401b0381111561032e5761032e6101ad565b6103428161033c8454610291565b846102c9565b602080601f831160018114610375575f841561035e5750858301515b5f19600386901b1c1916600185901b1785556103cc565b5f85815260208120601f198616915b828110156103a357888601518255948401946001909101908401610384565b50858210156103c057878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b805160208083015191908110156102c3575f1960209190910360031b1b16919050565b60805160a05160c05160e0516101005161012051610140516110d561047d5f395f61080601525f6107d901525f61074e01525f61072601525f61068101525f6106ab01525f6106d501526110d55ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806370a0823111610093578063a9059cbb11610063578063a9059cbb146101ea578063cade97aa146101fd578063d505accf14610210578063dd62ed3e14610223575f80fd5b806370a082311461018c5780637ecebe00146101b457806384b0196e146101c757806395d89b41146101e2575f80fd5b806323b872dd116100ce57806323b872dd14610147578063313ce5671461015a5780633644e5151461016f57806340c10f1914610177575f80fd5b806306fdde03146100f4578063095ea7b31461011257806318160ddd14610135575b5f80fd5b6100fc61025b565b6040516101099190610e35565b60405180910390f35b610125610120366004610e69565b6102eb565b6040519015158152602001610109565b6002545b604051908152602001610109565b610125610155366004610e91565b610304565b60085460405160ff9091168152602001610109565b610139610327565b61018a610185366004610e69565b610335565b005b61013961019a366004610eca565b6001600160a01b03165f9081526020819052604090205490565b6101396101c2366004610eca565b610343565b6101cf610360565b6040516101099796959493929190610ee3565b6100fc6103be565b6101256101f8366004610e69565b6103cd565b61018a61020b366004610eca565b6103da565b61018a61021e366004610f96565b610404565b610139610231366004611003565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b60606003805461026a90611034565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611034565b80156102e15780601f106102b8576101008083540402835291602001916102e1565b820191905f5260205f20905b8154815290600101906020018083116102c457829003601f168201915b5050505050905090565b5f336102f8818585610571565b60019150505b92915050565b5f33610311858285610583565b61031c858585610618565b506001949350505050565b5f610330610675565b905090565b61033f828261079e565b5050565b6001600160a01b0381165f908152600760205260408120546102fe565b5f6060805f805f60606103716107d2565b6103796107ff565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b60606004805461026a90611034565b5f336102f8818585610618565b610401816103fc836001600160a01b03165f9081526020819052604090205490565b61082c565b50565b83421115610446576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886104918c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f6104eb82610860565b90505f6104fa828787876108a7565b9050896001600160a01b0316816001600160a01b03161461055a576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b16602482015260440161043d565b6105658a8a8a610571565b50505050505050505050565b61057e83838360016108d3565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106125781811015610604576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044810183905260640161043d565b61061284848484035f6108d3565b50505050565b6001600160a01b03831661064157604051634b637e8f60e11b81525f600482015260240161043d565b6001600160a01b03821661066a5760405163ec442f0560e01b81525f600482015260240161043d565b61057e8383836109d7565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156106cd57507f000000000000000000000000000000000000000000000000000000000000000046145b156106f757507f000000000000000000000000000000000000000000000000000000000000000090565b610330604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166107c75760405163ec442f0560e01b81525f600482015260240161043d565b61033f5f83836109d7565b60606103307f00000000000000000000000000000000000000000000000000000000000000006005610b16565b60606103307f00000000000000000000000000000000000000000000000000000000000000006006610b16565b6001600160a01b03821661085557604051634b637e8f60e11b81525f600482015260240161043d565b61033f825f836109d7565b5f6102fe61086c610675565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f805f806108b788888888610bbf565b9250925092506108c78282610c87565b50909695505050505050565b6001600160a01b038416610915576040517fe602df050000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038316610957576040517f94280d620000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561061257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109c991815260200190565b60405180910390a350505050565b6001600160a01b038316610a01578060025f8282546109f6919061106c565b90915550610a8a9050565b6001600160a01b0383165f9081526020819052604090205481811015610a6c576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602481018290526044810183905260640161043d565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610aa657600280548290039055610ac4565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610b0991815260200190565b60405180910390a3505050565b606060ff8314610b3057610b2983610d8a565b90506102fe565b818054610b3c90611034565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6890611034565b8015610bb35780601f10610b8a57610100808354040283529160200191610bb3565b820191905f5260205f20905b815481529060010190602001808311610b9657829003601f168201915b505050505090506102fe565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610bf857505f91506003905082610c7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610c49573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610c7457505f925060019150829050610c7d565b92505f91508190505b9450945094915050565b5f826003811115610c9a57610c9a61108b565b03610ca3575050565b6001826003811115610cb757610cb761108b565b03610cee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610d0257610d0261108b565b03610d3c576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b6003826003811115610d5057610d5061108b565b0361033f576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b60605f610d9683610dc7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f8111156102fe576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e476020830184610e07565b9392505050565b80356001600160a01b0381168114610e64575f80fd5b919050565b5f8060408385031215610e7a575f80fd5b610e8383610e4e565b946020939093013593505050565b5f805f60608486031215610ea3575f80fd5b610eac84610e4e565b9250610eba60208501610e4e565b9150604084013590509250925092565b5f60208284031215610eda575f80fd5b610e4782610e4e565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e06020840152610f1f60e084018a610e07565b8381036040850152610f31818a610e07565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b81811015610f8457835183529284019291840191600101610f68565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a031215610fac575f80fd5b610fb588610e4e565b9650610fc360208901610e4e565b95506040880135945060608801359350608088013560ff81168114610fe6575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611014575f80fd5b61101d83610e4e565b915061102b60208401610e4e565b90509250929050565b600181811c9082168061104857607f821691505b60208210810361106657634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102fe57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220cdc2566732702bdfff4697695617b2f6b1e00e79e3174e5aaad85856d16daf8764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c806370a0823111610093578063a9059cbb11610063578063a9059cbb146101ea578063cade97aa146101fd578063d505accf14610210578063dd62ed3e14610223575f80fd5b806370a082311461018c5780637ecebe00146101b457806384b0196e146101c757806395d89b41146101e2575f80fd5b806323b872dd116100ce57806323b872dd14610147578063313ce5671461015a5780633644e5151461016f57806340c10f1914610177575f80fd5b806306fdde03146100f4578063095ea7b31461011257806318160ddd14610135575b5f80fd5b6100fc61025b565b6040516101099190610e35565b60405180910390f35b610125610120366004610e69565b6102eb565b6040519015158152602001610109565b6002545b604051908152602001610109565b610125610155366004610e91565b610304565b60085460405160ff9091168152602001610109565b610139610327565b61018a610185366004610e69565b610335565b005b61013961019a366004610eca565b6001600160a01b03165f9081526020819052604090205490565b6101396101c2366004610eca565b610343565b6101cf610360565b6040516101099796959493929190610ee3565b6100fc6103be565b6101256101f8366004610e69565b6103cd565b61018a61020b366004610eca565b6103da565b61018a61021e366004610f96565b610404565b610139610231366004611003565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b60606003805461026a90611034565b80601f016020809104026020016040519081016040528092919081815260200182805461029690611034565b80156102e15780601f106102b8576101008083540402835291602001916102e1565b820191905f5260205f20905b8154815290600101906020018083116102c457829003601f168201915b5050505050905090565b5f336102f8818585610571565b60019150505b92915050565b5f33610311858285610583565b61031c858585610618565b506001949350505050565b5f610330610675565b905090565b61033f828261079e565b5050565b6001600160a01b0381165f908152600760205260408120546102fe565b5f6060805f805f60606103716107d2565b6103796107ff565b604080515f808252602082019092527f0f000000000000000000000000000000000000000000000000000000000000009b939a50919850469750309650945092509050565b60606004805461026a90611034565b5f336102f8818585610618565b610401816103fc836001600160a01b03165f9081526020819052604090205490565b61082c565b50565b83421115610446576040517f62791302000000000000000000000000000000000000000000000000000000008152600481018590526024015b60405180910390fd5b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886104918c6001600160a01b03165f90815260076020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f6104eb82610860565b90505f6104fa828787876108a7565b9050896001600160a01b0316816001600160a01b03161461055a576040517f4b800e460000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301528b16602482015260440161043d565b6105658a8a8a610571565b50505050505050505050565b61057e83838360016108d3565b505050565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198110156106125781811015610604576040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018290526044810183905260640161043d565b61061284848484035f6108d3565b50505050565b6001600160a01b03831661064157604051634b637e8f60e11b81525f600482015260240161043d565b6001600160a01b03821661066a5760405163ec442f0560e01b81525f600482015260240161043d565b61057e8383836109d7565b5f306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156106cd57507f000000000000000000000000000000000000000000000000000000000000000046145b156106f757507f000000000000000000000000000000000000000000000000000000000000000090565b610330604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a08201525f9060c00160405160208183030381529060405280519060200120905090565b6001600160a01b0382166107c75760405163ec442f0560e01b81525f600482015260240161043d565b61033f5f83836109d7565b60606103307f00000000000000000000000000000000000000000000000000000000000000006005610b16565b60606103307f00000000000000000000000000000000000000000000000000000000000000006006610b16565b6001600160a01b03821661085557604051634b637e8f60e11b81525f600482015260240161043d565b61033f825f836109d7565b5f6102fe61086c610675565b836040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b5f805f806108b788888888610bbf565b9250925092506108c78282610c87565b50909695505050505050565b6001600160a01b038416610915576040517fe602df050000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038316610957576040517f94280d620000000000000000000000000000000000000000000000000000000081525f600482015260240161043d565b6001600160a01b038085165f908152600160209081526040808320938716835292905220829055801561061257826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516109c991815260200190565b60405180910390a350505050565b6001600160a01b038316610a01578060025f8282546109f6919061106c565b90915550610a8a9050565b6001600160a01b0383165f9081526020819052604090205481811015610a6c576040517fe450d38c0000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602481018290526044810183905260640161043d565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b038216610aa657600280548290039055610ac4565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051610b0991815260200190565b60405180910390a3505050565b606060ff8314610b3057610b2983610d8a565b90506102fe565b818054610b3c90611034565b80601f0160208091040260200160405190810160405280929190818152602001828054610b6890611034565b8015610bb35780601f10610b8a57610100808354040283529160200191610bb3565b820191905f5260205f20905b815481529060010190602001808311610b9657829003601f168201915b505050505090506102fe565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610bf857505f91506003905082610c7d565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610c49573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610c7457505f925060019150829050610c7d565b92505f91508190505b9450945094915050565b5f826003811115610c9a57610c9a61108b565b03610ca3575050565b6001826003811115610cb757610cb761108b565b03610cee576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002826003811115610d0257610d0261108b565b03610d3c576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b6003826003811115610d5057610d5061108b565b0361033f576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240161043d565b60605f610d9683610dc7565b6040805160208082528183019092529192505f91906020820181803683375050509182525060208101929092525090565b5f60ff8216601f8111156102fe576040517fb3512b0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610e476020830184610e07565b9392505050565b80356001600160a01b0381168114610e64575f80fd5b919050565b5f8060408385031215610e7a575f80fd5b610e8383610e4e565b946020939093013593505050565b5f805f60608486031215610ea3575f80fd5b610eac84610e4e565b9250610eba60208501610e4e565b9150604084013590509250925092565b5f60208284031215610eda575f80fd5b610e4782610e4e565b7fff00000000000000000000000000000000000000000000000000000000000000881681525f602060e06020840152610f1f60e084018a610e07565b8381036040850152610f31818a610e07565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825260208088019350909101905f5b81811015610f8457835183529284019291840191600101610f68565b50909c9b505050505050505050505050565b5f805f805f805f60e0888a031215610fac575f80fd5b610fb588610e4e565b9650610fc360208901610e4e565b95506040880135945060608801359350608088013560ff81168114610fe6575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611014575f80fd5b61101d83610e4e565b915061102b60208401610e4e565b90509250929050565b600181811c9082168061104857607f821691505b60208210810361106657634e487b7160e01b5f52602260045260245ffd5b50919050565b808201808211156102fe57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfea2646970667358221220cdc2566732702bdfff4697695617b2f6b1e00e79e3174e5aaad85856d16daf8764736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "46225": [ + { + "length": 32, + "start": 1749 + } + ], + "46227": [ + { + "length": 32, + "start": 1707 + } + ], + "46229": [ + { + "length": 32, + "start": 1665 + } + ], + "46231": [ + { + "length": 32, + "start": 1830 + } + ], + "46233": [ + { + "length": 32, + "start": 1870 + } + ], + "46236": [ + { + "length": 32, + "start": 2009 + } + ], + "46239": [ + { + "length": 32, + "start": 2054 + } + ] + }, + "inputSourceName": "project/test/mocks/MockERC20.sol", + "devdoc": { + "errors": { + "ECDSAInvalidSignature()": [ + { + "details": "The signature derives the `address(0)`." + } + ], + "ECDSAInvalidSignatureLength(uint256)": [ + { + "details": "The signature has an invalid length." + } + ], + "ECDSAInvalidSignatureS(bytes32)": [ + { + "details": "The signature has an S value that is in the upper half order." + } + ], + "ERC20InsufficientAllowance(address,uint256,uint256)": [ + { + "details": "Indicates a failure with the `spender`’s `allowance`. Used in transfers.", + "params": { + "allowance": "Amount of tokens a `spender` is allowed to operate with.", + "needed": "Minimum amount required to perform a transfer.", + "spender": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC20InsufficientBalance(address,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC20InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC20InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC20InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC20InvalidSpender(address)": [ + { + "details": "Indicates a failure with the `spender` to be approved. Used in approvals.", + "params": { + "spender": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC2612ExpiredSignature(uint256)": [ + { + "details": "Permit deadline has expired." + } + ], + "ERC2612InvalidSigner(address,address)": [ + { + "details": "Mismatched signature." + } + ], + "InvalidAccountNonce(address,uint256)": [ + { + "details": "The nonce used for an `account` is not the expected current nonce." + } + ] + }, + "events": { + "Approval(address,address,uint256)": { + "details": "Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance." + }, + "EIP712DomainChanged()": { + "details": "MAY be emitted to signal that the domain could have changed." + }, + "Transfer(address,address,uint256)": { + "details": "Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero." + } + }, + "kind": "dev", + "methods": { + "DOMAIN_SEPARATOR()": { + "details": "Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}." + }, + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "eip712Domain()": { + "details": "returns the fields and values that describe the domain separator used by this contract for EIP-712 signature." + }, + "name()": { + "details": "Returns the name of the token." + }, + "nonces(address)": { + "details": "Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times." + }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "861800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "DOMAIN_SEPARATOR()": "infinite", + "allowance(address,address)": "infinite", + "approve(address,uint256)": "24758", + "balanceOf(address)": "2560", + "decimals()": "2333", + "eip712Domain()": "infinite", + "mint(address,uint256)": "infinite", + "name()": "infinite", + "nonces(address)": "2613", + "nuke(address)": "53133", + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": "infinite", + "symbol()": "infinite", + "totalSupply()": "2348", + "transfer(address,uint256)": "51238", + "transferFrom(address,address,uint256)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"allowance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientAllowance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"}],\"name\":\"ERC20InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC20InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"ERC20InvalidSpender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"ERC2612ExpiredSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC2612InvalidSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"currentNonce\",\"type\":\"uint256\"}],\"name\":\"InvalidAccountNonce\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidShortString\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"str\",\"type\":\"string\"}],\"name\":\"StringTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EIP712DomainChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eip712Domain\",\"outputs\":[{\"internalType\":\"bytes1\",\"name\":\"fields\",\"type\":\"bytes1\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"verifyingContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"extensions\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nuke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ECDSAInvalidSignature()\":[{\"details\":\"The signature derives the `address(0)`.\"}],\"ECDSAInvalidSignatureLength(uint256)\":[{\"details\":\"The signature has an invalid length.\"}],\"ECDSAInvalidSignatureS(bytes32)\":[{\"details\":\"The signature has an S value that is in the upper half order.\"}],\"ERC20InsufficientAllowance(address,uint256,uint256)\":[{\"details\":\"Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\",\"params\":{\"allowance\":\"Amount of tokens a `spender` is allowed to operate with.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC20InsufficientBalance(address,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC20InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC20InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC20InvalidSpender(address)\":[{\"details\":\"Indicates a failure with the `spender` to be approved. Used in approvals.\",\"params\":{\"spender\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC2612ExpiredSignature(uint256)\":[{\"details\":\"Permit deadline has expired.\"}],\"ERC2612InvalidSigner(address,address)\":[{\"details\":\"Mismatched signature.\"}],\"InvalidAccountNonce(address,uint256)\":[{\"details\":\"The nonce used for an `account` is not the expected current nonce.\"}]},\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"EIP712DomainChanged()\":{\"details\":\"MAY be emitted to signal that the domain could have changed.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `value` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"eip712Domain()\":{\"details\":\"returns the fields and values that describe the domain separator used by this contract for EIP-712 signature.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `value`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Skips emitting an {Approval} event indicating an allowance update. This is not required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `value`. - the caller must have allowance for ``from``'s tokens of at least `value`.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/test/mocks/MockERC20.sol\":\"MockERC20\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC5267.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)\\n\\npragma solidity ^0.8.20;\\n\\ninterface IERC5267 {\\n /**\\n * @dev MAY be emitted to signal that the domain could have changed.\\n */\\n event EIP712DomainChanged();\\n\\n /**\\n * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712\\n * signature.\\n */\\n function eip712Domain()\\n external\\n view\\n returns (\\n bytes1 fields,\\n string memory name,\\n string memory version,\\n uint256 chainId,\\n address verifyingContract,\\n bytes32 salt,\\n uint256[] memory extensions\\n );\\n}\\n\",\"keccak256\":\"0x92aa1df62dc3d33f1656d63bede0923e0df0b706ad4137c8b10b0a8fe549fd92\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC20Metadata} from \\\"./extensions/IERC20Metadata.sol\\\";\\nimport {Context} from \\\"../../utils/Context.sol\\\";\\nimport {IERC20Errors} from \\\"../../interfaces/draft-IERC6093.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 *\\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 * The default value of {decimals} is 18. To change this, you should override\\n * this function so it returns a different value.\\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 ERC-20\\n * applications.\\n */\\nabstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {\\n mapping(address account => uint256) private _balances;\\n\\n mapping(address account => mapping(address spender => 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 * Both values are immutable: they can only be set once during 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 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 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 default value returned by this function, unless\\n * it's 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 returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual 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 `value`.\\n */\\n function transfer(address to, uint256 value) public virtual returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, value);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `value` 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 value) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, value);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Skips emitting an {Approval} event indicating an allowance update. This is not\\n * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\\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 `value`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `value`.\\n */\\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, value);\\n _transfer(from, to, value);\\n return true;\\n }\\n\\n /**\\n * @dev Moves a `value` 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 * NOTE: This function is not virtual, {_update} should be overridden instead.\\n */\\n function _transfer(address from, address to, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC20InvalidSender(address(0));\\n }\\n if (to == address(0)) {\\n revert ERC20InvalidReceiver(address(0));\\n }\\n _update(from, to, value);\\n }\\n\\n /**\\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\\n * this function.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _update(address from, address to, uint256 value) internal virtual {\\n if (from == address(0)) {\\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\\n _totalSupply += value;\\n } else {\\n uint256 fromBalance = _balances[from];\\n if (fromBalance < value) {\\n revert ERC20InsufficientBalance(from, fromBalance, value);\\n }\\n unchecked {\\n // Overflow not possible: value <= fromBalance <= totalSupply.\\n _balances[from] = fromBalance - value;\\n }\\n }\\n\\n if (to == address(0)) {\\n unchecked {\\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\\n _totalSupply -= value;\\n }\\n } else {\\n unchecked {\\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\\n _balances[to] += value;\\n }\\n }\\n\\n emit Transfer(from, to, value);\\n }\\n\\n /**\\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\\n * Relies on the `_update` mechanism\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * NOTE: This function is not virtual, {_update} should be overridden instead.\\n */\\n function _mint(address account, uint256 value) internal {\\n if (account == address(0)) {\\n revert ERC20InvalidReceiver(address(0));\\n }\\n _update(address(0), account, value);\\n }\\n\\n /**\\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\\n * Relies on the `_update` mechanism.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * NOTE: This function is not virtual, {_update} should be overridden instead\\n */\\n function _burn(address account, uint256 value) internal {\\n if (account == address(0)) {\\n revert ERC20InvalidSender(address(0));\\n }\\n _update(account, address(0), value);\\n }\\n\\n /**\\n * @dev Sets `value` 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 * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\\n */\\n function _approve(address owner, address spender, uint256 value) internal {\\n _approve(owner, spender, value, true);\\n }\\n\\n /**\\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\\n *\\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\\n * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any\\n * `Approval` event during `transferFrom` operations.\\n *\\n * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to\\n * true using the following override:\\n *\\n * ```solidity\\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\\n * super._approve(owner, spender, value, true);\\n * }\\n * ```\\n *\\n * Requirements are the same as {_approve}.\\n */\\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\\n if (owner == address(0)) {\\n revert ERC20InvalidApprover(address(0));\\n }\\n if (spender == address(0)) {\\n revert ERC20InvalidSpender(address(0));\\n }\\n _allowances[owner][spender] = value;\\n if (emitEvent) {\\n emit Approval(owner, spender, value);\\n }\\n }\\n\\n /**\\n * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\\n *\\n * Does not update the allowance value in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Does not emit an {Approval} event.\\n */\\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance < type(uint256).max) {\\n if (currentAllowance < value) {\\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\\n }\\n unchecked {\\n _approve(owner, spender, currentAllowance - value, false);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x41f6b3b9e030561e7896dbef372b499cc8d418a80c3884a4d65a68f2fdc7493a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC20Permit.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20Permit} from \\\"./IERC20Permit.sol\\\";\\nimport {ERC20} from \\\"../ERC20.sol\\\";\\nimport {ECDSA} from \\\"../../../utils/cryptography/ECDSA.sol\\\";\\nimport {EIP712} from \\\"../../../utils/cryptography/EIP712.sol\\\";\\nimport {Nonces} from \\\"../../../utils/Nonces.sol\\\";\\n\\n/**\\n * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC-20 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 */\\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {\\n bytes32 private constant PERMIT_TYPEHASH =\\n keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\");\\n\\n /**\\n * @dev Permit deadline has expired.\\n */\\n error ERC2612ExpiredSignature(uint256 deadline);\\n\\n /**\\n * @dev Mismatched signature.\\n */\\n error ERC2612InvalidSigner(address signer, address owner);\\n\\n /**\\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\\\"1\\\"`.\\n *\\n * It's a good idea to use the same `name` that is defined as the ERC-20 token name.\\n */\\n constructor(string memory name) EIP712(name, \\\"1\\\") {}\\n\\n /**\\n * @inheritdoc IERC20Permit\\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 ) public virtual {\\n if (block.timestamp > deadline) {\\n revert ERC2612ExpiredSignature(deadline);\\n }\\n\\n bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\\n\\n bytes32 hash = _hashTypedDataV4(structHash);\\n\\n address signer = ECDSA.recover(hash, v, r, s);\\n if (signer != owner) {\\n revert ERC2612InvalidSigner(signer, owner);\\n }\\n\\n _approve(owner, spender, value);\\n }\\n\\n /**\\n * @inheritdoc IERC20Permit\\n */\\n function nonces(address owner) public view virtual override(IERC20Permit, Nonces) returns (uint256) {\\n return super.nonces(owner);\\n }\\n\\n /**\\n * @inheritdoc IERC20Permit\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view virtual returns (bytes32) {\\n return _domainSeparatorV4();\\n }\\n}\\n\",\"keccak256\":\"0xaa7f0646f49ebe2606eeca169f85c56451bbaeeeb06265fa076a03369a25d1d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\\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\",\"keccak256\":\"0x70f2f713b13b7ce4610bcd0ac9fec0f3cc43693b043abcb8dc40a42a726eb330\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC-20 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 *\\n * ==== Security Considerations\\n *\\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\\n * generally recommended is:\\n *\\n * ```solidity\\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\\n * doThing(..., value);\\n * }\\n *\\n * function doThing(..., uint256 value) public {\\n * token.safeTransferFrom(msg.sender, address(this), value);\\n * ...\\n * }\\n * ```\\n *\\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\\n * {SafeERC20-safeTransferFrom}).\\n *\\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\\n * contracts should have entry points that don't rely on permit.\\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 * CAUTION: See Security Considerations above.\\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\",\"keccak256\":\"0x27dbc90e5136ffe46c04f7596fc2dbcc3acebd8d504da3d93fdb8496e6de04f6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Nonces.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Nonces.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides tracking nonces for addresses. Nonces will only increment.\\n */\\nabstract contract Nonces {\\n /**\\n * @dev The nonce used for an `account` is not the expected current nonce.\\n */\\n error InvalidAccountNonce(address account, uint256 currentNonce);\\n\\n mapping(address account => uint256) private _nonces;\\n\\n /**\\n * @dev Returns the next unused nonce for an address.\\n */\\n function nonces(address owner) public view virtual returns (uint256) {\\n return _nonces[owner];\\n }\\n\\n /**\\n * @dev Consumes a nonce.\\n *\\n * Returns the current value and increments nonce.\\n */\\n function _useNonce(address owner) internal virtual returns (uint256) {\\n // For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be\\n // decremented or reset. This guarantees that the nonce never overflows.\\n unchecked {\\n // It is important to do x++ and not ++x here.\\n return _nonces[owner]++;\\n }\\n }\\n\\n /**\\n * @dev Same as {_useNonce} but checking that `nonce` is the next valid for `owner`.\\n */\\n function _useCheckedNonce(address owner, uint256 nonce) internal virtual {\\n uint256 current = _useNonce(owner);\\n if (nonce != current) {\\n revert InvalidAccountNonce(owner, current);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0082767004fca261c332e9ad100868327a863a88ef724e844857128845ab350f\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/ShortStrings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\n\\n// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |\\n// | length | 0x BB |\\ntype ShortString is bytes32;\\n\\n/**\\n * @dev This library provides functions to convert short memory strings\\n * into a `ShortString` type that can be used as an immutable variable.\\n *\\n * Strings of arbitrary length can be optimized using this library if\\n * they are short enough (up to 31 bytes) by packing them with their\\n * length (1 byte) in a single EVM word (32 bytes). Additionally, a\\n * fallback mechanism can be used for every other case.\\n *\\n * Usage example:\\n *\\n * ```solidity\\n * contract Named {\\n * using ShortStrings for *;\\n *\\n * ShortString private immutable _name;\\n * string private _nameFallback;\\n *\\n * constructor(string memory contractName) {\\n * _name = contractName.toShortStringWithFallback(_nameFallback);\\n * }\\n *\\n * function name() external view returns (string memory) {\\n * return _name.toStringWithFallback(_nameFallback);\\n * }\\n * }\\n * ```\\n */\\nlibrary ShortStrings {\\n // Used as an identifier for strings longer than 31 bytes.\\n bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF;\\n\\n error StringTooLong(string str);\\n error InvalidShortString();\\n\\n /**\\n * @dev Encode a string of at most 31 chars into a `ShortString`.\\n *\\n * This will trigger a `StringTooLong` error is the input string is too long.\\n */\\n function toShortString(string memory str) internal pure returns (ShortString) {\\n bytes memory bstr = bytes(str);\\n if (bstr.length > 31) {\\n revert StringTooLong(str);\\n }\\n return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));\\n }\\n\\n /**\\n * @dev Decode a `ShortString` back to a \\\"normal\\\" string.\\n */\\n function toString(ShortString sstr) internal pure returns (string memory) {\\n uint256 len = byteLength(sstr);\\n // using `new string(len)` would work locally but is not memory safe.\\n string memory str = new string(32);\\n assembly (\\\"memory-safe\\\") {\\n mstore(str, len)\\n mstore(add(str, 0x20), sstr)\\n }\\n return str;\\n }\\n\\n /**\\n * @dev Return the length of a `ShortString`.\\n */\\n function byteLength(ShortString sstr) internal pure returns (uint256) {\\n uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF;\\n if (result > 31) {\\n revert InvalidShortString();\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Encode a string into a `ShortString`, or write it to storage if it is too long.\\n */\\n function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) {\\n if (bytes(value).length < 32) {\\n return toShortString(value);\\n } else {\\n StorageSlot.getStringSlot(store).value = value;\\n return ShortString.wrap(FALLBACK_SENTINEL);\\n }\\n }\\n\\n /**\\n * @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}.\\n */\\n function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {\\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\\n return toString(value);\\n } else {\\n return store;\\n }\\n }\\n\\n /**\\n * @dev Return the length of a string that was encoded to `ShortString` or written to storage using\\n * {toShortStringWithFallback}.\\n *\\n * WARNING: This will return the \\\"byte length\\\" of the string. This may not reflect the actual length in terms of\\n * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.\\n */\\n function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) {\\n if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {\\n return byteLength(value);\\n } else {\\n return bytes(store).length;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1fcf8cceb1a67e6c8512267e780933c4a3f63ef44756e6c818fda79be51c8402\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Math} from \\\"./math/Math.sol\\\";\\nimport {SafeCast} from \\\"./math/SafeCast.sol\\\";\\nimport {SignedMath} from \\\"./math/SignedMath.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n using SafeCast for *;\\n\\n bytes16 private constant HEX_DIGITS = \\\"0123456789abcdef\\\";\\n uint8 private constant ADDRESS_LENGTH = 20;\\n uint256 private constant SPECIAL_CHARS_LOOKUP =\\n (1 << 0x08) | // backspace\\n (1 << 0x09) | // tab\\n (1 << 0x0a) | // newline\\n (1 << 0x0c) | // form feed\\n (1 << 0x0d) | // carriage return\\n (1 << 0x22) | // double quote\\n (1 << 0x5c); // backslash\\n\\n /**\\n * @dev The `value` string doesn't fit in the specified `length`.\\n */\\n error StringsInsufficientHexLength(uint256 value, uint256 length);\\n\\n /**\\n * @dev The string being parsed contains characters that are not in scope of the given base.\\n */\\n error StringsInvalidChar();\\n\\n /**\\n * @dev The string being parsed is not a properly formatted address.\\n */\\n error StringsInvalidAddressFormat();\\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 assembly (\\\"memory-safe\\\") {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n assembly (\\\"memory-safe\\\") {\\n mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\\n */\\n function toStringSigned(int256 value) internal pure returns (string memory) {\\n return string.concat(value < 0 ? \\\"-\\\" : \\\"\\\", toString(SignedMath.abs(value)));\\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 uint256 localValue = value;\\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] = HEX_DIGITS[localValue & 0xf];\\n localValue >>= 4;\\n }\\n if (localValue != 0) {\\n revert StringsInsufficientHexLength(value, length);\\n }\\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\\n * representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\\n * representation, according to EIP-55.\\n */\\n function toChecksumHexString(address addr) internal pure returns (string memory) {\\n bytes memory buffer = bytes(toHexString(addr));\\n\\n // hash the hex part of buffer (skip length + 2 bytes, length 40)\\n uint256 hashValue;\\n assembly (\\\"memory-safe\\\") {\\n hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\\n }\\n\\n for (uint256 i = 41; i > 1; --i) {\\n // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\\n if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\\n // case shift by xoring with 0x20\\n buffer[i] ^= 0x20;\\n }\\n hashValue >>= 4;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Returns true if the two strings are equal.\\n */\\n function equal(string memory a, string memory b) internal pure returns (bool) {\\n return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input) internal pure returns (uint256) {\\n return parseUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[0-9]*`\\n * - The result must fit into an `uint256` type\\n */\\n function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n uint256 result = 0;\\n for (uint256 i = begin; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 9) return (false, 0);\\n result *= 10;\\n result += chr;\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a decimal string and returns the value as a `int256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input) internal pure returns (int256) {\\n return parseInt(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `[-+]?[0-9]*`\\n * - The result must fit in an `int256` type.\\n */\\n function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\\n (bool success, int256 value) = tryParseInt(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\\n * the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\\n return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n uint256 private constant ABS_MIN_INT256 = 2 ** 255;\\n\\n /**\\n * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\\n * character or if the result does not fit in a `int256`.\\n *\\n * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\\n */\\n function tryParseInt(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, int256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseIntUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseIntUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, int256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // Check presence of a negative sign.\\n bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n bool positiveSign = sign == bytes1(\\\"+\\\");\\n bool negativeSign = sign == bytes1(\\\"-\\\");\\n uint256 offset = (positiveSign || negativeSign).toUint();\\n\\n (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\\n\\n if (absSuccess && absValue < ABS_MIN_INT256) {\\n return (true, negativeSign ? -int256(absValue) : int256(absValue));\\n } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\\n return (true, type(int256).min);\\n } else return (false, 0);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as a `uint256`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input) internal pure returns (uint256) {\\n return parseHexUint(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\\n * - The result must fit in an `uint256` type.\\n */\\n function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\\n (bool success, uint256 value) = tryParseHexUint(input, begin, end);\\n if (!success) revert StringsInvalidChar();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\\n return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\\n * invalid character.\\n *\\n * NOTE: This function will revert if the result does not fit in a `uint256`.\\n */\\n function tryParseHexUint(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, uint256 value) {\\n if (end > bytes(input).length || begin > end) return (false, 0);\\n return _tryParseHexUintUncheckedBounds(input, begin, end);\\n }\\n\\n /**\\n * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\\n * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\\n */\\n function _tryParseHexUintUncheckedBounds(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) private pure returns (bool success, uint256 value) {\\n bytes memory buffer = bytes(input);\\n\\n // skip 0x prefix if present\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 offset = hasPrefix.toUint() * 2;\\n\\n uint256 result = 0;\\n for (uint256 i = begin + offset; i < end; ++i) {\\n uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\\n if (chr > 15) return (false, 0);\\n result *= 16;\\n unchecked {\\n // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\\n // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.\\n result += chr;\\n }\\n }\\n return (true, result);\\n }\\n\\n /**\\n * @dev Parse a hexadecimal string (with or without \\\"0x\\\" prefix), and returns the value as an `address`.\\n *\\n * Requirements:\\n * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input) internal pure returns (address) {\\n return parseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and\\n * `end` (excluded).\\n *\\n * Requirements:\\n * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\\n */\\n function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\\n (bool success, address value) = tryParseAddress(input, begin, end);\\n if (!success) revert StringsInvalidAddressFormat();\\n return value;\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\\n * formatted address. See {parseAddress-string} requirements.\\n */\\n function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\\n return tryParseAddress(input, 0, bytes(input).length);\\n }\\n\\n /**\\n * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\\n * formatted address. See {parseAddress-string-uint256-uint256} requirements.\\n */\\n function tryParseAddress(\\n string memory input,\\n uint256 begin,\\n uint256 end\\n ) internal pure returns (bool success, address value) {\\n if (end > bytes(input).length || begin > end) return (false, address(0));\\n\\n bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\\\"0x\\\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\\n uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\\n\\n // check that input is the correct length\\n if (end - begin == expectedLength) {\\n // length guarantees that this does not overflow, and value is at most type(uint160).max\\n (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\\n return (s, address(uint160(v)));\\n } else {\\n return (false, address(0));\\n }\\n }\\n\\n function _tryParseChr(bytes1 chr) private pure returns (uint8) {\\n uint8 value = uint8(chr);\\n\\n // Try to parse `chr`:\\n // - Case 1: [0-9]\\n // - Case 2: [a-f]\\n // - Case 3: [A-F]\\n // - otherwise not supported\\n unchecked {\\n if (value > 47 && value < 58) value -= 48;\\n else if (value > 96 && value < 103) value -= 87;\\n else if (value > 64 && value < 71) value -= 55;\\n else return type(uint8).max;\\n }\\n\\n return value;\\n }\\n\\n /**\\n * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.\\n *\\n * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.\\n *\\n * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of\\n * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode\\n * characters that are not in this range, but other tooling may provide different results.\\n */\\n function escapeJSON(string memory input) internal pure returns (string memory) {\\n bytes memory buffer = bytes(input);\\n bytes memory output = new bytes(2 * buffer.length); // worst case scenario\\n uint256 outputLength = 0;\\n\\n for (uint256 i; i < buffer.length; ++i) {\\n bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));\\n if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {\\n output[outputLength++] = \\\"\\\\\\\\\\\";\\n if (char == 0x08) output[outputLength++] = \\\"b\\\";\\n else if (char == 0x09) output[outputLength++] = \\\"t\\\";\\n else if (char == 0x0a) output[outputLength++] = \\\"n\\\";\\n else if (char == 0x0c) output[outputLength++] = \\\"f\\\";\\n else if (char == 0x0d) output[outputLength++] = \\\"r\\\";\\n else if (char == 0x5c) output[outputLength++] = \\\"\\\\\\\\\\\";\\n else if (char == 0x22) {\\n // solhint-disable-next-line quotes\\n output[outputLength++] = '\\\"';\\n }\\n } else {\\n output[outputLength++] = char;\\n }\\n }\\n // write the actual length and deallocate unused memory\\n assembly (\\\"memory-safe\\\") {\\n mstore(output, outputLength)\\n mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))\\n }\\n\\n return string(output);\\n }\\n\\n /**\\n * @dev Reads a bytes32 from a bytes array without bounds checking.\\n *\\n * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\\n * assembly block as such would prevent some optimizations.\\n */\\n function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\\n // This is not memory safe in the general case, but all calls to this private function are within bounds.\\n assembly (\\\"memory-safe\\\") {\\n value := mload(add(buffer, add(0x20, offset)))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x81c274a60a7ae232ae3dc9ff3a4011b4849a853c13b0832cd3351bb1bb2f0dae\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.20;\\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 }\\n\\n /**\\n * @dev The signature derives the `address(0)`.\\n */\\n error ECDSAInvalidSignature();\\n\\n /**\\n * @dev The signature has an invalid length.\\n */\\n error ECDSAInvalidSignatureLength(uint256 length);\\n\\n /**\\n * @dev The signature has an S value that is in the upper half order.\\n */\\n error ECDSAInvalidSignatureS(bytes32 s);\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not\\n * return address(0) without also returning an error description. Errors are documented using an enum (error type)\\n * and a bytes32 providing additional information about the error.\\n *\\n * If no error is returned, then the address can be used for verification purposes.\\n *\\n * The `ecrecover` EVM precompile 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 {MessageHashUtils-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 function tryRecover(\\n bytes32 hash,\\n bytes memory signature\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\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 assembly (\\\"memory-safe\\\") {\\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, bytes32(signature.length));\\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 precompile 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 {MessageHashUtils-toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);\\n _throwError(error, errorArg);\\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[ERC-2098 short signatures]\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\n unchecked {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n // We do not check for an overflow here since the shift operation results in 0 or 1.\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n */\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);\\n _throwError(error, errorArg);\\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 function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) {\\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, s);\\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, bytes32(0));\\n }\\n\\n return (signer, RecoverError.NoError, bytes32(0));\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);\\n _throwError(error, errorArg);\\n return recovered;\\n }\\n\\n /**\\n * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.\\n */\\n function _throwError(RecoverError error, bytes32 errorArg) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert ECDSAInvalidSignature();\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert ECDSAInvalidSignatureLength(uint256(errorArg));\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert ECDSAInvalidSignatureS(errorArg);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x69f54c02b7d81d505910ec198c11ed4c6a728418a868b906b4a0cf29946fda84\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/EIP712.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {MessageHashUtils} from \\\"./MessageHashUtils.sol\\\";\\nimport {ShortStrings, ShortString} from \\\"../ShortStrings.sol\\\";\\nimport {IERC5267} from \\\"../../interfaces/IERC5267.sol\\\";\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.\\n *\\n * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose\\n * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract\\n * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to\\n * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.\\n *\\n * This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\\n * ({_hashTypedDataV4}).\\n *\\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\\n * the chain id to protect against replay attacks on an eventual fork of the chain.\\n *\\n * NOTE: This contract implements the version of the encoding known as \\\"v4\\\", as implemented by the JSON RPC method\\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\\n *\\n * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain\\n * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the\\n * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.\\n *\\n * @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n */\\nabstract contract EIP712 is IERC5267 {\\n using ShortStrings for *;\\n\\n bytes32 private constant TYPE_HASH =\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\");\\n\\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\\n // invalidate the cached domain separator if the chain id changes.\\n bytes32 private immutable _cachedDomainSeparator;\\n uint256 private immutable _cachedChainId;\\n address private immutable _cachedThis;\\n\\n bytes32 private immutable _hashedName;\\n bytes32 private immutable _hashedVersion;\\n\\n ShortString private immutable _name;\\n ShortString private immutable _version;\\n // slither-disable-next-line constable-states\\n string private _nameFallback;\\n // slither-disable-next-line constable-states\\n string private _versionFallback;\\n\\n /**\\n * @dev Initializes the domain separator and parameter caches.\\n *\\n * The meaning of `name` and `version` is specified in\\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:\\n *\\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\\n * - `version`: the current major version of the signing domain.\\n *\\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\\n * contract upgrade].\\n */\\n constructor(string memory name, string memory version) {\\n _name = name.toShortStringWithFallback(_nameFallback);\\n _version = version.toShortStringWithFallback(_versionFallback);\\n _hashedName = keccak256(bytes(name));\\n _hashedVersion = keccak256(bytes(version));\\n\\n _cachedChainId = block.chainid;\\n _cachedDomainSeparator = _buildDomainSeparator();\\n _cachedThis = address(this);\\n }\\n\\n /**\\n * @dev Returns the domain separator for the current chain.\\n */\\n function _domainSeparatorV4() internal view returns (bytes32) {\\n if (address(this) == _cachedThis && block.chainid == _cachedChainId) {\\n return _cachedDomainSeparator;\\n } else {\\n return _buildDomainSeparator();\\n }\\n }\\n\\n function _buildDomainSeparator() private view returns (bytes32) {\\n return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));\\n }\\n\\n /**\\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\\n * function returns the hash of the fully encoded EIP712 message for this domain.\\n *\\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\\n *\\n * ```solidity\\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\\n * keccak256(\\\"Mail(address to,string contents)\\\"),\\n * mailTo,\\n * keccak256(bytes(mailContents))\\n * )));\\n * address signer = ECDSA.recover(digest, signature);\\n * ```\\n */\\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\\n return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);\\n }\\n\\n /**\\n * @inheritdoc IERC5267\\n */\\n function eip712Domain()\\n public\\n view\\n virtual\\n returns (\\n bytes1 fields,\\n string memory name,\\n string memory version,\\n uint256 chainId,\\n address verifyingContract,\\n bytes32 salt,\\n uint256[] memory extensions\\n )\\n {\\n return (\\n hex\\\"0f\\\", // 01111\\n _EIP712Name(),\\n _EIP712Version(),\\n block.chainid,\\n address(this),\\n bytes32(0),\\n new uint256[](0)\\n );\\n }\\n\\n /**\\n * @dev The name parameter for the EIP712 domain.\\n *\\n * NOTE: By default this function reads _name which is an immutable value.\\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function _EIP712Name() internal view returns (string memory) {\\n return _name.toStringWithFallback(_nameFallback);\\n }\\n\\n /**\\n * @dev The version parameter for the EIP712 domain.\\n *\\n * NOTE: By default this function reads _version which is an immutable value.\\n * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function _EIP712Version() internal view returns (string memory) {\\n return _version.toStringWithFallback(_versionFallback);\\n }\\n}\\n\",\"keccak256\":\"0x0c60057e7351874f086db8dc9291b7ada9ad62cb7725befd2991430d04a74572\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/cryptography/MessageHashUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Strings} from \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.\\n *\\n * The library provides methods for generating a hash of a message that conforms to the\\n * https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]\\n * specifications.\\n */\\nlibrary MessageHashUtils {\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x45` (`personal_sign` messages).\\n *\\n * The digest is calculated by prefixing a bytes32 `messageHash` with\\n * `\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\"` and hashing the result. It corresponds with the\\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\\n *\\n * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with\\n * keccak256, although any bytes32 value can be safely used because the final digest will\\n * be re-hashed.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\") // 32 is the bytes-length of messageHash\\n mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix\\n digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)\\n }\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x45` (`personal_sign` messages).\\n *\\n * The digest is calculated by prefixing an arbitrary `message` with\\n * `\\\"\\\\x19Ethereum Signed Message:\\\\n\\\" + len(message)` and hashing the result. It corresponds with the\\n * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) {\\n return\\n keccak256(bytes.concat(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", bytes(Strings.toString(message.length)), message));\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an ERC-191 signed data with version\\n * `0x00` (data with intended validator).\\n *\\n * The digest is calculated by prefixing an arbitrary `data` with `\\\"\\\\x19\\\\x00\\\"` and the intended\\n * `validator` address. Then hashing the result.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(hex\\\"19_00\\\", validator, data));\\n }\\n\\n /**\\n * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.\\n */\\n function toDataWithIntendedValidatorHash(\\n address validator,\\n bytes32 messageHash\\n ) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, hex\\\"19_00\\\")\\n mstore(0x02, shl(96, validator))\\n mstore(0x16, messageHash)\\n digest := keccak256(0x00, 0x36)\\n }\\n }\\n\\n /**\\n * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).\\n *\\n * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with\\n * `\\\\x19\\\\x01` and hashing the result. It corresponds to the hash signed by the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.\\n *\\n * See {ECDSA-recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n mstore(ptr, hex\\\"19_01\\\")\\n mstore(add(ptr, 0x02), domainSeparator)\\n mstore(add(ptr, 0x22), structHash)\\n digest := keccak256(ptr, 0x42)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x26670fef37d4adf55570ba78815eec5f31cb017e708f61886add4fc4da665631\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard signed math utilities missing in the Solidity language.\\n */\\nlibrary SignedMath {\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\\n }\\n }\\n\\n /**\\n * @dev Returns the largest of two signed numbers.\\n */\\n function max(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a > b, a, b);\\n }\\n\\n /**\\n * @dev Returns the smallest of two signed numbers.\\n */\\n function min(int256 a, int256 b) internal pure returns (int256) {\\n return ternary(a < b, a, b);\\n }\\n\\n /**\\n * @dev Returns the average of two signed numbers without overflow.\\n * The result is rounded towards zero.\\n */\\n function average(int256 a, int256 b) internal pure returns (int256) {\\n // Formula from the book \\\"Hacker's Delight\\\"\\n int256 x = (a & b) + ((a ^ b) >> 1);\\n return x + (int256(uint256(x) >> 255) & (a ^ b));\\n }\\n\\n /**\\n * @dev Returns the absolute unsigned value of a signed value.\\n */\\n function abs(int256 n) internal pure returns (uint256) {\\n unchecked {\\n // Formula from the \\\"Bit Twiddling Hacks\\\" by Sean Eron Anderson.\\n // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\\n // taking advantage of the most significant (or \\\"sign\\\" bit) in two's complement representation.\\n // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\\n // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\\n int256 mask = n >> 255;\\n\\n // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\\n return uint256((n + mask) ^ mask);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb1970fac7b64e6c09611e6691791e848d5e3fe410fa5899e7df2e0afd77a99e3\",\"license\":\"MIT\"},\"project/test/mocks/MockERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC20} from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport {ERC20Permit} from \\\"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol\\\";\\n\\ncontract MockERC20 is ERC20Permit {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n uint8 private _decimals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor(string memory symbol, uint8 decimals_) ERC20(symbol, symbol) ERC20Permit(symbol) {\\n _decimals = decimals_;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function mint(address to, uint256 amount) external {\\n _mint(to, amount);\\n }\\n\\n function nuke(address owner) external {\\n _burn(owner, balanceOf(owner));\\n }\\n\\n function decimals() public view virtual override returns (uint8) {\\n return _decimals;\\n }\\n}\\n\\n\\ncontract MockERC20Blacklist is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n mapping(address account => bool isBlacklisted) public isBlacklisted;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n error Blacklisted(address);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"BLACK\\\", 6) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function setBlacklisted(address account, bool blacklisted) external {\\n isBlacklisted[account] = blacklisted;\\n }\\n\\n function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\\n _checkBlacklist(from);\\n _checkBlacklist(to);\\n return super.transferFrom(from, to, amount);\\n }\\n\\n function _checkBlacklist(address addr) internal view {\\n if (isBlacklisted[addr]) {\\n revert Blacklisted(addr);\\n }\\n }\\n}\\n\\n\\ncontract MockERC20VoidReturn is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"VOID\\\", 11) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function transferFrom(address from, address to, uint256 amount) public override returns (bool) {\\n super.transferFrom(from, to, amount);\\n assembly {\\n return(0, 0) // return void\\n }\\n }\\n}\\n\\n\\ncontract MockERC20FalseReturn is MockERC20 {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n constructor() MockERC20(\\\"FALSE\\\", 13) {}\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n function transferFrom(address, address, uint256) public pure override returns (bool) {\\n return false; // return false instead of revert\\n }\\n}\\n\",\"keccak256\":\"0xf418c9e3b57c817e2ae0085dacf3b79d531ff5e4c5d51634c09d0981d834472b\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 38520, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 38526, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 38528, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 38530, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 38532, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + }, + { + "astId": 46241, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_nameFallback", + "offset": 0, + "slot": "5", + "type": "t_string_storage" + }, + { + "astId": 46243, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_versionFallback", + "offset": 0, + "slot": "6", + "type": "t_string_storage" + }, + { + "astId": 43769, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_nonces", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 76079, + "contract": "project/test/mocks/MockERC20.sol:MockERC20", + "label": "_decimals", + "offset": 0, + "slot": "8", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "argsData": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000045553444300000000000000000000000000000000000000000000000000000000", + "transaction": { + "hash": "0xe1bfd736448fc813a11f567b13ee433c982f89de9a6566ade5fe583c7c217af7", + "nonce": "0x11", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x38b1e06cf9c9bb108a9446df3300012ef8f0b04426bbdf85c4b881b7fdcb14fb", + "blockNumber": "0xaa56ba", + "transactionIndex": "0xaf" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/PermissionedResolverImpl.json b/contracts/deployments/sepolia/PermissionedResolverImpl.json new file mode 100644 index 000000000..5518b94fa --- /dev/null +++ b/contracts/deployments/sepolia/PermissionedResolverImpl.json @@ -0,0 +1,2840 @@ +{ + "address": "0x7e4b2d59938930168024201752ee5503df402303", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + } + ], + "name": "InvalidContentType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "name": "InvalidEVMAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "UnsupportedResolverProfile", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + } + ], + "name": "ABIChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "a", + "type": "address" + } + ], + "name": "AddrChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newAddress", + "type": "bytes" + } + ], + "name": "AddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes", + "name": "indexedFromName", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "indexedToName", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "fromName", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "toName", + "type": "bytes" + } + ], + "name": "AliasChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "ContenthashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "indexedData", + "type": "bytes" + } + ], + "name": "DataChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "InterfaceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "NameChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "NamedAddrResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "NamedDataResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "NamedResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "NamedTextResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "name": "PubkeyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "TextChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newVersion", + "type": "uint64" + } + ], + "name": "VersionChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "contentTypes", + "type": "uint256" + } + ], + "name": "ABI", + "outputs": [ + { + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "grant", + "type": "bool" + } + ], + "name": "authorizeAddrRoles", + "outputs": [ + { + "internalType": "bool", + "name": "updated", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "grant", + "type": "bool" + } + ], + "name": "authorizeDataRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "grant", + "type": "bool" + } + ], + "name": "authorizeNameRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "grant", + "type": "bool" + } + ], + "name": "authorizeTextRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "canUpgradeFrom", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "clearRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "contenthash", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "data", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "fromName", + "type": "bytes" + } + ], + "name": "getAlias", + "outputs": [ + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "hasAddr", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "setters", + "type": "bytes[]" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "interfaceImplementer", + "outputs": [ + { + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "calls", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes[]", + "name": "calls", + "type": "bytes[]" + } + ], + "name": "multicallWithNodeCheck", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "pubkey", + "outputs": [ + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "recordVersions", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "fromName", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "fromData", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "setABI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "name": "setAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "addr_", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "fromName", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "toName", + "type": "bytes" + } + ], + "name": "setAlias", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "setContenthash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "setData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "setInterface", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "primary", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "name": "setPubkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "setText", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "feature", + "type": "bytes4" + } + ], + "name": "supportsFeature", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "text", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "contractName": "PermissionedResolver", + "sourceName": "src/resolver/PermissionedResolver.sol", + "bytecode": "0x60a060405230608052348015610013575f80fd5b50604051614921380380614921833981016040819052610032916103c2565b61005e5f7f0100000000000000000000000000000001000000000000000000000000000000838261006d565b50610067610168565b50610429565b5f835f0361007c57505f610160565b61008584610205565b6001600160a01b0383166100ac5760405163761fe2c960e11b815260040160405180910390fd5b5f858152602081815260408083206001600160a01b038716845290915290205484811780821461015a575f878152602081815260408083206001600160a01b03891684529091529020819055811986166101088882600161024e565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050610160565b5f925050505b949350505050565b5f61017161037e565b805490915068010000000000000000900460ff16156101a35760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146102025780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561020257604051630153d96960e51b8152600481018290526024015b60405180910390fd5b5f610258836103a8565b905081156102ee575f8481526001602052604090205461029e9082161980195f8051602061490183398151915291909101165f805160206148e183398151915216151590565b156102c657604051631f22ca6960e31b81526004810185905260248101849052604401610245565b5f84815260016020526040812080548592906102e3908490610403565b909155506103789050565b5f8481526001602052604090205461032d901982161980195f8051602061490183398151915291909101165f805160206148e183398151915216151590565b1561035557604051631f80c19b60e01b81526004810185905260248101849052604401610245565b5f8481526001602052604081208054859290610372908490610416565b90915550505b50505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b5f6103b282610205565b50600181901b17600281901b1790565b5f602082840312156103d2575f80fd5b81516001600160a01b03811681146103e8575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156103a2576103a26103ef565b818103818111156103a2576103a26103ef565b60805161449261044f5f395f8181612c0c01528181612c350152612dc901526144925ff3fe60806040526004361061030e575f3560e01c8063691f34311161019c578063c80ef4e0116100e7578063dfa70d8b11610092578063ecbfada31161006d578063ecbfada314610a25578063f1cb7e0614610a44578063f2d1eb2514610a63578063f41a143d14610a82575f80fd5b8063dfa70d8b146109c8578063e32954eb146109e7578063e59d895d14610a06575f80fd5b8063d3bf89b1116100c2578063d3bf89b1146108ed578063d5fa2b001461095a578063d700ff3314610979575f80fd5b8063c80ef4e01461085b578063c86902331461087a578063ce156e82146108ce575f80fd5b80638b95dd7111610147578063ad3cb1cc11610122578063ad3cb1cc146107d5578063bbd9abb51461081d578063bc1c58d11461083c575f80fd5b80638b95dd711461076b5780639061b9231461078a578063ac9650d8146107a9575f80fd5b8063773722131161017757806377372213146106d7578063781ef8db146106f65780637c3005861461074c575f80fd5b8063691f34311461067a5780636f3ff726146106995780637058b559146106b8575f80fd5b806332f111d71161025c57806352d1902d1161020757806359d1d43c116101e257806359d1d43c146106105780635adf47241461063c578063623195b01461065b575f80fd5b806352d1902d14610594578063582de3e7146105a8578063587eefd1146105f1575f80fd5b80633b3b57de116102375780633b3b57de146105435780634eb9c45e146105625780634f1ef28614610581575f80fd5b806332f111d7146104d15780633603d758146104f05780633634f9111461050f575f80fd5b80631c3fc3eb116102bc57806329cd62ea1161029757806329cd62ea146104685780632f27fa2414610487578063304e6ade146104b2575f80fd5b80631c3fc3eb146103fb5780632203ab561461041c578063291770ae14610449575f80fd5b806311b8e00a116102ec57806311b8e00a14610386578063124a319c146103a55780631a76b72c146103dc575f80fd5b806301ffc9a714610312578063072d5d771461034657806310f13a8c14610365575b5f80fd5b34801561031d575f80fd5b5061033161032c366004613848565b610aa2565b60405190151581526020015b60405180910390f35b348015610351575f80fd5b50610331610360366004613877565b610e59565b348015610370575f80fd5b5061038461037f3660046138df565b610e7f565b005b348015610391575f80fd5b506103316103a0366004613953565b61100f565b3480156103b0575f80fd5b506103c46103bf366004613973565b611026565b6040516001600160a01b03909116815260200161033d565b3480156103e7575f80fd5b506103316103f63660046139a3565b61109b565b348015610406575f80fd5b5061040e5f81565b60405190815260200161033d565b348015610427575f80fd5b5061043b610436366004613953565b6111f0565b60405161033d929190613a5b565b348015610454575f80fd5b50610384610463366004613a73565b61130c565b348015610473575f80fd5b50610384610482366004613ada565b6113ef565b348015610492575f80fd5b5061040e6104a1366004613b03565b5f9081526001602052604090205490565b3480156104bd575f80fd5b506103846104cc366004613b1a565b611493565b3480156104dc575f80fd5b506103316104eb366004613953565b611518565b3480156104fb575f80fd5b5061038461050a366004613b03565b611567565b34801561051a575f80fd5b5061052e610529366004613953565b611617565b6040805192835260208301919091520161033d565b34801561054e575f80fd5b506103c461055d366004613b03565b61163a565b34801561056d575f80fd5b5061038461057c3660046138df565b611658565b61038461058f366004613c20565b6117b2565b34801561059f575f80fd5b5061040e6117d1565b3480156105b3575f80fd5b506103316105c2366004613848565b6001600160e01b0319167f96b62db8000000000000000000000000000000000000000000000000000000001490565b3480156105fc575f80fd5b5061033161060b366004613c6b565b6117ff565b34801561061b575f80fd5b5061062f61062a366004613b1a565b611900565b60405161033d9190613cd4565b348015610647575f80fd5b5061040e610656366004613877565b6119e0565b348015610666575f80fd5b50610384610675366004613ce6565b611a05565b348015610685575f80fd5b5061062f610694366004613b03565b611ae6565b3480156106a4575f80fd5b506103316106b3366004613d29565b611ba5565b3480156106c3575f80fd5b506103846106d2366004613d83565b611bf6565b3480156106e2575f80fd5b506103846106f1366004613b1a565b611d36565b348015610701575f80fd5b50610331610710366004613877565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b348015610757575f80fd5b50610331610766366004613dcd565b611dc0565b348015610776575f80fd5b50610384610785366004613dff565b611df4565b348015610795575f80fd5b5061062f6107a4366004613a73565b611f62565b3480156107b4575f80fd5b506107c86107c3366004613e4b565b61225f565b60405161033d9190613e8a565b3480156107e0575f80fd5b5061062f6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b348015610828575f80fd5b50610331610837366004613c6b565b612366565b348015610847575f80fd5b5061062f610856366004613b03565b61244e565b348015610866575f80fd5b5061062f610875366004613eec565b612487565b348015610885575f80fd5b5061052e610894366004613b03565b5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902060018101546002909101549091565b3480156108d9575f80fd5b506103316108e8366004613877565b6124d1565b3480156108f8575f80fd5b50610331610907366004613dcd565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b348015610965575f80fd5b50610384610974366004613877565b6124ec565b348015610984575f80fd5b506109af610993366004613b03565b5f908152610103602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff909116815260200161033d565b3480156109d3575f80fd5b506103316109e2366004613dcd565b612528565b3480156109f2575f80fd5b506107c8610a01366004613f1e565b61255c565b348015610a11575f80fd5b50610384610a20366004613f59565b612568565b348015610a30575f80fd5b5061062f610a3f366004613b1a565b612621565b348015610a4f575f80fd5b5061062f610a5e366004613953565b612662565b348015610a6e575f80fd5b50610331610a7d3660046139a3565b6127ee565b348015610a8d575f80fd5b50610331610a9c366004613d29565b50600190565b5f7f91413117000000000000000000000000000000000000000000000000000000006001600160e01b031983161480610b0457507f9061b923000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610b3857507f582de3e7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610b6c57507f4fbf0433000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610ba057507f2203ab56000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610bd457507f3b3b57de000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c0857507ff1cb7e06000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c3c57507fbc1c58d1000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c7057507fecbfada3000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610ca457507f32f111d7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610cd857507f124a319c000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d0c57507f691f3431000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d4057507fc8690233000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d7457507f59d1d43c000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610da857507fd700ff33000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610ddc57507fb0f3d367000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e1057507ff41a143d000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e4457507f6f3ff726000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e535750610e53826128f7565b92915050565b5f8083610e67828233612944565b610e745f86866001612992565b92505b505092915050565b84610ebe85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612aa292505050565b6010811580610f335750610f1c610ed58484612aad565b5f908152602081815260408083203384528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925290912054178216821490565b158015610f335750610f31610ed55f84612aad565b155b15610f4c57610f4c610f45845f612aad565b8233612acf565b8484610f808a5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b6005018989604051610f93929190613f89565b90815260200160405180910390209182610fae92919061400e565b508686604051610fbf929190613f89565b6040518091039020887f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a189898989604051610ffd94939291906140f0565b60405180910390a35050505050505050565b5f8061101b8484611617565b501515949350505050565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083206001600160e01b0319851684526008019091529020546001600160a01b031680610e53575f61107f8461163a565b905061108b8184612aeb565b15611094578091505b5092915050565b5f806110db88888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b90506410000000005f6110ee8382612aad565b90505f611138846111338b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612aa292505050565b612aad565b905085156111ce5761114b828433612944565b5f818152600160205260409020545f036111b657888860405161116f929190613f89565b6040518091039020817fdb7aa4f21d01358b79d5574f3f3f6805f4f97606c53cb70598063387352206ac8d8d8d8d6040516111ad94939291906140f0565b60405180910390a35b6111c38184896001612992565b9450505050506111e6565b6111d9828433612b37565b6111c38184896001612b7f565b9695505050505050565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206001906060905b5f831180156112315750838311155b156112f157828416156112e5575f8381526007820160205260409020805461125890613f98565b80601f016020809104026020016040519081016040528092919081815260200182805461128490613f98565b80156112cf5780601f106112a6576101008083540402835291602001916112cf565b820191905f5260205f20905b8154815290600101906020018083116112b257829003601f168201915b505050505091505f825111156112e55750611305565b600183901b9250611222565b505060408051602081019091525f80825291505b9250929050565b631000000061131c5f8233612acf565b82826101025f61136089898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b81526020019081526020015f20918261137a92919061400e565b50828260405161138b929190613f89565b604051809103902085856040516113a3929190613f89565b60405180910390207fa8c2ea0876733fd2146051b3e195e5e1d1f85eff08bf169191dce9569281c529878787876040516113e094939291906140f0565b60405180910390a35050505050565b825f611000611401610f45845f612aad565b60408051808201825286815260208082018790525f898152610104825283812061010383528482205467ffffffffffffffff1682529091529190912060010190600261144e9291906137e3565b50604080518681526020810186905287917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a2505050505050565b825f6101006114a5610f45845f612aad565b84846114d9885f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b916114e591908361400e565b50857fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788686604051611483929190614116565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083208484526004019091528120805482919061155c90613f98565b905011905092915050565b805f64010000000061157c610f45845f612aad565b5f84815261010360205260408120805482906115a19067ffffffffffffffff1661413d565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790559050847fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db44482604051611608919067ffffffffffffffff91909116815260200190565b60405180910390a25050505050565b5f8061162283612be7565b5f948552600160205260409094205484169492505050565b5f61164682603c612662565b61164f90614163565b60601c92915050565b8461169785858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612aa292505050565b6410000000008115806116c957506116b2610ed58484612aad565b1580156116c957506116c7610ed55f84612aad565b155b156116db576116db610f45845f612aad565b848461170f8a5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b6006018989604051611722929190613f89565b9081526020016040518091039020918261173d92919061400e565b50848460405161174e929190613f89565b60405180910390208787604051611766929190613f89565b6040518091039020897f3b7ea3580e046bf897ca24f2f45fcf5491dafba8d1b3dd17ca92aa0e82b4dd218a8a6040516117a0929190614116565b60405180910390a45050505050505050565b6117ba612c01565b6117c382612cba565b6117cd8282612cd6565b5050565b5f6117da612dbe565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f8061183f87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b905060015f61184e8382612aad565b90505f611864846111338a5f9081526020902090565b905085156118df57611877828433612944565b5f818152600160205260409020545f036118c75787817f2fe6caf984256b1a1844b92f52cf88703e829b07ce397a6c7fcf1f779db7a1858c8c6040516118be929190614116565b60405180910390a35b6118d48184896001612992565b9450505050506118f7565b6118ea828433612b37565b6118d48184896001612b7f565b95945050505050565b5f8381526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906005018383604051611941929190613f89565b9081526020016040518091039020805461195a90613f98565b80601f016020809104026020016040519081016040528092919081815260200182805461198690613f98565b80156119d15780601f106119a8576101008083540402835291602001916119d1565b820191905f5260205f20905b8154815290600101906020018083116119b457829003601f168201915b505050505090505b9392505050565b5f828152602081815260408083206001600160a01b03851684529091528120546119d9565b835f62010000611a18610f45845f612aad565b611a2186612e07565b611a5f576040517f5742bb26000000000000000000000000000000000000000000000000000000008152600481018790526024015b60405180910390fd5b8484611a93895f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b5f8981526007919091016020526040902091611ab091908361400e565b50604051869088907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3905f90a350505050505050565b5f8181526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906003018054611b2290613f98565b80601f0160208091040260200160405190810160405280929190818152602001828054611b4e90613f98565b8015611b995780601f10611b7057610100808354040283529160200191611b99565b820191905f5260205f20905b815481529060010190602001808311611b7c57829003601f168201915b50505050509050919050565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb560205260408120546f0100000000000000000000000000000090811614610e53565b5f611bff612e26565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f81158015611c2b5750825b90505f8267ffffffffffffffff166001148015611c475750303b155b905081158015611c55575080155b15611c8c576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315611cc057845468ff00000000000000001916680100000000000000001785555b611cc8612e4e565b611cd45f898b5f612992565b50611cdf878761225f565b508315611d2b57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b825f6301000000611d4a610f45845f612aad565b8484611d7e885f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b60030191611d8d91908361400e565b50857fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78686604051611483929190614116565b60405163d1a3b35560e01b815260048101849052602481018390526001600160a01b03821660448201525f90606401611a56565b5f8281526020902083906001811580611e2c5750611e15610ed58484612aad565b158015611e2c5750611e2a610ed55f84612aad565b155b15611e3e57611e3e610f45845f612aad565b835115801590611e5057508351601414155b8015611e605750611e6085612e56565b15611e9957836040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611a569190613cd4565b5f8681526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083208884526004019091529020611ed9858261419f565b50857f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528686604051611f0c929190613a5b565b60405180910390a2603c8503611f5a57857f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2611f4786614163565b60405160609190911c8152602001611483565b505050505050565b60605f611fa386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061248792505050565b90505f611ffd8585611ff885515f14611fbc5785611ff2565b8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050505b5f612b06565b612e7b565b90507fac9650d8000000000000000000000000000000000000000000000000000000006120298261425b565b6001600160e01b031916036121ab578051600319810160048301908152915f9161205c919081016020019060240161428e565b90505f5b81518110156121805781818151811061207b5761207b614384565b602002602001015192505f306001600160a01b03168460405161209e9190614398565b5f60405180830381855afa9150503d805f81146120d6576040519150601f19603f3d011682016040523d82523d5f602084013e6120db565b606091505b5091505080515f0361215957637b1c461b60e01b6120f88561425b565b6040516001600160e01b0319909116602482015260440160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290505b8083838151811061216c5761216c614384565b602090810291909101015250600101612060565b50806040516020016121929190613e8a565b6040516020818303038152906040529350505050612257565b5f80306001600160a01b0316836040516121c59190614398565b5f60405180830381855afa9150503d805f81146121fd576040519150601f19603f3d011682016040523d82523d5f602084013e612202565b606091505b50915091508161221457805160208201fd5b80515f0361224c5761222686886143ae565b604051637b1c461b60e01b81526001600160e01b03199091166004820152602401611a56565b935061225792505050565b949350505050565b60608167ffffffffffffffff81111561227a5761227a613b62565b6040519080825280602002602001820160405280156122ad57816020015b60608152602001906001900390816122985790505b5090505f5b82811015611094575f80308686858181106122cf576122cf614384565b90506020028101906122e191906143dc565b6040516122ef929190613f89565b5f60405180830381855af49150503d805f8114612327576040519150601f19603f3d011682016040523d82523d5f602084013e61232c565b606091505b50915091508161233e57805160208201fd5b8084848151811061235157612351614384565b602090810291909101015250506001016122b2565b5f806123a687878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b90505f6123b38282612aad565b90508315612436576123c6818733612944565b80158015906123e057505f81815260016020526040902054155b1561242057807f737038e72be1d204e2c7336c20bff2169d9dffe11face28c5969af4ecce04f678989604051612417929190614116565b60405180910390a25b61242d8187876001612992565b925050506118f7565b612441818733612b37565b61242d8187876001612b7f565b5f8181526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060908054611b2290613f98565b60605f5b606061249684612f58565b80519095509091505f036124aa57506124cb565b805160208201208281036124bf5750506124cb565b849350915061248b9050565b50919050565b5f80836124df828233612b37565b610e745f86866001612b7f565b6040516bffffffffffffffffffffffff19606083901b1660208201526117cd908390603c90603401604051602081830303815290604052611df4565b6040516314c09c6360e31b815260048101849052602481018390526001600160a01b03821660448201525f90606401611a56565b6060612257838361225f565b825f6210000061257b610f45845f612aad565b5f8681526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083206001600160e01b031989168085526008909101835292819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389169081179091558151908152905189927f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa928290030190a3505050505050565b5f8381526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906006018383604051611941929190613f89565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff168452825280832084845260048101909252909120805460609291906126aa90613f98565b80601f01602080910402602001604051908101604052809291908181526020018280546126d690613f98565b80156127215780601f106126f857610100808354040283529160200191612721565b820191905f5260205f20905b81548152906001019060200180831161270457829003601f168201915b5050505050915081515f14801561274557505f61273d846130a7565b63ffffffff16115b156110945763800000005f9081526004820160205260409020805461276990613f98565b80601f016020809104026020016040519081016040528092919081815260200182805461279590613f98565b80156127e05780601f106127b7576101008083540402835291602001916127e0565b820191905f5260205f20905b8154815290600101906020018083116127c357829003601f168201915b505050505091505092915050565b5f8061282e88888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b905060105f61283d8382612aad565b90505f612882846111338b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612aa292505050565b905085156111ce57612895828433612944565b5f818152600160205260409020545f036111b65788886040516128b9929190613f89565b6040518091039020817fab228e072dd20e63d6891264ea8f6a2459e6852ab494b707970f978ba630859c8d8d8d8d6040516111ad94939291906140f0565b5f6001600160e01b031982167f8f452d62000000000000000000000000000000000000000000000000000000001480610e5357506301ffc9a760e01b6001600160e01b0319831614610e53565b5f61294f84836130d1565b9050801983161561298c5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401611a56565b50505050565b5f835f036129a157505f612257565b6129aa84613148565b6001600160a01b0383166129ea576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214612a98575f878152602081815260408083206001600160a01b0389168452909152902081905581198616612a46888260016131a8565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050612257565b5f92505050612257565b805160209091012090565b5f82151580612abb57508115155b15610e5357505f9182526020526040902090565b612ad7613344565b612ae657612ae6838383613362565b505050565b5f612af5836133fe565b80156119d957506119d98383613430565b5f612b1183836134cb565b925090508015610e53576119d9612b288484612b06565b825f9182526020526040902090565b5f612b4284836130d1565b9050801983161561298c576040516314c09c6360e31b815260048101859052602481018490526001600160a01b0383166044820152606401611a56565b5f612b8984613148565b5f858152602081815260408083206001600160a01b038716845290915290205484198116808214612a98575f878152602081815260408083206001600160a01b0389168452909152812082905586831690612a4690899083906131a8565b5f612bf182613148565b50600181901b17600281901b1790565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480612c9a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612c8e7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b15612cb85760405163703e46dd60e11b815260040160405180910390fd5b565b6f100000000000000000000000000000006117cd5f8233612acf565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612d30575060408051601f3d908101601f19168201909252612d2d9181019061441f565b60015b612d5857604051634c9c8ce360e01b81526001600160a01b0383166004820152602401611a56565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612db4576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401611a56565b612ae683836134f8565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612cb85760405163703e46dd60e11b815260040160405180910390fd5b5f8082118015610e53575081612e1e600182614436565b161592915050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610e53565b612cb861354d565b5f6380000000821480610e5357505f612e6e836130a7565b63ffffffff161192915050565b606083838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929350612f4a92505050565b602481019050600481035160e01c63ac9650d88114612eea5781831015612ee25750505050565b83825261298c565b815182019180831015612efe575050505050565b825160051b5b8015611f5a5760208401915080840151820182811015612f245750612f41565b8051810180871015612f335750855b612f3e888284612ebb565b50505b601f1901612f04565b6119d9828251830183612ebb565b6060805f5b83518110156130a1576101025f612f748684612b06565b81526020019081526020015f208054612f8c90613f98565b80601f0160208091040260200160405190810160405280929190818152602001828054612fb890613f98565b80156130035780601f10612fda57610100808354040283529160200191613003565b820191905f5260205f20905b815481529060010190602001808311612fe657829003601f168201915b505050505092505f8351111561308e5780156130865782516130259082614449565b67ffffffffffffffff81111561303d5761303d613b62565b6040519080825280601f01601f191660200182016040528015613067576020820181803683370190505b5091508060208501602084015e8251602084018260200184015e6130a1565b8291506130a1565b613098848261358b565b9150612f5d9050565b50915091565b5f603c82036130b857506001919050565b63800000009182189182106130cd575f610e53565b5090565b5f828152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925282205417608081901c7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176119d9565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156131a5576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401611a56565b50565b5f6131b283612be7565b9050811561327b575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615613253576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401611a56565b5f8481526001602052604081208054859290613270908490614449565b9091555061298c9050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615613315576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401611a56565b5f8481526001602052604081208054859290613332908490614436565b909155505050505050565b5050505050565b5f61334d612e26565b5468010000000000000000900460ff16919050565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5909252909120541782168214612ae6576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401611a56565b5f613410826301ffc9a760e01b613430565b8015610e535750613429826001600160e01b0319613430565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f5190508280156134b5575060208210155b80156134c057505f81115b979650505050505050565b5f805f6134d8858561358b565b9250905060ff8116156134f057806021858701012092505b509250929050565b61350182613608565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561354557612ae6828261368b565b6117cd6136f4565b613555613344565b612cb8576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80835183106135b0578360405163ba4adc2360e01b8152600401611a569190613cd4565b8383815181106135c2576135c2614384565b016020015160f81c915050818101600101816135e25783518114156135e8565b83518110155b15611305578360405163ba4adc2360e01b8152600401611a569190613cd4565b806001600160a01b03163b5f0361363d57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401611a56565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516136a79190614398565b5f60405180830381855af49150503d805f81146136df576040519150601f19603f3d011682016040523d82523d5f602084013e6136e4565b606091505b5091509150610e7485838361372c565b3415612cb8576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826137415761373c826137a1565b6119d9565b815115801561375857506001600160a01b0384163b155b1561379a576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401611a56565b50806119d9565b8051156137b15780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260028101928215613811579160200282015b828111156138115782518255916020019190600101906137f6565b506130cd9291505b808211156130cd575f8155600101613819565b80356001600160e01b031981168114613843575f80fd5b919050565b5f60208284031215613858575f80fd5b6119d98261382c565b80356001600160a01b0381168114613843575f80fd5b5f8060408385031215613888575f80fd5b8235915061389860208401613861565b90509250929050565b5f8083601f8401126138b1575f80fd5b50813567ffffffffffffffff8111156138c8575f80fd5b602083019150836020828501011115611305575f80fd5b5f805f805f606086880312156138f3575f80fd5b85359450602086013567ffffffffffffffff80821115613911575f80fd5b61391d89838a016138a1565b90965094506040880135915080821115613935575f80fd5b50613942888289016138a1565b969995985093965092949392505050565b5f8060408385031215613964575f80fd5b50508035926020909101359150565b5f8060408385031215613984575f80fd5b823591506138986020840161382c565b80358015158114613843575f80fd5b5f805f805f80608087890312156139b8575f80fd5b863567ffffffffffffffff808211156139cf575f80fd5b6139db8a838b016138a1565b909850965060208901359150808211156139f3575f80fd5b50613a0089828a016138a1565b9095509350613a13905060408801613861565b9150613a2160608801613994565b90509295509295509295565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f6122576040830184613a2d565b5f805f8060408587031215613a86575f80fd5b843567ffffffffffffffff80821115613a9d575f80fd5b613aa9888389016138a1565b90965094506020870135915080821115613ac1575f80fd5b50613ace878288016138a1565b95989497509550505050565b5f805f60608486031215613aec575f80fd5b505081359360208301359350604090920135919050565b5f60208284031215613b13575f80fd5b5035919050565b5f805f60408486031215613b2c575f80fd5b83359250602084013567ffffffffffffffff811115613b49575f80fd5b613b55868287016138a1565b9497909650939450505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613b9f57613b9f613b62565b604052919050565b5f67ffffffffffffffff821115613bc057613bc0613b62565b50601f01601f191660200190565b5f82601f830112613bdd575f80fd5b8135613bf0613beb82613ba7565b613b76565b818152846020838601011115613c04575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613c31575f80fd5b613c3a83613861565b9150602083013567ffffffffffffffff811115613c55575f80fd5b613c6185828601613bce565b9150509250929050565b5f805f805f60808688031215613c7f575f80fd5b853567ffffffffffffffff811115613c95575f80fd5b613ca1888289016138a1565b90965094505060208601359250613cba60408701613861565b9150613cc860608701613994565b90509295509295909350565b602081525f6119d96020830184613a2d565b5f805f8060608587031215613cf9575f80fd5b8435935060208501359250604085013567ffffffffffffffff811115613d1d575f80fd5b613ace878288016138a1565b5f60208284031215613d39575f80fd5b6119d982613861565b5f8083601f840112613d52575f80fd5b50813567ffffffffffffffff811115613d69575f80fd5b6020830191508360208260051b8501011115611305575f80fd5b5f805f8060608587031215613d96575f80fd5b613d9f85613861565b935060208501359250604085013567ffffffffffffffff811115613dc1575f80fd5b613ace87828801613d42565b5f805f60608486031215613ddf575f80fd5b8335925060208401359150613df660408501613861565b90509250925092565b5f805f60608486031215613e11575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115613e35575f80fd5b613e4186828701613bce565b9150509250925092565b5f8060208385031215613e5c575f80fd5b823567ffffffffffffffff811115613e72575f80fd5b613e7e85828601613d42565b90969095509350505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015613edf57603f19888603018452613ecd858351613a2d565b94509285019290850190600101613eb1565b5092979650505050505050565b5f60208284031215613efc575f80fd5b813567ffffffffffffffff811115613f12575f80fd5b61225784828501613bce565b5f805f60408486031215613f30575f80fd5b83359250602084013567ffffffffffffffff811115613f4d575f80fd5b613b5586828701613d42565b5f805f60608486031215613f6b575f80fd5b83359250613f7b6020850161382c565b9150613df660408501613861565b818382375f9101908152919050565b600181811c90821680613fac57607f821691505b6020821081036124cb57634e487b7160e01b5f52602260045260245ffd5b601f821115612ae657805f5260205f20601f840160051c81016020851015613fef5750805b601f840160051c820191505b8181101561333d575f8155600101613ffb565b67ffffffffffffffff83111561402657614026613b62565b61403a836140348354613f98565b83613fca565b5f601f84116001811461406b575f85156140545750838201355b5f19600387901b1c1916600186901b17835561333d565b5f83815260208120601f198716915b8281101561409a578685013582556020948501946001909201910161407a565b50868210156140b6575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f6141036040830186886140c8565b82810360208401526134c08185876140c8565b602081525f6122576020830184866140c8565b634e487b7160e01b5f52601160045260245ffd5b5f67ffffffffffffffff80831681810361415957614159614129565b6001019392505050565b805160208201516bffffffffffffffffffffffff1980821692919060148310156141975780818460140360031b1b83161693505b505050919050565b815167ffffffffffffffff8111156141b9576141b9613b62565b6141cd816141c78454613f98565b84613fca565b602080601f831160018114614200575f84156141e95750858301515b5f19600386901b1c1916600185901b178555611f5a565b5f85815260208120601f198616915b8281101561422e5788860151825594840194600190910190840161420f565b508582101561424b57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f815160208301516001600160e01b0319808216935060048310156141975760049290920360031b82901b161692915050565b5f602080838503121561429f575f80fd5b825167ffffffffffffffff808211156142b6575f80fd5b818501915085601f8301126142c9575f80fd5b8151818111156142db576142db613b62565b8060051b6142ea858201613b76565b9182528381018501918581019089841115614303575f80fd5b86860192505b838310156143775782518581111561431f575f80fd5b8601603f81018b1361432f575f80fd5b878101516040614341613beb83613ba7565b8281528d82848601011115614354575f80fd5b828285018c83015e5f9281018b0192909252508352509186019190860190614309565b9998505050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f82518060208501845e5f920191825250919050565b6001600160e01b03198135818116916004851015610e775760049490940360031b84901b1690921692915050565b5f808335601e198436030181126143f1575f80fd5b83018035915067ffffffffffffffff82111561440b575f80fd5b602001915036819003821315611305575f80fd5b5f6020828403121561442f575f80fd5b5051919050565b81810381811115610e5357610e53614129565b80820180821115610e5357610e5361412956fea2646970667358221220c298371357a2661f2a63005836391f02d9a0e5e38ab18ffb06624f8e638d437664736f6c634300081900338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x60806040526004361061030e575f3560e01c8063691f34311161019c578063c80ef4e0116100e7578063dfa70d8b11610092578063ecbfada31161006d578063ecbfada314610a25578063f1cb7e0614610a44578063f2d1eb2514610a63578063f41a143d14610a82575f80fd5b8063dfa70d8b146109c8578063e32954eb146109e7578063e59d895d14610a06575f80fd5b8063d3bf89b1116100c2578063d3bf89b1146108ed578063d5fa2b001461095a578063d700ff3314610979575f80fd5b8063c80ef4e01461085b578063c86902331461087a578063ce156e82146108ce575f80fd5b80638b95dd7111610147578063ad3cb1cc11610122578063ad3cb1cc146107d5578063bbd9abb51461081d578063bc1c58d11461083c575f80fd5b80638b95dd711461076b5780639061b9231461078a578063ac9650d8146107a9575f80fd5b8063773722131161017757806377372213146106d7578063781ef8db146106f65780637c3005861461074c575f80fd5b8063691f34311461067a5780636f3ff726146106995780637058b559146106b8575f80fd5b806332f111d71161025c57806352d1902d1161020757806359d1d43c116101e257806359d1d43c146106105780635adf47241461063c578063623195b01461065b575f80fd5b806352d1902d14610594578063582de3e7146105a8578063587eefd1146105f1575f80fd5b80633b3b57de116102375780633b3b57de146105435780634eb9c45e146105625780634f1ef28614610581575f80fd5b806332f111d7146104d15780633603d758146104f05780633634f9111461050f575f80fd5b80631c3fc3eb116102bc57806329cd62ea1161029757806329cd62ea146104685780632f27fa2414610487578063304e6ade146104b2575f80fd5b80631c3fc3eb146103fb5780632203ab561461041c578063291770ae14610449575f80fd5b806311b8e00a116102ec57806311b8e00a14610386578063124a319c146103a55780631a76b72c146103dc575f80fd5b806301ffc9a714610312578063072d5d771461034657806310f13a8c14610365575b5f80fd5b34801561031d575f80fd5b5061033161032c366004613848565b610aa2565b60405190151581526020015b60405180910390f35b348015610351575f80fd5b50610331610360366004613877565b610e59565b348015610370575f80fd5b5061038461037f3660046138df565b610e7f565b005b348015610391575f80fd5b506103316103a0366004613953565b61100f565b3480156103b0575f80fd5b506103c46103bf366004613973565b611026565b6040516001600160a01b03909116815260200161033d565b3480156103e7575f80fd5b506103316103f63660046139a3565b61109b565b348015610406575f80fd5b5061040e5f81565b60405190815260200161033d565b348015610427575f80fd5b5061043b610436366004613953565b6111f0565b60405161033d929190613a5b565b348015610454575f80fd5b50610384610463366004613a73565b61130c565b348015610473575f80fd5b50610384610482366004613ada565b6113ef565b348015610492575f80fd5b5061040e6104a1366004613b03565b5f9081526001602052604090205490565b3480156104bd575f80fd5b506103846104cc366004613b1a565b611493565b3480156104dc575f80fd5b506103316104eb366004613953565b611518565b3480156104fb575f80fd5b5061038461050a366004613b03565b611567565b34801561051a575f80fd5b5061052e610529366004613953565b611617565b6040805192835260208301919091520161033d565b34801561054e575f80fd5b506103c461055d366004613b03565b61163a565b34801561056d575f80fd5b5061038461057c3660046138df565b611658565b61038461058f366004613c20565b6117b2565b34801561059f575f80fd5b5061040e6117d1565b3480156105b3575f80fd5b506103316105c2366004613848565b6001600160e01b0319167f96b62db8000000000000000000000000000000000000000000000000000000001490565b3480156105fc575f80fd5b5061033161060b366004613c6b565b6117ff565b34801561061b575f80fd5b5061062f61062a366004613b1a565b611900565b60405161033d9190613cd4565b348015610647575f80fd5b5061040e610656366004613877565b6119e0565b348015610666575f80fd5b50610384610675366004613ce6565b611a05565b348015610685575f80fd5b5061062f610694366004613b03565b611ae6565b3480156106a4575f80fd5b506103316106b3366004613d29565b611ba5565b3480156106c3575f80fd5b506103846106d2366004613d83565b611bf6565b3480156106e2575f80fd5b506103846106f1366004613b1a565b611d36565b348015610701575f80fd5b50610331610710366004613877565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b348015610757575f80fd5b50610331610766366004613dcd565b611dc0565b348015610776575f80fd5b50610384610785366004613dff565b611df4565b348015610795575f80fd5b5061062f6107a4366004613a73565b611f62565b3480156107b4575f80fd5b506107c86107c3366004613e4b565b61225f565b60405161033d9190613e8a565b3480156107e0575f80fd5b5061062f6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b348015610828575f80fd5b50610331610837366004613c6b565b612366565b348015610847575f80fd5b5061062f610856366004613b03565b61244e565b348015610866575f80fd5b5061062f610875366004613eec565b612487565b348015610885575f80fd5b5061052e610894366004613b03565b5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902060018101546002909101549091565b3480156108d9575f80fd5b506103316108e8366004613877565b6124d1565b3480156108f8575f80fd5b50610331610907366004613dcd565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b348015610965575f80fd5b50610384610974366004613877565b6124ec565b348015610984575f80fd5b506109af610993366004613b03565b5f908152610103602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff909116815260200161033d565b3480156109d3575f80fd5b506103316109e2366004613dcd565b612528565b3480156109f2575f80fd5b506107c8610a01366004613f1e565b61255c565b348015610a11575f80fd5b50610384610a20366004613f59565b612568565b348015610a30575f80fd5b5061062f610a3f366004613b1a565b612621565b348015610a4f575f80fd5b5061062f610a5e366004613953565b612662565b348015610a6e575f80fd5b50610331610a7d3660046139a3565b6127ee565b348015610a8d575f80fd5b50610331610a9c366004613d29565b50600190565b5f7f91413117000000000000000000000000000000000000000000000000000000006001600160e01b031983161480610b0457507f9061b923000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610b3857507f582de3e7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610b6c57507f4fbf0433000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610ba057507f2203ab56000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610bd457507f3b3b57de000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c0857507ff1cb7e06000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c3c57507fbc1c58d1000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610c7057507fecbfada3000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610ca457507f32f111d7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610cd857507f124a319c000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d0c57507f691f3431000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d4057507fc8690233000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d7457507f59d1d43c000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610da857507fd700ff33000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610ddc57507fb0f3d367000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e1057507ff41a143d000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e4457507f6f3ff726000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610e535750610e53826128f7565b92915050565b5f8083610e67828233612944565b610e745f86866001612992565b92505b505092915050565b84610ebe85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612aa292505050565b6010811580610f335750610f1c610ed58484612aad565b5f908152602081815260408083203384528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925290912054178216821490565b158015610f335750610f31610ed55f84612aad565b155b15610f4c57610f4c610f45845f612aad565b8233612acf565b8484610f808a5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b6005018989604051610f93929190613f89565b90815260200160405180910390209182610fae92919061400e565b508686604051610fbf929190613f89565b6040518091039020887f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a189898989604051610ffd94939291906140f0565b60405180910390a35050505050505050565b5f8061101b8484611617565b501515949350505050565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083206001600160e01b0319851684526008019091529020546001600160a01b031680610e53575f61107f8461163a565b905061108b8184612aeb565b15611094578091505b5092915050565b5f806110db88888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b90506410000000005f6110ee8382612aad565b90505f611138846111338b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612aa292505050565b612aad565b905085156111ce5761114b828433612944565b5f818152600160205260409020545f036111b657888860405161116f929190613f89565b6040518091039020817fdb7aa4f21d01358b79d5574f3f3f6805f4f97606c53cb70598063387352206ac8d8d8d8d6040516111ad94939291906140f0565b60405180910390a35b6111c38184896001612992565b9450505050506111e6565b6111d9828433612b37565b6111c38184896001612b7f565b9695505050505050565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206001906060905b5f831180156112315750838311155b156112f157828416156112e5575f8381526007820160205260409020805461125890613f98565b80601f016020809104026020016040519081016040528092919081815260200182805461128490613f98565b80156112cf5780601f106112a6576101008083540402835291602001916112cf565b820191905f5260205f20905b8154815290600101906020018083116112b257829003601f168201915b505050505091505f825111156112e55750611305565b600183901b9250611222565b505060408051602081019091525f80825291505b9250929050565b631000000061131c5f8233612acf565b82826101025f61136089898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b81526020019081526020015f20918261137a92919061400e565b50828260405161138b929190613f89565b604051809103902085856040516113a3929190613f89565b60405180910390207fa8c2ea0876733fd2146051b3e195e5e1d1f85eff08bf169191dce9569281c529878787876040516113e094939291906140f0565b60405180910390a35050505050565b825f611000611401610f45845f612aad565b60408051808201825286815260208082018790525f898152610104825283812061010383528482205467ffffffffffffffff1682529091529190912060010190600261144e9291906137e3565b50604080518681526020810186905287917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a2505050505050565b825f6101006114a5610f45845f612aad565b84846114d9885f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b916114e591908361400e565b50857fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788686604051611483929190614116565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083208484526004019091528120805482919061155c90613f98565b905011905092915050565b805f64010000000061157c610f45845f612aad565b5f84815261010360205260408120805482906115a19067ffffffffffffffff1661413d565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790559050847fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db44482604051611608919067ffffffffffffffff91909116815260200190565b60405180910390a25050505050565b5f8061162283612be7565b5f948552600160205260409094205484169492505050565b5f61164682603c612662565b61164f90614163565b60601c92915050565b8461169785858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612aa292505050565b6410000000008115806116c957506116b2610ed58484612aad565b1580156116c957506116c7610ed55f84612aad565b155b156116db576116db610f45845f612aad565b848461170f8a5f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b6006018989604051611722929190613f89565b9081526020016040518091039020918261173d92919061400e565b50848460405161174e929190613f89565b60405180910390208787604051611766929190613f89565b6040518091039020897f3b7ea3580e046bf897ca24f2f45fcf5491dafba8d1b3dd17ca92aa0e82b4dd218a8a6040516117a0929190614116565b60405180910390a45050505050505050565b6117ba612c01565b6117c382612cba565b6117cd8282612cd6565b5050565b5f6117da612dbe565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f8061183f87878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b905060015f61184e8382612aad565b90505f611864846111338a5f9081526020902090565b905085156118df57611877828433612944565b5f818152600160205260409020545f036118c75787817f2fe6caf984256b1a1844b92f52cf88703e829b07ce397a6c7fcf1f779db7a1858c8c6040516118be929190614116565b60405180910390a35b6118d48184896001612992565b9450505050506118f7565b6118ea828433612b37565b6118d48184896001612b7f565b95945050505050565b5f8381526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906005018383604051611941929190613f89565b9081526020016040518091039020805461195a90613f98565b80601f016020809104026020016040519081016040528092919081815260200182805461198690613f98565b80156119d15780601f106119a8576101008083540402835291602001916119d1565b820191905f5260205f20905b8154815290600101906020018083116119b457829003601f168201915b505050505090505b9392505050565b5f828152602081815260408083206001600160a01b03851684529091528120546119d9565b835f62010000611a18610f45845f612aad565b611a2186612e07565b611a5f576040517f5742bb26000000000000000000000000000000000000000000000000000000008152600481018790526024015b60405180910390fd5b8484611a93895f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b5f8981526007919091016020526040902091611ab091908361400e565b50604051869088907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3905f90a350505050505050565b5f8181526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906003018054611b2290613f98565b80601f0160208091040260200160405190810160405280929190818152602001828054611b4e90613f98565b8015611b995780601f10611b7057610100808354040283529160200191611b99565b820191905f5260205f20905b815481529060010190602001808311611b7c57829003601f168201915b50505050509050919050565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb560205260408120546f0100000000000000000000000000000090811614610e53565b5f611bff612e26565b805490915060ff68010000000000000000820416159067ffffffffffffffff165f81158015611c2b5750825b90505f8267ffffffffffffffff166001148015611c475750303b155b905081158015611c55575080155b15611c8c576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315611cc057845468ff00000000000000001916680100000000000000001785555b611cc8612e4e565b611cd45f898b5f612992565b50611cdf878761225f565b508315611d2b57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b825f6301000000611d4a610f45845f612aad565b8484611d7e885f9081526101046020908152604080832061010383528184205467ffffffffffffffff168452909152902090565b60030191611d8d91908361400e565b50857fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78686604051611483929190614116565b60405163d1a3b35560e01b815260048101849052602481018390526001600160a01b03821660448201525f90606401611a56565b5f8281526020902083906001811580611e2c5750611e15610ed58484612aad565b158015611e2c5750611e2a610ed55f84612aad565b155b15611e3e57611e3e610f45845f612aad565b835115801590611e5057508351601414155b8015611e605750611e6085612e56565b15611e9957836040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401611a569190613cd4565b5f8681526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083208884526004019091529020611ed9858261419f565b50857f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528686604051611f0c929190613a5b565b60405180910390a2603c8503611f5a57857f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd2611f4786614163565b60405160609190911c8152602001611483565b505050505050565b60605f611fa386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061248792505050565b90505f611ffd8585611ff885515f14611fbc5785611ff2565b8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050505b5f612b06565b612e7b565b90507fac9650d8000000000000000000000000000000000000000000000000000000006120298261425b565b6001600160e01b031916036121ab578051600319810160048301908152915f9161205c919081016020019060240161428e565b90505f5b81518110156121805781818151811061207b5761207b614384565b602002602001015192505f306001600160a01b03168460405161209e9190614398565b5f60405180830381855afa9150503d805f81146120d6576040519150601f19603f3d011682016040523d82523d5f602084013e6120db565b606091505b5091505080515f0361215957637b1c461b60e01b6120f88561425b565b6040516001600160e01b0319909116602482015260440160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290505b8083838151811061216c5761216c614384565b602090810291909101015250600101612060565b50806040516020016121929190613e8a565b6040516020818303038152906040529350505050612257565b5f80306001600160a01b0316836040516121c59190614398565b5f60405180830381855afa9150503d805f81146121fd576040519150601f19603f3d011682016040523d82523d5f602084013e612202565b606091505b50915091508161221457805160208201fd5b80515f0361224c5761222686886143ae565b604051637b1c461b60e01b81526001600160e01b03199091166004820152602401611a56565b935061225792505050565b949350505050565b60608167ffffffffffffffff81111561227a5761227a613b62565b6040519080825280602002602001820160405280156122ad57816020015b60608152602001906001900390816122985790505b5090505f5b82811015611094575f80308686858181106122cf576122cf614384565b90506020028101906122e191906143dc565b6040516122ef929190613f89565b5f60405180830381855af49150503d805f8114612327576040519150601f19603f3d011682016040523d82523d5f602084013e61232c565b606091505b50915091508161233e57805160208201fd5b8084848151811061235157612351614384565b602090810291909101015250506001016122b2565b5f806123a687878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b90505f6123b38282612aad565b90508315612436576123c6818733612944565b80158015906123e057505f81815260016020526040902054155b1561242057807f737038e72be1d204e2c7336c20bff2169d9dffe11face28c5969af4ecce04f678989604051612417929190614116565b60405180910390a25b61242d8187876001612992565b925050506118f7565b612441818733612b37565b61242d8187876001612b7f565b5f8181526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060908054611b2290613f98565b60605f5b606061249684612f58565b80519095509091505f036124aa57506124cb565b805160208201208281036124bf5750506124cb565b849350915061248b9050565b50919050565b5f80836124df828233612b37565b610e745f86866001612b7f565b6040516bffffffffffffffffffffffff19606083901b1660208201526117cd908390603c90603401604051602081830303815290604052611df4565b6040516314c09c6360e31b815260048101849052602481018390526001600160a01b03821660448201525f90606401611a56565b6060612257838361225f565b825f6210000061257b610f45845f612aad565b5f8681526101046020908152604080832061010383528184205467ffffffffffffffff16845282528083206001600160e01b031989168085526008909101835292819020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0389169081179091558151908152905189927f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa928290030190a3505050505050565b5f8381526101046020908152604080832061010383528184205467ffffffffffffffff16845290915290206060906006018383604051611941929190613f89565b5f8281526101046020908152604080832061010383528184205467ffffffffffffffff168452825280832084845260048101909252909120805460609291906126aa90613f98565b80601f01602080910402602001604051908101604052809291908181526020018280546126d690613f98565b80156127215780601f106126f857610100808354040283529160200191612721565b820191905f5260205f20905b81548152906001019060200180831161270457829003601f168201915b5050505050915081515f14801561274557505f61273d846130a7565b63ffffffff16115b156110945763800000005f9081526004820160205260409020805461276990613f98565b80601f016020809104026020016040519081016040528092919081815260200182805461279590613f98565b80156127e05780601f106127b7576101008083540402835291602001916127e0565b820191905f5260205f20905b8154815290600101906020018083116127c357829003601f168201915b505050505091505092915050565b5f8061282e88888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612b06915050565b905060105f61283d8382612aad565b90505f612882846111338b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612aa292505050565b905085156111ce57612895828433612944565b5f818152600160205260409020545f036111b65788886040516128b9929190613f89565b6040518091039020817fab228e072dd20e63d6891264ea8f6a2459e6852ab494b707970f978ba630859c8d8d8d8d6040516111ad94939291906140f0565b5f6001600160e01b031982167f8f452d62000000000000000000000000000000000000000000000000000000001480610e5357506301ffc9a760e01b6001600160e01b0319831614610e53565b5f61294f84836130d1565b9050801983161561298c5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401611a56565b50505050565b5f835f036129a157505f612257565b6129aa84613148565b6001600160a01b0383166129ea576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214612a98575f878152602081815260408083206001600160a01b0389168452909152902081905581198616612a46888260016131a8565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050612257565b5f92505050612257565b805160209091012090565b5f82151580612abb57508115155b15610e5357505f9182526020526040902090565b612ad7613344565b612ae657612ae6838383613362565b505050565b5f612af5836133fe565b80156119d957506119d98383613430565b5f612b1183836134cb565b925090508015610e53576119d9612b288484612b06565b825f9182526020526040902090565b5f612b4284836130d1565b9050801983161561298c576040516314c09c6360e31b815260048101859052602481018490526001600160a01b0383166044820152606401611a56565b5f612b8984613148565b5f858152602081815260408083206001600160a01b038716845290915290205484198116808214612a98575f878152602081815260408083206001600160a01b0389168452909152812082905586831690612a4690899083906131a8565b5f612bf182613148565b50600181901b17600281901b1790565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480612c9a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612c8e7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b15612cb85760405163703e46dd60e11b815260040160405180910390fd5b565b6f100000000000000000000000000000006117cd5f8233612acf565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612d30575060408051601f3d908101601f19168201909252612d2d9181019061441f565b60015b612d5857604051634c9c8ce360e01b81526001600160a01b0383166004820152602401611a56565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612db4576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401611a56565b612ae683836134f8565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612cb85760405163703e46dd60e11b815260040160405180910390fd5b5f8082118015610e53575081612e1e600182614436565b161592915050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610e53565b612cb861354d565b5f6380000000821480610e5357505f612e6e836130a7565b63ffffffff161192915050565b606083838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929350612f4a92505050565b602481019050600481035160e01c63ac9650d88114612eea5781831015612ee25750505050565b83825261298c565b815182019180831015612efe575050505050565b825160051b5b8015611f5a5760208401915080840151820182811015612f245750612f41565b8051810180871015612f335750855b612f3e888284612ebb565b50505b601f1901612f04565b6119d9828251830183612ebb565b6060805f5b83518110156130a1576101025f612f748684612b06565b81526020019081526020015f208054612f8c90613f98565b80601f0160208091040260200160405190810160405280929190818152602001828054612fb890613f98565b80156130035780601f10612fda57610100808354040283529160200191613003565b820191905f5260205f20905b815481529060010190602001808311612fe657829003601f168201915b505050505092505f8351111561308e5780156130865782516130259082614449565b67ffffffffffffffff81111561303d5761303d613b62565b6040519080825280601f01601f191660200182016040528015613067576020820181803683370190505b5091508060208501602084015e8251602084018260200184015e6130a1565b8291506130a1565b613098848261358b565b9150612f5d9050565b50915091565b5f603c82036130b857506001919050565b63800000009182189182106130cd575f610e53565b5090565b5f828152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925282205417608081901c7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176119d9565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156131a5576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401611a56565b50565b5f6131b283612be7565b9050811561327b575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615613253576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401611a56565b5f8481526001602052604081208054859290613270908490614449565b9091555061298c9050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615613315576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401611a56565b5f8481526001602052604081208054859290613332908490614436565b909155505050505050565b5050505050565b5f61334d612e26565b5468010000000000000000900460ff16919050565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5909252909120541782168214612ae6576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401611a56565b5f613410826301ffc9a760e01b613430565b8015610e535750613429826001600160e01b0319613430565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f5190508280156134b5575060208210155b80156134c057505f81115b979650505050505050565b5f805f6134d8858561358b565b9250905060ff8116156134f057806021858701012092505b509250929050565b61350182613608565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561354557612ae6828261368b565b6117cd6136f4565b613555613344565b612cb8576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80835183106135b0578360405163ba4adc2360e01b8152600401611a569190613cd4565b8383815181106135c2576135c2614384565b016020015160f81c915050818101600101816135e25783518114156135e8565b83518110155b15611305578360405163ba4adc2360e01b8152600401611a569190613cd4565b806001600160a01b03163b5f0361363d57604051634c9c8ce360e01b81526001600160a01b0382166004820152602401611a56565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516136a79190614398565b5f60405180830381855af49150503d805f81146136df576040519150601f19603f3d011682016040523d82523d5f602084013e6136e4565b606091505b5091509150610e7485838361372c565b3415612cb8576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826137415761373c826137a1565b6119d9565b815115801561375857506001600160a01b0384163b155b1561379a576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401611a56565b50806119d9565b8051156137b15780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260028101928215613811579160200282015b828111156138115782518255916020019190600101906137f6565b506130cd9291505b808211156130cd575f8155600101613819565b80356001600160e01b031981168114613843575f80fd5b919050565b5f60208284031215613858575f80fd5b6119d98261382c565b80356001600160a01b0381168114613843575f80fd5b5f8060408385031215613888575f80fd5b8235915061389860208401613861565b90509250929050565b5f8083601f8401126138b1575f80fd5b50813567ffffffffffffffff8111156138c8575f80fd5b602083019150836020828501011115611305575f80fd5b5f805f805f606086880312156138f3575f80fd5b85359450602086013567ffffffffffffffff80821115613911575f80fd5b61391d89838a016138a1565b90965094506040880135915080821115613935575f80fd5b50613942888289016138a1565b969995985093965092949392505050565b5f8060408385031215613964575f80fd5b50508035926020909101359150565b5f8060408385031215613984575f80fd5b823591506138986020840161382c565b80358015158114613843575f80fd5b5f805f805f80608087890312156139b8575f80fd5b863567ffffffffffffffff808211156139cf575f80fd5b6139db8a838b016138a1565b909850965060208901359150808211156139f3575f80fd5b50613a0089828a016138a1565b9095509350613a13905060408801613861565b9150613a2160608801613994565b90509295509295509295565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f6122576040830184613a2d565b5f805f8060408587031215613a86575f80fd5b843567ffffffffffffffff80821115613a9d575f80fd5b613aa9888389016138a1565b90965094506020870135915080821115613ac1575f80fd5b50613ace878288016138a1565b95989497509550505050565b5f805f60608486031215613aec575f80fd5b505081359360208301359350604090920135919050565b5f60208284031215613b13575f80fd5b5035919050565b5f805f60408486031215613b2c575f80fd5b83359250602084013567ffffffffffffffff811115613b49575f80fd5b613b55868287016138a1565b9497909650939450505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613b9f57613b9f613b62565b604052919050565b5f67ffffffffffffffff821115613bc057613bc0613b62565b50601f01601f191660200190565b5f82601f830112613bdd575f80fd5b8135613bf0613beb82613ba7565b613b76565b818152846020838601011115613c04575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613c31575f80fd5b613c3a83613861565b9150602083013567ffffffffffffffff811115613c55575f80fd5b613c6185828601613bce565b9150509250929050565b5f805f805f60808688031215613c7f575f80fd5b853567ffffffffffffffff811115613c95575f80fd5b613ca1888289016138a1565b90965094505060208601359250613cba60408701613861565b9150613cc860608701613994565b90509295509295909350565b602081525f6119d96020830184613a2d565b5f805f8060608587031215613cf9575f80fd5b8435935060208501359250604085013567ffffffffffffffff811115613d1d575f80fd5b613ace878288016138a1565b5f60208284031215613d39575f80fd5b6119d982613861565b5f8083601f840112613d52575f80fd5b50813567ffffffffffffffff811115613d69575f80fd5b6020830191508360208260051b8501011115611305575f80fd5b5f805f8060608587031215613d96575f80fd5b613d9f85613861565b935060208501359250604085013567ffffffffffffffff811115613dc1575f80fd5b613ace87828801613d42565b5f805f60608486031215613ddf575f80fd5b8335925060208401359150613df660408501613861565b90509250925092565b5f805f60608486031215613e11575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115613e35575f80fd5b613e4186828701613bce565b9150509250925092565b5f8060208385031215613e5c575f80fd5b823567ffffffffffffffff811115613e72575f80fd5b613e7e85828601613d42565b90969095509350505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015613edf57603f19888603018452613ecd858351613a2d565b94509285019290850190600101613eb1565b5092979650505050505050565b5f60208284031215613efc575f80fd5b813567ffffffffffffffff811115613f12575f80fd5b61225784828501613bce565b5f805f60408486031215613f30575f80fd5b83359250602084013567ffffffffffffffff811115613f4d575f80fd5b613b5586828701613d42565b5f805f60608486031215613f6b575f80fd5b83359250613f7b6020850161382c565b9150613df660408501613861565b818382375f9101908152919050565b600181811c90821680613fac57607f821691505b6020821081036124cb57634e487b7160e01b5f52602260045260245ffd5b601f821115612ae657805f5260205f20601f840160051c81016020851015613fef5750805b601f840160051c820191505b8181101561333d575f8155600101613ffb565b67ffffffffffffffff83111561402657614026613b62565b61403a836140348354613f98565b83613fca565b5f601f84116001811461406b575f85156140545750838201355b5f19600387901b1c1916600186901b17835561333d565b5f83815260208120601f198716915b8281101561409a578685013582556020948501946001909201910161407a565b50868210156140b6575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f6141036040830186886140c8565b82810360208401526134c08185876140c8565b602081525f6122576020830184866140c8565b634e487b7160e01b5f52601160045260245ffd5b5f67ffffffffffffffff80831681810361415957614159614129565b6001019392505050565b805160208201516bffffffffffffffffffffffff1980821692919060148310156141975780818460140360031b1b83161693505b505050919050565b815167ffffffffffffffff8111156141b9576141b9613b62565b6141cd816141c78454613f98565b84613fca565b602080601f831160018114614200575f84156141e95750858301515b5f19600386901b1c1916600185901b178555611f5a565b5f85815260208120601f198616915b8281101561422e5788860151825594840194600190910190840161420f565b508582101561424b57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f815160208301516001600160e01b0319808216935060048310156141975760049290920360031b82901b161692915050565b5f602080838503121561429f575f80fd5b825167ffffffffffffffff808211156142b6575f80fd5b818501915085601f8301126142c9575f80fd5b8151818111156142db576142db613b62565b8060051b6142ea858201613b76565b9182528381018501918581019089841115614303575f80fd5b86860192505b838310156143775782518581111561431f575f80fd5b8601603f81018b1361432f575f80fd5b878101516040614341613beb83613ba7565b8281528d82848601011115614354575f80fd5b828285018c83015e5f9281018b0192909252508352509186019190860190614309565b9998505050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f82518060208501845e5f920191825250919050565b6001600160e01b03198135818116916004851015610e775760049490940360031b84901b1690921692915050565b5f808335601e198436030181126143f1575f80fd5b83018035915067ffffffffffffffff82111561440b575f80fd5b602001915036819003821315611305575f80fd5b5f6020828403121561442f575f80fd5b5051919050565b81810381811115610e5357610e53614129565b80820180821115610e5357610e5361412956fea2646970667358221220c298371357a2661f2a63005836391f02d9a0e5e38ab18ffb06624f8e638d437664736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "29968": [ + { + "length": 32, + "start": 11276 + }, + { + "length": 32, + "start": 11317 + }, + { + "length": 32, + "start": 11721 + } + ] + }, + "inputSourceName": "project/src/resolver/PermissionedResolver.sol", + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "InvalidContentType(uint256)": [ + { + "details": "Error selector: `0x5742bb26`" + } + ], + "InvalidEVMAddress(bytes)": [ + { + "details": "Error selector: `0x8d666f60`" + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ], + "UnsupportedResolverProfile(bytes4)": [ + { + "details": "Error selector: `0x7b1c461b`" + } + ] + }, + "events": { + "AliasChanged(bytes,bytes,bytes,bytes)": { + "params": { + "fromName": "The source DNS-encoded name.", + "indexedFromName": "The source DNS-encoded name. (indexed bytes, hashed)", + "indexedToName": "The destination DNS-encoded name. (indexed bytes, hashed)", + "toName": "The destination DNS-encoded name." + } + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "NamedAddrResource(uint256,bytes,uint256)": { + "params": { + "coinType": "The coin type.", + "name": "The name.", + "resource": "The EAC resource." + } + }, + "NamedDataResource(uint256,bytes,bytes32,string)": { + "params": { + "key": "The key.", + "keyHash": "The hash of the key.", + "name": "The name.", + "resource": "The EAC resource." + } + }, + "NamedResource(uint256,bytes)": { + "params": { + "name": "The name.", + "resource": "The EAC resource." + } + }, + "NamedTextResource(uint256,bytes,bytes32,string)": { + "params": { + "key": "The key.", + "keyHash": "The hash of the key.", + "name": "The name.", + "resource": "The EAC resource." + } + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "ABI(bytes32,uint256)": { + "params": { + "contentTypes": "A bitwise OR of the ABI formats accepted by the caller.", + "node": "The ENS node to query" + }, + "returns": { + "contentType": "The content type of the return value", + "value": "data The ABI data" + } + }, + "addr(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated address." + } + }, + "authorizeAddrRoles(bytes,uint256,address,bool)": { + "params": { + "account": "The account to authorize roles to.", + "coinType": "The coin type to authorize roles for.", + "grant": "If `true`, grants, otherwise, revokes.", + "toName": "The name to authorize roles for." + }, + "returns": { + "updated": "`true` if the roles were updated." + } + }, + "authorizeDataRoles(bytes,string,address,bool)": { + "params": { + "account": "The account to authorize roles to.", + "grant": "If `true`, grants, otherwise, revokes.", + "key": "The data key to authorize roles for.", + "toName": "The name to authorize roles for." + }, + "returns": { + "_0": "`true` if the roles were updated." + } + }, + "authorizeNameRoles(bytes,uint256,address,bool)": { + "params": { + "account": "The account to authorize roles to.", + "grant": "If `true`, grants, otherwise, revokes.", + "roleBitmap": "The roles to authorize.", + "toName": "The name to authorize roles for." + }, + "returns": { + "_0": "success Whether the roles were updated." + } + }, + "authorizeTextRoles(bytes,string,address,bool)": { + "params": { + "account": "The account to authorize roles to.", + "grant": "If `true`, grants, otherwise, revokes.", + "key": "The text key to authorize roles for.", + "toName": "The name to authorize roles for." + }, + "returns": { + "_0": "`true` if the roles were updated." + } + }, + "canUpgradeFrom(address)": { + "details": "Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call.", + "params": { + "": "{previousImplementation} Ignored." + }, + "returns": { + "allowed": "Always `true` for implementations in this resolver family." + } + }, + "clearRecords(bytes32)": { + "params": { + "node": "The node to update." + } + }, + "constructor": { + "params": { + "namer": "The implementation namer." + } + }, + "contenthash(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated contenthash." + } + }, + "data(bytes32,string)": { + "params": { + "key": "The key.", + "node": "The node (namehash) for which data is being fetched." + }, + "returns": { + "_0": "The associated arbitrary `bytes` data." + } + }, + "getAlias(bytes)": { + "params": { + "fromName": "The source DNS-encoded name." + }, + "returns": { + "toName": "The destination DNS-encoded name or empty if not aliased." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "Ignored.", + "resource": "Ignored.", + "roleBitmap": "Ignored." + }, + "returns": { + "_0": "success Ignored, always reverts." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAddr(bytes32,uint256)": { + "params": { + "coinType": "The coin type.", + "node": "The node to query." + }, + "returns": { + "_0": "True if the associated address is not empty." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "initialize(address,uint256,bytes[])": { + "params": { + "admin": "The resolver owner.", + "roleBitmap": "The roles granted to `admin`.", + "setters": "The setter calldata that avoids permission checks." + } + }, + "interfaceImplementer(bytes32,bytes4)": { + "params": { + "interfaceID": "The EIP 165 interface ID to check for.", + "node": "The ENS node to query." + }, + "returns": { + "implementer": "The address that implements this interface, or 0 if the interface is unsupported." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "multicall(bytes[])": { + "details": "Reverts with first error.", + "params": { + "calls": "The calls to make." + }, + "returns": { + "results": "The results of the calls." + } + }, + "multicallWithNodeCheck(bytes32,bytes[])": { + "details": "The node parameter is accepted for interface compatibility but is not used. Permission checking is handled by individual function calls within the multicall.", + "params": { + "": "{node} Ignored, for interface compatibility.", + "calls": "The calls to make." + }, + "returns": { + "_0": "results The results of the calls." + } + }, + "name(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated name." + } + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "pubkey(bytes32)": { + "params": { + "node": "The ENS node to query" + }, + "returns": { + "x": "The X coordinate of the curve point for the public key.", + "y": "The Y coordinate of the curve point for the public key." + } + }, + "recordVersions(bytes32)": { + "params": { + "node": "The node to check." + }, + "returns": { + "_0": "version The current version." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "Ignored.", + "resource": "Ignored.", + "roleBitmap": "Ignored." + }, + "returns": { + "_0": "success Ignored, always reverts." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "setABI(bytes32,uint256,bytes)": { + "params": { + "contentType": "The content type of the ABI.", + "node": "The node to update.", + "value": "The ABI data." + } + }, + "setAddr(bytes32,address)": { + "params": { + "addr_": "The mainnet address.", + "node": "The node to update." + } + }, + "setAddr(bytes32,uint256,bytes)": { + "params": { + "addressBytes": "The encoded address.", + "coinType": "The coin type.", + "node": "The node to update." + } + }, + "setAlias(bytes,bytes)": { + "params": { + "fromName": "The source DNS-encoded name.", + "toName": "The destination DNS-encoded name." + } + }, + "setContenthash(bytes32,bytes)": { + "params": { + "hash": "The contenthash to set.", + "node": "The node to update." + } + }, + "setData(bytes32,string,bytes)": { + "params": { + "key": "The data key.", + "node": "The node to update.", + "value": "The data value." + } + }, + "setInterface(bytes32,bytes4,address)": { + "params": { + "implementer": "The address of the contract that implements this interface for this node.", + "interfaceId": "The EIP-165 interface ID.", + "node": "The node to update." + } + }, + "setName(bytes32,string)": { + "params": { + "node": "The node to update.", + "primary": "The primary name." + } + }, + "setPubkey(bytes32,bytes32,bytes32)": { + "params": { + "node": "The node to update.", + "x": "The x coordinate of the public key.", + "y": "The y coordinate of the public key." + } + }, + "setText(bytes32,string,string)": { + "params": { + "key": "The text key.", + "node": "The node to update.", + "value": "The text value." + } + }, + "supportsFeature(bytes4)": { + "params": { + "featureId": "The feature identifier." + }, + "returns": { + "_0": "`true` if the feature is supported by the contract." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "text(bytes32,string)": { + "params": { + "key": "The text data key to query.", + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated text data." + } + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + } + }, + "stateVariables": { + "_aliases": { + "details": "Aliases for names." + }, + "_records": { + "details": "Records for nodes." + }, + "_versions": { + "details": "Versions for nodes." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "3510800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ABI(bytes32,uint256)": "infinite", + "ROOT_RESOURCE()": "262", + "UPGRADE_INTERFACE_VERSION()": "infinite", + "addr(bytes32)": "infinite", + "addr(bytes32,uint256)": "infinite", + "authorizeAddrRoles(bytes,uint256,address,bool)": "infinite", + "authorizeDataRoles(bytes,string,address,bool)": "infinite", + "authorizeNameRoles(bytes,uint256,address,bool)": "infinite", + "authorizeTextRoles(bytes,string,address,bool)": "infinite", + "canUpgradeFrom(address)": "480", + "clearRecords(bytes32)": "infinite", + "contenthash(bytes32)": "infinite", + "data(bytes32,string)": "infinite", + "getAlias(bytes)": "infinite", + "getAssigneeCount(uint256,uint256)": "2749", + "grantRoles(uint256,uint256,address)": "594", + "grantRootRoles(uint256,address)": "infinite", + "hasAddr(bytes32,uint256)": "4985", + "hasAssignees(uint256,uint256)": "2733", + "hasRoles(uint256,uint256,address)": "4894", + "hasRootRoles(uint256,address)": "2654", + "initialize(address,uint256,bytes[])": "infinite", + "interfaceImplementer(bytes32,bytes4)": "infinite", + "isContractNamer(address)": "2669", + "multicall(bytes[])": "infinite", + "multicallWithNodeCheck(bytes32,bytes[])": "infinite", + "name(bytes32)": "infinite", + "proxiableUUID()": "infinite", + "pubkey(bytes32)": "6905", + "recordVersions(bytes32)": "2561", + "resolve(bytes,bytes)": "infinite", + "revokeRoles(uint256,uint256,address)": "549", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "2525", + "roles(uint256,address)": "2751", + "setABI(bytes32,uint256,bytes)": "infinite", + "setAddr(bytes32,address)": "infinite", + "setAddr(bytes32,uint256,bytes)": "infinite", + "setAlias(bytes,bytes)": "infinite", + "setContenthash(bytes32,bytes)": "infinite", + "setData(bytes32,string,bytes)": "infinite", + "setInterface(bytes32,bytes4,address)": "infinite", + "setName(bytes32,string)": "infinite", + "setPubkey(bytes32,bytes32,bytes32)": "infinite", + "setText(bytes32,string,string)": "infinite", + "supportsFeature(bytes4)": "463", + "supportsInterface(bytes4)": "infinite", + "text(bytes32,string)": "infinite", + "upgradeToAndCall(address,bytes)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite", + "_checkRoles(uint256,uint256,address)": "infinite", + "_isPowerOf2(uint256)": "140", + "_record(bytes32)": "infinite", + "_resolveAlias(bytes memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"InvalidContentType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"selector\",\"type\":\"bytes4\"}],\"name\":\"UnsupportedResolverProfile\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"ABIChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"a\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newAddress\",\"type\":\"bytes\"}],\"name\":\"AddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"indexedFromName\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"indexedToName\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"fromName\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"}],\"name\":\"AliasChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"ContenthashChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"indexedData\",\"type\":\"bytes\"}],\"name\":\"DataChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"name\":\"InterfaceChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"NamedAddrResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"NamedDataResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"NamedResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"NamedTextResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"PubkeyChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newVersion\",\"type\":\"uint64\"}],\"name\":\"VersionChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"contentTypes\",\"type\":\"uint256\"}],\"name\":\"ABI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"grant\",\"type\":\"bool\"}],\"name\":\"authorizeAddrRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"updated\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"grant\",\"type\":\"bool\"}],\"name\":\"authorizeDataRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"grant\",\"type\":\"bool\"}],\"name\":\"authorizeNameRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"grant\",\"type\":\"bool\"}],\"name\":\"authorizeTextRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"canUpgradeFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"clearRecords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"contenthash\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"fromName\",\"type\":\"bytes\"}],\"name\":\"getAlias\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"hasAddr\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"setters\",\"type\":\"bytes[]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"interfaceImplementer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"calls\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"calls\",\"type\":\"bytes[]\"}],\"name\":\"multicallWithNodeCheck\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"recordVersions\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"fromName\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"fromData\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"name\":\"setABI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"addr_\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"fromName\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"toName\",\"type\":\"bytes\"}],\"name\":\"setAlias\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"setContenthash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"name\":\"setData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"},{\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"name\":\"setInterface\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"setText\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"feature\",\"type\":\"bytes4\"}],\"name\":\"supportsFeature\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidContentType(uint256)\":[{\"details\":\"Error selector: `0x5742bb26`\"}],\"InvalidEVMAddress(bytes)\":[{\"details\":\"Error selector: `0x8d666f60`\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}],\"UnsupportedResolverProfile(bytes4)\":[{\"details\":\"Error selector: `0x7b1c461b`\"}]},\"events\":{\"AliasChanged(bytes,bytes,bytes,bytes)\":{\"params\":{\"fromName\":\"The source DNS-encoded name.\",\"indexedFromName\":\"The source DNS-encoded name. (indexed bytes, hashed)\",\"indexedToName\":\"The destination DNS-encoded name. (indexed bytes, hashed)\",\"toName\":\"The destination DNS-encoded name.\"}},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"NamedAddrResource(uint256,bytes,uint256)\":{\"params\":{\"coinType\":\"The coin type.\",\"name\":\"The name.\",\"resource\":\"The EAC resource.\"}},\"NamedDataResource(uint256,bytes,bytes32,string)\":{\"params\":{\"key\":\"The key.\",\"keyHash\":\"The hash of the key.\",\"name\":\"The name.\",\"resource\":\"The EAC resource.\"}},\"NamedResource(uint256,bytes)\":{\"params\":{\"name\":\"The name.\",\"resource\":\"The EAC resource.\"}},\"NamedTextResource(uint256,bytes,bytes32,string)\":{\"params\":{\"key\":\"The key.\",\"keyHash\":\"The hash of the key.\",\"name\":\"The name.\",\"resource\":\"The EAC resource.\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"ABI(bytes32,uint256)\":{\"params\":{\"contentTypes\":\"A bitwise OR of the ABI formats accepted by the caller.\",\"node\":\"The ENS node to query\"},\"returns\":{\"contentType\":\"The content type of the return value\",\"value\":\"data The ABI data\"}},\"addr(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated address.\"}},\"authorizeAddrRoles(bytes,uint256,address,bool)\":{\"params\":{\"account\":\"The account to authorize roles to.\",\"coinType\":\"The coin type to authorize roles for.\",\"grant\":\"If `true`, grants, otherwise, revokes.\",\"toName\":\"The name to authorize roles for.\"},\"returns\":{\"updated\":\"`true` if the roles were updated.\"}},\"authorizeDataRoles(bytes,string,address,bool)\":{\"params\":{\"account\":\"The account to authorize roles to.\",\"grant\":\"If `true`, grants, otherwise, revokes.\",\"key\":\"The data key to authorize roles for.\",\"toName\":\"The name to authorize roles for.\"},\"returns\":{\"_0\":\"`true` if the roles were updated.\"}},\"authorizeNameRoles(bytes,uint256,address,bool)\":{\"params\":{\"account\":\"The account to authorize roles to.\",\"grant\":\"If `true`, grants, otherwise, revokes.\",\"roleBitmap\":\"The roles to authorize.\",\"toName\":\"The name to authorize roles for.\"},\"returns\":{\"_0\":\"success Whether the roles were updated.\"}},\"authorizeTextRoles(bytes,string,address,bool)\":{\"params\":{\"account\":\"The account to authorize roles to.\",\"grant\":\"If `true`, grants, otherwise, revokes.\",\"key\":\"The text key to authorize roles for.\",\"toName\":\"The name to authorize roles for.\"},\"returns\":{\"_0\":\"`true` if the roles were updated.\"}},\"canUpgradeFrom(address)\":{\"details\":\"Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call.\",\"params\":{\"\":\"{previousImplementation} Ignored.\"},\"returns\":{\"allowed\":\"Always `true` for implementations in this resolver family.\"}},\"clearRecords(bytes32)\":{\"params\":{\"node\":\"The node to update.\"}},\"constructor\":{\"params\":{\"namer\":\"The implementation namer.\"}},\"contenthash(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated contenthash.\"}},\"data(bytes32,string)\":{\"params\":{\"key\":\"The key.\",\"node\":\"The node (namehash) for which data is being fetched.\"},\"returns\":{\"_0\":\"The associated arbitrary `bytes` data.\"}},\"getAlias(bytes)\":{\"params\":{\"fromName\":\"The source DNS-encoded name.\"},\"returns\":{\"toName\":\"The destination DNS-encoded name or empty if not aliased.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"Ignored.\",\"resource\":\"Ignored.\",\"roleBitmap\":\"Ignored.\"},\"returns\":{\"_0\":\"success Ignored, always reverts.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAddr(bytes32,uint256)\":{\"params\":{\"coinType\":\"The coin type.\",\"node\":\"The node to query.\"},\"returns\":{\"_0\":\"True if the associated address is not empty.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"initialize(address,uint256,bytes[])\":{\"params\":{\"admin\":\"The resolver owner.\",\"roleBitmap\":\"The roles granted to `admin`.\",\"setters\":\"The setter calldata that avoids permission checks.\"}},\"interfaceImplementer(bytes32,bytes4)\":{\"params\":{\"interfaceID\":\"The EIP 165 interface ID to check for.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"implementer\":\"The address that implements this interface, or 0 if the interface is unsupported.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"multicall(bytes[])\":{\"details\":\"Reverts with first error.\",\"params\":{\"calls\":\"The calls to make.\"},\"returns\":{\"results\":\"The results of the calls.\"}},\"multicallWithNodeCheck(bytes32,bytes[])\":{\"details\":\"The node parameter is accepted for interface compatibility but is not used. Permission checking is handled by individual function calls within the multicall.\",\"params\":{\"\":\"{node} Ignored, for interface compatibility.\",\"calls\":\"The calls to make.\"},\"returns\":{\"_0\":\"results The results of the calls.\"}},\"name(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated name.\"}},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"pubkey(bytes32)\":{\"params\":{\"node\":\"The ENS node to query\"},\"returns\":{\"x\":\"The X coordinate of the curve point for the public key.\",\"y\":\"The Y coordinate of the curve point for the public key.\"}},\"recordVersions(bytes32)\":{\"params\":{\"node\":\"The node to check.\"},\"returns\":{\"_0\":\"version The current version.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"Ignored.\",\"resource\":\"Ignored.\",\"roleBitmap\":\"Ignored.\"},\"returns\":{\"_0\":\"success Ignored, always reverts.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"setABI(bytes32,uint256,bytes)\":{\"params\":{\"contentType\":\"The content type of the ABI.\",\"node\":\"The node to update.\",\"value\":\"The ABI data.\"}},\"setAddr(bytes32,address)\":{\"params\":{\"addr_\":\"The mainnet address.\",\"node\":\"The node to update.\"}},\"setAddr(bytes32,uint256,bytes)\":{\"params\":{\"addressBytes\":\"The encoded address.\",\"coinType\":\"The coin type.\",\"node\":\"The node to update.\"}},\"setAlias(bytes,bytes)\":{\"params\":{\"fromName\":\"The source DNS-encoded name.\",\"toName\":\"The destination DNS-encoded name.\"}},\"setContenthash(bytes32,bytes)\":{\"params\":{\"hash\":\"The contenthash to set.\",\"node\":\"The node to update.\"}},\"setData(bytes32,string,bytes)\":{\"params\":{\"key\":\"The data key.\",\"node\":\"The node to update.\",\"value\":\"The data value.\"}},\"setInterface(bytes32,bytes4,address)\":{\"params\":{\"implementer\":\"The address of the contract that implements this interface for this node.\",\"interfaceId\":\"The EIP-165 interface ID.\",\"node\":\"The node to update.\"}},\"setName(bytes32,string)\":{\"params\":{\"node\":\"The node to update.\",\"primary\":\"The primary name.\"}},\"setPubkey(bytes32,bytes32,bytes32)\":{\"params\":{\"node\":\"The node to update.\",\"x\":\"The x coordinate of the public key.\",\"y\":\"The y coordinate of the public key.\"}},\"setText(bytes32,string,string)\":{\"params\":{\"key\":\"The text key.\",\"node\":\"The node to update.\",\"value\":\"The text value.\"}},\"supportsFeature(bytes4)\":{\"params\":{\"featureId\":\"The feature identifier.\"},\"returns\":{\"_0\":\"`true` if the feature is supported by the contract.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"text(bytes32,string)\":{\"params\":{\"key\":\"The text data key to query.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated text data.\"}},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"stateVariables\":{\"_aliases\":{\"details\":\"Aliases for names.\"},\"_records\":{\"details\":\"Records for nodes.\"},\"_versions\":{\"details\":\"Versions for nodes.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidContentType(uint256)\":[{\"notice\":\"The coin type is not a power of 2.\"}],\"InvalidEVMAddress(bytes)\":[{\"notice\":\"The address could not be converted to `address`.\"}],\"UnsupportedResolverProfile(bytes4)\":[{\"notice\":\"The resolver profile cannot be answered.\"}]},\"events\":{\"AliasChanged(bytes,bytes,bytes,bytes)\":{\"notice\":\"An alias was changed.\"},\"DataChanged(bytes32,string,string,bytes)\":{\"notice\":\"For a specific `node`, the data associated with a `key` has changed.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"NamedAddrResource(uint256,bytes,uint256)\":{\"notice\":\"Associate an EAC resource with a name and specific `addr(coinType)` record.\"},\"NamedDataResource(uint256,bytes,bytes32,string)\":{\"notice\":\"Associate an EAC resource with a name and specific `data(key)` record.\"},\"NamedResource(uint256,bytes)\":{\"notice\":\"Associate an EAC resource with a name.\"},\"NamedTextResource(uint256,bytes,bytes32,string)\":{\"notice\":\"Associate an EAC resource with a name and specific `text(key)` record.\"}},\"kind\":\"user\",\"methods\":{\"ABI(bytes32,uint256)\":{\"notice\":\"Returns the ABI associated with an ENS node. Defined in EIP205.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"addr(bytes32)\":{\"notice\":\"Returns the address associated with an ENS node.\"},\"authorizeAddrRoles(bytes,uint256,address,bool)\":{\"notice\":\"Authorize `setAddr(coinType)` permission to `account` for `toName`. Use `NameCoder.encode(\\\"\\\")` for any name.\"},\"authorizeDataRoles(bytes,string,address,bool)\":{\"notice\":\"Authorize `setData(key)` permission to `account` for `toName`. Use `NameCoder.encode(\\\"\\\")` for any name.\"},\"authorizeNameRoles(bytes,uint256,address,bool)\":{\"notice\":\"Authorize `roleBitmap` permissions to `account` for `toName`. Use `NameCoder.encode(\\\"\\\")` for any name, which is equivalent to `grantRootRoles()`.\"},\"authorizeTextRoles(bytes,string,address,bool)\":{\"notice\":\"Authorize `setText(key)` permission to `account` for `toName`. Use `NameCoder.encode(\\\"\\\")` for any name.\"},\"canUpgradeFrom(address)\":{\"notice\":\"Declares this implementation as an eligible verifiable proxy upgrade target.\"},\"clearRecords(bytes32)\":{\"notice\":\"Clear all records for `node`.\"},\"contenthash(bytes32)\":{\"notice\":\"Returns the contenthash associated with an ENS node.\"},\"data(bytes32,string)\":{\"notice\":\"For a specific `node`, get the data associated with the key, `key`.\"},\"getAlias(bytes)\":{\"notice\":\"Determine which name is queried when `fromName` is resolved.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAddr(bytes32,uint256)\":{\"notice\":\"Determine if an addresss is stored for the coin type of the associated ENS node.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"initialize(address,uint256,bytes[])\":{\"notice\":\"Initialize the contract.\"},\"interfaceImplementer(bytes32,bytes4)\":{\"notice\":\"Returns the address of a contract that implements the specified interface for this name. If an implementer has not been set for this interfaceID and name, the resolver will query the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that contract implements EIP165 and returns `true` for the specified interfaceID, its address will be returned.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"multicall(bytes[])\":{\"notice\":\"Perform multiple write operations.\"},\"multicallWithNodeCheck(bytes32,bytes[])\":{\"notice\":\"Same as `multicall()`.\"},\"name(bytes32)\":{\"notice\":\"Returns the name associated with an ENS node, for reverse records. Defined in EIP181.\"},\"pubkey(bytes32)\":{\"notice\":\"Returns the SECP256k1 public key associated with an ENS node. Defined in EIP 619.\"},\"recordVersions(bytes32)\":{\"notice\":\"Get the current version.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"setABI(bytes32,uint256,bytes)\":{\"notice\":\"Set ABI data of the associated ENS node.\"},\"setAddr(bytes32,address)\":{\"notice\":\"Set Ethereum mainnet address of the associated ENS node. `address(0)` is stored as `new bytes(20)`.\"},\"setAddr(bytes32,uint256,bytes)\":{\"notice\":\"Set the address for `coinType` of the associated ENS node. Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes.\"},\"setAlias(bytes,bytes)\":{\"notice\":\"Create an alias from `fromName` to `toName`.\"},\"setContenthash(bytes32,bytes)\":{\"notice\":\"Set the contenthash of the associated ENS node.\"},\"setData(bytes32,string,bytes)\":{\"notice\":\"Set the data for `key` of the associated ENS node.\"},\"setInterface(bytes32,bytes4,address)\":{\"notice\":\"Set an interface of the associated ENS node.\"},\"setName(bytes32,string)\":{\"notice\":\"Set the name of the associated ENS node.\"},\"setPubkey(bytes32,bytes32,bytes32)\":{\"notice\":\"Set the SECP256k1 public key associated with an ENS node.\"},\"setText(bytes32,string,string)\":{\"notice\":\"Set the text for `key` of the associated ENS node.\"},\"supportsFeature(bytes4)\":{\"notice\":\"Check if a feature is supported.\"},\"text(bytes32,string)\":{\"notice\":\"Returns the text data associated with an ENS node and key.\"}},\"notice\":\"A resolver that supports many profiles, multiple names, internal aliasing, and fine-grained permissions. Supported profiles and standards: - ENSIP-1 / EIP-137: addr() - ENSIP-3 / EIP-181: name() - ENSIP-4 / EIP-205: ABI() - EIP-619: pubkey() - ENSIP-5 / EIP-634: text(key) - ENSIP-7 / EIP-1577: contenthash() - ENSIP-8: interfaceImplementer() - ENSIP-9 / EIP-2304: addr(coinType) - ENSIP-19: addr(default) - ENSIP-24: data(key) - IERC7996: supportsFeature() - IVersionableResolver: version() - IHasAddrResolver: hasAddr() Internal Aliasing: * Resolved names find the longest match and rewrite the suffix. * Successful matches recursively check for additional aliasing. * `bytes32 node` in calldata is updated accordingly. * Cycles of length 1 apply once. * Cycles of length 2+ result in OOG. eg. `setAlias(\\\"a.eth\\\", \\\"b.eth\\\")` * `getAlias(\\\"a.eth\\\") => \\\"b.eth\\\"` * `getAlias(\\\"[sub].a.eth\\\") => \\\"[sub].b.eth\\\"` * `getAlias(\\\"[x.y].a.eth\\\") => \\\"[x.y].b.eth\\\"` * `getAlias(\\\"abc.eth\\\") => \\\"\\\"` Fine-grained Permissions: * `setText(key)` can be permissioned with `authorizeTextRoles()` - caller requires `ROLE_SET_TEXT_ADMIN` on `resource(, 0)` - `ROLE_SET_TEXT` is authorized on `resource(, )` * `setData(key)` can be permissioned with `authorizeDataRoles()` - caller requires `ROLE_SET_DATA_ADMIN` on `resource(, 0)` - `ROLE_SET_DATA` is authorized on `resource(, )` * `setAddr(coinType)` can be permissioned with `authorizeAddrRoles()` - caller requires `ROLE_SET_ADDR_ADMIN` on `resource(, 0)` - `ROLE_SET_ADDR` is authorized on `resource(, )` Setters with `node` check (4) EAC resources: Parts Resources +-----------------------------+------------------------------+ | Any (*) | Specific (1) | +--------------+-----------------------------+------------------------------+ | Any (*) | resource(0, 0) | resource(0, ) | Names |--------------+-----------------------------+------------------------------+ | Specific (1) | resource(, 0) | resource(, ) | +--------------+-----------------------------+------------------------------+\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/resolver/PermissionedResolver.sol\":\"PermissionedResolver\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverFeatures.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary ResolverFeatures {\\n /// @notice Implements `resolve(multicall([...]))`.\\n /// @dev Feature: `0x96b62db8`\\n bytes4 constant RESOLVE_MULTICALL =\\n bytes4(keccak256(\\\"eth.ens.resolver.extended.multicall\\\"));\\n\\n /// @notice Returns the same records independent of name or node.\\n /// @dev Feature: `0x86fb8da8`\\n bytes4 constant SINGULAR = bytes4(keccak256(\\\"eth.ens.resolver.singular\\\"));\\n}\\n\",\"keccak256\":\"0x87d131fcbdd7951a17b0a94f7f02470ec3f62c6004cf91c2d2acc54098373be6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IABIResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IABIResolver {\\n event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\\n\\n /// Returns the ABI associated with an ENS node.\\n /// Defined in EIP205.\\n /// @param node The ENS node to query\\n /// @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\\n /// @return contentType The content type of the return value\\n /// @return data The ABI data\\n function ABI(\\n bytes32 node,\\n uint256 contentTypes\\n ) external view returns (uint256, bytes memory);\\n}\\n\",\"keccak256\":\"0x3a7a763d7a4f0d196c4b628545b022b1d1d0e37baf84eaa6eecb1a57a1633cad\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the legacy (ETH-only) addr function.\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /// Returns the address associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated address.\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x91dd0c350698c505d6c7e4c919da9f981d4b8d7ad062e25073fa1f6af7cb79d1\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the new (multicoin) addr function.\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x8da5dd0fc1c5ab4f47e03c23126976a86d4b2dbeac161e70e3af9e2a13330cf0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IContentHashResolver {\\n event ContenthashChanged(bytes32 indexed node, bytes hash);\\n\\n /// Returns the contenthash associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function contenthash(bytes32 node) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0xaa978b1ee4c19e99c8aa409dc553e9b4c1bf9fe3c5bad718cd3589e6c9e6d121\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// @dev Interface selector: `0xecbfada3`\\ninterface IDataResolver {\\n /// @notice For a specific `node`, the data associated with a `key` has changed.\\n event DataChanged(\\n bytes32 indexed node, \\n string indexed indexedKey,\\n string key, \\n bytes indexed indexedData\\n );\\n \\n /// @notice For a specific `node`, get the data associated with the key, `key`.\\n /// @param node The node (namehash) for which data is being fetched.\\n /// @param key The key.\\n /// @return The associated arbitrary `bytes` data.\\n function data(\\n bytes32 node,\\n string calldata key\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x502a38d58d2047db3fa021897eda32bb6f4cde9746606e691e6acf25c396d88e\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IHasAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IHasAddressResolver {\\n /// @notice Determine if an addresss is stored for the coin type of the associated ENS node.\\n /// @param node The node to query.\\n /// @param coinType The coin type.\\n /// @return True if the associated address is not empty.\\n function hasAddr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbe13530b8cc027517c235e422326abd36bb1152dac8546713471be2a7335cf2b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IInterfaceResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IInterfaceResolver {\\n event InterfaceChanged(\\n bytes32 indexed node,\\n bytes4 indexed interfaceID,\\n address implementer\\n );\\n\\n /// Returns the address of a contract that implements the specified interface for this name.\\n /// If an implementer has not been set for this interfaceID and name, the resolver will query\\n /// the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\\n /// contract implements EIP165 and returns `true` for the specified interfaceID, its address\\n /// will be returned.\\n /// @param node The ENS node to query.\\n /// @param interfaceID The EIP 165 interface ID to check for.\\n /// @return The address that implements this interface, or 0 if the interface is unsupported.\\n function interfaceImplementer(\\n bytes32 node,\\n bytes4 interfaceID\\n ) external view returns (address);\\n}\\n\",\"keccak256\":\"0x510176a3fe60471775328756ab025d8bafda7063f52f218728ca559b8f61a357\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x3ab986332e0baad7aeb4b426aace3aa1c235be5efff8db4b6f1ce501bcdd9e68\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IPubkeyResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IPubkeyResolver {\\n event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\\n\\n /// Returns the SECP256k1 public key associated with an ENS node.\\n /// Defined in EIP 619.\\n /// @param node The ENS node to query\\n /// @return x The X coordinate of the curve point for the public key.\\n /// @return y The Y coordinate of the curve point for the public key.\\n function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);\\n}\\n\",\"keccak256\":\"0x1a21561b58ce17db400c015882ff07f12f9bd0df0e7b9305841799aada441820\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ITextResolver {\\n event TextChanged(\\n bytes32 indexed node,\\n string indexed indexedKey,\\n string key,\\n string value\\n );\\n\\n /// Returns the text data associated with an ENS node and key.\\n /// @param node The ENS node to query.\\n /// @param key The text data key to query.\\n /// @return The associated text data.\\n function text(\\n bytes32 node,\\n string calldata key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xe91c15697be2d20417cce3c58d4ecce34796986fdedc97be5b93a823be58e471\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IVersionableResolver {\\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\\n\\n function recordVersions(bytes32 node) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0xd0d09596f20c57bafb2ffa8521a8c57120e9af6c6b194f9c689d4da56f91a57c\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/ENSIP19.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {HexUtils} from \\\"../utils/HexUtils.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\n\\nuint32 constant CHAIN_ID_ETH = 1;\\n\\nuint256 constant COIN_TYPE_ETH = 60;\\nuint256 constant COIN_TYPE_DEFAULT = 1 << 31; // 0x8000_0000\\n\\nstring constant SLUG_ETH = \\\"addr\\\"; // <=> COIN_TYPE_ETH\\nstring constant SLUG_DEFAULT = \\\"default\\\"; // <=> COIN_TYPE_DEFAULT\\nstring constant TLD_REVERSE = \\\"reverse\\\";\\n\\n/// @dev Library for generating reverse names according to ENSIP-19.\\n/// https://docs.ens.domains/ensip/19\\nlibrary ENSIP19 {\\n /// @dev The supplied address was `0x`.\\n /// Error selector: `0x7138356f`\\n error EmptyAddress();\\n\\n /// @dev Extract Chain ID from `coinType`.\\n /// @param coinType The coin type.\\n /// @return The Chain ID or 0 if non-EVM Chain.\\n function chainFromCoinType(\\n uint256 coinType\\n ) internal pure returns (uint32) {\\n if (coinType == COIN_TYPE_ETH) return CHAIN_ID_ETH;\\n coinType ^= COIN_TYPE_DEFAULT;\\n return uint32(coinType < COIN_TYPE_DEFAULT ? coinType : 0);\\n }\\n\\n /// @dev Determine if Coin Type is for an EVM address.\\n /// @param coinType The coin type.\\n /// @return True if coin type represents an EVM address.\\n function isEVMCoinType(uint256 coinType) internal pure returns (bool) {\\n return coinType == COIN_TYPE_DEFAULT || chainFromCoinType(coinType) > 0;\\n }\\n\\n /// @dev Generate Reverse Name from Address + Coin Type.\\n /// Reverts `EmptyAddress` if `addressBytes` is `0x`.\\n /// @param addressBytes The input address.\\n /// @param coinType The coin type.\\n /// @return The ENS reverse name, eg. `1234abcd.addr.reverse`.\\n function reverseName(\\n bytes memory addressBytes,\\n uint256 coinType\\n ) internal pure returns (string memory) {\\n if (addressBytes.length == 0) {\\n revert EmptyAddress();\\n }\\n return\\n string(\\n abi.encodePacked(\\n HexUtils.bytesToHex(addressBytes),\\n bytes1(\\\".\\\"),\\n coinType == COIN_TYPE_ETH\\n ? SLUG_ETH\\n : coinType == COIN_TYPE_DEFAULT\\n ? SLUG_DEFAULT\\n : HexUtils.unpaddedUintToHex(coinType, true),\\n bytes1(\\\".\\\"),\\n TLD_REVERSE\\n )\\n );\\n }\\n\\n /// @dev Parse Reverse Name into Address + Coin Type.\\n /// Matches: `/^[0-9a-fA-F]+\\\\.([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @return addressBytes The address or empty if invalid.\\n /// @return coinType The coin type.\\n function parse(\\n bytes memory name\\n ) internal pure returns (bytes memory addressBytes, uint256 coinType) {\\n (, uint256 offset) = NameCoder.readLabel(name, 0);\\n bool valid;\\n (addressBytes, valid) = HexUtils.hexToBytes(name, 1, offset);\\n if (!valid || addressBytes.length == 0) return (\\\"\\\", 0); // addressBytes not 1+ hex\\n (valid, coinType) = parseNamespace(name, offset);\\n if (!valid) return (\\\"\\\", 0); // invalid namespace\\n }\\n\\n /// @dev Parse Reverse Namespace into Coin Type.\\n /// Matches: `/^([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset to begin parsing.\\n /// @return valid True if a valid reverse namespace.\\n /// @return coinType The coin type.\\n function parseNamespace(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bool valid, uint256 coinType) {\\n (bytes32 labelHash, uint256 offsetTLD) = NameCoder.readLabel(\\n name,\\n offset\\n );\\n if (labelHash == keccak256(bytes(SLUG_ETH))) {\\n coinType = COIN_TYPE_ETH;\\n } else if (labelHash == keccak256(bytes(SLUG_DEFAULT))) {\\n coinType = COIN_TYPE_DEFAULT;\\n } else if (labelHash == bytes32(0)) {\\n return (false, 0); // no slug\\n } else {\\n (bytes32 word, bool validHex) = HexUtils.hexStringToBytes32(\\n name,\\n 1 + offset,\\n offsetTLD\\n );\\n if (!validHex) return (false, 0); // invalid coinType or too long\\n coinType = uint256(word);\\n }\\n (labelHash, offset) = NameCoder.readLabel(name, offsetTLD);\\n if (labelHash != keccak256(bytes(TLD_REVERSE))) return (false, 0); // invalid tld\\n (labelHash, ) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) return (false, 0); // not tld\\n valid = true;\\n }\\n}\\n\",\"keccak256\":\"0xd1af09b014028de4c50489bd58ae424273180bb96d95353d8eefd14845f31824\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/IERC7996.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for expressing contract features not visible from the ABI.\\n/// @dev Interface selector: `0x582de3e7`\\ninterface IERC7996 {\\n /// @notice Check if a feature is supported.\\n /// @param featureId The feature identifier.\\n /// @return `true` if the feature is supported by the contract.\\n function supportsFeature(bytes4 featureId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf499a48e4e879ec7775f375d2cb5af047720ab6ae4b6f89a40a578c4e0f51631\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\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 * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\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 Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\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 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\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 _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\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 // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\\n *\\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\\n */\\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\\n return INITIALIZABLE_STORAGE;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n bytes32 slot = _initializableStorageSlot();\\n assembly {\\n $.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IERC1822Proxiable} from \\\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\\\";\\nimport {Initializable} from \\\"./Initializable.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 */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\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 _checkNotDelegated();\\n _;\\n }\\n\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\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 * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {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 onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: 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\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\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 ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\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 ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.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 the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\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 ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\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 * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, bytes memory returndata) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n _revert(returndata);\\n }\\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 or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) 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 assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IProxyAuthorization {\\n function canUpgradeFrom(address previousImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, msg.sender);\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _getRoles(resource, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _getRoles(ROOT_RESOURCE, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return _effectiveRoles(resource, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the roles bitmap for an account for permission checks.\\n function _getRoles(uint256 resource, address account) internal view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the effective roles bitmap for an account for permission checks.\\n function _effectiveRoles(uint256 resource, address account) private view returns (uint256) {\\n return _getRoles(ROOT_RESOURCE, account) | _getRoles(resource, account);\\n }\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n}\\n\",\"keccak256\":\"0x934655016f502e7a2f8e5cbd294ef48e85f238821f5608de5675c023f48037af\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Admin roles imply their corresponding regular roles.\\n function withAdminRolesApplied(uint256 roleBitmap) internal pure returns (uint256) {\\n roleBitmap >>= 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Derive roles bitmap from assignee counts.\\n /// @param counts Packed role counts (0-15) as `uint4x64`.\\n function fromCounts(uint256 counts) internal pure returns (uint256) {\\n return (counts | (counts >> 1) | (counts >> 2) | (counts >> 3)) & ALL_ROLES;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function hasZeroNybbles(uint256 value) internal pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 zeroNybbles;\\n unchecked {\\n zeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return zeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xc14f05abd508e75c9f16a35e31d0fb9f1f1dd904b65d058201c788a9ddd562eb\",\"license\":\"MIT\"},\"project/src/resolver/PermissionedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {IMulticallable} from \\\"@ens/contracts/resolvers/IMulticallable.sol\\\";\\nimport {IABIResolver} from \\\"@ens/contracts/resolvers/profiles/IABIResolver.sol\\\";\\nimport {IAddressResolver} from \\\"@ens/contracts/resolvers/profiles/IAddressResolver.sol\\\";\\nimport {IAddrResolver} from \\\"@ens/contracts/resolvers/profiles/IAddrResolver.sol\\\";\\nimport {IContentHashResolver} from \\\"@ens/contracts/resolvers/profiles/IContentHashResolver.sol\\\";\\nimport {IDataResolver} from \\\"@ens/contracts/resolvers/profiles/IDataResolver.sol\\\";\\nimport {IExtendedResolver} from \\\"@ens/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {IHasAddressResolver} from \\\"@ens/contracts/resolvers/profiles/IHasAddressResolver.sol\\\";\\nimport {IInterfaceResolver} from \\\"@ens/contracts/resolvers/profiles/IInterfaceResolver.sol\\\";\\nimport {INameResolver} from \\\"@ens/contracts/resolvers/profiles/INameResolver.sol\\\";\\nimport {IPubkeyResolver} from \\\"@ens/contracts/resolvers/profiles/IPubkeyResolver.sol\\\";\\nimport {ITextResolver} from \\\"@ens/contracts/resolvers/profiles/ITextResolver.sol\\\";\\nimport {IVersionableResolver} from \\\"@ens/contracts/resolvers/profiles/IVersionableResolver.sol\\\";\\nimport {ResolverFeatures} from \\\"@ens/contracts/resolvers/ResolverFeatures.sol\\\";\\nimport {ENSIP19, COIN_TYPE_ETH, COIN_TYPE_DEFAULT} from \\\"@ens/contracts/utils/ENSIP19.sol\\\";\\nimport {IERC7996} from \\\"@ens/contracts/utils/IERC7996.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {IProxyAuthorization} from \\\"@ensdomains/verifiable-factory/IProxyAuthorization.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IEnhancedAccessControl} from \\\"../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IPermissionedResolver} from \\\"./interfaces/IPermissionedResolver.sol\\\";\\nimport {PermissionedResolverLib} from \\\"./libraries/PermissionedResolverLib.sol\\\";\\nimport {ResolverProfileRewriterLib} from \\\"./libraries/ResolverProfileRewriterLib.sol\\\";\\n\\n/// @notice A resolver that supports many profiles, multiple names, internal aliasing, and fine-grained permissions.\\n///\\n/// Supported profiles and standards:\\n///\\n/// - ENSIP-1 / EIP-137: addr()\\n/// - ENSIP-3 / EIP-181: name()\\n/// - ENSIP-4 / EIP-205: ABI()\\n/// - EIP-619: pubkey()\\n/// - ENSIP-5 / EIP-634: text(key)\\n/// - ENSIP-7 / EIP-1577: contenthash()\\n/// - ENSIP-8: interfaceImplementer()\\n/// - ENSIP-9 / EIP-2304: addr(coinType)\\n/// - ENSIP-19: addr(default)\\n/// - ENSIP-24: data(key)\\n/// - IERC7996: supportsFeature()\\n/// - IVersionableResolver: version()\\n/// - IHasAddrResolver: hasAddr()\\n///\\n/// Internal Aliasing:\\n///\\n/// * Resolved names find the longest match and rewrite the suffix.\\n/// * Successful matches recursively check for additional aliasing.\\n/// * `bytes32 node` in calldata is updated accordingly.\\n/// * Cycles of length 1 apply once.\\n/// * Cycles of length 2+ result in OOG.\\n///\\n/// eg. `setAlias(\\\"a.eth\\\", \\\"b.eth\\\")`\\n/// * `getAlias(\\\"a.eth\\\") => \\\"b.eth\\\"`\\n/// * `getAlias(\\\"[sub].a.eth\\\") => \\\"[sub].b.eth\\\"`\\n/// * `getAlias(\\\"[x.y].a.eth\\\") => \\\"[x.y].b.eth\\\"`\\n/// * `getAlias(\\\"abc.eth\\\") => \\\"\\\"`\\n///\\n/// Fine-grained Permissions:\\n///\\n/// * `setText(key)` can be permissioned with `authorizeTextRoles()`\\n/// - caller requires `ROLE_SET_TEXT_ADMIN` on `resource(, 0)`\\n/// - `ROLE_SET_TEXT` is authorized on `resource(, )`\\n/// * `setData(key)` can be permissioned with `authorizeDataRoles()`\\n/// - caller requires `ROLE_SET_DATA_ADMIN` on `resource(, 0)`\\n/// - `ROLE_SET_DATA` is authorized on `resource(, )`\\n/// * `setAddr(coinType)` can be permissioned with `authorizeAddrRoles()`\\n/// - caller requires `ROLE_SET_ADDR_ADMIN` on `resource(, 0)`\\n/// - `ROLE_SET_ADDR` is authorized on `resource(, )`\\n///\\n/// Setters with `node` check (4) EAC resources:\\n/// Parts\\n/// Resources +-----------------------------+------------------------------+\\n/// | Any (*) | Specific (1) |\\n/// +--------------+-----------------------------+------------------------------+\\n/// | Any (*) | resource(0, 0) | resource(0, ) |\\n/// Names |--------------+-----------------------------+------------------------------+\\n/// | Specific (1) | resource(, 0) | resource(, ) |\\n/// +--------------+-----------------------------+------------------------------+\\n///\\ncontract PermissionedResolver is\\n IPermissionedResolver,\\n UUPSUpgradeable,\\n EnhancedAccessControl,\\n IERC7996,\\n IMulticallable,\\n IABIResolver,\\n IAddrResolver,\\n IAddressResolver,\\n IContentHashResolver,\\n IDataResolver,\\n IHasAddressResolver,\\n IInterfaceResolver,\\n INameResolver,\\n IPubkeyResolver,\\n ITextResolver,\\n IVersionableResolver,\\n IProxyAuthorization,\\n IContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n struct Record {\\n bytes contenthash;\\n bytes32[2] pubkey;\\n string name;\\n mapping(uint256 coinType => bytes addressBytes) addresses;\\n mapping(string key => string value) texts;\\n mapping(string key => bytes value) datas;\\n mapping(uint256 contentType => bytes value) abis;\\n mapping(bytes4 interfaceId => address implementer) interfaces;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Aliases for names.\\n mapping(bytes32 node => bytes name) internal _aliases;\\n\\n /// @dev Versions for nodes.\\n mapping(bytes32 node => uint64 version) internal _versions;\\n\\n /// @dev Records for nodes.\\n mapping(bytes32 node => mapping(uint64 version => Record)) internal _records;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate an EAC resource with a name.\\n /// @param resource The EAC resource.\\n /// @param name The name.\\n event NamedResource(uint256 indexed resource, bytes name);\\n\\n /// @notice Associate an EAC resource with a name and specific `text(key)` record.\\n /// @param resource The EAC resource.\\n /// @param name The name.\\n /// @param keyHash The hash of the key.\\n /// @param key The key.\\n event NamedTextResource(\\n uint256 indexed resource,\\n bytes name,\\n bytes32 indexed keyHash,\\n string key\\n );\\n\\n /// @notice Associate an EAC resource with a name and specific `data(key)` record.\\n /// @param resource The EAC resource.\\n /// @param name The name.\\n /// @param keyHash The hash of the key.\\n /// @param key The key.\\n event NamedDataResource(\\n uint256 indexed resource,\\n bytes name,\\n bytes32 indexed keyHash,\\n string key\\n );\\n\\n /// @notice Associate an EAC resource with a name and specific `addr(coinType)` record.\\n /// @param resource The EAC resource.\\n /// @param name The name.\\n /// @param coinType The coin type.\\n event NamedAddrResource(uint256 indexed resource, bytes name, uint256 indexed coinType);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n modifier onlyPartRoles(bytes32 node, bytes32 part, uint256 roleBitmap) {\\n if (\\n part == bytes32(0) ||\\n (!hasRoles(PermissionedResolverLib.resource(node, part), roleBitmap, msg.sender) &&\\n !hasRoles(PermissionedResolverLib.resource(0, part), roleBitmap, msg.sender))\\n ) {\\n _checkRoles(PermissionedResolverLib.resource(node, 0), roleBitmap, msg.sender); // reverts using \\\"widest\\\" resource\\n }\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param namer The implementation namer.\\n constructor(address namer) {\\n _grantRoles(\\n ROOT_RESOURCE,\\n PermissionedResolverLib.ROLE_CAN_NAME | PermissionedResolverLib.ROLE_CAN_NAME_ADMIN,\\n namer,\\n false\\n );\\n _disableInitializers();\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n type(IPermissionedResolver).interfaceId == interfaceId ||\\n type(IExtendedResolver).interfaceId == interfaceId ||\\n type(IERC7996).interfaceId == interfaceId ||\\n type(IMulticallable).interfaceId == interfaceId ||\\n type(IABIResolver).interfaceId == interfaceId ||\\n type(IAddrResolver).interfaceId == interfaceId ||\\n type(IAddressResolver).interfaceId == interfaceId ||\\n type(IContentHashResolver).interfaceId == interfaceId ||\\n type(IDataResolver).interfaceId == interfaceId ||\\n type(IHasAddressResolver).interfaceId == interfaceId ||\\n type(IInterfaceResolver).interfaceId == interfaceId ||\\n type(INameResolver).interfaceId == interfaceId ||\\n type(IPubkeyResolver).interfaceId == interfaceId ||\\n type(ITextResolver).interfaceId == interfaceId ||\\n type(IVersionableResolver).interfaceId == interfaceId ||\\n type(UUPSUpgradeable).interfaceId == interfaceId ||\\n type(IProxyAuthorization).interfaceId == interfaceId ||\\n type(IContractNamer).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /// @inheritdoc IERC7996\\n function supportsFeature(bytes4 feature) external pure returns (bool) {\\n return ResolverFeatures.RESOLVE_MULTICALL == feature;\\n }\\n\\n /// @inheritdoc IPermissionedResolver\\n function initialize(address admin, uint256 roleBitmap, bytes[] calldata setters)\\n external\\n initializer\\n {\\n __UUPSUpgradeable_init();\\n _grantRoles(ROOT_RESOURCE, roleBitmap, admin, false);\\n multicall(setters);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Clear all records for `node`.\\n /// @param node The node to update.\\n function clearRecords(bytes32 node)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_CLEAR)\\n {\\n uint64 version = ++_versions[node];\\n emit VersionChanged(node, version);\\n }\\n\\n /// @inheritdoc IPermissionedResolver\\n function setAlias(bytes calldata fromName, bytes calldata toName)\\n external\\n onlyRootRoles(PermissionedResolverLib.ROLE_SET_ALIAS)\\n {\\n _aliases[NameCoder.namehash(fromName, 0)] = toName;\\n emit AliasChanged(fromName, toName, fromName, toName);\\n }\\n\\n /// @notice Authorize `roleBitmap` permissions to `account` for `toName`.\\n /// Use `NameCoder.encode(\\\"\\\")` for any name, which is equivalent to `grantRootRoles()`.\\n /// @param toName The name to authorize roles for.\\n /// @param roleBitmap The roles to authorize.\\n /// @param account The account to authorize roles to.\\n /// @param grant If `true`, grants, otherwise, revokes.\\n /// @return success Whether the roles were updated.\\n function authorizeNameRoles(\\n bytes calldata toName,\\n uint256 roleBitmap,\\n address account,\\n bool grant\\n )\\n external\\n returns (bool)\\n {\\n bytes32 node = NameCoder.namehash(toName, 0);\\n uint256 resource = PermissionedResolverLib.resource(node, 0);\\n if (grant) {\\n _checkCanGrantRoles(resource, roleBitmap, msg.sender);\\n if (resource != ROOT_RESOURCE && roleCount(resource) == 0) {\\n emit NamedResource(resource, toName);\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n } else {\\n _checkCanRevokeRoles(resource, roleBitmap, msg.sender);\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n }\\n\\n /// @notice Authorize `setText(key)` permission to `account` for `toName`.\\n /// Use `NameCoder.encode(\\\"\\\")` for any name.\\n /// @param toName The name to authorize roles for.\\n /// @param key The text key to authorize roles for.\\n /// @param account The account to authorize roles to.\\n /// @param grant If `true`, grants, otherwise, revokes.\\n /// @return `true` if the roles were updated.\\n function authorizeTextRoles(\\n bytes calldata toName,\\n string calldata key,\\n address account,\\n bool grant\\n )\\n external\\n returns (bool)\\n {\\n bytes32 node = NameCoder.namehash(toName, 0);\\n uint256 roleBit = PermissionedResolverLib.ROLE_SET_TEXT;\\n uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0));\\n uint256 partResource =\\n PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(key));\\n if (grant) {\\n _checkCanGrantRoles(nodeResource, roleBit, msg.sender);\\n if (roleCount(partResource) == 0) {\\n emit NamedTextResource(partResource, toName, keccak256(bytes(key)), key);\\n }\\n return _grantRoles(partResource, roleBit, account, true);\\n } else {\\n _checkCanRevokeRoles(nodeResource, roleBit, msg.sender);\\n return _revokeRoles(partResource, roleBit, account, true);\\n }\\n }\\n\\n /// @notice Authorize `setData(key)` permission to `account` for `toName`.\\n /// Use `NameCoder.encode(\\\"\\\")` for any name.\\n /// @param toName The name to authorize roles for.\\n /// @param key The data key to authorize roles for.\\n /// @param account The account to authorize roles to.\\n /// @param grant If `true`, grants, otherwise, revokes.\\n /// @return `true` if the roles were updated.\\n function authorizeDataRoles(\\n bytes calldata toName,\\n string calldata key,\\n address account,\\n bool grant\\n )\\n external\\n returns (bool)\\n {\\n bytes32 node = NameCoder.namehash(toName, 0);\\n uint256 roleBit = PermissionedResolverLib.ROLE_SET_DATA;\\n uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0));\\n uint256 partResource =\\n PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(key));\\n if (grant) {\\n _checkCanGrantRoles(nodeResource, roleBit, msg.sender);\\n if (roleCount(partResource) == 0) {\\n emit NamedDataResource(partResource, toName, keccak256(bytes(key)), key);\\n }\\n return _grantRoles(partResource, roleBit, account, true);\\n } else {\\n _checkCanRevokeRoles(nodeResource, roleBit, msg.sender);\\n return _revokeRoles(partResource, roleBit, account, true);\\n }\\n }\\n\\n /// @notice Authorize `setAddr(coinType)` permission to `account` for `toName`.\\n /// Use `NameCoder.encode(\\\"\\\")` for any name.\\n /// @param toName The name to authorize roles for.\\n /// @param coinType The coin type to authorize roles for.\\n /// @param account The account to authorize roles to.\\n /// @param grant If `true`, grants, otherwise, revokes.\\n /// @return updated `true` if the roles were updated.\\n function authorizeAddrRoles(bytes calldata toName, uint256 coinType, address account, bool grant)\\n external\\n returns (bool updated)\\n {\\n bytes32 node = NameCoder.namehash(toName, 0);\\n uint256 roleBit = PermissionedResolverLib.ROLE_SET_ADDR;\\n uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0));\\n uint256 partResource =\\n PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(coinType));\\n if (grant) {\\n _checkCanGrantRoles(nodeResource, roleBit, msg.sender);\\n if (roleCount(partResource) == 0) {\\n emit NamedAddrResource(partResource, toName, coinType);\\n }\\n return _grantRoles(partResource, roleBit, account, true);\\n } else {\\n _checkCanRevokeRoles(nodeResource, roleBit, msg.sender);\\n return _revokeRoles(partResource, roleBit, account, true);\\n }\\n }\\n\\n /// @notice Set ABI data of the associated ENS node.\\n /// @param node The node to update.\\n /// @param contentType The content type of the ABI.\\n /// @param value The ABI data.\\n function setABI(bytes32 node, uint256 contentType, bytes calldata value)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_ABI)\\n {\\n if (!_isPowerOf2(contentType)) {\\n revert InvalidContentType(contentType);\\n }\\n _record(node).abis[contentType] = value;\\n emit ABIChanged(node, contentType);\\n }\\n\\n /// @notice Set Ethereum mainnet address of the associated ENS node.\\n /// `address(0)` is stored as `new bytes(20)`.\\n /// @param node The node to update.\\n /// @param addr_ The mainnet address.\\n function setAddr(bytes32 node, address addr_) external {\\n setAddr(node, COIN_TYPE_ETH, abi.encodePacked(addr_));\\n }\\n\\n /// @notice Set the contenthash of the associated ENS node.\\n /// @param node The node to update.\\n /// @param hash The contenthash to set.\\n function setContenthash(bytes32 node, bytes calldata hash)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_CONTENTHASH)\\n {\\n _record(node).contenthash = hash;\\n emit ContenthashChanged(node, hash);\\n }\\n\\n /// @notice Set the data for `key` of the associated ENS node.\\n /// @param node The node to update.\\n /// @param key The data key.\\n /// @param value The data value.\\n function setData(bytes32 node, string calldata key, bytes calldata value)\\n external\\n onlyPartRoles(\\n node,\\n PermissionedResolverLib.partHash(key),\\n PermissionedResolverLib.ROLE_SET_DATA\\n )\\n {\\n _record(node).datas[key] = value;\\n emit DataChanged(node, key, key, value);\\n }\\n\\n /// @notice Set an interface of the associated ENS node.\\n /// @param node The node to update.\\n /// @param interfaceId The EIP-165 interface ID.\\n /// @param implementer The address of the contract that implements this interface for this node.\\n function setInterface(bytes32 node, bytes4 interfaceId, address implementer)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_INTERFACE)\\n {\\n _record(node).interfaces[interfaceId] = implementer;\\n emit InterfaceChanged(node, interfaceId, implementer);\\n }\\n\\n /// @notice Set the SECP256k1 public key associated with an ENS node.\\n /// @param node The node to update.\\n /// @param x The x coordinate of the public key.\\n /// @param y The y coordinate of the public key.\\n function setPubkey(bytes32 node, bytes32 x, bytes32 y)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_PUBKEY)\\n {\\n _record(node).pubkey = [x, y];\\n emit PubkeyChanged(node, x, y);\\n }\\n\\n /// @notice Set the name of the associated ENS node.\\n /// @param node The node to update.\\n /// @param primary The primary name.\\n function setName(bytes32 node, string calldata primary)\\n external\\n onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_NAME)\\n {\\n _record(node).name = primary;\\n emit NameChanged(node, primary);\\n }\\n\\n /// @notice Set the text for `key` of the associated ENS node.\\n /// @param node The node to update.\\n /// @param key The text key.\\n /// @param value The text value.\\n function setText(bytes32 node, string calldata key, string calldata value)\\n external\\n onlyPartRoles(\\n node,\\n PermissionedResolverLib.partHash(key),\\n PermissionedResolverLib.ROLE_SET_TEXT\\n )\\n {\\n _record(node).texts[key] = value;\\n emit TextChanged(node, key, key, value);\\n }\\n\\n /// @notice Same as `multicall()`.\\n /// @dev The node parameter is accepted for interface compatibility but is not used.\\n /// Permission checking is handled by individual function calls within the multicall.\\n /// @param {node} Ignored, for interface compatibility.\\n /// @param calls The calls to make.\\n /// @return results The results of the calls.\\n function multicallWithNodeCheck(\\n bytes32 /* node */,\\n bytes[] calldata calls\\n )\\n external\\n returns (bytes[] memory)\\n {\\n return multicall(calls);\\n }\\n\\n /// @inheritdoc IExtendedResolver\\n function resolve(bytes calldata fromName, bytes calldata fromData)\\n external\\n view\\n returns (bytes memory)\\n {\\n bytes memory toName = getAlias(fromName);\\n bytes memory toData =\\n ResolverProfileRewriterLib.replaceNode(\\n fromData,\\n NameCoder.namehash(toName.length == 0 ? fromName : toName, 0) // always rewrite node\\n );\\n if (bytes4(toData) == IMulticallable.multicall.selector) {\\n // note: cannot staticcall multicall() because it reverts with first error\\n assembly {\\n mstore(add(toData, 4), sub(mload(toData), 4))\\n toData := add(toData, 4) // drop selector\\n }\\n bytes[] memory m = abi.decode(toData, (bytes[]));\\n for (uint256 i; i < m.length; ++i) {\\n toData = m[i];\\n (, bytes memory v) = address(this).staticcall(toData);\\n if (v.length == 0) {\\n v = abi.encodeWithSelector(UnsupportedResolverProfile.selector, bytes4(toData));\\n }\\n m[i] = v;\\n }\\n return abi.encode(m);\\n } else {\\n (bool ok, bytes memory v) = address(this).staticcall(toData);\\n if (!ok) {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n } else if (v.length == 0) {\\n revert UnsupportedResolverProfile(bytes4(fromData));\\n }\\n return v;\\n }\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return hasRootRoles(PermissionedResolverLib.ROLE_CAN_NAME, namer);\\n }\\n\\n /// @notice Get the current version.\\n /// @param node The node to check.\\n /// @return version The current version.\\n function recordVersions(bytes32 node) external view returns (uint64) {\\n return _versions[node];\\n }\\n\\n /// @inheritdoc IABIResolver\\n function ABI(bytes32 node, uint256 contentTypes)\\n external\\n view\\n returns (uint256 contentType, bytes memory value)\\n {\\n Record storage r = _record(node);\\n for (contentType = 1; contentType > 0 && contentType <= contentTypes; contentType <<= 1) {\\n if ((contentType & contentTypes) != 0) {\\n value = r.abis[contentType];\\n if (value.length > 0) {\\n return (contentType, value);\\n }\\n }\\n }\\n return (0, \\\"\\\");\\n }\\n\\n /// @inheritdoc IHasAddressResolver\\n function hasAddr(bytes32 node, uint256 coinType) external view returns (bool) {\\n return _record(node).addresses[coinType].length > 0;\\n }\\n\\n /// @inheritdoc IContentHashResolver\\n function contenthash(bytes32 node) external view returns (bytes memory) {\\n return _record(node).contenthash;\\n }\\n\\n /// @inheritdoc IDataResolver\\n function data(bytes32 node, string calldata key) external view returns (bytes memory) {\\n return _record(node).datas[key];\\n }\\n\\n /// @inheritdoc IInterfaceResolver\\n function interfaceImplementer(bytes32 node, bytes4 interfaceId)\\n external\\n view\\n returns (address implementer)\\n {\\n implementer = _record(node).interfaces[interfaceId];\\n if (implementer == address(0)) {\\n address pointer = addr(node);\\n if (ERC165Checker.supportsInterface(pointer, interfaceId)) {\\n implementer = pointer;\\n }\\n }\\n }\\n\\n /// @inheritdoc INameResolver\\n function name(bytes32 node) external view returns (string memory) {\\n return _record(node).name;\\n }\\n\\n /// @inheritdoc IPubkeyResolver\\n function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y) {\\n Record storage r = _record(node);\\n x = r.pubkey[0];\\n y = r.pubkey[1];\\n }\\n\\n /// @inheritdoc ITextResolver\\n function text(bytes32 node, string calldata key) external view returns (string memory) {\\n return _record(node).texts[key];\\n }\\n\\n /// @notice Declares this implementation as an eligible verifiable proxy upgrade target.\\n /// @dev Upgrade authorization is still enforced by the current implementation during the UUPS\\n /// upgrade call.\\n /// @param {previousImplementation} Ignored.\\n /// @return allowed Always `true` for implementations in this resolver family.\\n function canUpgradeFrom(\\n address /* previousImplementation */\\n )\\n external\\n pure\\n virtual\\n override\\n returns (bool allowed)\\n {\\n return true;\\n }\\n\\n /// @notice Perform multiple write operations.\\n /// @dev Reverts with first error.\\n /// @param calls The calls to make.\\n /// @return results The results of the calls.\\n function multicall(bytes[] calldata calls) public returns (bytes[] memory results) {\\n results = new bytes[](calls.length);\\n for (uint256 i; i < calls.length; ++i) {\\n (bool ok, bytes memory v) = address(this).delegatecall(calls[i]);\\n if (!ok) {\\n assembly {\\n revert(add(v, 32), mload(v)) // propagate the first error\\n }\\n }\\n results[i] = v;\\n }\\n return results;\\n }\\n\\n /// @notice Set the address for `coinType` of the associated ENS node.\\n /// Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes.\\n /// @param node The node to update.\\n /// @param coinType The coin type.\\n /// @param addressBytes The encoded address.\\n function setAddr(bytes32 node, uint256 coinType, bytes memory addressBytes)\\n public\\n onlyPartRoles(\\n node,\\n PermissionedResolverLib.partHash(coinType),\\n PermissionedResolverLib.ROLE_SET_ADDR\\n )\\n {\\n if (\\n addressBytes.length != 0 && addressBytes.length != 20 && ENSIP19.isEVMCoinType(coinType)\\n ) {\\n revert InvalidEVMAddress(addressBytes);\\n }\\n _record(node).addresses[coinType] = addressBytes;\\n emit AddressChanged(node, coinType, addressBytes);\\n if (coinType == COIN_TYPE_ETH) {\\n emit AddrChanged(node, address(bytes20(addressBytes)));\\n }\\n }\\n\\n /// @inheritdoc IAddressResolver\\n function addr(bytes32 node, uint256 coinType) public view returns (bytes memory addressBytes) {\\n Record storage r = _record(node);\\n addressBytes = r.addresses[coinType];\\n if (addressBytes.length == 0 && ENSIP19.chainFromCoinType(coinType) > 0) {\\n addressBytes = r.addresses[COIN_TYPE_DEFAULT];\\n }\\n }\\n\\n /// @inheritdoc IAddrResolver\\n function addr(bytes32 node) public view returns (address payable) {\\n return payable(address(bytes20(addr(node, COIN_TYPE_ETH))));\\n }\\n\\n /// @inheritdoc IPermissionedResolver\\n function getAlias(bytes memory fromName) public view returns (bytes memory toName) {\\n bytes32 prev;\\n for (;;) {\\n bytes memory matchName;\\n (matchName, fromName) = _resolveAlias(fromName);\\n if (fromName.length == 0)\\n break; // no alias\\n bytes32 next = keccak256(matchName);\\n if (next == prev)\\n break; // same alias\\n toName = fromName;\\n prev = next;\\n }\\n }\\n\\n /// @notice Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead.\\n /// @param resource Ignored.\\n /// @param roleBitmap Ignored.\\n /// @param account Ignored.\\n /// @return success Ignored, always reverts.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n pure\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n\\n /// @notice Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead.\\n /// @param resource Ignored.\\n /// @param roleBitmap Ignored.\\n /// @param account Ignored.\\n /// @return success Ignored, always reverts.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n pure\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Allow `ROLE_UPGRADE` to upgrade.\\n function _authorizeUpgrade(address newImplementation)\\n internal\\n override\\n onlyRootRoles(PermissionedResolverLib.ROLE_UPGRADE)\\n {\\n //\\n }\\n\\n /// @dev Avoid permission checks during initialization.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n override\\n {\\n if (!_isInitializing()) {\\n super._checkRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Apply one round of aliasing.\\n /// @param fromName The source DNS-encoded name.\\n /// @return matchName The alias that matched.\\n /// @return toName The destination DNS-encoded name or empty if no match.\\n function _resolveAlias(bytes memory fromName)\\n internal\\n view\\n returns (bytes memory matchName, bytes memory toName)\\n {\\n uint256 offset;\\n while (offset < fromName.length) {\\n matchName = _aliases[NameCoder.namehash(fromName, offset)];\\n if (matchName.length > 0) {\\n if (offset > 0) {\\n // rewrite prefix: [x.y].{fromName[offset:]} => [x.y].{matchName}\\n toName = new bytes(offset + matchName.length);\\n assembly {\\n mcopy(add(toName, 32), add(fromName, 32), offset) // copy prefix\\n mcopy(\\n add(toName, add(32, offset)),\\n add(matchName, 32),\\n mload(matchName)\\n ) // copy suffix\\n }\\n } else {\\n toName = matchName;\\n }\\n break;\\n }\\n (, offset) = NameCoder.nextLabel(fromName, offset);\\n }\\n }\\n\\n /// @dev Access record storage pointer.\\n function _record(bytes32 node) internal view returns (Record storage) {\\n return _records[node][_versions[node]];\\n }\\n\\n /// @dev Returns true if `x` has a single bit set.\\n function _isPowerOf2(uint256 x) internal pure returns (bool) {\\n return x > 0 && (x - 1) & x == 0;\\n }\\n}\\n\",\"keccak256\":\"0xf5633d37d19044ddcd67a42ecb0162e1d79c1914cc2ccc0f337b270c387b8acc\",\"license\":\"MIT\"},\"project/src/resolver/interfaces/IPermissionedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {IExtendedResolver} from \\\"@ens/contracts/resolvers/profiles/IExtendedResolver.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\n\\n/// @dev Interface selector: `0x91413117`\\ninterface IPermissionedResolver is IExtendedResolver, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice An alias was changed.\\n /// @param indexedFromName The source DNS-encoded name. (indexed bytes, hashed)\\n /// @param indexedToName The destination DNS-encoded name. (indexed bytes, hashed)\\n /// @param fromName The source DNS-encoded name.\\n /// @param toName The destination DNS-encoded name.\\n event AliasChanged(\\n bytes indexed indexedFromName,\\n bytes indexed indexedToName,\\n bytes fromName,\\n bytes toName\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The resolver profile cannot be answered.\\n /// @dev Error selector: `0x7b1c461b`\\n error UnsupportedResolverProfile(bytes4 selector);\\n\\n /// @notice The address could not be converted to `address`.\\n /// @dev Error selector: `0x8d666f60`\\n error InvalidEVMAddress(bytes addressBytes);\\n\\n /// @notice The coin type is not a power of 2.\\n /// @dev Error selector: `0x5742bb26`\\n error InvalidContentType(uint256 contentType);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Initialize the contract.\\n /// @param admin The resolver owner.\\n /// @param roleBitmap The roles granted to `admin`.\\n /// @param setters The setter calldata that avoids permission checks.\\n function initialize(address admin, uint256 roleBitmap, bytes[] calldata setters) external;\\n\\n /// @notice Create an alias from `fromName` to `toName`.\\n /// @param fromName The source DNS-encoded name.\\n /// @param toName The destination DNS-encoded name.\\n function setAlias(bytes calldata fromName, bytes calldata toName) external;\\n\\n /// @notice Determine which name is queried when `fromName` is resolved.\\n /// @param fromName The source DNS-encoded name.\\n /// @return toName The destination DNS-encoded name or empty if not aliased.\\n function getAlias(bytes memory fromName) external view returns (bytes memory toName);\\n}\\n\",\"keccak256\":\"0x4e44311fb98d22e7ceb57627eddb23de9594207cf615febe41e7c8b48149aac6\",\"license\":\"MIT\"},\"project/src/resolver/libraries/PermissionedResolverLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Roles for PermissionedResolver.\\nlibrary PermissionedResolverLib {\\n /// @dev Nybble 0: authorizes setting address records. Root or name.\\n uint256 internal constant ROLE_SET_ADDR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting ROLE_SET_ADDR.\\n uint256 internal constant ROLE_SET_ADDR_ADMIN = ROLE_SET_ADDR << 128;\\n\\n /// @dev Nybble 1: authorizes setting text records. Root or name.\\n uint256 internal constant ROLE_SET_TEXT = 1 << 4;\\n /// @dev Nybble 33: authorizes setting ROLE_SET_TEXT.\\n uint256 internal constant ROLE_SET_TEXT_ADMIN = ROLE_SET_TEXT << 128;\\n\\n /// @dev Nybble 2: authorizes setting the contenthash record. Root or name.\\n uint256 internal constant ROLE_SET_CONTENTHASH = 1 << 8;\\n /// @dev Nybble 34: authorizes setting ROLE_SET_CONTENTHASH.\\n uint256 internal constant ROLE_SET_CONTENTHASH_ADMIN = ROLE_SET_CONTENTHASH << 128;\\n\\n /// @dev Nybble 3: authorizes setting the public key record. Root or name.\\n uint256 internal constant ROLE_SET_PUBKEY = 1 << 12;\\n /// @dev Nybble 35: authorizes setting ROLE_SET_PUBKEY.\\n uint256 internal constant ROLE_SET_PUBKEY_ADMIN = ROLE_SET_PUBKEY << 128;\\n\\n /// @dev Nybble 4: authorizes setting ABI records. Root or name.\\n uint256 internal constant ROLE_SET_ABI = 1 << 16;\\n /// @dev Nybble 36: authorizes setting ROLE_SET_ABI.\\n uint256 internal constant ROLE_SET_ABI_ADMIN = ROLE_SET_ABI << 128;\\n\\n /// @dev Nybble 5: authorizes setting interface implementer records. Root or name.\\n uint256 internal constant ROLE_SET_INTERFACE = 1 << 20;\\n /// @dev Nybble 37: authorizes setting ROLE_SET_INTERFACE.\\n uint256 internal constant ROLE_SET_INTERFACE_ADMIN = ROLE_SET_INTERFACE << 128;\\n\\n /// @dev Nybble 6: authorizes setting the reverse name record. Root or name.\\n uint256 internal constant ROLE_SET_NAME = 1 << 24;\\n /// @dev Nybble 38: authorizes setting ROLE_SET_NAME.\\n uint256 internal constant ROLE_SET_NAME_ADMIN = ROLE_SET_NAME << 128;\\n\\n /// @dev Nybble 7: authorizes setting alias targets for name rewriting. Root-only.\\n uint256 internal constant ROLE_SET_ALIAS = 1 << 28;\\n /// @dev Nybble 39: authorizes setting ROLE_SET_ALIAS.\\n uint256 internal constant ROLE_SET_ALIAS_ADMIN = ROLE_SET_ALIAS << 128;\\n\\n /// @dev Nybble 8: authorizes clearing (version-bumping) all records for a node. Root or name.\\n uint256 internal constant ROLE_CLEAR = 1 << 32;\\n /// @dev Nybble 40: authorizes setting ROLE_CLEAR.\\n uint256 internal constant ROLE_CLEAR_ADMIN = ROLE_CLEAR << 128;\\n\\n /// @dev Nybble 9: authorizes setting data records. Root or name.\\n uint256 internal constant ROLE_SET_DATA = 1 << 36;\\n /// @dev Nybble 41: authorizes setting ROLE_SET_DATA.\\n uint256 internal constant ROLE_SET_DATA_ADMIN = ROLE_SET_DATA << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting ROLE_UPGRADE.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n\\n /// @dev Computes `keccak256(node, part)` to create a unique EAC resource ID scoped to both\\n /// a name and a record type. Enables fine-grained per-record permissions.\\n /// @param node The ENS namehash of the name.\\n /// @param part The record-type identifier (e.g. from `addrPart` or `textPart`).\\n /// @return ret The computed resource ID.\\n function resource(bytes32 node, bytes32 part) internal pure returns (uint256 ret) {\\n if (node != bytes32(0) || part != bytes32(0)) {\\n assembly {\\n mstore(0, node)\\n mstore(32, part)\\n ret := keccak256(0, 64)\\n }\\n // Equivalent: return uint256(keccak256(abi.encode(node, part)));\\n }\\n }\\n\\n /// @dev Computes a record-type identifier for uint256-keyed records.\\n /// @param x The uint256 value.\\n /// @return part The computed record-type identifier.\\n function partHash(uint256 x) internal pure returns (bytes32 part) {\\n assembly {\\n mstore(0, x)\\n part := keccak256(0, 32)\\n }\\n }\\n\\n /// @dev Computes a record-type identifier for string-keyed records.\\n /// @param x The string value.\\n /// @return part The computed record-type identifier.\\n function partHash(string memory x) internal pure returns (bytes32) {\\n return keccak256(bytes(x));\\n }\\n}\\n\",\"keccak256\":\"0xd0a807cfe94700e67bd26d5975e644f112299d457a102a8d0176af741b7f09f4\",\"license\":\"MIT\"},\"project/src/resolver/libraries/ResolverProfileRewriterLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Rewrites the `bytes32 node` parameter in resolver calldata. Resolver functions follow\\n/// the convention `func(bytes32 node, ...)`, with the node at calldata offset 4. This library\\n/// replaces that node in a memory copy of the calldata, recursively handling `multicall(bytes[])`\\n/// (selector `0xac9650d8`) to rewrite the node in every nested call at arbitrary depth.\\n///\\n/// Used by `PermissionedResolver` when resolving aliased names: after determining the alias target,\\n/// the original calldata must be updated with the new node before forwarding to the actual\\n/// resolver logic.\\n///\\nlibrary ResolverProfileRewriterLib {\\n /// @dev Replace the node in the calldata with a new node.\\n /// Supports `multicall()` to arbitrary depth.\\n /// @param call The calldata for a resolver.\\n /// @param newNode The replacement node.\\n /// @return copy A copy of the calldata with node replaced.\\n function replaceNode(bytes calldata call, bytes32 newNode)\\n internal\\n pure\\n returns (bytes memory copy)\\n {\\n // 0xac9650d8 // selector\\n // 0000000000000000000000000000000000000000000000000000000000000020 // jump\\n // 0000000000000000000000000000000000000000000000000000000000000002 // .length @ jump\\n // 0000000000000000000000000000000000000000000000000000000000000040 // jump[0]\\n // 00000000000000000000000000000000000000000000000000000000000000a0 // jump[1]\\n // 0000000000000000000000000000000000000000000000000000000000000024 // [0].length @ jump[0]\\n // ...\\n // 0000000000000000000000000000000000000000000000000000000000000024 // [1].length @ jump[1]\\n // ...\\n copy = call; // make a copy\\n assembly {\\n function replace(ptr, bound, node) {\\n ptr := add(ptr, 36) // skip length + selector\\n switch shr(224, mload(sub(ptr, 4))) // read selector\\n case 0xac9650d8 {\\n // multicall(bytes[])\\n let lower := ptr\\n ptr := add(ptr, mload(ptr)) // follow jump\\n if lt(ptr, lower) {\\n leave // underflow\\n }\\n let size := shl(5, mload(ptr)) // read word count as size\\n // prettier-ignore\\n for { } size { size := sub(size, 32) } { // backwards\\n lower := add(ptr, 32)\\n let p := add(lower, mload(add(ptr, size))) // local ptr\\n if lt(p, lower) {\\n continue // underflow\\n }\\n let b := add(p, mload(p)) // local bound w/room for 1 word\\n if lt(bound, b) {\\n b := bound // global bound is smaller\\n }\\n replace(p, b, node)\\n }\\n }\\n default {\\n // only bound checks on write\\n if lt(bound, ptr) {\\n leave\\n }\\n mstore(ptr, node) // replace node\\n }\\n }\\n replace(copy, add(copy, mload(copy)), newNode) // bound w/room for 1 word\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdb4abf724531e5ffa50dcb4ed44954beba4dd96949513aa594f0b02bd5d983ea\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 56727, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_roles", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 56732, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_roleCount", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 56737, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 69710, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_aliases", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_bytes32,t_bytes_storage)" + }, + { + "astId": 69715, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_versions", + "offset": 0, + "slot": "259", + "type": "t_mapping(t_bytes32,t_uint64)" + }, + { + "astId": 69723, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "_records", + "offset": 0, + "slot": "260", + "type": "t_mapping(t_bytes32,t_mapping(t_uint64,t_struct(Record)69705_storage))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)2_storage": { + "base": "t_bytes32", + "encoding": "inplace", + "label": "bytes32[2]", + "numberOfBytes": "64" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_bytes32,t_mapping(t_uint64,t_struct(Record)69705_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(uint64 => struct PermissionedResolver.Record))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint64,t_struct(Record)69705_storage)" + }, + "t_mapping(t_bytes32,t_uint64)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint64)", + "numberOfBytes": "32", + "value": "t_uint64" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_string_memory_ptr,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_string_memory_ptr,t_string_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_uint256,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint64,t_struct(Record)69705_storage)": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => struct PermissionedResolver.Record)", + "numberOfBytes": "32", + "value": "t_struct(Record)69705_storage" + }, + "t_string_memory_ptr": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Record)69705_storage": { + "encoding": "inplace", + "label": "struct PermissionedResolver.Record", + "members": [ + { + "astId": 69678, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "contenthash", + "offset": 0, + "slot": "0", + "type": "t_bytes_storage" + }, + { + "astId": 69682, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "pubkey", + "offset": 0, + "slot": "1", + "type": "t_array(t_bytes32)2_storage" + }, + { + "astId": 69684, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 69688, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "addresses", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint256,t_bytes_storage)" + }, + { + "astId": 69692, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "texts", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_string_memory_ptr,t_string_storage)" + }, + { + "astId": 69696, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "datas", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_string_memory_ptr,t_bytes_storage)" + }, + { + "astId": 69700, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "abis", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint256,t_bytes_storage)" + }, + { + "astId": 69704, + "contract": "project/src/resolver/PermissionedResolver.sol:PermissionedResolver", + "label": "interfaces", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_bytes4,t_address)" + } + ], + "numberOfBytes": "288" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "InvalidContentType(uint256)": [ + { + "notice": "The coin type is not a power of 2." + } + ], + "InvalidEVMAddress(bytes)": [ + { + "notice": "The address could not be converted to `address`." + } + ], + "UnsupportedResolverProfile(bytes4)": [ + { + "notice": "The resolver profile cannot be answered." + } + ] + }, + "events": { + "AliasChanged(bytes,bytes,bytes,bytes)": { + "notice": "An alias was changed." + }, + "DataChanged(bytes32,string,string,bytes)": { + "notice": "For a specific `node`, the data associated with a `key` has changed." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "NamedAddrResource(uint256,bytes,uint256)": { + "notice": "Associate an EAC resource with a name and specific `addr(coinType)` record." + }, + "NamedDataResource(uint256,bytes,bytes32,string)": { + "notice": "Associate an EAC resource with a name and specific `data(key)` record." + }, + "NamedResource(uint256,bytes)": { + "notice": "Associate an EAC resource with a name." + }, + "NamedTextResource(uint256,bytes,bytes32,string)": { + "notice": "Associate an EAC resource with a name and specific `text(key)` record." + } + }, + "kind": "user", + "methods": { + "ABI(bytes32,uint256)": { + "notice": "Returns the ABI associated with an ENS node. Defined in EIP205." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "addr(bytes32)": { + "notice": "Returns the address associated with an ENS node." + }, + "authorizeAddrRoles(bytes,uint256,address,bool)": { + "notice": "Authorize `setAddr(coinType)` permission to `account` for `toName`. Use `NameCoder.encode(\"\")` for any name." + }, + "authorizeDataRoles(bytes,string,address,bool)": { + "notice": "Authorize `setData(key)` permission to `account` for `toName`. Use `NameCoder.encode(\"\")` for any name." + }, + "authorizeNameRoles(bytes,uint256,address,bool)": { + "notice": "Authorize `roleBitmap` permissions to `account` for `toName`. Use `NameCoder.encode(\"\")` for any name, which is equivalent to `grantRootRoles()`." + }, + "authorizeTextRoles(bytes,string,address,bool)": { + "notice": "Authorize `setText(key)` permission to `account` for `toName`. Use `NameCoder.encode(\"\")` for any name." + }, + "canUpgradeFrom(address)": { + "notice": "Declares this implementation as an eligible verifiable proxy upgrade target." + }, + "clearRecords(bytes32)": { + "notice": "Clear all records for `node`." + }, + "contenthash(bytes32)": { + "notice": "Returns the contenthash associated with an ENS node." + }, + "data(bytes32,string)": { + "notice": "For a specific `node`, get the data associated with the key, `key`." + }, + "getAlias(bytes)": { + "notice": "Determine which name is queried when `fromName` is resolved." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAddr(bytes32,uint256)": { + "notice": "Determine if an addresss is stored for the coin type of the associated ENS node." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "initialize(address,uint256,bytes[])": { + "notice": "Initialize the contract." + }, + "interfaceImplementer(bytes32,bytes4)": { + "notice": "Returns the address of a contract that implements the specified interface for this name. If an implementer has not been set for this interfaceID and name, the resolver will query the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that contract implements EIP165 and returns `true` for the specified interfaceID, its address will be returned." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "multicall(bytes[])": { + "notice": "Perform multiple write operations." + }, + "multicallWithNodeCheck(bytes32,bytes[])": { + "notice": "Same as `multicall()`." + }, + "name(bytes32)": { + "notice": "Returns the name associated with an ENS node, for reverse records. Defined in EIP181." + }, + "pubkey(bytes32)": { + "notice": "Returns the SECP256k1 public key associated with an ENS node. Defined in EIP 619." + }, + "recordVersions(bytes32)": { + "notice": "Get the current version." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "setABI(bytes32,uint256,bytes)": { + "notice": "Set ABI data of the associated ENS node." + }, + "setAddr(bytes32,address)": { + "notice": "Set Ethereum mainnet address of the associated ENS node. `address(0)` is stored as `new bytes(20)`." + }, + "setAddr(bytes32,uint256,bytes)": { + "notice": "Set the address for `coinType` of the associated ENS node. Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes." + }, + "setAlias(bytes,bytes)": { + "notice": "Create an alias from `fromName` to `toName`." + }, + "setContenthash(bytes32,bytes)": { + "notice": "Set the contenthash of the associated ENS node." + }, + "setData(bytes32,string,bytes)": { + "notice": "Set the data for `key` of the associated ENS node." + }, + "setInterface(bytes32,bytes4,address)": { + "notice": "Set an interface of the associated ENS node." + }, + "setName(bytes32,string)": { + "notice": "Set the name of the associated ENS node." + }, + "setPubkey(bytes32,bytes32,bytes32)": { + "notice": "Set the SECP256k1 public key associated with an ENS node." + }, + "setText(bytes32,string,string)": { + "notice": "Set the text for `key` of the associated ENS node." + }, + "supportsFeature(bytes4)": { + "notice": "Check if a feature is supported." + }, + "text(bytes32,string)": { + "notice": "Returns the text data associated with an ENS node and key." + } + }, + "notice": "A resolver that supports many profiles, multiple names, internal aliasing, and fine-grained permissions. Supported profiles and standards: - ENSIP-1 / EIP-137: addr() - ENSIP-3 / EIP-181: name() - ENSIP-4 / EIP-205: ABI() - EIP-619: pubkey() - ENSIP-5 / EIP-634: text(key) - ENSIP-7 / EIP-1577: contenthash() - ENSIP-8: interfaceImplementer() - ENSIP-9 / EIP-2304: addr(coinType) - ENSIP-19: addr(default) - ENSIP-24: data(key) - IERC7996: supportsFeature() - IVersionableResolver: version() - IHasAddrResolver: hasAddr() Internal Aliasing: * Resolved names find the longest match and rewrite the suffix. * Successful matches recursively check for additional aliasing. * `bytes32 node` in calldata is updated accordingly. * Cycles of length 1 apply once. * Cycles of length 2+ result in OOG. eg. `setAlias(\"a.eth\", \"b.eth\")` * `getAlias(\"a.eth\") => \"b.eth\"` * `getAlias(\"[sub].a.eth\") => \"[sub].b.eth\"` * `getAlias(\"[x.y].a.eth\") => \"[x.y].b.eth\"` * `getAlias(\"abc.eth\") => \"\"` Fine-grained Permissions: * `setText(key)` can be permissioned with `authorizeTextRoles()` - caller requires `ROLE_SET_TEXT_ADMIN` on `resource(, 0)` - `ROLE_SET_TEXT` is authorized on `resource(, )` * `setData(key)` can be permissioned with `authorizeDataRoles()` - caller requires `ROLE_SET_DATA_ADMIN` on `resource(, 0)` - `ROLE_SET_DATA` is authorized on `resource(, )` * `setAddr(coinType)` can be permissioned with `authorizeAddrRoles()` - caller requires `ROLE_SET_ADDR_ADMIN` on `resource(, 0)` - `ROLE_SET_ADDR` is authorized on `resource(, )` Setters with `node` check (4) EAC resources: Parts Resources +-----------------------------+------------------------------+ | Any (*) | Specific (1) | +--------------+-----------------------------+------------------------------+ | Any (*) | resource(0, 0) | resource(0, ) | Names |--------------+-----------------------------+------------------------------+ | Specific (1) | resource(, 0) | resource(, ) | +--------------+-----------------------------+------------------------------+", + "version": 1 + }, + "argsData": "0x00000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d3", + "transaction": { + "hash": "0x52be24fe0886207ee8b21c714423b24def8d29fd450665d2cf47ca3abf53922d", + "nonce": "0x4f", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x1403857270a1b5b13ccca87eff52293283987aba8805c26069d0958fd320fde2", + "blockNumber": "0xaa5703", + "transactionIndex": "0x7f" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/PublicResolverSet.json b/contracts/deployments/sepolia/PublicResolverSet.json new file mode 100644 index 000000000..059a563fd --- /dev/null +++ b/contracts/deployments/sepolia/PublicResolverSet.json @@ -0,0 +1,918 @@ +{ + "address": "0x24be557df149980a52241dd78a376d78f73689a5", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ApprovalChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "includes", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "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" + } + ], + "contractName": "PermissionedAddressSet", + "sourceName": "src/utils/PermissionedAddressSet.sol", + "bytecode": "0x608060405234801561000f575f80fd5b5060405161107938038061107983398101604081905261002e916102e3565b61004b5f7011000000000000000000000000000000118382610052565b5050610350565b5f835f0361006157505f610145565b61006a8461014d565b6001600160a01b0383166100915760405163761fe2c960e11b815260040160405180910390fd5b5f858152602081815260408083206001600160a01b038716845290915290205484811780821461013f575f878152602081815260408083206001600160a01b03891684529091529020819055811986166100ed88826001610199565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050610145565b5f925050505b949350505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561019657604051630153d96960e51b8152600481018290526024015b60405180910390fd5b50565b5f6101a3836102c9565b90508115610239575f848152600160205260409020546101e99082161980195f8051602061105983398151915291909101165f8051602061103983398151915216151590565b1561021157604051631f22ca6960e31b8152600481018590526024810184905260440161018d565b5f848152600160205260408120805485929061022e908490610324565b909155506102c39050565b5f84815260016020526040902054610278901982161980195f8051602061105983398151915291909101165f8051602061103983398151915216151590565b156102a057604051631f80c19b60e01b8152600481018590526024810184905260440161018d565b5f84815260016020526040812080548592906102bd90849061033d565b90915550505b50505050565b5f6102d38261014d565b50600181901b17600281901b1790565b5f602082840312156102f3575f80fd5b81516001600160a01b0381168114610309575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561033757610337610310565b92915050565b8181038181111561033757610337610310565b610cdc8061035d5f395ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c80633d140d21116100935780637c300586116100635780637c3005861461028c578063ce156e821461029f578063d3bf89b1146102b2578063dfa70d8b14610313575f80fd5b80633d140d21146101ca5780635adf4724146101df5780636f3ff726146101f2578063781ef8db14610242575f80fd5b80631aedefda116100ce5780631aedefda146101425780631c3fc3eb1461016e5780632f27fa24146101835780633634f911146101a2575f80fd5b806301ffc9a7146100f4578063072d5d771461011c57806311b8e00a1461012f575b5f80fd5b610107610102366004610b2c565b610326565b60405190151581526020015b60405180910390f35b61010761012a366004610b6e565b61039d565b61010761013d366004610b98565b6103c1565b610107610150366004610bb8565b6001600160a01b03165f908152610102602052604090205460ff1690565b6101755f81565b604051908152602001610113565b610175610191366004610bd1565b5f9081526001602052604090205490565b6101b56101b0366004610b98565b6103d8565b60408051928352602083019190915201610113565b6101dd6101d8366004610be8565b6103fb565b005b6101756101ed366004610b6e565b610497565b610107610200366004610bb8565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020526040812054601090811614610397565b610107610250366004610b6e565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b61010761029a366004610c21565b6104bf565b6101076102ad366004610b6e565b610502565b6101076102c0366004610c21565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b610107610321366004610c21565b61051d565b5f6001600160e01b031982167f1aedefda00000000000000000000000000000000000000000000000000000000148061038857506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b80610397575061039782610556565b92915050565b5f80836103ab8282336105bc565b6103b85f86866001610628565b95945050505050565b5f806103cd84846103d8565b501515949350505050565b5f806103e38361073c565b5f948552600160205260409094205484169492505050565b60016104085f8233610756565b6001600160a01b0383165f908152610102602052604090205482151560ff909116151503610434575f80fd5b6001600160a01b0383165f8181526101026020908152604091829020805460ff191686151590811790915591519182523392917f7da296e993dc16ba7339edda62347c967436bf5bd3c5e3b98a73bfcb27b38f66910160405180910390a3505050565b5f828152602081815260408083206001600160a01b03851684529091528120545b9392505050565b5f83836104cd8282336105bc565b856104eb57604051631850848b60e31b815260040160405180910390fd5b6104f88686866001610628565b9695505050505050565b5f80836105108282336107f7565b6103b85f86866001610858565b5f838361052b8282336107f7565b8561054957604051631850848b60e31b815260040160405180910390fd5b6104f88686866001610858565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061039757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610397565b5f6105c784836108c0565b90508019831615610622576040517fd1a3b35500000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b03831660448201526064015b60405180910390fd5b50505050565b5f835f0361063757505f610734565b61064084610937565b6001600160a01b038316610680576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b038716845290915290205484811780821461072e575f878152602081815260408083206001600160a01b03891684529091529020819055811986166106dc88826001610997565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050610734565b5f925050505b949350505050565b5f61074682610937565b50600181901b17600281901b1790565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb59092529091205417821682146107f2576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610619565b505050565b5f61080284836108c0565b90508019831615610622576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610619565b5f61086284610937565b5f858152602081815260408083206001600160a01b03871684529091529020548419811680821461072e575f878152602081815260408083206001600160a01b03891684529091528120829055868316906106dc9089908390610997565b5f828152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925282205417608081901c7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176104b8565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615610994576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610619565b50565b5f6109a18361073c565b90508115610a6a575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615610a42576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610619565b5f8481526001602052604081208054859290610a5f908490610c80565b909155506106229050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615610b04576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610619565b5f8481526001602052604081208054859290610b21908490610c93565b909155505050505050565b5f60208284031215610b3c575f80fd5b81356001600160e01b0319811681146104b8575f80fd5b80356001600160a01b0381168114610b69575f80fd5b919050565b5f8060408385031215610b7f575f80fd5b82359150610b8f60208401610b53565b90509250929050565b5f8060408385031215610ba9575f80fd5b50508035926020909101359150565b5f60208284031215610bc8575f80fd5b6104b882610b53565b5f60208284031215610be1575f80fd5b5035919050565b5f8060408385031215610bf9575f80fd5b610c0283610b53565b915060208301358015158114610c16575f80fd5b809150509250929050565b5f805f60608486031215610c33575f80fd5b8335925060208401359150610c4a60408501610b53565b90509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561039757610397610c53565b8181038181111561039757610397610c5356fea26469706673582212202f545feddfbdba601c42d2055dd2a9adb11154035b9d1767abc07ba3d23ae1e064736f6c634300081900338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c80633d140d21116100935780637c300586116100635780637c3005861461028c578063ce156e821461029f578063d3bf89b1146102b2578063dfa70d8b14610313575f80fd5b80633d140d21146101ca5780635adf4724146101df5780636f3ff726146101f2578063781ef8db14610242575f80fd5b80631aedefda116100ce5780631aedefda146101425780631c3fc3eb1461016e5780632f27fa24146101835780633634f911146101a2575f80fd5b806301ffc9a7146100f4578063072d5d771461011c57806311b8e00a1461012f575b5f80fd5b610107610102366004610b2c565b610326565b60405190151581526020015b60405180910390f35b61010761012a366004610b6e565b61039d565b61010761013d366004610b98565b6103c1565b610107610150366004610bb8565b6001600160a01b03165f908152610102602052604090205460ff1690565b6101755f81565b604051908152602001610113565b610175610191366004610bd1565b5f9081526001602052604090205490565b6101b56101b0366004610b98565b6103d8565b60408051928352602083019190915201610113565b6101dd6101d8366004610be8565b6103fb565b005b6101756101ed366004610b6e565b610497565b610107610200366004610bb8565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020526040812054601090811614610397565b610107610250366004610b6e565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b61010761029a366004610c21565b6104bf565b6101076102ad366004610b6e565b610502565b6101076102c0366004610c21565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b610107610321366004610c21565b61051d565b5f6001600160e01b031982167f1aedefda00000000000000000000000000000000000000000000000000000000148061038857506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b80610397575061039782610556565b92915050565b5f80836103ab8282336105bc565b6103b85f86866001610628565b95945050505050565b5f806103cd84846103d8565b501515949350505050565b5f806103e38361073c565b5f948552600160205260409094205484169492505050565b60016104085f8233610756565b6001600160a01b0383165f908152610102602052604090205482151560ff909116151503610434575f80fd5b6001600160a01b0383165f8181526101026020908152604091829020805460ff191686151590811790915591519182523392917f7da296e993dc16ba7339edda62347c967436bf5bd3c5e3b98a73bfcb27b38f66910160405180910390a3505050565b5f828152602081815260408083206001600160a01b03851684529091528120545b9392505050565b5f83836104cd8282336105bc565b856104eb57604051631850848b60e31b815260040160405180910390fd5b6104f88686866001610628565b9695505050505050565b5f80836105108282336107f7565b6103b85f86866001610858565b5f838361052b8282336107f7565b8561054957604051631850848b60e31b815260040160405180910390fd5b6104f88686866001610858565b5f6001600160e01b031982167f8f452d6200000000000000000000000000000000000000000000000000000000148061039757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610397565b5f6105c784836108c0565b90508019831615610622576040517fd1a3b35500000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b03831660448201526064015b60405180910390fd5b50505050565b5f835f0361063757505f610734565b61064084610937565b6001600160a01b038316610680576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b038716845290915290205484811780821461072e575f878152602081815260408083206001600160a01b03891684529091529020819055811986166106dc88826001610997565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050610734565b5f925050505b949350505050565b5f61074682610937565b50600181901b17600281901b1790565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb59092529091205417821682146107f2576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610619565b505050565b5f61080284836108c0565b90508019831615610622576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610619565b5f61086284610937565b5f858152602081815260408083206001600160a01b03871684529091529020548419811680821461072e575f878152602081815260408083206001600160a01b03891684529091528120829055868316906106dc9089908390610997565b5f828152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925282205417608081901c7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176104b8565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615610994576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610619565b50565b5f6109a18361073c565b90508115610a6a575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615610a42576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610619565b5f8481526001602052604081208054859290610a5f908490610c80565b909155506106229050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615610b04576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610619565b5f8481526001602052604081208054859290610b21908490610c93565b909155505050505050565b5f60208284031215610b3c575f80fd5b81356001600160e01b0319811681146104b8575f80fd5b80356001600160a01b0381168114610b69575f80fd5b919050565b5f8060408385031215610b7f575f80fd5b82359150610b8f60208401610b53565b90509250929050565b5f8060408385031215610ba9575f80fd5b50508035926020909101359150565b5f60208284031215610bc8575f80fd5b6104b882610b53565b5f60208284031215610be1575f80fd5b5035919050565b5f8060408385031215610bf9575f80fd5b610c0283610b53565b915060208301358015158114610c16575f80fd5b809150509250929050565b5f805f60608486031215610c33575f80fd5b8335925060208401359150610c4a60408501610b53565b90509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561039757610397610c53565b8181038181111561039757610397610c5356fea26469706673582212202f545feddfbdba601c42d2055dd2a9adb11154035b9d1767abc07ba3d23ae1e064736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/src/utils/PermissionedAddressSet.sol", + "devdoc": { + "errors": { + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ] + }, + "events": { + "ApprovalChanged(address,bool,address)": { + "params": { + "addr": "The address.", + "approved": "If `true`, added, otherwise removed.", + "sender": "The sender of the change." + } + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + } + }, + "kind": "dev", + "methods": { + "approve(address,bool)": { + "params": { + "addr": "The address to approve.", + "approved": "If `true`, added, otherwise removed." + } + }, + "constructor": { + "params": { + "rootAccount": "Account granted root roles." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "grantRoles(uint256,uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted. Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.", + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "includes(address)": { + "params": { + "addr": "The address to check." + }, + "returns": { + "_0": "`true` if included." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "revokeRoles(uint256,uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked. Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.", + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "stateVariables": { + "_approved": { + "details": "Mapping that determines members of the set." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "658400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ROOT_RESOURCE()": "238", + "approve(address,bool)": "33255", + "getAssigneeCount(uint256,uint256)": "2725", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "2732", + "hasRoles(uint256,uint256,address)": "4893", + "hasRootRoles(uint256,address)": "2653", + "includes(address)": "2558", + "isContractNamer(address)": "2633", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "2502", + "roles(uint256,address)": "2696", + "supportsInterface(bytes4)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ApprovalChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"includes\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"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\"}],\"devdoc\":{\"errors\":{\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}]},\"events\":{\"ApprovalChanged(address,bool,address)\":{\"params\":{\"addr\":\"The address.\",\"approved\":\"If `true`, added, otherwise removed.\",\"sender\":\"The sender of the change.\"}},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}}},\"kind\":\"dev\",\"methods\":{\"approve(address,bool)\":{\"params\":{\"addr\":\"The address to approve.\",\"approved\":\"If `true`, added, otherwise removed.\"}},\"constructor\":{\"params\":{\"rootAccount\":\"Account granted root roles.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"grantRoles(uint256,uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted. Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\",\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"includes(address)\":{\"params\":{\"addr\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if included.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"revokeRoles(uint256,uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked. Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"_approved\":{\"details\":\"Mapping that determines members of the set.\"}},\"version\":1},\"userdoc\":{\"events\":{\"ApprovalChanged(address,bool,address)\":{\"notice\":\"Inclusion of a member of the set has changed.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"}},\"kind\":\"user\",\"methods\":{\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"approve(address,bool)\":{\"notice\":\"Add or remove a member from the set.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"includes(address)\":{\"notice\":\"Check if `addr` is included in the set.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"}},\"notice\":\"An arbitrary set of addresses managed by EAC.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/utils/PermissionedAddressSet.sol\":\"PermissionedAddressSet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, msg.sender);\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _getRoles(resource, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _getRoles(ROOT_RESOURCE, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return _effectiveRoles(resource, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the roles bitmap for an account for permission checks.\\n function _getRoles(uint256 resource, address account) internal view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the effective roles bitmap for an account for permission checks.\\n function _effectiveRoles(uint256 resource, address account) private view returns (uint256) {\\n return _getRoles(ROOT_RESOURCE, account) | _getRoles(resource, account);\\n }\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n}\\n\",\"keccak256\":\"0x934655016f502e7a2f8e5cbd294ef48e85f238821f5608de5675c023f48037af\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Admin roles imply their corresponding regular roles.\\n function withAdminRolesApplied(uint256 roleBitmap) internal pure returns (uint256) {\\n roleBitmap >>= 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Derive roles bitmap from assignee counts.\\n /// @param counts Packed role counts (0-15) as `uint4x64`.\\n function fromCounts(uint256 counts) internal pure returns (uint256) {\\n return (counts | (counts >> 1) | (counts >> 2) | (counts >> 3)) & ALL_ROLES;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function hasZeroNybbles(uint256 value) internal pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 zeroNybbles;\\n unchecked {\\n zeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return zeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xc14f05abd508e75c9f16a35e31d0fb9f1f1dd904b65d058201c788a9ddd562eb\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/PermissionedAddressSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IAddressSet} from \\\"./interfaces/IAddressSet.sol\\\";\\n\\n/// @dev Nybble 0: authorizes modifying the set. Root only.\\nuint256 constant ROLE_APPROVE = 1 << 0;\\n\\n/// @dev Nybble 32: authorizes setting `ROLE_APPROVE`.\\nuint256 constant ROLE_APPROVE_ADMIN = ROLE_APPROVE << 128;\\n\\n/// @dev Nybble 1: authorizes contract naming. Root only.\\nuint256 constant ROLE_CAN_NAME = 1 << 4;\\n\\n/// @dev Nybble 33: authorizes setting `ROLE_CAN_NAME`.\\nuint256 constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n/// @dev Default root roles assigned at construction.\\nuint256 constant DEFAULT_ROLE_BITMAP =\\n ROLE_APPROVE | ROLE_APPROVE_ADMIN | ROLE_CAN_NAME | ROLE_CAN_NAME_ADMIN;\\n\\n/// @notice An arbitrary set of addresses managed by EAC.\\ncontract PermissionedAddressSet is EnhancedAccessControl, IAddressSet, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Mapping that determines members of the set.\\n mapping(address addr => bool approved) internal _approved;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Inclusion of a member of the set has changed.\\n /// @param addr The address.\\n /// @param approved If `true`, added, otherwise removed.\\n /// @param sender The sender of the change.\\n event ApprovalChanged(address indexed addr, bool approved, address indexed sender);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param rootAccount Account granted root roles.\\n constructor(address rootAccount) {\\n _grantRoles(ROOT_RESOURCE, DEFAULT_ROLE_BITMAP, rootAccount, false);\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IAddressSet).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Add or remove a member from the set.\\n /// @param addr The address to approve.\\n /// @param approved If `true`, added, otherwise removed.\\n function approve(address addr, bool approved) external onlyRootRoles(ROLE_APPROVE) {\\n require(_approved[addr] != approved);\\n _approved[addr] = approved;\\n emit ApprovalChanged(addr, approved, msg.sender);\\n }\\n\\n /// @inheritdoc IAddressSet\\n function includes(address addr) external view returns (bool) {\\n return _approved[addr];\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return hasRootRoles(ROLE_CAN_NAME, namer);\\n }\\n}\\n\",\"keccak256\":\"0xeffba36f03c50508b7196cd8403bca15d9f23053685d5439455e282af9863515\",\"license\":\"MIT\"},\"project/src/utils/interfaces/IAddressSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x1aedefda`\\ninterface IAddressSet {\\n /// @notice Check if `addr` is included in the set.\\n /// @param addr The address to check.\\n /// @return `true` if included.\\n function includes(address addr) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcb4f9c6364c1cf8a737591088f488ede7a7c6bc9d7d87f2dbdac731b492bd862\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 56727, + "contract": "project/src/utils/PermissionedAddressSet.sol:PermissionedAddressSet", + "label": "_roles", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 56732, + "contract": "project/src/utils/PermissionedAddressSet.sol:PermissionedAddressSet", + "label": "_roleCount", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 56737, + "contract": "project/src/utils/PermissionedAddressSet.sol:PermissionedAddressSet", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 75689, + "contract": "project/src/utils/PermissionedAddressSet.sol:PermissionedAddressSet", + "label": "_approved", + "offset": 0, + "slot": "258", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "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_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,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" + } + } + }, + "userdoc": { + "events": { + "ApprovalChanged(address,bool,address)": { + "notice": "Inclusion of a member of the set has changed." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + } + }, + "kind": "user", + "methods": { + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "approve(address,bool)": { + "notice": "Add or remove a member from the set." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "includes(address)": { + "notice": "Check if `addr` is included in the set." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + } + }, + "notice": "An arbitrary set of addresses managed by EAC.", + "version": 1 + }, + "argsData": "0x00000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d3", + "transaction": { + "hash": "0xe4b9246b465680d299e2c14dde512735699681ee4c084e3fe8f75a3a617c117b", + "nonce": "0x5b", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x3dae6de8ef4907198ca4af1f9d8a69556e774b4edb4e5996ef0c9e79e7046491", + "blockNumber": "0xaa570f", + "transactionIndex": "0x6a" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/PublicResolverV2.json b/contracts/deployments/sepolia/PublicResolverV2.json new file mode 100644 index 000000000..0e87bcbaf --- /dev/null +++ b/contracts/deployments/sepolia/PublicResolverV2.json @@ -0,0 +1,2159 @@ +{ + "address": "0xd25f66dd4ff61486c2c5c1e6201a23576698d3df", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "rootRegistry", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "name": "InvalidEVMAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + } + ], + "name": "ABIChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "a", + "type": "address" + } + ], + "name": "AddrChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newAddress", + "type": "bytes" + } + ], + "name": "AddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "Approved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "ContenthashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "resource", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "record", + "type": "bytes" + } + ], + "name": "DNSRecordChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "resource", + "type": "uint16" + } + ], + "name": "DNSRecordDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "lastzonehash", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "zonehash", + "type": "bytes" + } + ], + "name": "DNSZonehashChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "indexedData", + "type": "bytes" + } + ], + "name": "DataChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "InterfaceChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "NameChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "name": "PubkeyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "string", + "name": "indexedKey", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "TextChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newVersion", + "type": "uint64" + } + ], + "name": "VersionChanged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "contentTypes", + "type": "uint256" + } + ], + "name": "ABI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "canModifyName", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "clearRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "contenthash", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "data", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "name", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "resource", + "type": "uint16" + } + ], + "name": "dnsRecord", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "hasAddr", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "name", + "type": "bytes32" + } + ], + "name": "hasDNSRecords", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "interfaceImplementer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + } + ], + "name": "isApprovedFor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "nodehash", + "type": "bytes32" + }, + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicallWithNodeCheck", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "pubkey", + "outputs": [ + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "recordVersions", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "contentType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "setABI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "addressBytes", + "type": "bytes" + } + ], + "name": "setAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "setContenthash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "setDNSRecords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "setData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + }, + { + "internalType": "address", + "name": "implementer", + "type": "address" + } + ], + "name": "setInterface", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "y", + "type": "bytes32" + } + ], + "name": "setPubkey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "setText", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "hash", + "type": "bytes" + } + ], + "name": "setZonehash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "key", + "type": "string" + } + ], + "name": "text", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "zonehash", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "PublicResolverV2", + "sourceName": "src/resolver/PublicResolverV2.sol", + "bytecode": "0x60e060405234801561000f575f80fd5b5060405161392d38038061392d83398101604081905261002e91610062565b6001600160a01b0390811660805291821660a0521660c0526100ac565b6001600160a01b038116811461005f575f80fd5b50565b5f805f60608486031215610074575f80fd5b835161007f8161004b565b60208501519093506100908161004b565b60408501519092506100a18161004b565b809150509250925092565b60805160a05160c0516138426100eb5f395f81816105df015261105b01525f81816103070152610fd701525f81816103c101526114e501526138425ff3fe608060405234801561000f575f80fd5b5060043610610283575f3560e01c80636f3ff72611610157578063c8690233116100d2578063e32954eb11610088578063e985e9c51161006e578063e985e9c51461068f578063ecbfada3146106ca578063f1cb7e06146106dd575f80fd5b8063e32954eb14610669578063e59d895d1461067c575f80fd5b8063ce3decdc116100b8578063ce3decdc14610601578063d5fa2b0014610614578063d700ff3314610627575f80fd5b8063c869023314610582578063c92cc49a146105da575f80fd5b8063a4b91a0111610127578063a9784b3e1161010d578063a9784b3e1461050c578063ac9650d81461054f578063bc1c58d11461056f575f80fd5b8063a4b91a01146104e6578063a8fa5682146104f9575f80fd5b80636f3ff7261461049a57806377372213146104ad5780638b95dd71146104c0578063a22cb465146104d3575f80fd5b80633603d758116102015780634eb9c45e116101b75780635c98042b1161019d5780635c98042b14610461578063623195b014610474578063691f343114610487575f80fd5b80634eb9c45e1461042e57806359d1d43c14610441575f80fd5b806341415eab116101e757806341415eab146103a957806348ee1bcc146103bc5780634cbf6ba4146103e3575f80fd5b80633603d758146103835780633b3b57de14610396575f80fd5b8063192cf07d1161025657806329cd62ea1161023c57806329cd62ea1461034a578063304e6ade1461035d57806332f111d714610370575f80fd5b8063192cf07d146103025780632203ab5614610329575f80fd5b806301ffc9a7146102875780630af179d7146102af57806310f13a8c146102c4578063124a319c146102d7575b5f80fd5b61029a610295366004612cf5565b6106f0565b60405190151581526020015b60405180910390f35b6102c26102bd366004612d4c565b610700565b005b6102c26102d2366004612d94565b610903565b6102ea6102e5366004612e08565b6109ce565b6040516001600160a01b0390911681526020016102a6565b6102ea7f000000000000000000000000000000000000000000000000000000000000000081565b61033c610337366004612e32565b610c44565b6040516102a6929190612e80565b6102c2610358366004612e98565b610d80565b6102c261036b366004612d4c565b610e19565b61029a61037e366004612e32565b610e93565b6102c2610391366004612ec1565b610ede565b6102ea6103a4366004612ec1565b610f7e565b61029a6103b7366004612eec565b610f9c565b6102ea7f000000000000000000000000000000000000000000000000000000000000000081565b61029a6103f1366004612e32565b5f828152602081815260408083205467ffffffffffffffff1683526007825280832094835293815283822092825291909152205461ffff16151590565b6102c261043c366004612d94565b611107565b61045461044f366004612d4c565b611258565b6040516102a69190612f1a565b61045461046f366004612ec1565b611336565b6102c2610482366004612f2c565b6113f2565b610454610495366004612ec1565b61148b565b61029a6104a8366004612f7b565b6114c4565b6102c26104bb366004612d4c565b611550565b6102c26104ce366004613002565b6115ca565b6102c26104e136600461309b565b611707565b6102c26104f43660046130c7565b6117f2565b610454610507366004613106565b6118c5565b61029a61051a366004613137565b6001600160a01b039283165f908152600d60209081526040808320948352938152838220929094168152925290205460ff1690565b61056261055d3660046131ac565b611912565b6040516102a691906131eb565b61045461057d366004612ec1565b61191f565b6105c5610590366004612ec1565b5f818152602081815260408083205467ffffffffffffffff168352600a82528083209383529290522080546001909101549091565b604080519283526020830191909152016102a6565b6102ea7f000000000000000000000000000000000000000000000000000000000000000081565b6102c261060f366004612d4c565b611958565b6102c2610622366004612eec565b611a96565b610650610635366004612ec1565b5f6020819052908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102a6565b61056261067736600461324d565b611ae9565b6102c261068a366004613288565b611afe565b61029a61069d3660046132ba565b6001600160a01b039182165f908152600c6020908152604080832093909416825291909152205460ff1690565b6104546106d8366004612d4c565b611bbb565b6104546106eb366004612e32565b611bfa565b5f6106fa82611d81565b92915050565b8261070a81611da5565b610712575f80fd5b5f84815260208181526040808320548151601f870184900484028101840190925285825283926060928392859267ffffffffffffffff9091169183916107769183918d908d90819084018382808284375f920191909152509293925050611db09050565b90505b8051516020820151101561089d578661ffff165f036107dd57806040015196506107a281611e0b565b9450846040516020016107b591906132e6565b6040516020818303038152906040528051906020012092506107d681611e2c565b935061088f565b5f6107e782611e0b565b9050816040015161ffff168861ffff1614158061080b57506108098682611e48565b155b1561088d576108668c878a8e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505060208801518d915061085d908290613310565b8b51158a611e6c565b81604001519750816020015196508095508580519060200120935061088a82611e2c565b94505b505b610898816120d1565b610779565b508351156108f7576108f78a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c92506108ee91508290508f613310565b89511588611e6c565b50505050505050505050565b8461090d81611da5565b610915575f80fd5b5f868152602081815260408083205467ffffffffffffffff168352600b8252808320898452909152908190209051849184916109549089908990613323565b9081526020016040518091039020918261096f9291906133ae565b508484604051610980929190613323565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a1878787876040516109be9493929190613490565b60405180910390a3505050505050565b5f828152602081815260408083205467ffffffffffffffff1683526008825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b03168015610a215790506106fa565b5f610a2b85610f7e565b90506001600160a01b038116610a45575f925050506106fa565b6040516301ffc9a760e01b60248201525f9081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610a9c91906132e6565b5f60405180830381855afa9150503d805f8114610ad4576040519150601f19603f3d011682016040523d82523d5f602084013e610ad9565b606091505b5091509150811580610aec575060208151105b80610b2e575080601f81518110610b0557610b056134b6565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610b3f575f9450505050506106fa565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610b9591906132e6565b5f60405180830381855afa9150503d805f8114610bcd576040519150601f19603f3d011682016040523d82523d5f602084013e610bd2565b606091505b509092509050811580610be6575060208151105b80610c28575080601f81518110610bff57610bff6134b6565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610c39575f9450505050506106fa565b509095945050505050565b5f828152602081815260408083205467ffffffffffffffff168352600180835281842086855290925282206060915b5f81118015610c825750848111155b15610d625780851615801590610caf57505f8181526020839052604081208054610cab90613332565b9050115b15610d5a5780825f8381526020019081526020015f20808054610cd190613332565b80601f0160208091040260200160405190810160405280929190818152602001828054610cfd90613332565b8015610d485780601f10610d1f57610100808354040283529160200191610d48565b820191905f5260205f20905b815481529060010190602001808311610d2b57829003601f168201915b50505050509050935093505050610d79565b60011b610c73565b505f60405180602001604052805f81525092509250505b9250929050565b82610d8a81611da5565b610d92575f80fd5b60408051808201825284815260208082018581525f8881528083528481205467ffffffffffffffff168152600a835284812089825283528490209251835551600190920191909155815185815290810184905285917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a250505050565b82610e2381611da5565b610e2b575f80fd5b5f848152602081815260408083205467ffffffffffffffff168352600382528083208784529091529020610e608385836133ae565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788484604051610e0b9291906134ca565b5f828152602081815260408083205467ffffffffffffffff16835260028252808320858452825280832084845290915281208054829190610ed390613332565b905011905092915050565b80610ee881611da5565b610ef0575f80fd5b5f828152602081905260408120805467ffffffffffffffff1691610f13836134dd565b82546101009290920a67ffffffffffffffff8181021990931691831602179091555f84815260208181526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b5f610f8a82603c611bfa565b610f9390613503565b60601c92915050565b6040517f20c38e2b000000000000000000000000000000000000000000000000000000008152600481018390525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906320c38e2b906024015f60405180830381865afa15801561101b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611042919081019061353f565b905080515f03611055575f9150506106fa565b5f6110817f0000000000000000000000000000000000000000000000000000000000000000835f6121b6565b9050836001600160a01b0316816001600160a01b031614806110c757506001600160a01b038082165f908152600c602090815260408083209388168352929052205460ff165b806110fe57506001600160a01b038082165f908152600d6020908152604080832089845282528083209388168352929052205460ff165b95945050505050565b8461111181611da5565b611119575f80fd5b5f868152602081815260408083205467ffffffffffffffff16835260048252808320898452909152908190209051849184916111589089908990613323565b908152602001604051809103902091826111739291906133ae565b506111e68686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f92019190915250611ae492505050565b82826040516111f6929190613323565b6040518091039020858560405161120e929190613323565b6040518091039020877f3b7ea3580e046bf897ca24f2f45fcf5491dafba8d1b3dd17ca92aa0e82b4dd2188886040516112489291906134ca565b60405180910390a4505050505050565b5f838152602081815260408083205467ffffffffffffffff168352600b8252808320868452909152908190209051606091906112979085908590613323565b908152602001604051809103902080546112b090613332565b80601f01602080910402602001604051908101604052809291908181526020018280546112dc90613332565b80156113275780601f106112fe57610100808354040283529160200191611327565b820191905f5260205f20905b81548152906001019060200180831161130a57829003601f168201915b505050505090505b9392505050565b5f818152602081815260408083205467ffffffffffffffff16835260058252808320848452909152902080546060919061136f90613332565b80601f016020809104026020016040519081016040528092919081815260200182805461139b90613332565b80156113e65780601f106113bd576101008083540402835291602001916113e6565b820191905f5260205f20905b8154815290600101906020018083116113c957829003601f168201915b50505050509050919050565b836113fc81611da5565b611404575f80fd5b83611410600182613310565b161561141a575f80fd5b5f858152602081815260408083205467ffffffffffffffff16835260018252808320888452825280832087845290915290206114578385836133ae565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3905f90a35050505050565b5f818152602081815260408083205467ffffffffffffffff16835260098252808320848452909152902080546060919061136f90613332565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561152c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106fa91906135b4565b8261155a81611da5565b611562575f80fd5b5f848152602081815260408083205467ffffffffffffffff1683526009825280832087845290915290206115978385836133ae565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051610e0b9291906134ca565b826115d481611da5565b6115dc575f80fd5b8151158015906115ee57508151601414155b80156115fe57506115fe83612274565b1561164057816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016116379190612f1a565b60405180910390fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528484604051611672929190612e80565b60405180910390a2603c83036116c457837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd26116ad84613503565b60405160609190911c815260200160405180910390a25b5f848152602081815260408083205467ffffffffffffffff168352600282528083208784528252808320868452909152902061170083826135cf565b5050505050565b336001600160a01b03831681036117865760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152608401611637565b6001600160a01b038181165f818152600c6020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b336001600160a01b038316810361184b5760405162461bcd60e51b815260206004820181905260248201527f53657474696e672064656c65676174652073746174757320666f722073656c666044820152606401611637565b6001600160a01b038181165f818152600d60209081526040808320898452825280832094881680845294825291829020805460ff1916871515908117909155915192835290929187917ff0ddb3b04746704017f9aa8bd728fcc2c1d11675041205350018915f5e4750a0910160405180910390a450505050565b5f838152602081815260408083205467ffffffffffffffff168352600682528083208684528252808320858452825280832061ffff8516845290915290208054606091906112b090613332565b606061132f5f8484612299565b5f818152602081815260408083205467ffffffffffffffff16835260038252808320848452909152902080546060919061136f90613332565b8261196281611da5565b61196a575f80fd5b5f848152602081815260408083205467ffffffffffffffff1680845260058352818420888552909252822080549192916119a390613332565b80601f01602080910402602001604051908101604052809291908181526020018280546119cf90613332565b8015611a1a5780601f106119f157610100808354040283529160200191611a1a565b820191905f5260205f20905b8154815290600101906020018083116119fd57829003601f168201915b5050505067ffffffffffffffff84165f9081526005602090815260408083208b84529091529020919250611a5190508587836133ae565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f85828787604051611a869392919061368f565b60405180910390a2505050505050565b81611aa081611da5565b611aa8575f80fd5b6040516bffffffffffffffffffffffff19606084901b166020820152611ae4908490603c906034016040516020818303038152906040526115ca565b505050565b6060611af6848484612299565b949350505050565b82611b0881611da5565b611b10575f80fd5b5f848152602081815260408083205467ffffffffffffffff1683526008825280832087845282528083206001600160e01b031987168085529083529281902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b5f838152602081815260408083205467ffffffffffffffff16835260048252808320868452909152908190209051606091906112979085908590613323565b5f828152602081815260408083205467ffffffffffffffff1683526002825280832085845282528083208484529182905290912080546060929190611c3e90613332565b80601f0160208091040260200160405190810160405280929190818152602001828054611c6a90613332565b8015611cb55780601f10611c8c57610100808354040283529160200191611cb5565b820191905f5260205f20905b815481529060010190602001808311611c9857829003601f168201915b5050505050915081515f148015611cd957505f611cd184612458565b63ffffffff16115b15611d7a5763800000005f9081526020829052604090208054611cfb90613332565b80601f0160208091040260200160405190810160405280929190818152602001828054611d2790613332565b8015611d725780601f10611d4957610100808354040283529160200191611d72565b820191905f5260205f20905b815481529060010190602001808311611d5557829003601f168201915b505050505091505b5092915050565b5f6001600160e01b0319821663379ffb9360e11b14806106fa57506106fa82612482565b5f6106fa8233610f9c565b611df86040518060e00160405280606081526020015f81526020015f61ffff1681526020015f61ffff1681526020015f63ffffffff1681526020015f81526020015f81525090565b82815260c081018290526106fa816120d1565b602081015181516060916106fa91611e2390826124bf565b84519190612516565b60a081015160c08201516060916106fa91611e23908290613310565b5f8151835114801561132f5750508051602091820120825192909101919091201490565b865160208801205f611e7f878787612516565b90508315611fa65767ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611ec990613332565b159050611f275767ffffffffffffffff83165f9081526007602090815260408083208d845282528083208584529091528120805461ffff1691611f0b836136be565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c1684529091528120611f6791612c8b565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a604051611f999291906136da565b60405180910390a26108f7565b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611fe890613332565b90505f036120475767ffffffffffffffff83165f9081526007602090815260408083208d845282528083208584529091528120805461ffff169161202b836136ff565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152902061208882826135cf565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a846040516120bd93929190613715565b60405180910390a250505050505050505050565b60c081015160208201819052815151116120e85750565b5f6120fa825f015183602001516124bf565b82602001516121099190613743565b8251909150612118908261256b565b61ffff16604083015261212c600282613743565b825190915061213b908261256b565b61ffff16606083015261214f600282613743565b825190915061215e908261258c565b63ffffffff166080830152612174600482613743565b82519091505f90612185908361256b565b61ffff169050612196600283613743565b60a0840181905291506121a98183613743565b60c0909301929092525050565b5f806121c38585856125a8565b90506001600160a01b038116158015906121e957506121e9816331ab054760e11b6125d4565b1561226c575f6121f985856125ef565b506040516331ab054760e11b81529091506001600160a01b038316906363560a8e90612229908490600401612f1a565b602060405180830381865afa158015612244573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122689190613756565b9250505b509392505050565b5f63800000008214806106fa57505f61228c83612458565b63ffffffff161192915050565b60608167ffffffffffffffff8111156122b4576122b4612f96565b6040519080825280602002602001820160405280156122e757816020015b60608152602001906001900390816122d25790505b5090505f5b8281101561226c5784156123b0575f84848381811061230d5761230d6134b6565b905060200281019061231f9190613771565b61232e916024916004916137b4565b612337916137db565b90508581146123ae5760405162461bcd60e51b815260206004820152603460248201527f6d756c746963616c6c3a20416c6c207265636f726473206d757374206861766560448201527f2061206d61746368696e67206e616d65686173680000000000000000000000006064820152608401611637565b505b5f80308686858181106123c5576123c56134b6565b90506020028101906123d79190613771565b6040516123e5929190613323565b5f60405180830381855af49150503d805f811461241d576040519150601f19603f3d011682016040523d82523d5f602084013e612422565b606091505b509150915081612430575f80fd5b80848481518110612443576124436134b6565b602090810291909101015250506001016122ec565b5f603c820361246957506001919050565b638000000091821891821061247e575f6106fa565b5090565b5f6001600160e01b031982167f59d1d43c0000000000000000000000000000000000000000000000000000000014806106fa57506106fa8261266c565b5f815b835181106124d2576124d26137f8565b5f6124dd85836126a9565b60ff1690506124ed816001613743565b6124f79083613743565b9150805f03612506575061250c565b506124c2565b611af68382613310565b60608167ffffffffffffffff81111561253157612531612f96565b6040519080825280601f01601f19166020018201604052801561255b576020820181803683370190505b50905061132f8484835f866126db565b5f6125808361257b846002613743565b61270c565b50016020015160f01c90565b5f61259c8361257b846004613743565b50016020015160e01c90565b5f805f6125b58585612758565b909250905081156125cb57612268868683612785565b50509392505050565b5f6125de83612864565b801561132f575061132f8383612896565b60605f806125fd858561291c565b925090505f60ff821667ffffffffffffffff81111561261e5761261e612f96565b6040519080825280601f01601f191660200182016040528015612648576020820181803683370190505b5090506126616020820160218888010160ff8516612999565b959194509092505050565b5f6001600160e01b031982167fc86902330000000000000000000000000000000000000000000000000000000014806106fa57506106fa826129e2565b5f6126b98361257b846001613743565b8282815181106126cb576126cb6134b6565b016020015160f81c905092915050565b6126e98561257b8387613743565b6126f78361257b8385613743565b61170082602085010185602088010183612999565b81518111156127545781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152611637918391600401918252602082015260400190565b5050565b5f805f612765858561291c565b9250905060ff81161561277d57806021858701012092505b509250929050565b5f805f6127928585612758565b9092509050816127a657859250505061132f565b5f6127b2878784612785565b90506001600160a01b0381161561285a575f6127ce87876125ef565b506040517f35af62160000000000000000000000000000000000000000000000000000000081529091506001600160a01b038316906335af621690612817908490600401612f1a565b602060405180830381865afa158015612832573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128569190613756565b9450505b5050509392505050565b5f612876826301ffc9a760e01b612896565b80156106fa575061288f826001600160e01b0319612896565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015612906575060208210155b801561291157505f81115b979650505050505050565b5f8083518310612941578360405163ba4adc2360e01b81526004016116379190612f1a565b838381518110612953576129536134b6565b016020015160f81c91505081810160010181612973578351811415612979565b83518110155b15610d79578360405163ba4adc2360e01b81526004016116379190612f1a565b5b601f8111156129ba578151835260209283019290910190601f190161299a565b8015611ae45790518251600160209390930360031b9290921b5f190180199091169116179052565b5f6001600160e01b031982167f691f34310000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167f124a319c0000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167fa8fa5682000000000000000000000000000000000000000000000000000000001480612ab457506001600160e01b031982167f5c98042b00000000000000000000000000000000000000000000000000000000145b806106fa57506106fa825f6001600160e01b031982167fecbfada30000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167fbc1c58d10000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f7f3b3b57de000000000000000000000000000000000000000000000000000000006001600160e01b031983161480612b9057507ff1cb7e06000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80612bc457507f32f111d7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b806106fa57506106fa825f6001600160e01b031982167f2203ab560000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167fd700ff330000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167f4fbf04330000000000000000000000000000000000000000000000000000000014806106fa57506301ffc9a760e01b6001600160e01b03198316146106fa565b508054612c9790613332565b5f825580601f10612ca6575050565b601f0160209004905f5260205f2090810190612cc29190612cc5565b50565b5b8082111561247e575f8155600101612cc6565b80356001600160e01b031981168114612cf0575f80fd5b919050565b5f60208284031215612d05575f80fd5b61132f82612cd9565b5f8083601f840112612d1e575f80fd5b50813567ffffffffffffffff811115612d35575f80fd5b602083019150836020828501011115610d79575f80fd5b5f805f60408486031215612d5e575f80fd5b83359250602084013567ffffffffffffffff811115612d7b575f80fd5b612d8786828701612d0e565b9497909650939450505050565b5f805f805f60608688031215612da8575f80fd5b85359450602086013567ffffffffffffffff80821115612dc6575f80fd5b612dd289838a01612d0e565b90965094506040880135915080821115612dea575f80fd5b50612df788828901612d0e565b969995985093965092949392505050565b5f8060408385031215612e19575f80fd5b82359150612e2960208401612cd9565b90509250929050565b5f8060408385031215612e43575f80fd5b50508035926020909101359150565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f611af66040830184612e52565b5f805f60608486031215612eaa575f80fd5b505081359360208301359350604090920135919050565b5f60208284031215612ed1575f80fd5b5035919050565b6001600160a01b0381168114612cc2575f80fd5b5f8060408385031215612efd575f80fd5b823591506020830135612f0f81612ed8565b809150509250929050565b602081525f61132f6020830184612e52565b5f805f8060608587031215612f3f575f80fd5b8435935060208501359250604085013567ffffffffffffffff811115612f63575f80fd5b612f6f87828801612d0e565b95989497509550505050565b5f60208284031215612f8b575f80fd5b813561132f81612ed8565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612fd357612fd3612f96565b604052919050565b5f67ffffffffffffffff821115612ff457612ff4612f96565b50601f01601f191660200190565b5f805f60608486031215613014575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115613038575f80fd5b8401601f81018613613048575f80fd5b803561305b61305682612fdb565b612faa565b81815287602083850101111561306f575f80fd5b816020840160208301375f602083830101528093505050509250925092565b8015158114612cc2575f80fd5b5f80604083850312156130ac575f80fd5b82356130b781612ed8565b91506020830135612f0f8161308e565b5f805f606084860312156130d9575f80fd5b8335925060208401356130eb81612ed8565b915060408401356130fb8161308e565b809150509250925092565b5f805f60608486031215613118575f80fd5b8335925060208401359150604084013561ffff811681146130fb575f80fd5b5f805f60608486031215613149575f80fd5b833561315481612ed8565b92506020840135915060408401356130fb81612ed8565b5f8083601f84011261317b575f80fd5b50813567ffffffffffffffff811115613192575f80fd5b6020830191508360208260051b8501011115610d79575f80fd5b5f80602083850312156131bd575f80fd5b823567ffffffffffffffff8111156131d3575f80fd5b6131df8582860161316b565b90969095509350505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b8281101561324057603f1988860301845261322e858351612e52565b94509285019290850190600101613212565b5092979650505050505050565b5f805f6040848603121561325f575f80fd5b83359250602084013567ffffffffffffffff81111561327c575f80fd5b612d878682870161316b565b5f805f6060848603121561329a575f80fd5b833592506132aa60208501612cd9565b915060408401356130fb81612ed8565b5f80604083850312156132cb575f80fd5b82356132d681612ed8565b91506020830135612f0f81612ed8565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106fa576106fa6132fc565b818382375f9101908152919050565b600181811c9082168061334657607f821691505b60208210810361336457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115611ae457805f5260205f20601f840160051c8101602085101561338f5750805b601f840160051c820191505b81811015611700575f815560010161339b565b67ffffffffffffffff8311156133c6576133c6612f96565b6133da836133d48354613332565b8361336a565b5f601f84116001811461340b575f85156133f45750838201355b5f19600387901b1c1916600186901b178355611700565b5f83815260208120601f198716915b8281101561343a578685013582556020948501946001909201910161341a565b5086821015613456575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f6134a3604083018688613468565b8281036020840152612911818587613468565b634e487b7160e01b5f52603260045260245ffd5b602081525f611af6602083018486613468565b5f67ffffffffffffffff8083168181036134f9576134f96132fc565b6001019392505050565b805160208201516bffffffffffffffffffffffff1980821692919060148310156135375780818460140360031b1b83161693505b505050919050565b5f6020828403121561354f575f80fd5b815167ffffffffffffffff811115613565575f80fd5b8201601f81018413613575575f80fd5b805161358361305682612fdb565b818152856020838501011115613597575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b5f602082840312156135c4575f80fd5b815161132f8161308e565b815167ffffffffffffffff8111156135e9576135e9612f96565b6135fd816135f78454613332565b8461336a565b602080601f831160018114613630575f84156136195750858301515b5f19600386901b1c1916600185901b178555613687565b5f85815260208120601f198616915b8281101561365e5788860151825594840194600190910190840161363f565b508582101561367b57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b604081525f6136a16040830186612e52565b82810360208401526136b4818587613468565b9695505050505050565b5f61ffff8216806136d1576136d16132fc565b5f190192915050565b604081525f6136ec6040830185612e52565b905061ffff831660208301529392505050565b5f61ffff8083168181036134f9576134f96132fc565b606081525f6137276060830186612e52565b61ffff8516602084015282810360408401526136b48185612e52565b808201808211156106fa576106fa6132fc565b5f60208284031215613766575f80fd5b815161132f81612ed8565b5f808335601e19843603018112613786575f80fd5b83018035915067ffffffffffffffff8211156137a0575f80fd5b602001915036819003821315610d79575f80fd5b5f80858511156137c2575f80fd5b838611156137ce575f80fd5b5050820193919092039150565b803560208310156106fa575f19602084900360031b1b1692915050565b634e487b7160e01b5f52600160045260245ffdfea2646970667358221220d758b66459f0781ea3d56b8a5aeabf74291350f3156732d46f0c43dbbe86092d64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610283575f3560e01c80636f3ff72611610157578063c8690233116100d2578063e32954eb11610088578063e985e9c51161006e578063e985e9c51461068f578063ecbfada3146106ca578063f1cb7e06146106dd575f80fd5b8063e32954eb14610669578063e59d895d1461067c575f80fd5b8063ce3decdc116100b8578063ce3decdc14610601578063d5fa2b0014610614578063d700ff3314610627575f80fd5b8063c869023314610582578063c92cc49a146105da575f80fd5b8063a4b91a0111610127578063a9784b3e1161010d578063a9784b3e1461050c578063ac9650d81461054f578063bc1c58d11461056f575f80fd5b8063a4b91a01146104e6578063a8fa5682146104f9575f80fd5b80636f3ff7261461049a57806377372213146104ad5780638b95dd71146104c0578063a22cb465146104d3575f80fd5b80633603d758116102015780634eb9c45e116101b75780635c98042b1161019d5780635c98042b14610461578063623195b014610474578063691f343114610487575f80fd5b80634eb9c45e1461042e57806359d1d43c14610441575f80fd5b806341415eab116101e757806341415eab146103a957806348ee1bcc146103bc5780634cbf6ba4146103e3575f80fd5b80633603d758146103835780633b3b57de14610396575f80fd5b8063192cf07d1161025657806329cd62ea1161023c57806329cd62ea1461034a578063304e6ade1461035d57806332f111d714610370575f80fd5b8063192cf07d146103025780632203ab5614610329575f80fd5b806301ffc9a7146102875780630af179d7146102af57806310f13a8c146102c4578063124a319c146102d7575b5f80fd5b61029a610295366004612cf5565b6106f0565b60405190151581526020015b60405180910390f35b6102c26102bd366004612d4c565b610700565b005b6102c26102d2366004612d94565b610903565b6102ea6102e5366004612e08565b6109ce565b6040516001600160a01b0390911681526020016102a6565b6102ea7f000000000000000000000000000000000000000000000000000000000000000081565b61033c610337366004612e32565b610c44565b6040516102a6929190612e80565b6102c2610358366004612e98565b610d80565b6102c261036b366004612d4c565b610e19565b61029a61037e366004612e32565b610e93565b6102c2610391366004612ec1565b610ede565b6102ea6103a4366004612ec1565b610f7e565b61029a6103b7366004612eec565b610f9c565b6102ea7f000000000000000000000000000000000000000000000000000000000000000081565b61029a6103f1366004612e32565b5f828152602081815260408083205467ffffffffffffffff1683526007825280832094835293815283822092825291909152205461ffff16151590565b6102c261043c366004612d94565b611107565b61045461044f366004612d4c565b611258565b6040516102a69190612f1a565b61045461046f366004612ec1565b611336565b6102c2610482366004612f2c565b6113f2565b610454610495366004612ec1565b61148b565b61029a6104a8366004612f7b565b6114c4565b6102c26104bb366004612d4c565b611550565b6102c26104ce366004613002565b6115ca565b6102c26104e136600461309b565b611707565b6102c26104f43660046130c7565b6117f2565b610454610507366004613106565b6118c5565b61029a61051a366004613137565b6001600160a01b039283165f908152600d60209081526040808320948352938152838220929094168152925290205460ff1690565b61056261055d3660046131ac565b611912565b6040516102a691906131eb565b61045461057d366004612ec1565b61191f565b6105c5610590366004612ec1565b5f818152602081815260408083205467ffffffffffffffff168352600a82528083209383529290522080546001909101549091565b604080519283526020830191909152016102a6565b6102ea7f000000000000000000000000000000000000000000000000000000000000000081565b6102c261060f366004612d4c565b611958565b6102c2610622366004612eec565b611a96565b610650610635366004612ec1565b5f6020819052908152604090205467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102a6565b61056261067736600461324d565b611ae9565b6102c261068a366004613288565b611afe565b61029a61069d3660046132ba565b6001600160a01b039182165f908152600c6020908152604080832093909416825291909152205460ff1690565b6104546106d8366004612d4c565b611bbb565b6104546106eb366004612e32565b611bfa565b5f6106fa82611d81565b92915050565b8261070a81611da5565b610712575f80fd5b5f84815260208181526040808320548151601f870184900484028101840190925285825283926060928392859267ffffffffffffffff9091169183916107769183918d908d90819084018382808284375f920191909152509293925050611db09050565b90505b8051516020820151101561089d578661ffff165f036107dd57806040015196506107a281611e0b565b9450846040516020016107b591906132e6565b6040516020818303038152906040528051906020012092506107d681611e2c565b935061088f565b5f6107e782611e0b565b9050816040015161ffff168861ffff1614158061080b57506108098682611e48565b155b1561088d576108668c878a8e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505060208801518d915061085d908290613310565b8b51158a611e6c565b81604001519750816020015196508095508580519060200120935061088a82611e2c565b94505b505b610898816120d1565b610779565b508351156108f7576108f78a85888c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c92506108ee91508290508f613310565b89511588611e6c565b50505050505050505050565b8461090d81611da5565b610915575f80fd5b5f868152602081815260408083205467ffffffffffffffff168352600b8252808320898452909152908190209051849184916109549089908990613323565b9081526020016040518091039020918261096f9291906133ae565b508484604051610980929190613323565b6040518091039020867f448bc014f1536726cf8d54ff3d6481ed3cbc683c2591ca204274009afa09b1a1878787876040516109be9493929190613490565b60405180910390a3505050505050565b5f828152602081815260408083205467ffffffffffffffff1683526008825280832085845282528083206001600160e01b0319851684529091528120546001600160a01b03168015610a215790506106fa565b5f610a2b85610f7e565b90506001600160a01b038116610a45575f925050506106fa565b6040516301ffc9a760e01b60248201525f9081906001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610a9c91906132e6565b5f60405180830381855afa9150503d805f8114610ad4576040519150601f19603f3d011682016040523d82523d5f602084013e610ad9565b606091505b5091509150811580610aec575060208151105b80610b2e575080601f81518110610b0557610b056134b6565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610b3f575f9450505050506106fa565b6040516001600160e01b0319871660248201526001600160a01b0384169060440160408051601f198184030181529181526020820180516001600160e01b03166301ffc9a760e01b17905251610b9591906132e6565b5f60405180830381855afa9150503d805f8114610bcd576040519150601f19603f3d011682016040523d82523d5f602084013e610bd2565b606091505b509092509050811580610be6575060208151105b80610c28575080601f81518110610bff57610bff6134b6565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016155b15610c39575f9450505050506106fa565b509095945050505050565b5f828152602081815260408083205467ffffffffffffffff168352600180835281842086855290925282206060915b5f81118015610c825750848111155b15610d625780851615801590610caf57505f8181526020839052604081208054610cab90613332565b9050115b15610d5a5780825f8381526020019081526020015f20808054610cd190613332565b80601f0160208091040260200160405190810160405280929190818152602001828054610cfd90613332565b8015610d485780601f10610d1f57610100808354040283529160200191610d48565b820191905f5260205f20905b815481529060010190602001808311610d2b57829003601f168201915b50505050509050935093505050610d79565b60011b610c73565b505f60405180602001604052805f81525092509250505b9250929050565b82610d8a81611da5565b610d92575f80fd5b60408051808201825284815260208082018581525f8881528083528481205467ffffffffffffffff168152600a835284812089825283528490209251835551600190920191909155815185815290810184905285917f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e4691015b60405180910390a250505050565b82610e2381611da5565b610e2b575f80fd5b5f848152602081815260408083205467ffffffffffffffff168352600382528083208784529091529020610e608385836133ae565b50837fe379c1624ed7e714cc0937528a32359d69d5281337765313dba4e081b72d75788484604051610e0b9291906134ca565b5f828152602081815260408083205467ffffffffffffffff16835260028252808320858452825280832084845290915281208054829190610ed390613332565b905011905092915050565b80610ee881611da5565b610ef0575f80fd5b5f828152602081905260408120805467ffffffffffffffff1691610f13836134dd565b82546101009290920a67ffffffffffffffff8181021990931691831602179091555f84815260208181526040918290205491519190921681528492507fc6621ccb8f3f5a04bb6502154b2caf6adf5983fe76dfef1cfc9c42e3579db444910160405180910390a25050565b5f610f8a82603c611bfa565b610f9390613503565b60601c92915050565b6040517f20c38e2b000000000000000000000000000000000000000000000000000000008152600481018390525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906320c38e2b906024015f60405180830381865afa15801561101b573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611042919081019061353f565b905080515f03611055575f9150506106fa565b5f6110817f0000000000000000000000000000000000000000000000000000000000000000835f6121b6565b9050836001600160a01b0316816001600160a01b031614806110c757506001600160a01b038082165f908152600c602090815260408083209388168352929052205460ff165b806110fe57506001600160a01b038082165f908152600d6020908152604080832089845282528083209388168352929052205460ff165b95945050505050565b8461111181611da5565b611119575f80fd5b5f868152602081815260408083205467ffffffffffffffff16835260048252808320898452909152908190209051849184916111589089908990613323565b908152602001604051809103902091826111739291906133ae565b506111e68686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284375f92019190915250611ae492505050565b82826040516111f6929190613323565b6040518091039020858560405161120e929190613323565b6040518091039020877f3b7ea3580e046bf897ca24f2f45fcf5491dafba8d1b3dd17ca92aa0e82b4dd2188886040516112489291906134ca565b60405180910390a4505050505050565b5f838152602081815260408083205467ffffffffffffffff168352600b8252808320868452909152908190209051606091906112979085908590613323565b908152602001604051809103902080546112b090613332565b80601f01602080910402602001604051908101604052809291908181526020018280546112dc90613332565b80156113275780601f106112fe57610100808354040283529160200191611327565b820191905f5260205f20905b81548152906001019060200180831161130a57829003601f168201915b505050505090505b9392505050565b5f818152602081815260408083205467ffffffffffffffff16835260058252808320848452909152902080546060919061136f90613332565b80601f016020809104026020016040519081016040528092919081815260200182805461139b90613332565b80156113e65780601f106113bd576101008083540402835291602001916113e6565b820191905f5260205f20905b8154815290600101906020018083116113c957829003601f168201915b50505050509050919050565b836113fc81611da5565b611404575f80fd5b83611410600182613310565b161561141a575f80fd5b5f858152602081815260408083205467ffffffffffffffff16835260018252808320888452825280832087845290915290206114578385836133ae565b50604051849086907faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe3905f90a35050505050565b5f818152602081815260408083205467ffffffffffffffff16835260098252808320848452909152902080546060919061136f90613332565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa15801561152c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106fa91906135b4565b8261155a81611da5565b611562575f80fd5b5f848152602081815260408083205467ffffffffffffffff1683526009825280832087845290915290206115978385836133ae565b50837fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78484604051610e0b9291906134ca565b826115d481611da5565b6115dc575f80fd5b8151158015906115ee57508151601414155b80156115fe57506115fe83612274565b1561164057816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016116379190612f1a565b60405180910390fd5b837f65412581168e88a1e60c6459d7f44ae83ad0832e670826c05a4e2476b57af7528484604051611672929190612e80565b60405180910390a2603c83036116c457837f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd26116ad84613503565b60405160609190911c815260200160405180910390a25b5f848152602081815260408083205467ffffffffffffffff168352600282528083208784528252808320868452909152902061170083826135cf565b5050505050565b336001600160a01b03831681036117865760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360448201527f20666f722073656c6600000000000000000000000000000000000000000000006064820152608401611637565b6001600160a01b038181165f818152600c6020908152604080832094881680845294825291829020805460ff191687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b336001600160a01b038316810361184b5760405162461bcd60e51b815260206004820181905260248201527f53657474696e672064656c65676174652073746174757320666f722073656c666044820152606401611637565b6001600160a01b038181165f818152600d60209081526040808320898452825280832094881680845294825291829020805460ff1916871515908117909155915192835290929187917ff0ddb3b04746704017f9aa8bd728fcc2c1d11675041205350018915f5e4750a0910160405180910390a450505050565b5f838152602081815260408083205467ffffffffffffffff168352600682528083208684528252808320858452825280832061ffff8516845290915290208054606091906112b090613332565b606061132f5f8484612299565b5f818152602081815260408083205467ffffffffffffffff16835260038252808320848452909152902080546060919061136f90613332565b8261196281611da5565b61196a575f80fd5b5f848152602081815260408083205467ffffffffffffffff1680845260058352818420888552909252822080549192916119a390613332565b80601f01602080910402602001604051908101604052809291908181526020018280546119cf90613332565b8015611a1a5780601f106119f157610100808354040283529160200191611a1a565b820191905f5260205f20905b8154815290600101906020018083116119fd57829003601f168201915b5050505067ffffffffffffffff84165f9081526005602090815260408083208b84529091529020919250611a5190508587836133ae565b50857f8f15ed4b723ef428f250961da8315675b507046737e19319fc1a4d81bfe87f85828787604051611a869392919061368f565b60405180910390a2505050505050565b81611aa081611da5565b611aa8575f80fd5b6040516bffffffffffffffffffffffff19606084901b166020820152611ae4908490603c906034016040516020818303038152906040526115ca565b505050565b6060611af6848484612299565b949350505050565b82611b0881611da5565b611b10575f80fd5b5f848152602081815260408083205467ffffffffffffffff1683526008825280832087845282528083206001600160e01b031987168085529083529281902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038716908117909155905190815286917f7c69f06bea0bdef565b709e93a147836b0063ba2dd89f02d0b7e8d931e6a6daa910160405180910390a350505050565b5f838152602081815260408083205467ffffffffffffffff16835260048252808320868452909152908190209051606091906112979085908590613323565b5f828152602081815260408083205467ffffffffffffffff1683526002825280832085845282528083208484529182905290912080546060929190611c3e90613332565b80601f0160208091040260200160405190810160405280929190818152602001828054611c6a90613332565b8015611cb55780601f10611c8c57610100808354040283529160200191611cb5565b820191905f5260205f20905b815481529060010190602001808311611c9857829003601f168201915b5050505050915081515f148015611cd957505f611cd184612458565b63ffffffff16115b15611d7a5763800000005f9081526020829052604090208054611cfb90613332565b80601f0160208091040260200160405190810160405280929190818152602001828054611d2790613332565b8015611d725780601f10611d4957610100808354040283529160200191611d72565b820191905f5260205f20905b815481529060010190602001808311611d5557829003601f168201915b505050505091505b5092915050565b5f6001600160e01b0319821663379ffb9360e11b14806106fa57506106fa82612482565b5f6106fa8233610f9c565b611df86040518060e00160405280606081526020015f81526020015f61ffff1681526020015f61ffff1681526020015f63ffffffff1681526020015f81526020015f81525090565b82815260c081018290526106fa816120d1565b602081015181516060916106fa91611e2390826124bf565b84519190612516565b60a081015160c08201516060916106fa91611e23908290613310565b5f8151835114801561132f5750508051602091820120825192909101919091201490565b865160208801205f611e7f878787612516565b90508315611fa65767ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611ec990613332565b159050611f275767ffffffffffffffff83165f9081526007602090815260408083208d845282528083208584529091528120805461ffff1691611f0b836136be565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c1684529091528120611f6791612c8b565b897f03528ed0c2a3ebc993b12ce3c16bb382f9c7d88ef7d8a1bf290eaf35955a12078a8a604051611f999291906136da565b60405180910390a26108f7565b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c16845290915290208054611fe890613332565b90505f036120475767ffffffffffffffff83165f9081526007602090815260408083208d845282528083208584529091528120805461ffff169161202b836136ff565b91906101000a81548161ffff021916908361ffff160217905550505b67ffffffffffffffff83165f9081526006602090815260408083208d84528252808320858452825280832061ffff8c168452909152902061208882826135cf565b50897f52a608b3303a48862d07a73d82fa221318c0027fbbcfb1b2329bface3f19ff2b8a8a846040516120bd93929190613715565b60405180910390a250505050505050505050565b60c081015160208201819052815151116120e85750565b5f6120fa825f015183602001516124bf565b82602001516121099190613743565b8251909150612118908261256b565b61ffff16604083015261212c600282613743565b825190915061213b908261256b565b61ffff16606083015261214f600282613743565b825190915061215e908261258c565b63ffffffff166080830152612174600482613743565b82519091505f90612185908361256b565b61ffff169050612196600283613743565b60a0840181905291506121a98183613743565b60c0909301929092525050565b5f806121c38585856125a8565b90506001600160a01b038116158015906121e957506121e9816331ab054760e11b6125d4565b1561226c575f6121f985856125ef565b506040516331ab054760e11b81529091506001600160a01b038316906363560a8e90612229908490600401612f1a565b602060405180830381865afa158015612244573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122689190613756565b9250505b509392505050565b5f63800000008214806106fa57505f61228c83612458565b63ffffffff161192915050565b60608167ffffffffffffffff8111156122b4576122b4612f96565b6040519080825280602002602001820160405280156122e757816020015b60608152602001906001900390816122d25790505b5090505f5b8281101561226c5784156123b0575f84848381811061230d5761230d6134b6565b905060200281019061231f9190613771565b61232e916024916004916137b4565b612337916137db565b90508581146123ae5760405162461bcd60e51b815260206004820152603460248201527f6d756c746963616c6c3a20416c6c207265636f726473206d757374206861766560448201527f2061206d61746368696e67206e616d65686173680000000000000000000000006064820152608401611637565b505b5f80308686858181106123c5576123c56134b6565b90506020028101906123d79190613771565b6040516123e5929190613323565b5f60405180830381855af49150503d805f811461241d576040519150601f19603f3d011682016040523d82523d5f602084013e612422565b606091505b509150915081612430575f80fd5b80848481518110612443576124436134b6565b602090810291909101015250506001016122ec565b5f603c820361246957506001919050565b638000000091821891821061247e575f6106fa565b5090565b5f6001600160e01b031982167f59d1d43c0000000000000000000000000000000000000000000000000000000014806106fa57506106fa8261266c565b5f815b835181106124d2576124d26137f8565b5f6124dd85836126a9565b60ff1690506124ed816001613743565b6124f79083613743565b9150805f03612506575061250c565b506124c2565b611af68382613310565b60608167ffffffffffffffff81111561253157612531612f96565b6040519080825280601f01601f19166020018201604052801561255b576020820181803683370190505b50905061132f8484835f866126db565b5f6125808361257b846002613743565b61270c565b50016020015160f01c90565b5f61259c8361257b846004613743565b50016020015160e01c90565b5f805f6125b58585612758565b909250905081156125cb57612268868683612785565b50509392505050565b5f6125de83612864565b801561132f575061132f8383612896565b60605f806125fd858561291c565b925090505f60ff821667ffffffffffffffff81111561261e5761261e612f96565b6040519080825280601f01601f191660200182016040528015612648576020820181803683370190505b5090506126616020820160218888010160ff8516612999565b959194509092505050565b5f6001600160e01b031982167fc86902330000000000000000000000000000000000000000000000000000000014806106fa57506106fa826129e2565b5f6126b98361257b846001613743565b8282815181106126cb576126cb6134b6565b016020015160f81c905092915050565b6126e98561257b8387613743565b6126f78361257b8385613743565b61170082602085010185602088010183612999565b81518111156127545781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152611637918391600401918252602082015260400190565b5050565b5f805f612765858561291c565b9250905060ff81161561277d57806021858701012092505b509250929050565b5f805f6127928585612758565b9092509050816127a657859250505061132f565b5f6127b2878784612785565b90506001600160a01b0381161561285a575f6127ce87876125ef565b506040517f35af62160000000000000000000000000000000000000000000000000000000081529091506001600160a01b038316906335af621690612817908490600401612f1a565b602060405180830381865afa158015612832573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128569190613756565b9450505b5050509392505050565b5f612876826301ffc9a760e01b612896565b80156106fa575061288f826001600160e01b0319612896565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015612906575060208210155b801561291157505f81115b979650505050505050565b5f8083518310612941578360405163ba4adc2360e01b81526004016116379190612f1a565b838381518110612953576129536134b6565b016020015160f81c91505081810160010181612973578351811415612979565b83518110155b15610d79578360405163ba4adc2360e01b81526004016116379190612f1a565b5b601f8111156129ba578151835260209283019290910190601f190161299a565b8015611ae45790518251600160209390930360031b9290921b5f190180199091169116179052565b5f6001600160e01b031982167f691f34310000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167f124a319c0000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167fa8fa5682000000000000000000000000000000000000000000000000000000001480612ab457506001600160e01b031982167f5c98042b00000000000000000000000000000000000000000000000000000000145b806106fa57506106fa825f6001600160e01b031982167fecbfada30000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167fbc1c58d10000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f7f3b3b57de000000000000000000000000000000000000000000000000000000006001600160e01b031983161480612b9057507ff1cb7e06000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80612bc457507f32f111d7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b806106fa57506106fa825f6001600160e01b031982167f2203ab560000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167fd700ff330000000000000000000000000000000000000000000000000000000014806106fa57506106fa825f6001600160e01b031982167f4fbf04330000000000000000000000000000000000000000000000000000000014806106fa57506301ffc9a760e01b6001600160e01b03198316146106fa565b508054612c9790613332565b5f825580601f10612ca6575050565b601f0160209004905f5260205f2090810190612cc29190612cc5565b50565b5b8082111561247e575f8155600101612cc6565b80356001600160e01b031981168114612cf0575f80fd5b919050565b5f60208284031215612d05575f80fd5b61132f82612cd9565b5f8083601f840112612d1e575f80fd5b50813567ffffffffffffffff811115612d35575f80fd5b602083019150836020828501011115610d79575f80fd5b5f805f60408486031215612d5e575f80fd5b83359250602084013567ffffffffffffffff811115612d7b575f80fd5b612d8786828701612d0e565b9497909650939450505050565b5f805f805f60608688031215612da8575f80fd5b85359450602086013567ffffffffffffffff80821115612dc6575f80fd5b612dd289838a01612d0e565b90965094506040880135915080821115612dea575f80fd5b50612df788828901612d0e565b969995985093965092949392505050565b5f8060408385031215612e19575f80fd5b82359150612e2960208401612cd9565b90509250929050565b5f8060408385031215612e43575f80fd5b50508035926020909101359150565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b828152604060208201525f611af66040830184612e52565b5f805f60608486031215612eaa575f80fd5b505081359360208301359350604090920135919050565b5f60208284031215612ed1575f80fd5b5035919050565b6001600160a01b0381168114612cc2575f80fd5b5f8060408385031215612efd575f80fd5b823591506020830135612f0f81612ed8565b809150509250929050565b602081525f61132f6020830184612e52565b5f805f8060608587031215612f3f575f80fd5b8435935060208501359250604085013567ffffffffffffffff811115612f63575f80fd5b612f6f87828801612d0e565b95989497509550505050565b5f60208284031215612f8b575f80fd5b813561132f81612ed8565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612fd357612fd3612f96565b604052919050565b5f67ffffffffffffffff821115612ff457612ff4612f96565b50601f01601f191660200190565b5f805f60608486031215613014575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115613038575f80fd5b8401601f81018613613048575f80fd5b803561305b61305682612fdb565b612faa565b81815287602083850101111561306f575f80fd5b816020840160208301375f602083830101528093505050509250925092565b8015158114612cc2575f80fd5b5f80604083850312156130ac575f80fd5b82356130b781612ed8565b91506020830135612f0f8161308e565b5f805f606084860312156130d9575f80fd5b8335925060208401356130eb81612ed8565b915060408401356130fb8161308e565b809150509250925092565b5f805f60608486031215613118575f80fd5b8335925060208401359150604084013561ffff811681146130fb575f80fd5b5f805f60608486031215613149575f80fd5b833561315481612ed8565b92506020840135915060408401356130fb81612ed8565b5f8083601f84011261317b575f80fd5b50813567ffffffffffffffff811115613192575f80fd5b6020830191508360208260051b8501011115610d79575f80fd5b5f80602083850312156131bd575f80fd5b823567ffffffffffffffff8111156131d3575f80fd5b6131df8582860161316b565b90969095509350505050565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b8281101561324057603f1988860301845261322e858351612e52565b94509285019290850190600101613212565b5092979650505050505050565b5f805f6040848603121561325f575f80fd5b83359250602084013567ffffffffffffffff81111561327c575f80fd5b612d878682870161316b565b5f805f6060848603121561329a575f80fd5b833592506132aa60208501612cd9565b915060408401356130fb81612ed8565b5f80604083850312156132cb575f80fd5b82356132d681612ed8565b91506020830135612f0f81612ed8565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106fa576106fa6132fc565b818382375f9101908152919050565b600181811c9082168061334657607f821691505b60208210810361336457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115611ae457805f5260205f20601f840160051c8101602085101561338f5750805b601f840160051c820191505b81811015611700575f815560010161339b565b67ffffffffffffffff8311156133c6576133c6612f96565b6133da836133d48354613332565b8361336a565b5f601f84116001811461340b575f85156133f45750838201355b5f19600387901b1c1916600186901b178355611700565b5f83815260208120601f198716915b8281101561343a578685013582556020948501946001909201910161341a565b5086821015613456575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f6134a3604083018688613468565b8281036020840152612911818587613468565b634e487b7160e01b5f52603260045260245ffd5b602081525f611af6602083018486613468565b5f67ffffffffffffffff8083168181036134f9576134f96132fc565b6001019392505050565b805160208201516bffffffffffffffffffffffff1980821692919060148310156135375780818460140360031b1b83161693505b505050919050565b5f6020828403121561354f575f80fd5b815167ffffffffffffffff811115613565575f80fd5b8201601f81018413613575575f80fd5b805161358361305682612fdb565b818152856020838501011115613597575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b5f602082840312156135c4575f80fd5b815161132f8161308e565b815167ffffffffffffffff8111156135e9576135e9612f96565b6135fd816135f78454613332565b8461336a565b602080601f831160018114613630575f84156136195750858301515b5f19600386901b1c1916600185901b178555613687565b5f85815260208120601f198616915b8281101561365e5788860151825594840194600190910190840161363f565b508582101561367b57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b604081525f6136a16040830186612e52565b82810360208401526136b4818587613468565b9695505050505050565b5f61ffff8216806136d1576136d16132fc565b5f190192915050565b604081525f6136ec6040830185612e52565b905061ffff831660208301529392505050565b5f61ffff8083168181036134f9576134f96132fc565b606081525f6137276060830186612e52565b61ffff8516602084015282810360408401526136b48185612e52565b808201808211156106fa576106fa6132fc565b5f60208284031215613766575f80fd5b815161132f81612ed8565b5f808335601e19843603018112613786575f80fd5b83018035915067ffffffffffffffff8211156137a0575f80fd5b602001915036819003821315610d79575f80fd5b5f80858511156137c2575f80fd5b838611156137ce575f80fd5b5050820193919092039150565b803560208310156106fa575f19602084900360031b1b1692915050565b634e487b7160e01b5f52600160045260245ffdfea2646970667358221220d758b66459f0781ea3d56b8a5aeabf74291350f3156732d46f0c43dbbe86092d64736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "31623": [ + { + "length": 32, + "start": 775 + }, + { + "length": 32, + "start": 4055 + } + ], + "31627": [ + { + "length": 32, + "start": 1503 + }, + { + "length": 32, + "start": 4187 + } + ], + "33410": [ + { + "length": 32, + "start": 961 + }, + { + "length": 32, + "start": 5349 + } + ] + }, + "inputSourceName": "project/src/resolver/PublicResolverV2.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "InvalidEVMAddress(bytes)": [ + { + "details": "Error selector: `0x8d666f60`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "params": { + "approved": "If `true`, approved, otherwise revoked.", + "operator": "The approved account.", + "owner": "The node owner." + } + }, + "Approved(address,bytes32,address,bool)": { + "params": { + "approved": "If `true`, approved, otherwise revoked.", + "delegate": "The approved account.", + "node": "The namehash.", + "owner": "The node owner." + } + } + }, + "kind": "dev", + "methods": { + "ABI(bytes32,uint256)": { + "params": { + "contentTypes": "A bitwise OR of the ABI formats accepted by the caller.", + "node": "The ENS node to query" + }, + "returns": { + "_0": "contentType The content type of the return value", + "_1": "data The ABI data" + } + }, + "addr(bytes32)": { + "params": { + "node": "The node to query." + }, + "returns": { + "_0": "The associated address." + } + }, + "addr(bytes32,uint256)": { + "params": { + "coinType": "The coin type.", + "node": "The node to query." + }, + "returns": { + "addressBytes": "The assocated address." + } + }, + "approve(bytes32,address,bool)": { + "params": { + "approved": "If `true`, approved, otherwise revoked.", + "delegate": "The account to approve.", + "node": "The namehash to approve." + } + }, + "canModifyName(bytes32,address)": { + "params": { + "node": "The namehash to check.", + "operator": "The account requesting authorization." + }, + "returns": { + "_0": "`true` if `node` is authorized." + } + }, + "clearRecords(bytes32)": { + "params": { + "node": "The node to update." + } + }, + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "nameWrapper": "The ENSv1 `NameWrapper` contract.", + "rootRegistry": "The ENSv2 Root Registry contract." + } + }, + "contenthash(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated contenthash." + } + }, + "data(bytes32,string)": { + "params": { + "key": "The key.", + "node": "The node (namehash) for which data is being fetched." + }, + "returns": { + "_0": "The associated arbitrary `bytes` data." + } + }, + "dnsRecord(bytes32,bytes32,uint16)": { + "params": { + "name": "the keccak-256 hash of the fully-qualified name for which to fetch the record", + "node": "the namehash of the node for which to fetch the record", + "resource": "the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types" + }, + "returns": { + "_0": "the DNS record in wire format if present, otherwise empty" + } + }, + "hasAddr(bytes32,uint256)": { + "params": { + "coinType": "The coin type.", + "node": "The node to query." + }, + "returns": { + "_0": "True if the associated address is not empty." + } + }, + "hasDNSRecords(bytes32,bytes32)": { + "params": { + "name": "the namehash of the node for which to check the records", + "node": "the namehash of the node for which to check the records" + } + }, + "interfaceImplementer(bytes32,bytes4)": { + "params": { + "interfaceID": "The EIP 165 interface ID to check for.", + "node": "The ENS node to query." + }, + "returns": { + "_0": "The address that implements this interface, or 0 if the interface is unsupported." + } + }, + "isApprovedFor(address,bytes32,address)": { + "params": { + "delegate": "The delegated account.", + "node": "The namehash to check.", + "owner": "The owner account." + }, + "returns": { + "_0": "`true` if `operator` is approved." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "operator": "The operator account.", + "owner": "The owner account." + }, + "returns": { + "_0": "`true` if `operator` is approved." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "name(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated name." + } + }, + "pubkey(bytes32)": { + "params": { + "node": "The ENS node to query" + }, + "returns": { + "x": "The X coordinate of the curve point for the public key.", + "y": "The Y coordinate of the curve point for the public key." + } + }, + "setABI(bytes32,uint256,bytes)": { + "params": { + "contentType": "The content type of the ABI", + "data": "The ABI data.", + "node": "The node to update." + } + }, + "setAddr(bytes32,address)": { + "params": { + "_addr": "The address to set.", + "node": "The node to update." + } + }, + "setAddr(bytes32,uint256,bytes)": { + "params": { + "addressBytes": "The address to set.", + "coinType": "The coin type.", + "node": "The node to update." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "If `true`, approved, otherwise revoked.", + "operator": "The account to approve." + } + }, + "setContenthash(bytes32,bytes)": { + "params": { + "hash": "The contenthash to set", + "node": "The node to update." + } + }, + "setDNSRecords(bytes32,bytes)": { + "params": { + "data": "the DNS wire format records to set", + "node": "the namehash of the node for which to set the records" + } + }, + "setData(bytes32,string,bytes)": { + "params": { + "key": "The key to set.", + "node": "The node to update.", + "value": "The arbitrary `bytes` data to set." + } + }, + "setInterface(bytes32,bytes4,address)": { + "params": { + "implementer": "The address of a contract that implements this interface for this node.", + "interfaceID": "The EIP 165 interface ID.", + "node": "The node to update." + } + }, + "setName(bytes32,string)": { + "params": { + "node": "The node to update." + } + }, + "setPubkey(bytes32,bytes32,bytes32)": { + "params": { + "node": "The ENS node to query", + "x": "the X coordinate of the curve point for the public key.", + "y": "the Y coordinate of the curve point for the public key." + } + }, + "setText(bytes32,string,string)": { + "params": { + "key": "The key to set.", + "node": "The node to update.", + "value": "The text data value to set." + } + }, + "setZonehash(bytes32,bytes)": { + "params": { + "hash": "The zonehash to set", + "node": "The node to update." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "text(bytes32,string)": { + "params": { + "key": "The text data key to query.", + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated text data." + } + }, + "zonehash(bytes32)": { + "params": { + "node": "The ENS node to query." + }, + "returns": { + "_0": "The associated contenthash." + } + } + }, + "stateVariables": { + "_operatorApprovals": { + "details": "A mapping of operators. An address that is authorised for an address may make any changes to the name that the owner could, but may not update the set of authorisations." + }, + "_tokenApprovals": { + "details": "A mapping of delegates. A delegate that is authorised by an owner for a name may make changes to the name's resolver, but may not update the set of token approvals." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "2880400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "ABI(bytes32,uint256)": "infinite", + "CONTRACT_NAMER()": "infinite", + "NAME_WRAPPER()": "infinite", + "ROOT_REGISTRY()": "infinite", + "addr(bytes32)": "infinite", + "addr(bytes32,uint256)": "infinite", + "approve(bytes32,address,bool)": "infinite", + "canModifyName(bytes32,address)": "infinite", + "clearRecords(bytes32)": "infinite", + "contenthash(bytes32)": "infinite", + "data(bytes32,string)": "infinite", + "dnsRecord(bytes32,bytes32,uint16)": "infinite", + "hasAddr(bytes32,uint256)": "5028", + "hasDNSRecords(bytes32,bytes32)": "4881", + "interfaceImplementer(bytes32,bytes4)": "infinite", + "isApprovedFor(address,bytes32,address)": "infinite", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "infinite", + "multicall(bytes[])": "infinite", + "multicallWithNodeCheck(bytes32,bytes[])": "infinite", + "name(bytes32)": "infinite", + "pubkey(bytes32)": "6880", + "recordVersions(bytes32)": "2564", + "setABI(bytes32,uint256,bytes)": "infinite", + "setAddr(bytes32,address)": "infinite", + "setAddr(bytes32,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "infinite", + "setContenthash(bytes32,bytes)": "infinite", + "setDNSRecords(bytes32,bytes)": "infinite", + "setData(bytes32,string,bytes)": "infinite", + "setInterface(bytes32,bytes4,address)": "infinite", + "setName(bytes32,string)": "infinite", + "setPubkey(bytes32,bytes32,bytes32)": "infinite", + "setText(bytes32,string,string)": "infinite", + "setZonehash(bytes32,bytes)": "infinite", + "supportsInterface(bytes4)": "infinite", + "text(bytes32,string)": "infinite", + "zonehash(bytes32)": "infinite" + }, + "internal": { + "isAuthorised(bytes32)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"rootRegistry\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"}],\"name\":\"ABIChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"a\",\"type\":\"address\"}],\"name\":\"AddrChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newAddress\",\"type\":\"bytes\"}],\"name\":\"AddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"Approved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"ContenthashChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"resource\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"record\",\"type\":\"bytes\"}],\"name\":\"DNSRecordChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"resource\",\"type\":\"uint16\"}],\"name\":\"DNSRecordDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"lastzonehash\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"zonehash\",\"type\":\"bytes\"}],\"name\":\"DNSZonehashChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"indexedData\",\"type\":\"bytes\"}],\"name\":\"DataChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"name\":\"InterfaceChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NameChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"PubkeyChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"indexedKey\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"TextChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"newVersion\",\"type\":\"uint64\"}],\"name\":\"VersionChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"contentTypes\",\"type\":\"uint256\"}],\"name\":\"ABI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"address payable\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"addr\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"canModifyName\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"clearRecords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"contenthash\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"data\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"name\",\"type\":\"bytes32\"},{\"internalType\":\"uint16\",\"name\":\"resource\",\"type\":\"uint16\"}],\"name\":\"dnsRecord\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"hasAddr\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"name\",\"type\":\"bytes32\"}],\"name\":\"hasDNSRecords\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"interfaceImplementer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"}],\"name\":\"isApprovedFor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodehash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicallWithNodeCheck\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"pubkey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"recordVersions\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"contentType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"setABI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"addressBytes\",\"type\":\"bytes\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"setAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"setContenthash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"setDNSRecords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"value\",\"type\":\"bytes\"}],\"name\":\"setData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes4\",\"name\":\"interfaceID\",\"type\":\"bytes4\"},{\"internalType\":\"address\",\"name\":\"implementer\",\"type\":\"address\"}],\"name\":\"setInterface\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"newName\",\"type\":\"string\"}],\"name\":\"setName\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"y\",\"type\":\"bytes32\"}],\"name\":\"setPubkey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"}],\"name\":\"setText\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"hash\",\"type\":\"bytes\"}],\"name\":\"setZonehash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"text\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"zonehash\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"InvalidEVMAddress(bytes)\":[{\"details\":\"Error selector: `0x8d666f60`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"params\":{\"approved\":\"If `true`, approved, otherwise revoked.\",\"operator\":\"The approved account.\",\"owner\":\"The node owner.\"}},\"Approved(address,bytes32,address,bool)\":{\"params\":{\"approved\":\"If `true`, approved, otherwise revoked.\",\"delegate\":\"The approved account.\",\"node\":\"The namehash.\",\"owner\":\"The node owner.\"}}},\"kind\":\"dev\",\"methods\":{\"ABI(bytes32,uint256)\":{\"params\":{\"contentTypes\":\"A bitwise OR of the ABI formats accepted by the caller.\",\"node\":\"The ENS node to query\"},\"returns\":{\"_0\":\"contentType The content type of the return value\",\"_1\":\"data The ABI data\"}},\"addr(bytes32)\":{\"params\":{\"node\":\"The node to query.\"},\"returns\":{\"_0\":\"The associated address.\"}},\"addr(bytes32,uint256)\":{\"params\":{\"coinType\":\"The coin type.\",\"node\":\"The node to query.\"},\"returns\":{\"addressBytes\":\"The assocated address.\"}},\"approve(bytes32,address,bool)\":{\"params\":{\"approved\":\"If `true`, approved, otherwise revoked.\",\"delegate\":\"The account to approve.\",\"node\":\"The namehash to approve.\"}},\"canModifyName(bytes32,address)\":{\"params\":{\"node\":\"The namehash to check.\",\"operator\":\"The account requesting authorization.\"},\"returns\":{\"_0\":\"`true` if `node` is authorized.\"}},\"clearRecords(bytes32)\":{\"params\":{\"node\":\"The node to update.\"}},\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"nameWrapper\":\"The ENSv1 `NameWrapper` contract.\",\"rootRegistry\":\"The ENSv2 Root Registry contract.\"}},\"contenthash(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated contenthash.\"}},\"data(bytes32,string)\":{\"params\":{\"key\":\"The key.\",\"node\":\"The node (namehash) for which data is being fetched.\"},\"returns\":{\"_0\":\"The associated arbitrary `bytes` data.\"}},\"dnsRecord(bytes32,bytes32,uint16)\":{\"params\":{\"name\":\"the keccak-256 hash of the fully-qualified name for which to fetch the record\",\"node\":\"the namehash of the node for which to fetch the record\",\"resource\":\"the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\"},\"returns\":{\"_0\":\"the DNS record in wire format if present, otherwise empty\"}},\"hasAddr(bytes32,uint256)\":{\"params\":{\"coinType\":\"The coin type.\",\"node\":\"The node to query.\"},\"returns\":{\"_0\":\"True if the associated address is not empty.\"}},\"hasDNSRecords(bytes32,bytes32)\":{\"params\":{\"name\":\"the namehash of the node for which to check the records\",\"node\":\"the namehash of the node for which to check the records\"}},\"interfaceImplementer(bytes32,bytes4)\":{\"params\":{\"interfaceID\":\"The EIP 165 interface ID to check for.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The address that implements this interface, or 0 if the interface is unsupported.\"}},\"isApprovedFor(address,bytes32,address)\":{\"params\":{\"delegate\":\"The delegated account.\",\"node\":\"The namehash to check.\",\"owner\":\"The owner account.\"},\"returns\":{\"_0\":\"`true` if `operator` is approved.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"operator\":\"The operator account.\",\"owner\":\"The owner account.\"},\"returns\":{\"_0\":\"`true` if `operator` is approved.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"name(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated name.\"}},\"pubkey(bytes32)\":{\"params\":{\"node\":\"The ENS node to query\"},\"returns\":{\"x\":\"The X coordinate of the curve point for the public key.\",\"y\":\"The Y coordinate of the curve point for the public key.\"}},\"setABI(bytes32,uint256,bytes)\":{\"params\":{\"contentType\":\"The content type of the ABI\",\"data\":\"The ABI data.\",\"node\":\"The node to update.\"}},\"setAddr(bytes32,address)\":{\"params\":{\"_addr\":\"The address to set.\",\"node\":\"The node to update.\"}},\"setAddr(bytes32,uint256,bytes)\":{\"params\":{\"addressBytes\":\"The address to set.\",\"coinType\":\"The coin type.\",\"node\":\"The node to update.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"If `true`, approved, otherwise revoked.\",\"operator\":\"The account to approve.\"}},\"setContenthash(bytes32,bytes)\":{\"params\":{\"hash\":\"The contenthash to set\",\"node\":\"The node to update.\"}},\"setDNSRecords(bytes32,bytes)\":{\"params\":{\"data\":\"the DNS wire format records to set\",\"node\":\"the namehash of the node for which to set the records\"}},\"setData(bytes32,string,bytes)\":{\"params\":{\"key\":\"The key to set.\",\"node\":\"The node to update.\",\"value\":\"The arbitrary `bytes` data to set.\"}},\"setInterface(bytes32,bytes4,address)\":{\"params\":{\"implementer\":\"The address of a contract that implements this interface for this node.\",\"interfaceID\":\"The EIP 165 interface ID.\",\"node\":\"The node to update.\"}},\"setName(bytes32,string)\":{\"params\":{\"node\":\"The node to update.\"}},\"setPubkey(bytes32,bytes32,bytes32)\":{\"params\":{\"node\":\"The ENS node to query\",\"x\":\"the X coordinate of the curve point for the public key.\",\"y\":\"the Y coordinate of the curve point for the public key.\"}},\"setText(bytes32,string,string)\":{\"params\":{\"key\":\"The key to set.\",\"node\":\"The node to update.\",\"value\":\"The text data value to set.\"}},\"setZonehash(bytes32,bytes)\":{\"params\":{\"hash\":\"The zonehash to set\",\"node\":\"The node to update.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"text(bytes32,string)\":{\"params\":{\"key\":\"The text data key to query.\",\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated text data.\"}},\"zonehash(bytes32)\":{\"params\":{\"node\":\"The ENS node to query.\"},\"returns\":{\"_0\":\"The associated contenthash.\"}}},\"stateVariables\":{\"_operatorApprovals\":{\"details\":\"A mapping of operators. An address that is authorised for an address may make any changes to the name that the owner could, but may not update the set of authorisations.\"},\"_tokenApprovals\":{\"details\":\"A mapping of delegates. A delegate that is authorised by an owner for a name may make changes to the name's resolver, but may not update the set of token approvals.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidEVMAddress(bytes)\":[{\"notice\":\"The supplied address could not be converted to `address`.\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"notice\":\"An operator is added or removed.\"},\"Approved(address,bytes32,address,bool)\":{\"notice\":\"A delegate is approved or an approval is revoked.\"},\"DataChanged(bytes32,string,string,bytes)\":{\"notice\":\"For a specific `node`, the data associated with a `key` has changed.\"}},\"kind\":\"user\",\"methods\":{\"ABI(bytes32,uint256)\":{\"notice\":\"Returns the ABI associated with an ENS node. Defined in EIP205.\"},\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract.\"},\"ROOT_REGISTRY()\":{\"notice\":\"The ENSv2 Root Registry contract.\"},\"addr(bytes32)\":{\"notice\":\"Get `addr(60)` as `address` of the associated ENS node.\"},\"addr(bytes32,uint256)\":{\"notice\":\"Get the address for coin type of the associated ENS node. If coin type is EVM and empty, defaults to `addr(COIN_TYPE_DEFAULT)`.\"},\"approve(bytes32,address,bool)\":{\"notice\":\"Grant or revoke `delegate` approval on a specific node.\"},\"canModifyName(bytes32,address)\":{\"notice\":\"Determine if `operator` is authorized for `node`.\"},\"clearRecords(bytes32)\":{\"notice\":\"Increments the record version associated with an ENS node. May only be called by the owner of that node in the ENS registry.\"},\"contenthash(bytes32)\":{\"notice\":\"Returns the contenthash associated with an ENS node.\"},\"data(bytes32,string)\":{\"notice\":\"For a specific `node`, get the data associated with the key, `key`.\"},\"dnsRecord(bytes32,bytes32,uint16)\":{\"notice\":\"Obtain a DNS record.\"},\"hasAddr(bytes32,uint256)\":{\"notice\":\"Determine if an addresss is stored for the coin type of the associated ENS node.\"},\"hasDNSRecords(bytes32,bytes32)\":{\"notice\":\"Check if a given node has records.\"},\"interfaceImplementer(bytes32,bytes4)\":{\"notice\":\"Returns the address of a contract that implements the specified interface for this name. If an implementer has not been set for this interfaceID and name, the resolver will query the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that contract implements EIP165 and returns `true` for the specified interfaceID, its address will be returned.\"},\"isApprovedFor(address,bytes32,address)\":{\"notice\":\"Check to see if the delegate has been approved by the owner for the node.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Check if `operator` is approved for all nodes owned by `account`.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"name(bytes32)\":{\"notice\":\"Returns the name associated with an ENS node, for reverse records. Defined in EIP181.\"},\"pubkey(bytes32)\":{\"notice\":\"Returns the SECP256k1 public key associated with an ENS node. Defined in EIP 619.\"},\"setABI(bytes32,uint256,bytes)\":{\"notice\":\"Sets the ABI associated with an ENS node. Nodes may have one ABI of each content type. To remove an ABI, set it to the empty string.\"},\"setAddr(bytes32,address)\":{\"notice\":\"Set `addr(60)` of the associated ENS node. `address(0)` is stored as `new bytes(20)`.\"},\"setAddr(bytes32,uint256,bytes)\":{\"notice\":\"Set the address for coin type of the associated ENS node. Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Grant or revoke `operator` approval.\"},\"setContenthash(bytes32,bytes)\":{\"notice\":\"Sets the contenthash associated with an ENS node. May only be called by the owner of that node in the ENS registry.\"},\"setDNSRecords(bytes32,bytes)\":{\"notice\":\"Set one or more DNS records. Records are supplied in wire-format. Records with the same node/name/resource must be supplied one after the other to ensure the data is updated correctly. For example, if the data was supplied: a.example.com IN A 1.2.3.4 a.example.com IN A 5.6.7.8 www.example.com IN CNAME a.example.com. then this would store the two A records for a.example.com correctly as a single RRSET, however if the data was supplied: a.example.com IN A 1.2.3.4 www.example.com IN CNAME a.example.com. a.example.com IN A 5.6.7.8 then this would store the first A record, the CNAME, then the second A record which would overwrite the first.\"},\"setData(bytes32,string,bytes)\":{\"notice\":\"Sets the data associated with the key, `key` for a specific `node`. May only be called by the owner of that node in the ENS registry.\"},\"setInterface(bytes32,bytes4,address)\":{\"notice\":\"Sets an interface associated with a name. Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support.\"},\"setName(bytes32,string)\":{\"notice\":\"Sets the name associated with an ENS node, for reverse records. May only be called by the owner of that node in the ENS registry.\"},\"setPubkey(bytes32,bytes32,bytes32)\":{\"notice\":\"Sets the SECP256k1 public key associated with an ENS node.\"},\"setText(bytes32,string,string)\":{\"notice\":\"Sets the text data associated with an ENS node and key. May only be called by the owner of that node in the ENS registry.\"},\"setZonehash(bytes32,bytes)\":{\"notice\":\"setZonehash sets the hash for the zone. May only be called by the owner of that node in the ENS registry.\"},\"text(bytes32,string)\":{\"notice\":\"Returns the text data associated with an ENS node and key.\"},\"zonehash(bytes32)\":{\"notice\":\"zonehash obtains the hash for the zone.\"}},\"notice\":\"PublicResolver that respects the ENSv2 registry.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/resolver/PublicResolverV2.sol\":\"PublicResolverV2\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/buffer/contracts/Buffer.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-2-Clause\\npragma solidity ^0.8.4;\\n\\n/**\\n* @dev A library for working with mutable byte buffers in Solidity.\\n*\\n* Byte buffers are mutable and expandable, and provide a variety of primitives\\n* for appending to them. At any time you can fetch a bytes object containing the\\n* current contents of the buffer. The bytes object should not be stored between\\n* operations, as it may change due to resizing of the buffer.\\n*/\\nlibrary Buffer {\\n /**\\n * @dev Represents a mutable buffer. Buffers have a current value (buf) and\\n * a capacity. The capacity may be longer than the current value, in\\n * which case it can be extended without the need to allocate more memory.\\n */\\n struct buffer {\\n bytes buf;\\n uint capacity;\\n }\\n\\n /**\\n * @dev Initializes a buffer with an initial capacity.\\n * @param buf The buffer to initialize.\\n * @param capacity The number of bytes of space to allocate the buffer.\\n * @return The buffer, for chaining.\\n */\\n function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\\n if (capacity % 32 != 0) {\\n capacity += 32 - (capacity % 32);\\n }\\n // Allocate space for the buffer data\\n buf.capacity = capacity;\\n assembly {\\n let ptr := mload(0x40)\\n mstore(buf, ptr)\\n mstore(ptr, 0)\\n let fpm := add(32, add(ptr, capacity))\\n if lt(fpm, ptr) {\\n revert(0, 0)\\n }\\n mstore(0x40, fpm)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Initializes a new buffer from an existing bytes object.\\n * Changes to the buffer may mutate the original value.\\n * @param b The bytes object to initialize the buffer with.\\n * @return A new buffer.\\n */\\n function fromBytes(bytes memory b) internal pure returns(buffer memory) {\\n buffer memory buf;\\n buf.buf = b;\\n buf.capacity = b.length;\\n return buf;\\n }\\n\\n function resize(buffer memory buf, uint capacity) private pure {\\n bytes memory oldbuf = buf.buf;\\n init(buf, capacity);\\n append(buf, oldbuf);\\n }\\n\\n /**\\n * @dev Sets buffer length to 0.\\n * @param buf The buffer to truncate.\\n * @return The original buffer, for chaining..\\n */\\n function truncate(buffer memory buf) internal pure returns (buffer memory) {\\n assembly {\\n let bufptr := mload(buf)\\n mstore(bufptr, 0)\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to copy.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) {\\n require(len <= data.length);\\n\\n uint off = buf.buf.length;\\n uint newCapacity = off + len;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n uint dest;\\n uint src;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Length of existing buffer data\\n let buflen := mload(bufptr)\\n // Start address = buffer address + offset + sizeof(buffer length)\\n dest := add(add(bufptr, 32), off)\\n // Update buffer length if we're extending it\\n if gt(newCapacity, buflen) {\\n mstore(bufptr, newCapacity)\\n }\\n src := add(data, 32)\\n }\\n\\n // Copy word-length chunks while possible\\n for (; len >= 32; len -= 32) {\\n assembly {\\n mstore(dest, mload(src))\\n }\\n dest += 32;\\n src += 32;\\n }\\n\\n // Copy remaining bytes\\n unchecked {\\n uint mask = (256 ** (32 - len)) - 1;\\n assembly {\\n let srcpart := and(mload(src), not(mask))\\n let destpart := and(mload(dest), mask)\\n mstore(dest, or(destpart, srcpart))\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\\n return append(buf, data, data.length);\\n }\\n\\n /**\\n * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\\n * capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint offPlusOne = off + 1;\\n if (off >= buf.capacity) {\\n resize(buf, offPlusOne * 2);\\n }\\n\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + off\\n let dest := add(add(bufptr, off), 32)\\n mstore8(dest, data)\\n // Update buffer length if we extended it\\n if gt(offPlusOne, mload(bufptr)) {\\n mstore(bufptr, offPlusOne)\\n }\\n }\\n\\n return buf;\\n }\\n\\n /**\\n * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (left-aligned).\\n * @return The original buffer, for chaining.\\n */\\n function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n unchecked {\\n uint mask = (256 ** len) - 1;\\n // Right-align data\\n data = data >> (8 * (32 - len));\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n }\\n return buf;\\n }\\n\\n /**\\n * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chhaining.\\n */\\n function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\\n return append(buf, bytes32(data), 20);\\n }\\n\\n /**\\n * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\\n * the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @return The original buffer, for chaining.\\n */\\n function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\\n return append(buf, data, 32);\\n }\\n\\n /**\\n * @dev Appends a byte to the end of the buffer. Resizes if doing so would\\n * exceed the capacity of the buffer.\\n * @param buf The buffer to append to.\\n * @param data The data to append.\\n * @param len The number of bytes to write (right-aligned).\\n * @return The original buffer.\\n */\\n function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\\n uint off = buf.buf.length;\\n uint newCapacity = len + off;\\n if (newCapacity > buf.capacity) {\\n resize(buf, newCapacity * 2);\\n }\\n\\n unchecked {\\n uint mask = (256 ** len) - 1;\\n assembly {\\n // Memory address of the buffer data\\n let bufptr := mload(buf)\\n // Address = buffer address + sizeof(buffer length) + newCapacity\\n let dest := add(bufptr, newCapacity)\\n mstore(dest, or(and(mload(dest), not(mask)), data))\\n // Update buffer length if we extended it\\n if gt(newCapacity, mload(bufptr)) {\\n mstore(bufptr, newCapacity)\\n }\\n }\\n }\\n return buf;\\n }\\n}\\n\",\"keccak256\":\"0xd85358722045348893aeedd23539816c9d1b218ab801a3fcd1ec4e38ecc8eb22\",\"license\":\"BSD-2-Clause\"},\"project/lib/ens-contracts/contracts/dnssec-oracle/RRUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../utils/BytesUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/// @dev RRUtils is a library that provides utilities for parsing DNS resource records.\\nlibrary RRUtils {\\n using BytesUtils for *;\\n using Buffer for *;\\n\\n /// @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.\\n /// @param self The byte array to read a name from.\\n /// @param offset The offset to start reading at.\\n /// @return The length of the DNS name at 'offset', in bytes.\\n function nameLength(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 idx = offset;\\n while (true) {\\n assert(idx < self.length);\\n uint256 labelLen = self.readUint8(idx);\\n idx += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n }\\n return idx - offset;\\n }\\n\\n /// @dev Returns a DNS format name at the specified offset of self.\\n /// @param self The byte array to read a name from.\\n /// @param offset The offset to start reading at.\\n /// @return ret The name.\\n function readName(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (bytes memory ret) {\\n uint256 len = nameLength(self, offset);\\n return self.substring(offset, len);\\n }\\n\\n /// @dev Returns the number of labels in the DNS name at 'offset' in 'self'.\\n /// @param self The byte array to read a name from.\\n /// @param offset The offset to start reading at.\\n /// @return The number of labels in the DNS name at 'offset', in bytes.\\n function labelCount(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (uint256) {\\n uint256 count = 0;\\n while (true) {\\n assert(offset < self.length);\\n uint256 labelLen = self.readUint8(offset);\\n offset += labelLen + 1;\\n if (labelLen == 0) {\\n break;\\n }\\n count += 1;\\n }\\n return count;\\n }\\n\\n uint256 constant RRSIG_TYPE = 0;\\n uint256 constant RRSIG_ALGORITHM = 2;\\n uint256 constant RRSIG_LABELS = 3;\\n uint256 constant RRSIG_TTL = 4;\\n uint256 constant RRSIG_EXPIRATION = 8;\\n uint256 constant RRSIG_INCEPTION = 12;\\n uint256 constant RRSIG_KEY_TAG = 16;\\n uint256 constant RRSIG_SIGNER_NAME = 18;\\n\\n struct SignedSet {\\n uint16 typeCovered;\\n uint8 algorithm;\\n uint8 labels;\\n uint32 ttl;\\n uint32 expiration;\\n uint32 inception;\\n uint16 keytag;\\n bytes signerName;\\n bytes data;\\n bytes name;\\n }\\n\\n function readSignedSet(\\n bytes memory data\\n ) internal pure returns (SignedSet memory self) {\\n self.typeCovered = data.readUint16(RRSIG_TYPE);\\n self.algorithm = data.readUint8(RRSIG_ALGORITHM);\\n self.labels = data.readUint8(RRSIG_LABELS);\\n self.ttl = data.readUint32(RRSIG_TTL);\\n self.expiration = data.readUint32(RRSIG_EXPIRATION);\\n self.inception = data.readUint32(RRSIG_INCEPTION);\\n self.keytag = data.readUint16(RRSIG_KEY_TAG);\\n self.signerName = readName(data, RRSIG_SIGNER_NAME);\\n self.data = data.substring(\\n RRSIG_SIGNER_NAME + self.signerName.length,\\n data.length - RRSIG_SIGNER_NAME - self.signerName.length\\n );\\n }\\n\\n function rrs(\\n SignedSet memory rrset\\n ) internal pure returns (RRIterator memory) {\\n return iterateRRs(rrset.data, 0);\\n }\\n\\n /// @dev An iterator over resource records.\\n struct RRIterator {\\n bytes data;\\n uint256 offset;\\n uint16 dnstype;\\n uint16 class;\\n uint32 ttl;\\n uint256 rdataOffset;\\n uint256 nextOffset;\\n }\\n\\n /// @dev Begins iterating over resource records.\\n /// @param self The byte string to read from.\\n /// @param offset The offset to start reading at.\\n /// @return ret An iterator object.\\n function iterateRRs(\\n bytes memory self,\\n uint256 offset\\n ) internal pure returns (RRIterator memory ret) {\\n ret.data = self;\\n ret.nextOffset = offset;\\n next(ret);\\n }\\n\\n /// @dev Returns true iff there are more RRs to iterate.\\n /// @param iter The iterator to check.\\n /// @return True iff the iterator has finished.\\n function done(RRIterator memory iter) internal pure returns (bool) {\\n return iter.offset >= iter.data.length;\\n }\\n\\n /// @dev Moves the iterator to the next resource record.\\n /// @param iter The iterator to advance.\\n function next(RRIterator memory iter) internal pure {\\n iter.offset = iter.nextOffset;\\n if (iter.offset >= iter.data.length) {\\n return;\\n }\\n\\n // Skip the name\\n uint256 off = iter.offset + nameLength(iter.data, iter.offset);\\n\\n // Read type, class, and ttl\\n iter.dnstype = iter.data.readUint16(off);\\n off += 2;\\n iter.class = iter.data.readUint16(off);\\n off += 2;\\n iter.ttl = iter.data.readUint32(off);\\n off += 4;\\n\\n // Read the rdata\\n uint256 rdataLength = iter.data.readUint16(off);\\n off += 2;\\n iter.rdataOffset = off;\\n iter.nextOffset = off + rdataLength;\\n }\\n\\n /// @dev Returns the name of the current record.\\n /// @param iter The iterator.\\n /// @return A new bytes object containing the owner name from the RR.\\n function name(RRIterator memory iter) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.offset,\\n nameLength(iter.data, iter.offset)\\n );\\n }\\n\\n /// @dev Returns the rdata portion of the current record.\\n /// @param iter The iterator.\\n /// @return A new bytes object containing the RR's RDATA.\\n function rdata(\\n RRIterator memory iter\\n ) internal pure returns (bytes memory) {\\n return\\n iter.data.substring(\\n iter.rdataOffset,\\n iter.nextOffset - iter.rdataOffset\\n );\\n }\\n\\n uint256 constant DNSKEY_FLAGS = 0;\\n uint256 constant DNSKEY_PROTOCOL = 2;\\n uint256 constant DNSKEY_ALGORITHM = 3;\\n uint256 constant DNSKEY_PUBKEY = 4;\\n\\n struct DNSKEY {\\n uint16 flags;\\n uint8 protocol;\\n uint8 algorithm;\\n bytes publicKey;\\n }\\n\\n function readDNSKEY(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DNSKEY memory self) {\\n self.flags = data.readUint16(offset + DNSKEY_FLAGS);\\n self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);\\n self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);\\n self.publicKey = data.substring(\\n offset + DNSKEY_PUBKEY,\\n length - DNSKEY_PUBKEY\\n );\\n }\\n\\n uint256 constant DS_KEY_TAG = 0;\\n uint256 constant DS_ALGORITHM = 2;\\n uint256 constant DS_DIGEST_TYPE = 3;\\n uint256 constant DS_DIGEST = 4;\\n\\n struct DS {\\n uint16 keytag;\\n uint8 algorithm;\\n uint8 digestType;\\n bytes digest;\\n }\\n\\n function readDS(\\n bytes memory data,\\n uint256 offset,\\n uint256 length\\n ) internal pure returns (DS memory self) {\\n self.keytag = data.readUint16(offset + DS_KEY_TAG);\\n self.algorithm = data.readUint8(offset + DS_ALGORITHM);\\n self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);\\n self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);\\n }\\n\\n function isSubdomainOf(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (bool) {\\n uint256 off = 0;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n while (counts > othercounts) {\\n off = progress(self, off);\\n counts--;\\n }\\n\\n return self.equals(off, other, 0);\\n }\\n\\n function compareNames(\\n bytes memory self,\\n bytes memory other\\n ) internal pure returns (int256) {\\n if (self.equals(other)) {\\n return 0;\\n }\\n\\n uint256 off;\\n uint256 otheroff;\\n uint256 prevoff;\\n uint256 otherprevoff;\\n uint256 counts = labelCount(self, 0);\\n uint256 othercounts = labelCount(other, 0);\\n\\n // Keep removing labels from the front of the name until both names are equal length\\n while (counts > othercounts) {\\n prevoff = off;\\n off = progress(self, off);\\n counts--;\\n }\\n\\n while (othercounts > counts) {\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n othercounts--;\\n }\\n\\n // Compare the last nonequal labels to each other\\n while (counts > 0 && !self.equals(off, other, otheroff)) {\\n prevoff = off;\\n off = progress(self, off);\\n otherprevoff = otheroff;\\n otheroff = progress(other, otheroff);\\n counts -= 1;\\n }\\n\\n if (off == 0) {\\n return -1;\\n }\\n if (otheroff == 0) {\\n return 1;\\n }\\n\\n return\\n self.compare(\\n prevoff + 1,\\n self.readUint8(prevoff),\\n other,\\n otherprevoff + 1,\\n other.readUint8(otherprevoff)\\n );\\n }\\n\\n /// @dev Compares two serial numbers using RFC1982 serial number math.\\n function serialNumberGte(\\n uint32 i1,\\n uint32 i2\\n ) internal pure returns (bool) {\\n unchecked {\\n return int32(i1) - int32(i2) >= 0;\\n }\\n }\\n\\n function progress(\\n bytes memory body,\\n uint256 off\\n ) internal pure returns (uint256) {\\n return off + 1 + body.readUint8(off);\\n }\\n\\n /// @dev Computes the keytag for a chunk of data.\\n /// @param data The data to compute a keytag for.\\n /// @return The computed key tag.\\n function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n /* This function probably deserves some explanation.\\n * The DNSSEC keytag function is a checksum that relies on summing up individual bytes\\n * from the input string, with some mild bitshifting. Here's a Naive solidity implementation:\\n *\\n * function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n * uint ac;\\n * for (uint i = 0; i < data.length; i++) {\\n * ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);\\n * }\\n * return uint16(ac + (ac >> 16));\\n * }\\n *\\n * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;\\n * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's\\n * large words work in our favour.\\n *\\n * The code below works by treating the input as a series of 256 bit words. It first masks out\\n * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.\\n * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're\\n * effectively summing 16 different numbers with each EVM ADD opcode.\\n *\\n * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.\\n * It does this using the same trick - mask out every other value, shift to align them, add them together.\\n * After the first addition on both accumulators, there's enough room to add the two accumulators together,\\n * and the remaining sums can be done just on ac1.\\n */\\n unchecked {\\n require(data.length <= 8192, \\\"Long keys not permitted\\\");\\n uint256 ac1;\\n uint256 ac2;\\n for (uint256 i = 0; i < data.length + 31; i += 32) {\\n uint256 word;\\n assembly {\\n word := mload(add(add(data, 32), i))\\n }\\n if (i + 32 > data.length) {\\n uint256 unused = 256 - (data.length - i) * 8;\\n word = (word >> unused) << unused;\\n }\\n ac1 +=\\n (word &\\n 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>\\n 8;\\n ac2 += (word &\\n 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);\\n }\\n ac1 =\\n (ac1 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac1 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac2 =\\n (ac2 &\\n 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) +\\n ((ac2 &\\n 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>\\n 16);\\n ac1 = (ac1 << 8) + ac2;\\n ac1 =\\n (ac1 &\\n 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>\\n 32);\\n ac1 =\\n (ac1 &\\n 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) +\\n ((ac1 &\\n 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>\\n 64);\\n ac1 =\\n (ac1 &\\n 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) +\\n (ac1 >> 128);\\n ac1 += (ac1 >> 16) & 0xFFFF;\\n return uint16(ac1);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xdbab10dde632a1a02ee1c706bd4a31f9fb6195bd15a360528f7f6615e8fc895a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/Multicallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"./IMulticallable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nabstract contract Multicallable is IMulticallable, ERC165 {\\n function _multicall(\\n bytes32 nodehash,\\n bytes[] calldata data\\n ) internal returns (bytes[] memory results) {\\n results = new bytes[](data.length);\\n for (uint256 i = 0; i < data.length; i++) {\\n if (nodehash != bytes32(0)) {\\n bytes32 txNamehash = bytes32(data[i][4:36]);\\n require(\\n txNamehash == nodehash,\\n \\\"multicall: All records must have a matching namehash\\\"\\n );\\n }\\n (bool success, bytes memory result) = address(this).delegatecall(\\n data[i]\\n );\\n require(success);\\n results[i] = result;\\n }\\n return results;\\n }\\n\\n // This function provides an extra security check when called\\n // from privileged contracts (such as EthRegistrarController)\\n // that can set records on behalf of the node owners\\n function multicallWithNodeCheck(\\n bytes32 nodehash,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results) {\\n return _multicall(nodehash, data);\\n }\\n\\n function multicall(\\n bytes[] calldata data\\n ) public override returns (bytes[] memory results) {\\n return _multicall(bytes32(0), data);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IMulticallable).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x2bf0cc11477d25abf9b3c85826bfe979911d1b48ea747f65a7fc4fd882bc9e9a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverBase.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport \\\"./profiles/IVersionableResolver.sol\\\";\\n\\nabstract contract ResolverBase is ERC165, IVersionableResolver {\\n mapping(bytes32 => uint64) public recordVersions;\\n\\n function isAuthorised(bytes32 node) internal view virtual returns (bool);\\n\\n modifier authorised(bytes32 node) {\\n require(isAuthorised(node));\\n _;\\n }\\n\\n /// Increments the record version associated with an ENS node.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n function clearRecords(bytes32 node) public virtual authorised(node) {\\n recordVersions[node]++;\\n emit VersionChanged(node, recordVersions[node]);\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IVersionableResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0xb063f86c1e75508779fd23762f20ebfbb2f3ef6d84328038e3de01cf59d18e4b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ABIResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"./IABIResolver.sol\\\";\\nimport \\\"../ResolverBase.sol\\\";\\n\\nabstract contract ABIResolver is IABIResolver, ResolverBase {\\n mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_abis;\\n\\n /// Sets the ABI associated with an ENS node.\\n /// Nodes may have one ABI of each content type. To remove an ABI, set it to\\n /// the empty string.\\n /// @param node The node to update.\\n /// @param contentType The content type of the ABI\\n /// @param data The ABI data.\\n function setABI(\\n bytes32 node,\\n uint256 contentType,\\n bytes calldata data\\n ) external virtual authorised(node) {\\n // Content types must be powers of 2\\n require(((contentType - 1) & contentType) == 0);\\n\\n versionable_abis[recordVersions[node]][node][contentType] = data;\\n emit ABIChanged(node, contentType);\\n }\\n\\n /// Returns the ABI associated with an ENS node.\\n /// Defined in EIP205.\\n /// @param node The ENS node to query\\n /// @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\\n /// @return contentType The content type of the return value\\n /// @return data The ABI data\\n function ABI(\\n bytes32 node,\\n uint256 contentTypes\\n ) external view virtual override returns (uint256, bytes memory) {\\n mapping(uint256 => bytes) storage abiset = versionable_abis[\\n recordVersions[node]\\n ][node];\\n\\n for (\\n uint256 contentType = 1;\\n contentType > 0 && contentType <= contentTypes;\\n contentType <<= 1\\n ) {\\n if (\\n (contentType & contentTypes) != 0 &&\\n abiset[contentType].length > 0\\n ) {\\n return (contentType, abiset[contentType]);\\n }\\n }\\n\\n return (0, bytes(\\\"\\\"));\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IABIResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0xf938b15d989964645a1aba2c151663fd63d2942c8daf46470ac7b15fe3d41641\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/AddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport {ResolverBase, IERC165} from \\\"../ResolverBase.sol\\\";\\nimport {IAddrResolver} from \\\"./IAddrResolver.sol\\\";\\nimport {IAddressResolver} from \\\"./IAddressResolver.sol\\\";\\nimport {IHasAddressResolver} from \\\"./IHasAddressResolver.sol\\\";\\nimport {ENSIP19, COIN_TYPE_ETH, COIN_TYPE_DEFAULT} from \\\"../../utils/ENSIP19.sol\\\";\\n\\nabstract contract AddrResolver is\\n IAddrResolver,\\n IAddressResolver,\\n IHasAddressResolver,\\n ResolverBase\\n{\\n mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes))) versionable_addresses;\\n\\n /// @notice The supplied address could not be converted to `address`.\\n /// @dev Error selector: `0x8d666f60`\\n error InvalidEVMAddress(bytes addressBytes);\\n\\n /// @notice Set `addr(60)` of the associated ENS node.\\n /// `address(0)` is stored as `new bytes(20)`.\\n /// @param node The node to update.\\n /// @param _addr The address to set.\\n function setAddr(\\n bytes32 node,\\n address _addr\\n ) external virtual authorised(node) {\\n setAddr(node, COIN_TYPE_ETH, abi.encodePacked(_addr));\\n }\\n\\n /// @notice Get `addr(60)` as `address` of the associated ENS node.\\n /// @param node The node to query.\\n /// @return The associated address.\\n function addr(\\n bytes32 node\\n ) public view virtual override returns (address payable) {\\n return payable(address(bytes20(addr(node, COIN_TYPE_ETH))));\\n }\\n\\n /// @notice Set the address for coin type of the associated ENS node.\\n /// Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes.\\n /// @param node The node to update.\\n /// @param coinType The coin type.\\n /// @param addressBytes The address to set.\\n function setAddr(\\n bytes32 node,\\n uint256 coinType,\\n bytes memory addressBytes\\n ) public virtual authorised(node) {\\n if (\\n addressBytes.length != 0 &&\\n addressBytes.length != 20 &&\\n ENSIP19.isEVMCoinType(coinType)\\n ) {\\n revert InvalidEVMAddress(addressBytes);\\n }\\n emit AddressChanged(node, coinType, addressBytes);\\n if (coinType == COIN_TYPE_ETH) {\\n emit AddrChanged(node, address(bytes20(addressBytes)));\\n }\\n versionable_addresses[recordVersions[node]][node][\\n coinType\\n ] = addressBytes;\\n }\\n\\n /// @notice Get the address for coin type of the associated ENS node.\\n /// If coin type is EVM and empty, defaults to `addr(COIN_TYPE_DEFAULT)`.\\n /// @param node The node to query.\\n /// @param coinType The coin type.\\n /// @return addressBytes The assocated address.\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) public view virtual override returns (bytes memory addressBytes) {\\n mapping(uint256 => bytes) storage addrs = versionable_addresses[\\n recordVersions[node]\\n ][node];\\n addressBytes = addrs[coinType];\\n if (\\n addressBytes.length == 0 && ENSIP19.chainFromCoinType(coinType) > 0\\n ) {\\n addressBytes = addrs[COIN_TYPE_DEFAULT];\\n }\\n }\\n\\n /// @inheritdoc IHasAddressResolver\\n function hasAddr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bool) {\\n return\\n versionable_addresses[recordVersions[node]][node][coinType].length >\\n 0;\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public view virtual override returns (bool) {\\n return\\n type(IAddrResolver).interfaceId == interfaceId ||\\n type(IAddressResolver).interfaceId == interfaceId ||\\n type(IHasAddressResolver).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n}\\n\",\"keccak256\":\"0x2d214ea1213dbd8cc02d32355edf044a6551296df56e8a4931d3447092e8abcc\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ContentHashResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./IContentHashResolver.sol\\\";\\n\\nabstract contract ContentHashResolver is IContentHashResolver, ResolverBase {\\n mapping(uint64 => mapping(bytes32 => bytes)) versionable_hashes;\\n\\n /// Sets the contenthash associated with an ENS node.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n /// @param hash The contenthash to set\\n function setContenthash(\\n bytes32 node,\\n bytes calldata hash\\n ) external virtual authorised(node) {\\n versionable_hashes[recordVersions[node]][node] = hash;\\n emit ContenthashChanged(node, hash);\\n }\\n\\n /// Returns the contenthash associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function contenthash(\\n bytes32 node\\n ) external view virtual override returns (bytes memory) {\\n return versionable_hashes[recordVersions[node]][node];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IContentHashResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x8eddfb712744906b41ad3458171438605982cdcd0c570d91fed49eca56bf7def\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/DNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"../../dnssec-oracle/RRUtils.sol\\\";\\nimport \\\"./IDNSRecordResolver.sol\\\";\\nimport \\\"./IDNSZoneResolver.sol\\\";\\n\\nabstract contract DNSResolver is\\n IDNSRecordResolver,\\n IDNSZoneResolver,\\n ResolverBase\\n{\\n using RRUtils for *;\\n using BytesUtils for bytes;\\n\\n // Zone hashes for the domains.\\n // A zone hash is an EIP-1577 content hash in binary format that should point to a\\n // resource containing a single zonefile.\\n // node => contenthash\\n mapping(uint64 => mapping(bytes32 => bytes)) private versionable_zonehashes;\\n\\n // The records themselves. Stored as binary RRSETs\\n // node => version => name => resource => data\\n mapping(uint64 => mapping(bytes32 => mapping(bytes32 => mapping(uint16 => bytes))))\\n private versionable_records;\\n\\n // Count of number of entries for a given name. Required for DNS resolvers\\n // when resolving wildcards.\\n // node => version => name => number of records\\n mapping(uint64 => mapping(bytes32 => mapping(bytes32 => uint16)))\\n private versionable_nameEntriesCount;\\n\\n /// Set one or more DNS records. Records are supplied in wire-format.\\n /// Records with the same node/name/resource must be supplied one after the\\n /// other to ensure the data is updated correctly. For example, if the data\\n /// was supplied:\\n /// a.example.com IN A 1.2.3.4\\n /// a.example.com IN A 5.6.7.8\\n /// www.example.com IN CNAME a.example.com.\\n /// then this would store the two A records for a.example.com correctly as a\\n /// single RRSET, however if the data was supplied:\\n /// a.example.com IN A 1.2.3.4\\n /// www.example.com IN CNAME a.example.com.\\n /// a.example.com IN A 5.6.7.8\\n /// then this would store the first A record, the CNAME, then the second A\\n /// record which would overwrite the first.\\n ///\\n /// @param node the namehash of the node for which to set the records\\n /// @param data the DNS wire format records to set\\n function setDNSRecords(\\n bytes32 node,\\n bytes calldata data\\n ) external virtual authorised(node) {\\n uint16 resource = 0;\\n uint256 offset = 0;\\n bytes memory name;\\n bytes memory value;\\n bytes32 nameHash;\\n uint64 version = recordVersions[node];\\n // Iterate over the data to add the resource records\\n for (\\n RRUtils.RRIterator memory iter = data.iterateRRs(0);\\n !iter.done();\\n iter.next()\\n ) {\\n if (resource == 0) {\\n resource = iter.dnstype;\\n name = iter.name();\\n nameHash = keccak256(abi.encodePacked(name));\\n value = bytes(iter.rdata());\\n } else {\\n bytes memory newName = iter.name();\\n if (resource != iter.dnstype || !name.equals(newName)) {\\n setDNSRRSet(\\n node,\\n name,\\n resource,\\n data,\\n offset,\\n iter.offset - offset,\\n value.length == 0,\\n version\\n );\\n resource = iter.dnstype;\\n offset = iter.offset;\\n name = newName;\\n nameHash = keccak256(name);\\n value = bytes(iter.rdata());\\n }\\n }\\n }\\n if (name.length > 0) {\\n setDNSRRSet(\\n node,\\n name,\\n resource,\\n data,\\n offset,\\n data.length - offset,\\n value.length == 0,\\n version\\n );\\n }\\n }\\n\\n /// Obtain a DNS record.\\n /// @param node the namehash of the node for which to fetch the record\\n /// @param name the keccak-256 hash of the fully-qualified name for which to fetch the record\\n /// @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\\n /// @return the DNS record in wire format if present, otherwise empty\\n function dnsRecord(\\n bytes32 node,\\n bytes32 name,\\n uint16 resource\\n ) public view virtual override returns (bytes memory) {\\n return versionable_records[recordVersions[node]][node][name][resource];\\n }\\n\\n /// Check if a given node has records.\\n /// @param node the namehash of the node for which to check the records\\n /// @param name the namehash of the node for which to check the records\\n function hasDNSRecords(\\n bytes32 node,\\n bytes32 name\\n ) public view virtual returns (bool) {\\n return (versionable_nameEntriesCount[recordVersions[node]][node][\\n name\\n ] != 0);\\n }\\n\\n /// setZonehash sets the hash for the zone.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n /// @param hash The zonehash to set\\n function setZonehash(\\n bytes32 node,\\n bytes calldata hash\\n ) external virtual authorised(node) {\\n uint64 currentRecordVersion = recordVersions[node];\\n bytes memory oldhash = versionable_zonehashes[currentRecordVersion][\\n node\\n ];\\n versionable_zonehashes[currentRecordVersion][node] = hash;\\n emit DNSZonehashChanged(node, oldhash, hash);\\n }\\n\\n /// zonehash obtains the hash for the zone.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function zonehash(\\n bytes32 node\\n ) external view virtual override returns (bytes memory) {\\n return versionable_zonehashes[recordVersions[node]][node];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IDNSRecordResolver).interfaceId ||\\n interfaceID == type(IDNSZoneResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n\\n function setDNSRRSet(\\n bytes32 node,\\n bytes memory name,\\n uint16 resource,\\n bytes memory data,\\n uint256 offset,\\n uint256 size,\\n bool deleteRecord,\\n uint64 version\\n ) private {\\n bytes32 nameHash = keccak256(name);\\n bytes memory rrData = data.substring(offset, size);\\n if (deleteRecord) {\\n if (\\n versionable_records[version][node][nameHash][resource].length !=\\n 0\\n ) {\\n versionable_nameEntriesCount[version][node][nameHash]--;\\n }\\n delete (versionable_records[version][node][nameHash][resource]);\\n emit DNSRecordDeleted(node, name, resource);\\n } else {\\n if (\\n versionable_records[version][node][nameHash][resource].length ==\\n 0\\n ) {\\n versionable_nameEntriesCount[version][node][nameHash]++;\\n }\\n versionable_records[version][node][nameHash][resource] = rrData;\\n emit DNSRecordChanged(node, name, resource, rrData);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3f5344239a3461c06389c952ae8e6feb29f0fd72dea1baaf31be81ba8b6a194a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/DataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./IDataResolver.sol\\\";\\n\\nabstract contract DataResolver is\\n IDataResolver,\\n ResolverBase\\n{\\n mapping(uint64 => mapping(bytes32 node => mapping(string key => bytes data)))\\n private versionable_dataStore;\\n\\n /// @notice Sets the data associated with the key, `key` for a specific `node`.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n /// @param key The key to set.\\n /// @param value The arbitrary `bytes` data to set.\\n function setData(\\n bytes32 node,\\n string calldata key,\\n bytes calldata value\\n ) external virtual authorised(node) {\\n versionable_dataStore[recordVersions[node]][node][key] = value;\\n _afterSetData(node, key, value);\\n emit DataChanged(node, key, key, value);\\n }\\n\\n /// @dev Hook called after data is set. Override to add custom behavior.\\n function _afterSetData(\\n bytes32 node,\\n string memory key,\\n bytes memory value\\n ) internal virtual {}\\n\\n /// @notice For a specific `node`, get the data associated with the key, `key`.\\n /// @param node The node (namehash) for which data is being fetched.\\n /// @param key The key.\\n /// @return The associated arbitrary `bytes` data.\\n function data(\\n bytes32 node,\\n string calldata key\\n ) external view returns (bytes memory) {\\n return versionable_dataStore[recordVersions[node]][node][key];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IDataResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x0ce3e6b2244a9d074371ecb43ba9eaca8a1b3410c73c50d852b4e3696de1cd7d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IABIResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IABIResolver {\\n event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\\n\\n /// Returns the ABI associated with an ENS node.\\n /// Defined in EIP205.\\n /// @param node The ENS node to query\\n /// @param contentTypes A bitwise OR of the ABI formats accepted by the caller.\\n /// @return contentType The content type of the return value\\n /// @return data The ABI data\\n function ABI(\\n bytes32 node,\\n uint256 contentTypes\\n ) external view returns (uint256, bytes memory);\\n}\\n\",\"keccak256\":\"0x3a7a763d7a4f0d196c4b628545b022b1d1d0e37baf84eaa6eecb1a57a1633cad\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the legacy (ETH-only) addr function.\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /// Returns the address associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated address.\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x91dd0c350698c505d6c7e4c919da9f981d4b8d7ad062e25073fa1f6af7cb79d1\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the new (multicoin) addr function.\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x8da5dd0fc1c5ab4f47e03c23126976a86d4b2dbeac161e70e3af9e2a13330cf0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IContentHashResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IContentHashResolver {\\n event ContenthashChanged(bytes32 indexed node, bytes hash);\\n\\n /// Returns the contenthash associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function contenthash(bytes32 node) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0xaa978b1ee4c19e99c8aa409dc553e9b4c1bf9fe3c5bad718cd3589e6c9e6d121\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDNSRecordResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IDNSRecordResolver {\\n // DNSRecordChanged is emitted whenever a given node/name/resource's RRSET is updated.\\n event DNSRecordChanged(\\n bytes32 indexed node,\\n bytes name,\\n uint16 resource,\\n bytes record\\n );\\n // DNSRecordDeleted is emitted whenever a given node/name/resource's RRSET is deleted.\\n event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);\\n\\n /// Obtain a DNS record.\\n /// @param node the namehash of the node for which to fetch the record\\n /// @param name the keccak-256 hash of the fully-qualified name for which to fetch the record\\n /// @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types\\n /// @return the DNS record in wire format if present, otherwise empty\\n function dnsRecord(\\n bytes32 node,\\n bytes32 name,\\n uint16 resource\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x434bf76bba71eed3e0f22b3a5b9f8aaed0ddd8b79f6a1e7c7447785be5924d3b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDNSZoneResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IDNSZoneResolver {\\n // DNSZonehashChanged is emitted whenever a given node's zone hash is updated.\\n event DNSZonehashChanged(\\n bytes32 indexed node,\\n bytes lastzonehash,\\n bytes zonehash\\n );\\n\\n /// zonehash obtains the hash for the zone.\\n /// @param node The ENS node to query.\\n /// @return The associated contenthash.\\n function zonehash(bytes32 node) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x3a028c0b13721c7627c55bbf5a7d0762d5b1db1045fdc0f8e417011876bd2d29\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IDataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// @dev Interface selector: `0xecbfada3`\\ninterface IDataResolver {\\n /// @notice For a specific `node`, the data associated with a `key` has changed.\\n event DataChanged(\\n bytes32 indexed node, \\n string indexed indexedKey,\\n string key, \\n bytes indexed indexedData\\n );\\n \\n /// @notice For a specific `node`, get the data associated with the key, `key`.\\n /// @param node The node (namehash) for which data is being fetched.\\n /// @param key The key.\\n /// @return The associated arbitrary `bytes` data.\\n function data(\\n bytes32 node,\\n string calldata key\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x502a38d58d2047db3fa021897eda32bb6f4cde9746606e691e6acf25c396d88e\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IHasAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IHasAddressResolver {\\n /// @notice Determine if an addresss is stored for the coin type of the associated ENS node.\\n /// @param node The node to query.\\n /// @param coinType The coin type.\\n /// @return True if the associated address is not empty.\\n function hasAddr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xbe13530b8cc027517c235e422326abd36bb1152dac8546713471be2a7335cf2b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IInterfaceResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IInterfaceResolver {\\n event InterfaceChanged(\\n bytes32 indexed node,\\n bytes4 indexed interfaceID,\\n address implementer\\n );\\n\\n /// Returns the address of a contract that implements the specified interface for this name.\\n /// If an implementer has not been set for this interfaceID and name, the resolver will query\\n /// the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\\n /// contract implements EIP165 and returns `true` for the specified interfaceID, its address\\n /// will be returned.\\n /// @param node The ENS node to query.\\n /// @param interfaceID The EIP 165 interface ID to check for.\\n /// @return The address that implements this interface, or 0 if the interface is unsupported.\\n function interfaceImplementer(\\n bytes32 node,\\n bytes4 interfaceID\\n ) external view returns (address);\\n}\\n\",\"keccak256\":\"0x510176a3fe60471775328756ab025d8bafda7063f52f218728ca559b8f61a357\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x3ab986332e0baad7aeb4b426aace3aa1c235be5efff8db4b6f1ce501bcdd9e68\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IPubkeyResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IPubkeyResolver {\\n event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\\n\\n /// Returns the SECP256k1 public key associated with an ENS node.\\n /// Defined in EIP 619.\\n /// @param node The ENS node to query\\n /// @return x The X coordinate of the curve point for the public key.\\n /// @return y The Y coordinate of the curve point for the public key.\\n function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);\\n}\\n\",\"keccak256\":\"0x1a21561b58ce17db400c015882ff07f12f9bd0df0e7b9305841799aada441820\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/ITextResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ITextResolver {\\n event TextChanged(\\n bytes32 indexed node,\\n string indexed indexedKey,\\n string key,\\n string value\\n );\\n\\n /// Returns the text data associated with an ENS node and key.\\n /// @param node The ENS node to query.\\n /// @param key The text data key to query.\\n /// @return The associated text data.\\n function text(\\n bytes32 node,\\n string calldata key\\n ) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xe91c15697be2d20417cce3c58d4ecce34796986fdedc97be5b93a823be58e471\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IVersionableResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface IVersionableResolver {\\n event VersionChanged(bytes32 indexed node, uint64 newVersion);\\n\\n function recordVersions(bytes32 node) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0xd0d09596f20c57bafb2ffa8521a8c57120e9af6c6b194f9c689d4da56f91a57c\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/InterfaceResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./AddrResolver.sol\\\";\\nimport \\\"./IInterfaceResolver.sol\\\";\\n\\nabstract contract InterfaceResolver is IInterfaceResolver, AddrResolver {\\n mapping(uint64 => mapping(bytes32 => mapping(bytes4 => address))) versionable_interfaces;\\n\\n /// Sets an interface associated with a name.\\n /// Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support.\\n /// @param node The node to update.\\n /// @param interfaceID The EIP 165 interface ID.\\n /// @param implementer The address of a contract that implements this interface for this node.\\n function setInterface(\\n bytes32 node,\\n bytes4 interfaceID,\\n address implementer\\n ) external virtual authorised(node) {\\n versionable_interfaces[recordVersions[node]][node][\\n interfaceID\\n ] = implementer;\\n emit InterfaceChanged(node, interfaceID, implementer);\\n }\\n\\n /// Returns the address of a contract that implements the specified interface for this name.\\n /// If an implementer has not been set for this interfaceID and name, the resolver will query\\n /// the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that\\n /// contract implements EIP165 and returns `true` for the specified interfaceID, its address\\n /// will be returned.\\n /// @param node The ENS node to query.\\n /// @param interfaceID The EIP 165 interface ID to check for.\\n /// @return The address that implements this interface, or 0 if the interface is unsupported.\\n function interfaceImplementer(\\n bytes32 node,\\n bytes4 interfaceID\\n ) external view virtual override returns (address) {\\n address implementer = versionable_interfaces[recordVersions[node]][\\n node\\n ][interfaceID];\\n if (implementer != address(0)) {\\n return implementer;\\n }\\n\\n address a = addr(node);\\n if (a == address(0)) {\\n return address(0);\\n }\\n\\n (bool success, bytes memory returnData) = a.staticcall(\\n abi.encodeWithSignature(\\n \\\"supportsInterface(bytes4)\\\",\\n type(IERC165).interfaceId\\n )\\n );\\n if (!success || returnData.length < 32 || returnData[31] == 0) {\\n // EIP 165 not supported by target\\n return address(0);\\n }\\n\\n (success, returnData) = a.staticcall(\\n abi.encodeWithSignature(\\\"supportsInterface(bytes4)\\\", interfaceID)\\n );\\n if (!success || returnData.length < 32 || returnData[31] == 0) {\\n // Specified interface not supported by target\\n return address(0);\\n }\\n\\n return a;\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IInterfaceResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x029b7f2fa0e763b914e2769c05b8b230aea7991f3947e5324499454e98310300\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/NameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./INameResolver.sol\\\";\\n\\nabstract contract NameResolver is INameResolver, ResolverBase {\\n mapping(uint64 => mapping(bytes32 => string)) versionable_names;\\n\\n /// Sets the name associated with an ENS node, for reverse records.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n function setName(\\n bytes32 node,\\n string calldata newName\\n ) external virtual authorised(node) {\\n versionable_names[recordVersions[node]][node] = newName;\\n emit NameChanged(node, newName);\\n }\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(\\n bytes32 node\\n ) external view virtual override returns (string memory) {\\n return versionable_names[recordVersions[node]][node];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(INameResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x2bee21414404629419db708bd8b8e284e702a175c17451c4b8f0f06ce5c7a250\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/PubkeyResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./IPubkeyResolver.sol\\\";\\n\\nabstract contract PubkeyResolver is IPubkeyResolver, ResolverBase {\\n struct PublicKey {\\n bytes32 x;\\n bytes32 y;\\n }\\n\\n mapping(uint64 => mapping(bytes32 => PublicKey)) versionable_pubkeys;\\n\\n /// Sets the SECP256k1 public key associated with an ENS node.\\n /// @param node The ENS node to query\\n /// @param x the X coordinate of the curve point for the public key.\\n /// @param y the Y coordinate of the curve point for the public key.\\n function setPubkey(\\n bytes32 node,\\n bytes32 x,\\n bytes32 y\\n ) external virtual authorised(node) {\\n versionable_pubkeys[recordVersions[node]][node] = PublicKey(x, y);\\n emit PubkeyChanged(node, x, y);\\n }\\n\\n /// Returns the SECP256k1 public key associated with an ENS node.\\n /// Defined in EIP 619.\\n /// @param node The ENS node to query\\n /// @return x The X coordinate of the curve point for the public key.\\n /// @return y The Y coordinate of the curve point for the public key.\\n function pubkey(\\n bytes32 node\\n ) external view virtual override returns (bytes32 x, bytes32 y) {\\n uint64 currentRecordVersion = recordVersions[node];\\n return (\\n versionable_pubkeys[currentRecordVersion][node].x,\\n versionable_pubkeys[currentRecordVersion][node].y\\n );\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(IPubkeyResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x697b350cd142af9ed401e1e73f395f039bb12cdb503bc6c3488482788d69587b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/TextResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nimport \\\"../ResolverBase.sol\\\";\\nimport \\\"./ITextResolver.sol\\\";\\n\\nabstract contract TextResolver is ITextResolver, ResolverBase {\\n mapping(uint64 => mapping(bytes32 => mapping(string => string))) versionable_texts;\\n\\n /// Sets the text data associated with an ENS node and key.\\n /// May only be called by the owner of that node in the ENS registry.\\n /// @param node The node to update.\\n /// @param key The key to set.\\n /// @param value The text data value to set.\\n function setText(\\n bytes32 node,\\n string calldata key,\\n string calldata value\\n ) external virtual authorised(node) {\\n versionable_texts[recordVersions[node]][node][key] = value;\\n emit TextChanged(node, key, key, value);\\n }\\n\\n /// Returns the text data associated with an ENS node and key.\\n /// @param node The ENS node to query.\\n /// @param key The text data key to query.\\n /// @return The associated text data.\\n function text(\\n bytes32 node,\\n string calldata key\\n ) external view virtual override returns (string memory) {\\n return versionable_texts[recordVersions[node]][node][key];\\n }\\n\\n function supportsInterface(\\n bytes4 interfaceID\\n ) public view virtual override returns (bool) {\\n return\\n interfaceID == type(ITextResolver).interfaceId ||\\n super.supportsInterface(interfaceID);\\n }\\n}\\n\",\"keccak256\":\"0x82a914dfe1b30634e729c03450e4c9ef4afd53919993231a92fb9cca2f8b3a83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/ENSIP19.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {HexUtils} from \\\"../utils/HexUtils.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\n\\nuint32 constant CHAIN_ID_ETH = 1;\\n\\nuint256 constant COIN_TYPE_ETH = 60;\\nuint256 constant COIN_TYPE_DEFAULT = 1 << 31; // 0x8000_0000\\n\\nstring constant SLUG_ETH = \\\"addr\\\"; // <=> COIN_TYPE_ETH\\nstring constant SLUG_DEFAULT = \\\"default\\\"; // <=> COIN_TYPE_DEFAULT\\nstring constant TLD_REVERSE = \\\"reverse\\\";\\n\\n/// @dev Library for generating reverse names according to ENSIP-19.\\n/// https://docs.ens.domains/ensip/19\\nlibrary ENSIP19 {\\n /// @dev The supplied address was `0x`.\\n /// Error selector: `0x7138356f`\\n error EmptyAddress();\\n\\n /// @dev Extract Chain ID from `coinType`.\\n /// @param coinType The coin type.\\n /// @return The Chain ID or 0 if non-EVM Chain.\\n function chainFromCoinType(\\n uint256 coinType\\n ) internal pure returns (uint32) {\\n if (coinType == COIN_TYPE_ETH) return CHAIN_ID_ETH;\\n coinType ^= COIN_TYPE_DEFAULT;\\n return uint32(coinType < COIN_TYPE_DEFAULT ? coinType : 0);\\n }\\n\\n /// @dev Determine if Coin Type is for an EVM address.\\n /// @param coinType The coin type.\\n /// @return True if coin type represents an EVM address.\\n function isEVMCoinType(uint256 coinType) internal pure returns (bool) {\\n return coinType == COIN_TYPE_DEFAULT || chainFromCoinType(coinType) > 0;\\n }\\n\\n /// @dev Generate Reverse Name from Address + Coin Type.\\n /// Reverts `EmptyAddress` if `addressBytes` is `0x`.\\n /// @param addressBytes The input address.\\n /// @param coinType The coin type.\\n /// @return The ENS reverse name, eg. `1234abcd.addr.reverse`.\\n function reverseName(\\n bytes memory addressBytes,\\n uint256 coinType\\n ) internal pure returns (string memory) {\\n if (addressBytes.length == 0) {\\n revert EmptyAddress();\\n }\\n return\\n string(\\n abi.encodePacked(\\n HexUtils.bytesToHex(addressBytes),\\n bytes1(\\\".\\\"),\\n coinType == COIN_TYPE_ETH\\n ? SLUG_ETH\\n : coinType == COIN_TYPE_DEFAULT\\n ? SLUG_DEFAULT\\n : HexUtils.unpaddedUintToHex(coinType, true),\\n bytes1(\\\".\\\"),\\n TLD_REVERSE\\n )\\n );\\n }\\n\\n /// @dev Parse Reverse Name into Address + Coin Type.\\n /// Matches: `/^[0-9a-fA-F]+\\\\.([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @return addressBytes The address or empty if invalid.\\n /// @return coinType The coin type.\\n function parse(\\n bytes memory name\\n ) internal pure returns (bytes memory addressBytes, uint256 coinType) {\\n (, uint256 offset) = NameCoder.readLabel(name, 0);\\n bool valid;\\n (addressBytes, valid) = HexUtils.hexToBytes(name, 1, offset);\\n if (!valid || addressBytes.length == 0) return (\\\"\\\", 0); // addressBytes not 1+ hex\\n (valid, coinType) = parseNamespace(name, offset);\\n if (!valid) return (\\\"\\\", 0); // invalid namespace\\n }\\n\\n /// @dev Parse Reverse Namespace into Coin Type.\\n /// Matches: `/^([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset to begin parsing.\\n /// @return valid True if a valid reverse namespace.\\n /// @return coinType The coin type.\\n function parseNamespace(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bool valid, uint256 coinType) {\\n (bytes32 labelHash, uint256 offsetTLD) = NameCoder.readLabel(\\n name,\\n offset\\n );\\n if (labelHash == keccak256(bytes(SLUG_ETH))) {\\n coinType = COIN_TYPE_ETH;\\n } else if (labelHash == keccak256(bytes(SLUG_DEFAULT))) {\\n coinType = COIN_TYPE_DEFAULT;\\n } else if (labelHash == bytes32(0)) {\\n return (false, 0); // no slug\\n } else {\\n (bytes32 word, bool validHex) = HexUtils.hexStringToBytes32(\\n name,\\n 1 + offset,\\n offsetTLD\\n );\\n if (!validHex) return (false, 0); // invalid coinType or too long\\n coinType = uint256(word);\\n }\\n (labelHash, offset) = NameCoder.readLabel(name, offsetTLD);\\n if (labelHash != keccak256(bytes(TLD_REVERSE))) return (false, 0); // invalid tld\\n (labelHash, ) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) return (false, 0); // not tld\\n valid = true;\\n }\\n}\\n\",\"keccak256\":\"0xd1af09b014028de4c50489bd58ae424273180bb96d95353d8eefd14845f31824\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/resolver/PublicResolverV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {Multicallable} from \\\"@ens/contracts/resolvers/Multicallable.sol\\\";\\nimport {ABIResolver} from \\\"@ens/contracts/resolvers/profiles/ABIResolver.sol\\\";\\nimport {AddrResolver} from \\\"@ens/contracts/resolvers/profiles/AddrResolver.sol\\\";\\nimport {ContentHashResolver} from \\\"@ens/contracts/resolvers/profiles/ContentHashResolver.sol\\\";\\nimport {DataResolver} from \\\"@ens/contracts/resolvers/profiles/DataResolver.sol\\\";\\nimport {DNSResolver} from \\\"@ens/contracts/resolvers/profiles/DNSResolver.sol\\\";\\nimport {InterfaceResolver} from \\\"@ens/contracts/resolvers/profiles/InterfaceResolver.sol\\\";\\nimport {NameResolver} from \\\"@ens/contracts/resolvers/profiles/NameResolver.sol\\\";\\nimport {PubkeyResolver} from \\\"@ens/contracts/resolvers/profiles/PubkeyResolver.sol\\\";\\nimport {TextResolver} from \\\"@ens/contracts/resolvers/profiles/TextResolver.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {LibRegistry} from \\\"../universalResolver/libraries/LibRegistry.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\n/// @notice PublicResolver that respects the ENSv2 registry.\\ncontract PublicResolverV2 is\\n ERC165,\\n Multicallable,\\n ABIResolver,\\n AddrResolver,\\n ContentHashResolver,\\n DataResolver,\\n DNSResolver,\\n InterfaceResolver,\\n NameResolver,\\n PubkeyResolver,\\n TextResolver,\\n DelegatedContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice The ENSv2 Root Registry contract.\\n IPermissionedRegistry public immutable ROOT_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev A mapping of operators. An address that is authorised for an address\\n /// may make any changes to the name that the owner could, but may not update\\n /// the set of authorisations.\\n mapping(address owner => mapping(address operator => bool approved)) internal _operatorApprovals;\\n\\n /// @dev A mapping of delegates. A delegate that is authorised by an owner\\n /// for a name may make changes to the name's resolver, but may not update\\n /// the set of token approvals.\\n mapping(address owner => mapping(bytes32 node => mapping(address delegate => bool approved))) internal _tokenApprovals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice An operator is added or removed.\\n /// @param owner The node owner.\\n /// @param operator The approved account.\\n /// @param approved If `true`, approved, otherwise revoked.\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /// @notice A delegate is approved or an approval is revoked.\\n /// @param owner The node owner.\\n /// @param node The namehash.\\n /// @param delegate The approved account.\\n /// @param approved If `true`, approved, otherwise revoked.\\n event Approved(\\n address owner,\\n bytes32 indexed node,\\n address indexed delegate,\\n bool indexed approved\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param rootRegistry The ENSv2 Root Registry contract.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n INameWrapper nameWrapper,\\n IPermissionedRegistry rootRegistry,\\n IContractNamer contractNamer\\n )\\n DelegatedContractNamer(contractNamer)\\n {\\n NAME_WRAPPER = nameWrapper;\\n ROOT_REGISTRY = rootRegistry;\\n }\\n\\n /// @inheritdoc AddrResolver\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n override(\\n ERC165,\\n Multicallable,\\n ABIResolver,\\n AddrResolver,\\n ContentHashResolver,\\n DataResolver,\\n DNSResolver,\\n InterfaceResolver,\\n NameResolver,\\n PubkeyResolver,\\n TextResolver,\\n DelegatedContractNamer\\n )\\n returns (bool)\\n {\\n return super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grant or revoke `operator` approval.\\n /// @param operator The account to approve.\\n /// @param approved If `true`, approved, otherwise revoked.\\n function setApprovalForAll(address operator, bool approved) external {\\n address sender = msg.sender;\\n require(sender != operator, \\\"ERC1155: setting approval status for self\\\");\\n _operatorApprovals[sender][operator] = approved;\\n emit ApprovalForAll(sender, operator, approved);\\n }\\n\\n /// @notice Grant or revoke `delegate` approval on a specific node.\\n /// @param node The namehash to approve.\\n /// @param delegate The account to approve.\\n /// @param approved If `true`, approved, otherwise revoked.\\n function approve(bytes32 node, address delegate, bool approved) external {\\n address sender = msg.sender;\\n require(sender != delegate, \\\"Setting delegate status for self\\\");\\n _tokenApprovals[sender][node][delegate] = approved;\\n emit Approved(sender, node, delegate, approved);\\n }\\n\\n /// @notice Check if `operator` is approved for all nodes owned by `account`.\\n /// @param owner The owner account.\\n /// @param operator The operator account.\\n /// @return `true` if `operator` is approved.\\n function isApprovedForAll(address owner, address operator) public view returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /// @notice Check to see if the delegate has been approved by the owner for the node.\\n /// @param owner The owner account.\\n /// @param node The namehash to check.\\n /// @param delegate The delegated account.\\n /// @return `true` if `operator` is approved.\\n function isApprovedFor(address owner, bytes32 node, address delegate)\\n public\\n view\\n returns (bool)\\n {\\n return _tokenApprovals[owner][node][delegate];\\n }\\n\\n /// @notice Determine if `operator` is authorized for `node`.\\n /// @param node The namehash to check.\\n /// @param operator The account requesting authorization.\\n /// @return `true` if `node` is authorized.\\n function canModifyName(bytes32 node, address operator) public view returns (bool) {\\n bytes memory name = NAME_WRAPPER.names(node);\\n if (name.length == 0) {\\n return false;\\n }\\n address owner = LibRegistry.findOwner(ROOT_REGISTRY, name, 0);\\n return\\n owner == operator ||\\n isApprovedForAll(owner, operator) ||\\n isApprovedFor(owner, node, operator);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n // solhint-disable private-vars-leading-underscore\\n /// @dev Determine if the caller is authorized for `node`.\\n function isAuthorised(bytes32 node) internal view override returns (bool) {\\n return canModifyName(node, msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xf1cc8800ea76210e8cc926198123b561252ac121175f0f8f81d73c6b03979f7e\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/universalResolver/libraries/LibRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"../../registry/interfaces/IOwnedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Recursive traversal helpers for the namechain registry tree \\u2014 resolver lookup, registry\\n/// discovery, canonical name construction, and ancestry enumeration.\\nlibrary LibRegistry {\\n /// @dev Find the resolver address for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return exactRegistry The exact registry or null if not exact.\\n /// @return resolver The resolver or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n // supply if end of name\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return (rootRegistry, address(0), bytes32(0), offset);\\n }\\n // lookup parent name\\n (exactRegistry, resolver, node, resolverOffset) = findResolver(rootRegistry, name, next);\\n // if there was a parent registry...\\n if (address(exactRegistry) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n // remember the resolver (if it exists)\\n address res = exactRegistry.getResolver(label);\\n if (res != address(0)) {\\n resolver = res;\\n resolverOffset = offset;\\n }\\n exactRegistry = exactRegistry.getSubregistry(label);\\n }\\n node = NameCoder.namehash(node, labelHash); // update namehash\\n }\\n\\n /// @dev Find the owner for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return owner The owner address or null if unowned or not found.\\n function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (address owner)\\n {\\n IRegistry registry = findParentRegistry(rootRegistry, name, offset);\\n if (\\n address(registry) != address(0) &&\\n ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId)\\n ) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n owner = IOwnedRegistry(address(registry)).findOwner(label);\\n }\\n }\\n\\n /// @dev Construct the canonical name for `registry`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param registry The registry to name.\\n /// @return name The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry rootRegistry, IRegistry registry)\\n internal\\n view\\n returns (bytes memory name)\\n {\\n if (address(registry) == address(0)) {\\n return \\\"\\\";\\n }\\n for (;;) {\\n if (address(registry) == address(rootRegistry)) {\\n return abi.encodePacked(name, uint8(0)); // add terminator\\n }\\n (IRegistry parent, string memory label) = registry.getParent();\\n if (address(parent) == address(0)) {\\n return \\\"\\\"; // no canonical parent\\n }\\n IRegistry child = parent.getSubregistry(label);\\n if (address(child) != address(registry)) {\\n return \\\"\\\"; // wrong canonical child\\n }\\n name = abi.encodePacked(name, NameCoder.assertLabelSize(label), label); // reverts if invalid label\\n registry = parent;\\n }\\n }\\n\\n /// @dev Find the registry for `name` and return it iff it is canonical for that name.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name)\\n internal\\n view\\n returns (IRegistry)\\n {\\n IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0);\\n return\\n address(registry) != address(0) &&\\n keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) ==\\n keccak256(name)\\n ? registry\\n : IRegistry(address(0));\\n }\\n\\n /// @dev Find the exact registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return exactRegistry The exact registry or null if not found.\\n function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return rootRegistry;\\n }\\n IRegistry parent = findExactRegistry(rootRegistry, name, next);\\n if (address(parent) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n exactRegistry = parent.getSubregistry(label);\\n }\\n }\\n\\n /// @dev Find the parent registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return parentRegistry The parent registry or null if not found.\\n function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry parentRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n parentRegistry = findExactRegistry(rootRegistry, name, next);\\n }\\n }\\n\\n /// @dev Find all registries in the ancestry of `name`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return registries Array of registries in label-order.\\n function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry[] memory registries)\\n {\\n registries = new IRegistry[](1 + NameCoder.countLabels(name, offset));\\n registries[registries.length - 1] = rootRegistry;\\n _findRegistries(name, offset, registries, 0);\\n }\\n\\n /// @dev Recursive function for building ancestry.\\n function _findRegistries(\\n bytes memory name,\\n uint256 offset,\\n IRegistry[] memory registries,\\n uint256 index\\n )\\n private\\n view\\n returns (IRegistry registry)\\n {\\n (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset);\\n if (bytes(label).length == 0) {\\n return registries[registries.length - 1];\\n }\\n registry = _findRegistries(name, nextOffset, registries, index + 1);\\n if (address(registry) != address(0)) {\\n registry = registry.getSubregistry(label);\\n registries[index] = registry;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0b5f34bcc76ee3e49d300444fbcbe1ed152faee49a91c87eaea5f6d61ce6fb0b\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 3977, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "recordVersions", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_bytes32,t_uint64)" + }, + { + "astId": 4077, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_abis", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage)))" + }, + { + "astId": 4244, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_addresses", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage)))" + }, + { + "astId": 4486, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_hashes", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_bytes_storage))" + }, + { + "astId": 5045, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_dataStore", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_bytes_storage)))" + }, + { + "astId": 4576, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_zonehashes", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_bytes_storage))" + }, + { + "astId": 4586, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_records", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage))))" + }, + { + "astId": 4594, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_nameEntriesCount", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes32,t_uint16)))" + }, + { + "astId": 5487, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_interfaces", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes4,t_address)))" + }, + { + "astId": 5679, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_names", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_string_storage))" + }, + { + "astId": 5766, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_pubkeys", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_struct(PublicKey)5759_storage))" + }, + { + "astId": 5869, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "versionable_texts", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage)))" + }, + { + "astId": 31634, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "_operatorApprovals", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 31643, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "_tokenApprovals", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_mapping(t_address,t_bool)))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_mapping(t_bytes32,t_mapping(t_address,t_bool)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(bytes32 => mapping(address => bool)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))" + }, + "t_mapping(t_bytes32,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_bytes32,t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage)))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(bytes32 => mapping(uint16 => bytes)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage))" + }, + "t_mapping(t_bytes32,t_mapping(t_bytes32,t_uint16))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(bytes32 => uint16))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_uint16)" + }, + "t_mapping(t_bytes32,t_mapping(t_bytes4,t_address))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(bytes4 => address))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes4,t_address)" + }, + "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_bytes_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(string => bytes))", + "numberOfBytes": "32", + "value": "t_mapping(t_string_memory_ptr,t_bytes_storage)" + }, + "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(string => string))", + "numberOfBytes": "32", + "value": "t_mapping(t_string_memory_ptr,t_string_storage)" + }, + "t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(uint16 => bytes))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint16,t_bytes_storage)" + }, + "t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(uint256 => bytes))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_bytes_storage)" + }, + "t_mapping(t_bytes32,t_string_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_bytes32,t_struct(PublicKey)5759_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct PubkeyResolver.PublicKey)", + "numberOfBytes": "32", + "value": "t_struct(PublicKey)5759_storage" + }, + "t_mapping(t_bytes32,t_uint16)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint16)", + "numberOfBytes": "32", + "value": "t_uint16" + }, + "t_mapping(t_bytes32,t_uint64)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint64)", + "numberOfBytes": "32", + "value": "t_uint64" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_string_memory_ptr,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_string_memory_ptr,t_string_storage)": { + "encoding": "mapping", + "key": "t_string_memory_ptr", + "label": "mapping(string => string)", + "numberOfBytes": "32", + "value": "t_string_storage" + }, + "t_mapping(t_uint16,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_uint16", + "label": "mapping(uint16 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_uint256,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_bytes_storage))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => bytes))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_bytes_storage)" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage))))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(bytes32 => mapping(uint16 => bytes))))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_bytes32,t_mapping(t_uint16,t_bytes_storage)))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes32,t_uint16)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(bytes32 => uint16)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_bytes32,t_uint16))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_bytes4,t_address)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(bytes4 => address)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_bytes4,t_address))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_bytes_storage)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(string => bytes)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_bytes_storage))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(string => string)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_string_memory_ptr,t_string_storage))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage)))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => mapping(uint256 => bytes)))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_mapping(t_uint256,t_bytes_storage))" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_string_storage))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => string))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_string_storage)" + }, + "t_mapping(t_uint64,t_mapping(t_bytes32,t_struct(PublicKey)5759_storage))": { + "encoding": "mapping", + "key": "t_uint64", + "label": "mapping(uint64 => mapping(bytes32 => struct PubkeyResolver.PublicKey))", + "numberOfBytes": "32", + "value": "t_mapping(t_bytes32,t_struct(PublicKey)5759_storage)" + }, + "t_string_memory_ptr": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(PublicKey)5759_storage": { + "encoding": "inplace", + "label": "struct PubkeyResolver.PublicKey", + "members": [ + { + "astId": 5756, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "x", + "offset": 0, + "slot": "0", + "type": "t_bytes32" + }, + { + "astId": 5758, + "contract": "project/src/resolver/PublicResolverV2.sol:PublicResolverV2", + "label": "y", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "encoding": "inplace", + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "InvalidEVMAddress(bytes)": [ + { + "notice": "The supplied address could not be converted to `address`." + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "notice": "An operator is added or removed." + }, + "Approved(address,bytes32,address,bool)": { + "notice": "A delegate is approved or an approval is revoked." + }, + "DataChanged(bytes32,string,string,bytes)": { + "notice": "For a specific `node`, the data associated with a `key` has changed." + } + }, + "kind": "user", + "methods": { + "ABI(bytes32,uint256)": { + "notice": "Returns the ABI associated with an ENS node. Defined in EIP205." + }, + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract." + }, + "ROOT_REGISTRY()": { + "notice": "The ENSv2 Root Registry contract." + }, + "addr(bytes32)": { + "notice": "Get `addr(60)` as `address` of the associated ENS node." + }, + "addr(bytes32,uint256)": { + "notice": "Get the address for coin type of the associated ENS node. If coin type is EVM and empty, defaults to `addr(COIN_TYPE_DEFAULT)`." + }, + "approve(bytes32,address,bool)": { + "notice": "Grant or revoke `delegate` approval on a specific node." + }, + "canModifyName(bytes32,address)": { + "notice": "Determine if `operator` is authorized for `node`." + }, + "clearRecords(bytes32)": { + "notice": "Increments the record version associated with an ENS node. May only be called by the owner of that node in the ENS registry." + }, + "contenthash(bytes32)": { + "notice": "Returns the contenthash associated with an ENS node." + }, + "data(bytes32,string)": { + "notice": "For a specific `node`, get the data associated with the key, `key`." + }, + "dnsRecord(bytes32,bytes32,uint16)": { + "notice": "Obtain a DNS record." + }, + "hasAddr(bytes32,uint256)": { + "notice": "Determine if an addresss is stored for the coin type of the associated ENS node." + }, + "hasDNSRecords(bytes32,bytes32)": { + "notice": "Check if a given node has records." + }, + "interfaceImplementer(bytes32,bytes4)": { + "notice": "Returns the address of a contract that implements the specified interface for this name. If an implementer has not been set for this interfaceID and name, the resolver will query the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that contract implements EIP165 and returns `true` for the specified interfaceID, its address will be returned." + }, + "isApprovedFor(address,bytes32,address)": { + "notice": "Check to see if the delegate has been approved by the owner for the node." + }, + "isApprovedForAll(address,address)": { + "notice": "Check if `operator` is approved for all nodes owned by `account`." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "name(bytes32)": { + "notice": "Returns the name associated with an ENS node, for reverse records. Defined in EIP181." + }, + "pubkey(bytes32)": { + "notice": "Returns the SECP256k1 public key associated with an ENS node. Defined in EIP 619." + }, + "setABI(bytes32,uint256,bytes)": { + "notice": "Sets the ABI associated with an ENS node. Nodes may have one ABI of each content type. To remove an ABI, set it to the empty string." + }, + "setAddr(bytes32,address)": { + "notice": "Set `addr(60)` of the associated ENS node. `address(0)` is stored as `new bytes(20)`." + }, + "setAddr(bytes32,uint256,bytes)": { + "notice": "Set the address for coin type of the associated ENS node. Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes." + }, + "setApprovalForAll(address,bool)": { + "notice": "Grant or revoke `operator` approval." + }, + "setContenthash(bytes32,bytes)": { + "notice": "Sets the contenthash associated with an ENS node. May only be called by the owner of that node in the ENS registry." + }, + "setDNSRecords(bytes32,bytes)": { + "notice": "Set one or more DNS records. Records are supplied in wire-format. Records with the same node/name/resource must be supplied one after the other to ensure the data is updated correctly. For example, if the data was supplied: a.example.com IN A 1.2.3.4 a.example.com IN A 5.6.7.8 www.example.com IN CNAME a.example.com. then this would store the two A records for a.example.com correctly as a single RRSET, however if the data was supplied: a.example.com IN A 1.2.3.4 www.example.com IN CNAME a.example.com. a.example.com IN A 5.6.7.8 then this would store the first A record, the CNAME, then the second A record which would overwrite the first." + }, + "setData(bytes32,string,bytes)": { + "notice": "Sets the data associated with the key, `key` for a specific `node`. May only be called by the owner of that node in the ENS registry." + }, + "setInterface(bytes32,bytes4,address)": { + "notice": "Sets an interface associated with a name. Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support." + }, + "setName(bytes32,string)": { + "notice": "Sets the name associated with an ENS node, for reverse records. May only be called by the owner of that node in the ENS registry." + }, + "setPubkey(bytes32,bytes32,bytes32)": { + "notice": "Sets the SECP256k1 public key associated with an ENS node." + }, + "setText(bytes32,string,string)": { + "notice": "Sets the text data associated with an ENS node and key. May only be called by the owner of that node in the ENS registry." + }, + "setZonehash(bytes32,bytes)": { + "notice": "setZonehash sets the hash for the zone. May only be called by the owner of that node in the ENS registry." + }, + "text(bytes32,string)": { + "notice": "Returns the text data associated with an ENS node and key." + }, + "zonehash(bytes32)": { + "notice": "zonehash obtains the hash for the zone." + } + }, + "notice": "PublicResolver that respects the ENSv2 registry.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce800000000000000000000000011b5bfbe9078d826b1edbdd1cfc12f5828d9f50c00000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0x51d1113cd86bf996b259661a931eb9c092c400d5434d289ff1a18b94a2a9d72e", + "nonce": "0x5d", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x70322a6ade44555128ae0c20502a305b8a9fce58475fe598790e8f6a4d063bfe", + "blockNumber": "0xaa5711", + "transactionIndex": "0x74" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/ReverseRegistrarAdapter.json b/contracts/deployments/sepolia/ReverseRegistrarAdapter.json new file mode 100644 index 000000000..30055b68d --- /dev/null +++ b/contracts/deployments/sepolia/ReverseRegistrarAdapter.json @@ -0,0 +1,241 @@ +{ + "address": "0x94e64e29e25533f93ba0a430646ae42cb47bf8f3", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IReverseRegistrar", + "name": "reverseRegistrar", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "UnauthorizedNamer", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REVERSE_REGISTRAR", + "outputs": [ + { + "internalType": "contract IReverseRegistrar", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "claim", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "ReverseRegistrarAdapter", + "sourceName": "src/reverse-registrar/ReverseRegistrarAdapter.sol", + "bytecode": "0x60c060405234801561000f575f80fd5b5060405161065538038061065583398101604081905261002e9161005c565b6001600160a01b039081166080521660a052610094565b6001600160a01b0381168114610059575f80fd5b50565b5f806040838503121561006d575f80fd5b825161007881610045565b602084015190925061008981610045565b809150509250929050565b60805160a0516105936100c25f395f818161010801526101fd01525f818160b6015261029001526105935ff3fe608060405234801561000f575f80fd5b5060043610610064575f3560e01c806348ee1bcc1161004d57806348ee1bcc146100b15780636f3ff726146100f0578063952899fc14610103575f80fd5b806301ffc9a71461006857806321c0b34214610090575b5f80fd5b61007b610076366004610464565b61012a565b60405190151581526020015b60405180910390f35b6100a361009e3660046104ba565b6101a9565b604051908152602001610087565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610087565b61007b6100fe3660046104f1565b61026f565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b5f7fffffffff00000000000000000000000000000000000000000000000000000000821663379ffb9360e11b14806101a357507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b5f336101b584826102fb565b6040517f656696310000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152828116602483015284811660448301527f000000000000000000000000000000000000000000000000000000000000000016906365669631906064016020604051808303815f875af1158015610243573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610267919061050c565b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa1580156102d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101a39190610523565b610305828261034e565b61034a576040517f0d1b7e4e0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260240160405180910390fd5b5050565b6001600160a01b038281169082161480158161037357505f836001600160a01b03163b115b156101a357826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156103d2575060408051601f3d908101601f191682019092526103cf91810190610542565b60015b156103f057826001600160a01b0316816001600160a01b0316149150505b806101a35760405163379ffb9360e11b81526001600160a01b038381166004830152841690636f3ff72690602401602060405180830381865afa925050508015610457575060408051601f3d908101601f1916820190925261045491810190610523565b60015b156101a3575b9392505050565b5f60208284031215610474575f80fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461045d575f80fd5b6001600160a01b03811681146104b7575f80fd5b50565b5f80604083850312156104cb575f80fd5b82356104d6816104a3565b915060208301356104e6816104a3565b809150509250929050565b5f60208284031215610501575f80fd5b813561045d816104a3565b5f6020828403121561051c575f80fd5b5051919050565b5f60208284031215610533575f80fd5b8151801515811461045d575f80fd5b5f60208284031215610552575f80fd5b815161045d816104a356fea264697066735822122023267b68b545ce6ed9a8cd5c201137adc025426647191e16c4781b6340aa8fe664736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610064575f3560e01c806348ee1bcc1161004d57806348ee1bcc146100b15780636f3ff726146100f0578063952899fc14610103575f80fd5b806301ffc9a71461006857806321c0b34214610090575b5f80fd5b61007b610076366004610464565b61012a565b60405190151581526020015b60405180910390f35b6100a361009e3660046104ba565b6101a9565b604051908152602001610087565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610087565b61007b6100fe3660046104f1565b61026f565b6100d87f000000000000000000000000000000000000000000000000000000000000000081565b5f7fffffffff00000000000000000000000000000000000000000000000000000000821663379ffb9360e11b14806101a357507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b5f336101b584826102fb565b6040517f656696310000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152828116602483015284811660448301527f000000000000000000000000000000000000000000000000000000000000000016906365669631906064016020604051808303815f875af1158015610243573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610267919061050c565b949350505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa1580156102d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101a39190610523565b610305828261034e565b61034a576040517f0d1b7e4e0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260240160405180910390fd5b5050565b6001600160a01b038281169082161480158161037357505f836001600160a01b03163b115b156101a357826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156103d2575060408051601f3d908101601f191682019092526103cf91810190610542565b60015b156103f057826001600160a01b0316816001600160a01b0316149150505b806101a35760405163379ffb9360e11b81526001600160a01b038381166004830152841690636f3ff72690602401602060405180830381865afa925050508015610457575060408051601f3d908101601f1916820190925261045491810190610523565b60015b156101a3575b9392505050565b5f60208284031215610474575f80fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461045d575f80fd5b6001600160a01b03811681146104b7575f80fd5b50565b5f80604083850312156104cb575f80fd5b82356104d6816104a3565b915060208301356104e6816104a3565b809150509250929050565b5f60208284031215610501575f80fd5b813561045d816104a3565b5f6020828403121561051c575f80fd5b5051919050565b5f60208284031215610533575f80fd5b8151801515811461045d575f80fd5b5f60208284031215610552575f80fd5b815161045d816104a356fea264697066735822122023267b68b545ce6ed9a8cd5c201137adc025426647191e16c4781b6340aa8fe664736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "72818": [ + { + "length": 32, + "start": 264 + }, + { + "length": 32, + "start": 509 + } + ], + "75299": [ + { + "length": 32, + "start": 182 + }, + { + "length": 32, + "start": 656 + } + ] + }, + "inputSourceName": "project/src/reverse-registrar/ReverseRegistrarAdapter.sol", + "devdoc": { + "details": "The adapter must be configured as a controller on the reverse registrar.", + "errors": { + "UnauthorizedNamer(address)": [ + { + "details": "Error selector: `0x0d1b7e4e`" + } + ] + }, + "kind": "dev", + "methods": { + "claim(address,address)": { + "params": { + "account": "The account to claim.", + "resolver": "The resolver to set." + }, + "returns": { + "_0": "The ENS node hash for the contract's reverse record." + } + }, + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "reverseRegistrar": "The v1 reverse registrar for `addr.reverse`." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "title": "Reverse Registrar Adapter", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "285400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "REVERSE_REGISTRAR()": "infinite", + "claim(address,address)": "infinite", + "isContractNamer(address)": "infinite", + "supportsInterface(bytes4)": "373" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IReverseRegistrar\",\"name\":\"reverseRegistrar\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"UnauthorizedNamer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"REVERSE_REGISTRAR\",\"outputs\":[{\"internalType\":\"contract IReverseRegistrar\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"claim\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"The adapter must be configured as a controller on the reverse registrar.\",\"errors\":{\"UnauthorizedNamer(address)\":[{\"details\":\"Error selector: `0x0d1b7e4e`\"}]},\"kind\":\"dev\",\"methods\":{\"claim(address,address)\":{\"params\":{\"account\":\"The account to claim.\",\"resolver\":\"The resolver to set.\"},\"returns\":{\"_0\":\"The ENS node hash for the contract's reverse record.\"}},\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"reverseRegistrar\":\"The v1 reverse registrar for `addr.reverse`.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"title\":\"Reverse Registrar Adapter\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"REVERSE_REGISTRAR()\":{\"notice\":\"The v1 reverse registrar for `addr.reverse`.\"},\"claim(address,address)\":{\"notice\":\"Claims account's `addr.reverse` node and sets its resolver.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"}},\"notice\":\"Forwarder for v1 `addr.reverse` registrar updates.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/reverse-registrar/ReverseRegistrarAdapter.sol\":\"ReverseRegistrarAdapter\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/reverseRegistrar/IReverseRegistrar.sol\":{\"content\":\"pragma solidity >=0.8.4;\\n\\ninterface IReverseRegistrar {\\n function setDefaultResolver(address resolver) external;\\n\\n function claim(address owner) external returns (bytes32);\\n\\n function claimForAddr(\\n address addr,\\n address owner,\\n address resolver\\n ) external returns (bytes32);\\n\\n function claimWithResolver(\\n address owner,\\n address resolver\\n ) external returns (bytes32);\\n\\n function setName(string memory name) external returns (bytes32);\\n\\n function setNameForAddr(\\n address addr,\\n address owner,\\n address resolver,\\n string memory name\\n ) external returns (bytes32);\\n\\n function node(address addr) external pure returns (bytes32);\\n}\\n\",\"keccak256\":\"0x83adfcf6da72b1bcd1e3ac387afe5fc7fdf7f2ac28b7601544d2ca4b9d45d159\"},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/reverse-registrar/ReverseRegistrarAdapter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.25;\\n\\nimport {IReverseRegistrar} from \\\"@ens/contracts/reverseRegistrar/IReverseRegistrar.sol\\\";\\n\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {IContractNamer} from \\\"./interfaces/IContractNamer.sol\\\";\\nimport {AccountNamerLib} from \\\"./libraries/AccountNamerLib.sol\\\";\\n\\n/// @title Reverse Registrar Adapter\\n/// @notice Forwarder for v1 `addr.reverse` registrar updates.\\n/// @dev The adapter must be configured as a controller on the reverse registrar.\\ncontract ReverseRegistrarAdapter is DelegatedContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The v1 reverse registrar for `addr.reverse`.\\n IReverseRegistrar public immutable REVERSE_REGISTRAR;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param reverseRegistrar The v1 reverse registrar for `addr.reverse`.\\n /// @param contractNamer Delegated contract namer.\\n constructor(IReverseRegistrar reverseRegistrar, IContractNamer contractNamer)\\n DelegatedContractNamer(contractNamer)\\n {\\n REVERSE_REGISTRAR = reverseRegistrar;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Claims account's `addr.reverse` node and sets its resolver.\\n /// @param account The account to claim.\\n /// @param resolver The resolver to set.\\n /// @return The ENS node hash for the contract's reverse record.\\n function claim(address account, address resolver) external returns (bytes32) {\\n address sender = msg.sender;\\n AccountNamerLib.requireNamer(account, sender);\\n return REVERSE_REGISTRAR.claimForAddr(account, sender, resolver);\\n }\\n}\\n\",\"keccak256\":\"0x8177759023568cf04912972a4ea4493a63e9b8b93ffbe6b3fb7eaddc60ea360e\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/reverse-registrar/libraries/AccountNamerLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport {IContractNamer} from \\\"../interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Determine if an address is nameable. \\nlibrary AccountNamerLib {\\n /// @dev Error selector: `0x0d1b7e4e`\\n error UnauthorizedNamer(address namer);\\n\\n /// @dev Check if an address can be named.\\n /// @param account The address to name.\\n /// @param namer The address of the namer.\\n /// @return canName `true` if `namer` can name `addr`.\\n function isNamer(address account, address namer) internal view returns (bool canName) {\\n canName = account == namer;\\n if (!canName && account.code.length > 0) {\\n try Ownable(account).owner() returns (address owner) {\\n canName = owner == namer;\\n } catch {}\\n if (!canName) {\\n try IContractNamer(account).isContractNamer(namer) returns (bool can) {\\n canName = can;\\n } catch {}\\n }\\n }\\n }\\n\\n /// @dev Ensure `namer` can name `account`.\\n /// @param account The address to name.\\n /// @param namer The address of the namer.\\n function requireNamer(address account, address namer) internal view {\\n if (!isNamer(account, namer)) {\\n revert UnauthorizedNamer(namer);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1a2e3cd6439f69053d2de151e240f34b12f6594920f9de0fe888653e01fe0d03\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "REVERSE_REGISTRAR()": { + "notice": "The v1 reverse registrar for `addr.reverse`." + }, + "claim(address,address)": { + "notice": "Claims account's `addr.reverse` node and sets its resolver." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + } + }, + "notice": "Forwarder for v1 `addr.reverse` registrar updates.", + "version": 1 + }, + "argsData": "0x000000000000000000000000a0a1abcdae1a2a4a2ef8e9113ff0e02dd81dc0c600000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0x37d44cf978ae98c5bc54adf15b176b2e5d1e2ee12c4f9a74bc1314ef47eaadfb", + "nonce": "0x53", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x1e70254e49a94437c7fa41944304bfdf0f5ae8a51a974aa028a9cc3cca678fc4", + "blockNumber": "0xaa5707", + "transactionIndex": "0x87" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/RootRegistry.json b/contracts/deployments/sepolia/RootRegistry.json new file mode 100644 index 000000000..703c52cc9 --- /dev/null +++ b/contracts/deployments/sepolia/RootRegistry.json @@ -0,0 +1,2795 @@ +{ + "address": "0x11b5bfbe9078d826b1edbdd1cfc12f5828d9f50c", + "abi": [ + { + "inputs": [ + { + "internalType": "contract ILabelStore", + "name": "labelStore", + "type": "address" + }, + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "oldExpiry", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "CannotReduceExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "CannotSetPastExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "LabelExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "TransferDisallowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExpiryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ParentUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RegistryCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ResolverUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SubregistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTokenId", + "type": "uint256" + } + ], + "name": "TokenRegenerated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "TokenResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "renderer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "URIUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "LABEL_STORE", + "outputs": [ + { + "internalType": "contract ILabelStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParent", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getResource", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "internalType": "address", + "name": "latestOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "internalType": "struct IPermissionedRegistry.State", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getStatus", + "outputs": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getSubregistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "latestOwnerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setParent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "setSubregistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + }, + { + "internalType": "contract IRegistryURIRenderer", + "name": "renderer", + "type": "address" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "PermissionedRegistry", + "sourceName": "src/registry/PermissionedRegistry.sol", + "bytecode": "0x60a060405234801561000f575f80fd5b5060405161490d38038061490d83398101604081905261002e91610d06565b6040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16001600160a01b03831660805261006f5f828482610078565b50505050610f37565b5f835f0361008757505f610182565b6100908461018a565b6001600160a01b0383166100b75760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461017c575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616610117888260016101d6565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561017057610170888785858b610306565b60019350505050610182565b5f925050505b949350505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8116156101d357604051630153d96960e51b8152600481018290526024015b60405180910390fd5b50565b5f6101e083610316565b90508115610276575f848152600360205260409020546102269082161980195f805160206148ed83398151915291909101165f805160206148cd83398151915216151590565b1561024e57604051631f22ca6960e31b815260048101859052602481018490526044016101ca565b5f848152600360205260408120805485929061026b908490610d5a565b909155506103009050565b5f848152600360205260409020546102b5901982161980195f805160206148ed83398151915291909101165f805160206148cd83398151915216151590565b156102dd57604051631f80c19b60e01b815260048101859052602481018490526044016101ca565b5f84815260036020526040812080548592906102fa908490610d6d565b90915550505b50505050565b61030f85610330565b5050505050565b5f6103208261018a565b50600181901b17600281901b1790565b80156101d35763ffffffff811681185f9081526101086020526040812090610358838361041c565b5f818152602081905260409020549091506001600160a01b031661037e8183600161043f565b8254839060049061039c90640100000000900463ffffffff16610d80565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6103cb838561041c60201b60201c565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a361030f8282600160405180602001604052805f8152506104a660201b60201c565b80545f9063ffffffff808516851864010000000090920416185b90505b92915050565b6001600160a01b03831661046757604051626a0d4560e21b81525f60048201526024016101ca565b604080516001808252602082018590528183019081526060820184905260a082019092525f6080820181815291929161030f918791859085908361051b565b6001600160a01b0384166104cf57604051632bfa23e760e11b81525f60048201526024016101ca565b604080516001808252602082018690528183019081526060820185905260808201909252906105025f878484878461051b565b505050505050565b63ffffffff82811690921891161890565b61052786868686610571565b6001600160a01b0385161561050257801561054f5761054a33878787878761064c565b610502565b60208481015190840151610567338989858589610776565b5050505050505050565b61057d8484848461085d565b6001600160a01b0383161580159061059d57506001600160a01b03841615155b15610300575f5b825181101561030f575f8382815181106105c0576105c0610da2565b602002602001015190506105df816001609c1b88610a4360201b60201c565b61060e576040516372c7b6ad60e11b8152600481018290526001600160a01b03871660248201526044016101ca565b5f83838151811061062157610621610da2565b602002602001015111156106435761064361063b82610a57565b87875f610a7e565b506001016105a4565b6001600160a01b0384163b156105025760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906106909089908990889088908890600401610e1e565b6020604051808303815f875af19250505080156106ca575060408051601f3d908101601f191682019092526106c791810190610e7b565b60015b610731573d8080156106f7576040519150601f19603f3d011682016040523d82523d5f602084013e6106fc565b606091505b5080515f0361072957604051632bfa23e760e11b81526001600160a01b03861660048201526024016101ca565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461076d57604051632bfa23e760e11b81526001600160a01b03861660048201526024016101ca565b50505050505050565b6001600160a01b0384163b156105025760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906107ba9089908990889088908890600401610ea9565b6020604051808303815f875af19250505080156107f4575060408051601f3d908101601f191682019092526107f191810190610e7b565b60015b610821573d8080156106f7576040519150601f19603f3d011682016040523d82523d5f602084013e6106fc565b6001600160e01b0319811663f23a6e6160e01b1461076d57604051632bfa23e760e11b81526001600160a01b03861660048201526024016101ca565b805182511461088c5781518151604051635b05999160e01b8152600481019290925260248201526044016101ca565b5f5b825181101561097d576020818102848101820151908401909101518015610973575f828152602081905260409020546001600160a01b039081169088168114610909576040516303dee4c560e01b81526001600160a01b03891660048201525f602482015260448101839052606481018490526084016101ca565b600182111561094b576040516303dee4c560e01b81526001600160a01b03891660048201526001602482015260448101839052606481018490526084016101ca565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0388161790555b505060010161088e565b5081516001036109e6576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050610300565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051610a35929190610eed565b60405180910390a450505050565b5f610182610a5085610a57565b8484610abf565b5f61043982610a798163ffffffff8116185f9081526101086020526040902090565b610ad6565b5f8481526002602090815260408083206001600160a01b0387168452909152902054801561030f57610ab285828685610b24565b5061050285828585610078565b5f8280610acc8685610b90565b1614949350505050565b5f82610ae3575081610439565b60018201546104369084906001600160401b0316421015610b1157835463ffffffff82811690921891161890565b835461050a9063ffffffff166001610f1a565b5f610b2e8461018a565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461017c575f8781526002602090815260408083206001600160a01b038916845290915281208290558683169061011790899083906101d6565b5f610b9b8383610bad565b610ba55f84610bad565b179392505050565b5f8281526002602090815260408083206001600160a01b03851684529091529020548215610439575f610bdf84610c6e565b90506001600160a01b03811615801590610c0b5750826001600160a01b0316816001600160a01b031614155b8015610c3b57506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b15610c67575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b63ffffffff811681185f90815261010860205260408120600101546001600160401b0316421015610cc457610cbf610ca583610ccb565b5f908152602081905260409020546001600160a01b031690565b610439565b5f92915050565b5f61043982610ced8163ffffffff8116185f9081526101086020526040902090565b61041c565b6001600160a01b03811681146101d3575f80fd5b5f805f60608486031215610d18575f80fd5b8351610d2381610cf2565b6020850151909350610d3481610cf2565b80925050604084015190509250925092565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561043957610439610d46565b8181038181111561043957610439610d46565b5f63ffffffff808316818103610d9857610d98610d46565b6001019392505050565b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b83811015610de557815187529582019590820190600101610dc9565b509495945050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0386811682528516602082015260a0604082018190525f90610e4990830186610db6565b8281036060840152610e5b8186610db6565b90508281036080840152610e6f8185610df0565b98975050505050505050565b5f60208284031215610e8b575f80fd5b81516001600160e01b031981168114610ea2575f80fd5b9392505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f90610ee290830184610df0565b979650505050505050565b604081525f610eff6040830185610db6565b8281036020840152610f118185610db6565b95945050505050565b63ffffffff818116838216019080821115610c6757610c67610d46565b608051613977610f565f395f81816105c70152611b0901526139775ff3fe608060405234801561000f575f80fd5b50600436106102cc575f3560e01c80636352211e1161017c578063a02b161e116100dd578063ce156e8211610093578063e4ae7d771161006e578063e4ae7d7714610681578063e985e9c514610694578063f242432a146106cf575f80fd5b8063ce156e8214610648578063d3bf89b11461065b578063dfa70d8b1461066e575f80fd5b8063bc7b6d62116100c3578063bc7b6d621461060f578063bd242bcb14610622578063c41a360a14610635575f80fd5b8063a02b161e146105e9578063a22cb465146105fc575f80fd5b80637c3005861161013257806385f3e6431161011857806385f3e6431461059c57806391b3c037146105af5780639dbba19d146105c2575f80fd5b80637c3005861461057357806380f7602114610586575f80fd5b80636f3ff726116101625780636f3ff7261461053a5780636f537c721461054d578063781ef8db14610560575f80fd5b80636352211e1461051457806363560a8e14610527575f80fd5b80632f27fa241161023157806348688f95116101e75780635569f33d116101c25780635569f33d146104ce5780635adf4724146104e15780635c622a0e146104f4575f80fd5b806348688f95146104885780634e1273f41461049b5780635357263f146104bb575f80fd5b806335af62161161021757806335af6216146104155780633634f9111461044057806344c9af2814610468575f80fd5b80632f27fa24146103ef578063341ec55914610402575f80fd5b806313c72608116102865780631c3fc3eb1161026c5780631c3fc3eb146103c05780631e8fca2d146103c75780632eb2c2d6146103da575f80fd5b806313c726081461035f57806314ff5ea3146103ad575f80fd5b8063072d5d77116102b6578063072d5d77146103195780630e89341c1461032c57806311b8e00a1461034c575f80fd5b8062fdd58e146102d057806301ffc9a7146102f6575b5f80fd5b6102e36102de366004612d2c565b6106e2565b6040519081526020015b60405180910390f35b610309610304366004612d6b565b61072d565b60405190151581526020016102ed565b610309610327366004612d86565b6108a2565b61033f61033a366004612db4565b6108c6565b6040516102ed9190612df9565b61030961035a366004612e0b565b6109f6565b61039461036d366004612db4565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016102ed565b6102e36103bb366004612db4565b610a10565b6102e35f81565b6102e36103d5366004612db4565b610a37565b6103ed6103e8366004612f73565b610a5e565b005b6102e36103fd366004612db4565b610a7c565b6103ed610410366004612d86565b610a9a565b610428610423366004613058565b610b22565b6040516001600160a01b0390911681526020016102ed565b61045361044e366004612e0b565b610bbd565b604080519283526020830191909152016102ed565b61047b610476366004612db4565b610bdd565b6040516102ed91906130cb565b6103ed61049636600461311e565b610caf565b6104ae6104a9366004613171565b610d3c565b6040516102ed9190613267565b6103ed6104c9366004613279565b610e0c565b6103ed6104dc3660046132d8565b610ea1565b6102e36104ef366004612d86565b610fef565b610507610502366004612db4565b611002565b6040516102ed9190613302565b610428610522366004612db4565b611058565b610428610535366004613058565b6110bd565b610309610548366004613310565b6110ff565b61039461055b366004613058565b61111a565b61030961056e366004612d86565b61115c565b61030961058136600461332b565b611172565b61058e611186565b6040516102ed929190613356565b6102e36105aa366004613377565b611231565b6102e36105bd366004613058565b61124d565b6104287f000000000000000000000000000000000000000000000000000000000000000081565b6103ed6105f7366004612db4565b61128f565b6103ed61060a366004613400565b61138b565b6103ed61061d366004612d86565b61139a565b610428610630366004612db4565b611428565b610428610643366004612db4565b611444565b610309610656366004612d86565b611488565b61030961066936600461332b565b6114a3565b61030961067c36600461332b565b6114b7565b61042861068f366004613058565b6114cb565b6103096106a2366004613430565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6103ed6106dd36600461345c565b611546565b5f6001600160a01b038316158015906107145750826001600160a01b031661070983611058565b6001600160a01b0316145b61071e575f610721565b60015b60ff1690505b92915050565b5f6001600160e01b031982167f6be50c6900000000000000000000000000000000000000000000000000000000148061078f57506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b806107c357506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b806107f757506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b8061082b57506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b8061085f57506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b8061089357506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061072757506107278261155d565b5f80836108b082823361159a565b6108bd5f868660016115e8565b95945050505050565b610107546060906001600160a01b03166109695761010680546108e8906134c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610914906134c0565b801561095f5780601f106109365761010080835404028352916020019161095f565b820191905f5260205f20905b81548152906001019060200180831161094257829003601f168201915b5050505050610727565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa1580156109cf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261072791908101906134f8565b5f610a09610a0384610a37565b83611711565b9392505050565b5f61072782610a328463ffffffff8116185f9081526101086020526040902090565b611728565b5f61072782610a598463ffffffff8116185f9081526101086020526040902090565b611746565b610a6885336117a0565b610a758585858585611831565b5050505050565b5f610727610a8983610a37565b5f9081526003602052604090205490565b5f80610aa98462100000611891565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038716908102919091178255604051929450909250339184907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a450505050565b5f80610b7e610b6585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610bb35780546801000000000000000090046001600160a01b0316610bb5565b5f5b949350505050565b5f80610bd1610bcb85610a37565b84611905565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610c3b8584611728565b606085018190529050610c4e8584611746565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610c7c8382611928565b85906002811115610c8f57610c8f613097565b90816002811115610ca257610ca2613097565b8152505050505050919050565b641000000000610cc05f823361195f565b610106610cce8486836135b1565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905560405133907fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd590610d2e9087908790879061366b565b60405180910390a250505050565b60608151835114610d725781518351604051635b05999160e01b8152600481019290925260248201526044015b60405180910390fd5b5f835167ffffffffffffffff811115610d8d57610d8d612e2b565b604051908082528060200260200182016040528015610db6578160200160208202803683370190505b5090505f5b8451811015610e0457602080820286010151610ddf906020808402870101516106e2565b828281518110610df157610df16136ab565b6020908102919091010152600101610dbb565b509392505050565b610100610e1a5f823361195f565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105610e5083826136bf565b50336001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff484604051610e949190612df9565b60405180910390a3505050565b63ffffffff821682185f9081526101086020526040812090610ec38483611728565b600183015490915067ffffffffffffffff16428111610f205767ffffffffffffffff81161580610efa5750610ef882336119be565b155b15610f1b5760405163311388dd60e21b815260048101839052602401610d69565b610f37565b610f37610f2d8685611746565b620100003361195f565b8067ffffffffffffffff168467ffffffffffffffff161015610f99576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015285166024820152604401610d69565b60018301805467ffffffffffffffff191667ffffffffffffffff861690811790915560405133919084907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a45050505050565b5f610a09610ffc84610a37565b836119cc565b63ffffffff811681185f908152610108602052604081206001810154610a099067ffffffffffffffff166110536110398685611728565b5f908152602081905260409020546001600160a01b031690565b611928565b63ffffffff811681185f908152610108602052604081206110798382611728565b831415806110955750600181015467ffffffffffffffff164210155b6110b5575f838152602081905260409020546001600160a01b0316610a09565b5f9392505050565b5f610a0961064384848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f6107276f010000000000000000000000000000008361115c565b5f610a0961036d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f82836111695f856119d3565b16149392505050565b5f610bb561117f85610a37565b8484611a94565b6101045461010580545f926060926001600160a01b039091169181906111ab906134c0565b80601f01602080910402602001604051908101604052809291908181526020018280546111d7906134c0565b80156112225780601f106111f957610100808354040283529160200191611222565b820191905f5260205f20905b81548152906001019060200180831161120557829003601f168201915b50505050509050915091509091565b5f6112428787878787876001611ad7565b979650505050505050565b5f610a096103bb84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f8061129d83611000611891565b6040519193509150339083907f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea8905f90a35f828152602081905260409020546001600160a01b03168015611368576112f78184600161200d565b815482905f9061130c9063ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166113499061378f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b611396338383612074565b5050565b5f806113aa846301000000611891565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b03881690810291909117909155604051929450909250339184907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a450505050565b5f818152602081905260408120546001600160a01b0316610727565b63ffffffff811681185f908152610108602052604081206001015467ffffffffffffffff164210156114815761147c61103983610a10565b610727565b5f92915050565b5f808361149682823361211a565b6108bd5f8686600161217b565b5f610bb56114b085610a37565b84846121e7565b5f610bb56114c485610a37565b84846121fe565b5f8061150e610b6585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b600181015490915067ffffffffffffffff16421015610bb35760018101546801000000000000000090046001600160a01b0316610bb5565b61155085336117a0565b610a758585858585612237565b5f6001600160e01b031982167f8f452d620000000000000000000000000000000000000000000000000000000014806107275750610727826122c4565b5f6115a58483612392565b905080198316156115e25760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610d69565b50505050565b5f835f036115f757505f610bb5565b611600846123db565b6001600160a01b038316611640576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611705575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166116a08882600161243b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a384156116f9576116f9888785858b6125d0565b60019350505050610bb5565b505f9695505050505050565b5f8061171d8484610bbd565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610a09565b5f82611753575081610727565b6001820154610a0990849067ffffffffffffffff1642101561177c57835463ffffffff1661178f565b835461178f9063ffffffff1660016137b1565b63ffffffff82811690921891161890565b806001600160a01b0316826001600160a01b0316141580156117e757506001600160a01b038083165f9081526001602090815260408083209385168352929052205460ff16155b15611396576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b03808316600483015283166024820152604401610d69565b6001600160a01b03841661185a57604051632bfa23e760e11b81525f6004820152602401610d69565b6001600160a01b03851661188257604051626a0d4560e21b81525f6004820152602401610d69565b610a75858585858560016125d9565b63ffffffff821682185f908152610108602052604081206118b28482611728565b600182015490925067ffffffffffffffff1642106118e65760405163311388dd60e21b815260048101839052602401610d69565b610bd66118f38583611746565b843361195f565b805160209091012090565b5f8061191083612630565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff8316421061194157505f610727565b6001600160a01b03821661195757506001610727565b506002610727565b61196a8383836114a3565b6119b9576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610d69565b505050565b5f610a09620100008361115c565b5f610a0983835b5f8281526002602090815260408083206001600160a01b03851684529091529020548215610727575f611a0584611444565b90506001600160a01b03811615801590611a315750826001600160a01b0316816001600160a01b031614155b8015611a6157506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b15611a8d575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b5f8383611aa282823361159a565b85611ac057604051631850848b60e31b815260040160405180910390fd5b611acd86868660016115e8565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990611b3e908b90600401612df9565b5f604051808303815f87803b158015611b55575f80fd5b505af1158015611b67573d5f803e3d5ffd5b5050895160208b012091505f9050611b928263ffffffff8116185f9081526101086020526040902090565b9050611b9e8282611728565b5f8181526020819052604090205460018301549194506001600160a01b03169067ffffffffffffffff164210611c28578415611be057611be05f60013361195f565b6001600160a01b038a16158015611bf657508615155b15611c235760405163d1a3b35560e01b81525f600482015260248101889052336044820152606401610d69565b611ced565b6001600160a01b03811615611c6b578a6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610d699190612df9565b6001600160a01b038a16611cad578a6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610d699190612df9565b8415611cbf57611cbf5f60103361195f565b8567ffffffffffffffff165f03611ce257600182015467ffffffffffffffff1695505b640100000000871796505b6001600160a01b038a1615611d0f5767ffffffffffffffff8616421015611d1c565b67ffffffffffffffff8616155b15611d5f576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602401610d69565b6001600160a01b03811615611df757611d7a8185600161200d565b815482905f90611d8f9063ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff16611dcc9061378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550611df48483611728565b93505b60018201805483546001600160a01b03808d16680100000000000000009081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921786558b81169091026001600160e01b031990921667ffffffffffffffff8a1617919091179091558a16611eb857336001600160a01b0316835f1b857f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88e8a604051611eab9291906137ce565b60405180910390a4611f71565b336001600160a01b0316835f1b857f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8e8e8b604051611ef9939291906137f9565b60405180910390a4611f1c8a85600160405180602001604052805f81525061264a565b5f611f278584611746565b905080611f3657611f36613834565b604051819086907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a3611f6e81898d5f6115e8565b50505b6001600160a01b03891615611fb85760405133906001600160a01b038b169086907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a45b6001600160a01b03881615611fff5760405133906001600160a01b038a169086907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a45b505050979650505050505050565b6001600160a01b03831661203557604051626a0d4560e21b81525f6004820152602401610d69565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291610a7591879185908590836125d9565b6001600160a01b0382166120b6576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610d69565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610e94565b5f61212584836126a6565b905080198316156115e2576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610d69565b5f612185846123db565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611705575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906116a0908990839061243b565b5f82836121f486856126e1565b1614949350505050565b5f838361220c82823361211a565b8561222a57604051631850848b60e31b815260040160405180910390fd5b611acd868686600161217b565b6001600160a01b03841661226057604051632bfa23e760e11b81525f6004820152602401610d69565b6001600160a01b03851661228857604051626a0d4560e21b81525f6004820152602401610d69565b604080516001808252602082018690528183019081526060820185905260808201909252906122bb87878484875f6125d9565b50505050505050565b5f6001600160e01b031982167fd9b67a2600000000000000000000000000000000000000000000000000000000148061232657506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b8061235a57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061072757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610727565b5f82158015906123b257505f6123a784611444565b6001600160a01b0316145b156123be57505f610727565b5f6123c984846126a6565b90508315610a0957608081901c610bb5565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612438576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610d69565b50565b5f61244583612630565b9050811561250e575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156124e6576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610d69565b5f8481526003602052604081208054859290612503908490613848565b909155506115e29050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156125a8576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610d69565b5f84815260036020526040812080548592906125c590849061385b565b909155505050505050565b610a75856126fe565b6125e5868686866127de565b6001600160a01b0385161561262857801561260d576126083387878787876128dc565b612628565b602084810151908401516126253389898585896129fd565b50505b505050505050565b5f61263a826123db565b50600181901b17600281901b1790565b6001600160a01b03841661267357604051632bfa23e760e11b81525f6004820152602401610d69565b604080516001808252602082018690528183019081526060820185905260808201909252906126285f87848487846125d9565b5f610a096126b484846126e1565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000811660809190911c1790565b5f6126ec83836119d3565b6126f65f846119d3565b179392505050565b80156124385763ffffffff811681185f90815261010860205260408120906127268383611728565b5f818152602081905260409020549091506001600160a01b031661274c8183600161200d565b8254839060049061276a90640100000000900463ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6127938385611728565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3610a758282600160405180602001604052805f81525061264a565b6127ea84848484612ae4565b6001600160a01b0383161580159061280a57506001600160a01b03841615155b156115e2575f5b8251811015610a75575f83828151811061282d5761282d6136ab565b6020026020010151905061285681731000000000000000000000000000000000000000886114a3565b61289e576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610d69565b5f8383815181106128b1576128b16136ab565b602002602001015111156128d3576128d36128cb82610a37565b87875f612cd7565b50600101612811565b6001600160a01b0384163b156126285760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612920908990899088908890889060040161386e565b6020604051808303815f875af192505050801561295a575060408051601f3d908101601f19168201909252612957918101906138cb565b60015b6129c1573d808015612987576040519150601f19603f3d011682016040523d82523d5f602084013e61298c565b606091505b5080515f036129b957604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b146122bb57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b6001600160a01b0384163b156126285760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612a4190899089908890889088906004016138e6565b6020604051808303815f875af1925050508015612a7b575060408051601f3d908101601f19168201909252612a78918101906138cb565b60015b612aa8573d808015612987576040519150601f19603f3d011682016040523d82523d5f602084013e61298c565b6001600160e01b0319811663f23a6e6160e01b146122bb57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b8051825114612b135781518151604051635b05999160e01b815260048101929092526024820152604401610d69565b5f5b8251811015612c11576020818102848101820151908401909101518015612c07575f828152602081905260409020546001600160a01b039081169088168114612b90576040516303dee4c560e01b81526001600160a01b03891660048201525f60248201526044810183905260648101849052608401610d69565b6001821115612bd2576040516303dee4c560e01b81526001600160a01b0389166004820152600160248201526044810183905260648101849052608401610d69565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388161790555b5050600101612b15565b508151600103612c7a576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450506115e2565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051612cc992919061391d565b60405180910390a450505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015610a7557612d0b8582868561217b565b50612628858285856115e8565b6001600160a01b0381168114612438575f80fd5b5f8060408385031215612d3d575f80fd5b8235612d4881612d18565b946020939093013593505050565b6001600160e01b031981168114612438575f80fd5b5f60208284031215612d7b575f80fd5b8135610a0981612d56565b5f8060408385031215612d97575f80fd5b823591506020830135612da981612d18565b809150509250929050565b5f60208284031215612dc4575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610a096020830184612dcb565b5f8060408385031215612e1c575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e6857612e68612e2b565b604052919050565b5f67ffffffffffffffff821115612e8957612e89612e2b565b5060051b60200190565b5f82601f830112612ea2575f80fd5b81356020612eb7612eb283612e70565b612e3f565b8083825260208201915060208460051b870101935086841115612ed8575f80fd5b602086015b84811015612ef45780358352918301918301612edd565b509695505050505050565b5f67ffffffffffffffff821115612f1857612f18612e2b565b50601f01601f191660200190565b5f82601f830112612f35575f80fd5b8135612f43612eb282612eff565b818152846020838601011115612f57575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a08688031215612f87575f80fd5b8535612f9281612d18565b94506020860135612fa281612d18565b9350604086013567ffffffffffffffff80821115612fbe575f80fd5b612fca89838a01612e93565b94506060880135915080821115612fdf575f80fd5b612feb89838a01612e93565b93506080880135915080821115613000575f80fd5b5061300d88828901612f26565b9150509295509295909350565b5f8083601f84011261302a575f80fd5b50813567ffffffffffffffff811115613041575f80fd5b602083019150836020828501011115610bd6575f80fd5b5f8060208385031215613069575f80fd5b823567ffffffffffffffff81111561307f575f80fd5b61308b8582860161301a565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600381106130c757634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506130dd8284516130ab565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f60408486031215613130575f80fd5b833567ffffffffffffffff811115613146575f80fd5b6131528682870161301a565b909450925050602084013561316681612d18565b809150509250925092565b5f8060408385031215613182575f80fd5b823567ffffffffffffffff80821115613199575f80fd5b818501915085601f8301126131ac575f80fd5b813560206131bc612eb283612e70565b82815260059290921b840181019181810190898411156131da575f80fd5b948201945b838610156132015785356131f281612d18565b825294820194908201906131df565b96505086013592505080821115613216575f80fd5b5061322385828601612e93565b9150509250929050565b5f815180845260208085019450602084015f5b8381101561325c57815187529582019590820190600101613240565b509495945050505050565b602081525f610a09602083018461322d565b5f806040838503121561328a575f80fd5b823561329581612d18565b9150602083013567ffffffffffffffff8111156132b0575f80fd5b61322385828601612f26565b803567ffffffffffffffff811681146132d3575f80fd5b919050565b5f80604083850312156132e9575f80fd5b823591506132f9602084016132bc565b90509250929050565b6020810161072782846130ab565b5f60208284031215613320575f80fd5b8135610a0981612d18565b5f805f6060848603121561333d575f80fd5b8335925060208401359150604084013561316681612d18565b6001600160a01b0383168152604060208201525f610bb56040830184612dcb565b5f805f805f8060c0878903121561338c575f80fd5b863567ffffffffffffffff8111156133a2575f80fd5b6133ae89828a01612f26565b96505060208701356133bf81612d18565b945060408701356133cf81612d18565b935060608701356133df81612d18565b9250608087013591506133f460a088016132bc565b90509295509295509295565b5f8060408385031215613411575f80fd5b823561341c81612d18565b915060208301358015158114612da9575f80fd5b5f8060408385031215613441575f80fd5b823561344c81612d18565b91506020830135612da981612d18565b5f805f805f60a08688031215613470575f80fd5b853561347b81612d18565b9450602086013561348b81612d18565b93506040860135925060608601359150608086013567ffffffffffffffff8111156134b4575f80fd5b61300d88828901612f26565b600181811c908216806134d457607f821691505b6020821081036134f257634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613508575f80fd5b815167ffffffffffffffff81111561351e575f80fd5b8201601f8101841361352e575f80fd5b805161353c612eb282612eff565b818152856020838501011115613550575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b601f8211156119b957805f5260205f20601f840160051c810160208510156135925750805b601f840160051c820191505b81811015610a75575f815560010161359e565b67ffffffffffffffff8311156135c9576135c9612e2b565b6135dd836135d783546134c0565b8361356d565b5f601f84116001811461360e575f85156135f75750838201355b5f19600387901b1c1916600186901b178355610a75565b5f83815260208120601f198716915b8281101561363d578685013582556020948501946001909201910161361d565b5086821015613659575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff8111156136d9576136d9612e2b565b6136ed816136e784546134c0565b8461356d565b602080601f831160018114613720575f84156137095750858301515b5f19600386901b1c1916600185901b178555612628565b5f85815260208120601f198616915b8281101561374e5788860151825594840194600190910190840161372f565b508582101561376b57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036137a7576137a761377b565b6001019392505050565b63ffffffff818116838216019080821115611a8d57611a8d61377b565b604081525f6137e06040830185612dcb565b905067ffffffffffffffff831660208301529392505050565b606081525f61380b6060830186612dcb565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b808201808211156107275761072761377b565b818103818111156107275761072761377b565b5f6001600160a01b03808816835280871660208401525060a0604083015261389960a083018661322d565b82810360608401526138ab818661322d565b905082810360808401526138bf8185612dcb565b98975050505050505050565b5f602082840312156138db575f80fd5b8151610a0981612d56565b5f6001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261124260a0830184612dcb565b604081525f61392f604083018561322d565b82810360208401526108bd818561322d56fea2646970667358221220d5c76270adee32355114bf29e4bad3cec273a3f6ceb196bf34b709a3beebecc164736f6c634300081900338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102cc575f3560e01c80636352211e1161017c578063a02b161e116100dd578063ce156e8211610093578063e4ae7d771161006e578063e4ae7d7714610681578063e985e9c514610694578063f242432a146106cf575f80fd5b8063ce156e8214610648578063d3bf89b11461065b578063dfa70d8b1461066e575f80fd5b8063bc7b6d62116100c3578063bc7b6d621461060f578063bd242bcb14610622578063c41a360a14610635575f80fd5b8063a02b161e146105e9578063a22cb465146105fc575f80fd5b80637c3005861161013257806385f3e6431161011857806385f3e6431461059c57806391b3c037146105af5780639dbba19d146105c2575f80fd5b80637c3005861461057357806380f7602114610586575f80fd5b80636f3ff726116101625780636f3ff7261461053a5780636f537c721461054d578063781ef8db14610560575f80fd5b80636352211e1461051457806363560a8e14610527575f80fd5b80632f27fa241161023157806348688f95116101e75780635569f33d116101c25780635569f33d146104ce5780635adf4724146104e15780635c622a0e146104f4575f80fd5b806348688f95146104885780634e1273f41461049b5780635357263f146104bb575f80fd5b806335af62161161021757806335af6216146104155780633634f9111461044057806344c9af2814610468575f80fd5b80632f27fa24146103ef578063341ec55914610402575f80fd5b806313c72608116102865780631c3fc3eb1161026c5780631c3fc3eb146103c05780631e8fca2d146103c75780632eb2c2d6146103da575f80fd5b806313c726081461035f57806314ff5ea3146103ad575f80fd5b8063072d5d77116102b6578063072d5d77146103195780630e89341c1461032c57806311b8e00a1461034c575f80fd5b8062fdd58e146102d057806301ffc9a7146102f6575b5f80fd5b6102e36102de366004612d2c565b6106e2565b6040519081526020015b60405180910390f35b610309610304366004612d6b565b61072d565b60405190151581526020016102ed565b610309610327366004612d86565b6108a2565b61033f61033a366004612db4565b6108c6565b6040516102ed9190612df9565b61030961035a366004612e0b565b6109f6565b61039461036d366004612db4565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016102ed565b6102e36103bb366004612db4565b610a10565b6102e35f81565b6102e36103d5366004612db4565b610a37565b6103ed6103e8366004612f73565b610a5e565b005b6102e36103fd366004612db4565b610a7c565b6103ed610410366004612d86565b610a9a565b610428610423366004613058565b610b22565b6040516001600160a01b0390911681526020016102ed565b61045361044e366004612e0b565b610bbd565b604080519283526020830191909152016102ed565b61047b610476366004612db4565b610bdd565b6040516102ed91906130cb565b6103ed61049636600461311e565b610caf565b6104ae6104a9366004613171565b610d3c565b6040516102ed9190613267565b6103ed6104c9366004613279565b610e0c565b6103ed6104dc3660046132d8565b610ea1565b6102e36104ef366004612d86565b610fef565b610507610502366004612db4565b611002565b6040516102ed9190613302565b610428610522366004612db4565b611058565b610428610535366004613058565b6110bd565b610309610548366004613310565b6110ff565b61039461055b366004613058565b61111a565b61030961056e366004612d86565b61115c565b61030961058136600461332b565b611172565b61058e611186565b6040516102ed929190613356565b6102e36105aa366004613377565b611231565b6102e36105bd366004613058565b61124d565b6104287f000000000000000000000000000000000000000000000000000000000000000081565b6103ed6105f7366004612db4565b61128f565b6103ed61060a366004613400565b61138b565b6103ed61061d366004612d86565b61139a565b610428610630366004612db4565b611428565b610428610643366004612db4565b611444565b610309610656366004612d86565b611488565b61030961066936600461332b565b6114a3565b61030961067c36600461332b565b6114b7565b61042861068f366004613058565b6114cb565b6103096106a2366004613430565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b6103ed6106dd36600461345c565b611546565b5f6001600160a01b038316158015906107145750826001600160a01b031661070983611058565b6001600160a01b0316145b61071e575f610721565b60015b60ff1690505b92915050565b5f6001600160e01b031982167f6be50c6900000000000000000000000000000000000000000000000000000000148061078f57506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b806107c357506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b806107f757506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b8061082b57506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b8061085f57506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b8061089357506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b8061072757506107278261155d565b5f80836108b082823361159a565b6108bd5f868660016115e8565b95945050505050565b610107546060906001600160a01b03166109695761010680546108e8906134c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610914906134c0565b801561095f5780601f106109365761010080835404028352916020019161095f565b820191905f5260205f20905b81548152906001019060200180831161094257829003601f168201915b5050505050610727565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa1580156109cf573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261072791908101906134f8565b5f610a09610a0384610a37565b83611711565b9392505050565b5f61072782610a328463ffffffff8116185f9081526101086020526040902090565b611728565b5f61072782610a598463ffffffff8116185f9081526101086020526040902090565b611746565b610a6885336117a0565b610a758585858585611831565b5050505050565b5f610727610a8983610a37565b5f9081526003602052604090205490565b5f80610aa98462100000611891565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b038716908102919091178255604051929450909250339184907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a450505050565b5f80610b7e610b6585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610bb35780546801000000000000000090046001600160a01b0316610bb5565b5f5b949350505050565b5f80610bd1610bcb85610a37565b84611905565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610c3b8584611728565b606085018190529050610c4e8584611746565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610c7c8382611928565b85906002811115610c8f57610c8f613097565b90816002811115610ca257610ca2613097565b8152505050505050919050565b641000000000610cc05f823361195f565b610106610cce8486836135b1565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905560405133907fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd590610d2e9087908790879061366b565b60405180910390a250505050565b60608151835114610d725781518351604051635b05999160e01b8152600481019290925260248201526044015b60405180910390fd5b5f835167ffffffffffffffff811115610d8d57610d8d612e2b565b604051908082528060200260200182016040528015610db6578160200160208202803683370190505b5090505f5b8451811015610e0457602080820286010151610ddf906020808402870101516106e2565b828281518110610df157610df16136ab565b6020908102919091010152600101610dbb565b509392505050565b610100610e1a5f823361195f565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105610e5083826136bf565b50336001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff484604051610e949190612df9565b60405180910390a3505050565b63ffffffff821682185f9081526101086020526040812090610ec38483611728565b600183015490915067ffffffffffffffff16428111610f205767ffffffffffffffff81161580610efa5750610ef882336119be565b155b15610f1b5760405163311388dd60e21b815260048101839052602401610d69565b610f37565b610f37610f2d8685611746565b620100003361195f565b8067ffffffffffffffff168467ffffffffffffffff161015610f99576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015285166024820152604401610d69565b60018301805467ffffffffffffffff191667ffffffffffffffff861690811790915560405133919084907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a45050505050565b5f610a09610ffc84610a37565b836119cc565b63ffffffff811681185f908152610108602052604081206001810154610a099067ffffffffffffffff166110536110398685611728565b5f908152602081905260409020546001600160a01b031690565b611928565b63ffffffff811681185f908152610108602052604081206110798382611728565b831415806110955750600181015467ffffffffffffffff164210155b6110b5575f838152602081905260409020546001600160a01b0316610a09565b5f9392505050565b5f610a0961064384848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f6107276f010000000000000000000000000000008361115c565b5f610a0961036d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f82836111695f856119d3565b16149392505050565b5f610bb561117f85610a37565b8484611a94565b6101045461010580545f926060926001600160a01b039091169181906111ab906134c0565b80601f01602080910402602001604051908101604052809291908181526020018280546111d7906134c0565b80156112225780601f106111f957610100808354040283529160200191611222565b820191905f5260205f20905b81548152906001019060200180831161120557829003601f168201915b50505050509050915091509091565b5f6112428787878787876001611ad7565b979650505050505050565b5f610a096103bb84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b5f8061129d83611000611891565b6040519193509150339083907f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea8905f90a35f828152602081905260409020546001600160a01b03168015611368576112f78184600161200d565b815482905f9061130c9063ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff166113499061378f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b611396338383612074565b5050565b5f806113aa846301000000611891565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16680100000000000000006001600160a01b03881690810291909117909155604051929450909250339184907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a450505050565b5f818152602081905260408120546001600160a01b0316610727565b63ffffffff811681185f908152610108602052604081206001015467ffffffffffffffff164210156114815761147c61103983610a10565b610727565b5f92915050565b5f808361149682823361211a565b6108bd5f8686600161217b565b5f610bb56114b085610a37565b84846121e7565b5f610bb56114c485610a37565b84846121fe565b5f8061150e610b6585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506118fa92505050565b600181015490915067ffffffffffffffff16421015610bb35760018101546801000000000000000090046001600160a01b0316610bb5565b61155085336117a0565b610a758585858585612237565b5f6001600160e01b031982167f8f452d620000000000000000000000000000000000000000000000000000000014806107275750610727826122c4565b5f6115a58483612392565b905080198316156115e25760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610d69565b50505050565b5f835f036115f757505f610bb5565b611600846123db565b6001600160a01b038316611640576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611705575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166116a08882600161243b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a384156116f9576116f9888785858b6125d0565b60019350505050610bb5565b505f9695505050505050565b5f8061171d8484610bbd565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610a09565b5f82611753575081610727565b6001820154610a0990849067ffffffffffffffff1642101561177c57835463ffffffff1661178f565b835461178f9063ffffffff1660016137b1565b63ffffffff82811690921891161890565b806001600160a01b0316826001600160a01b0316141580156117e757506001600160a01b038083165f9081526001602090815260408083209385168352929052205460ff16155b15611396576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b03808316600483015283166024820152604401610d69565b6001600160a01b03841661185a57604051632bfa23e760e11b81525f6004820152602401610d69565b6001600160a01b03851661188257604051626a0d4560e21b81525f6004820152602401610d69565b610a75858585858560016125d9565b63ffffffff821682185f908152610108602052604081206118b28482611728565b600182015490925067ffffffffffffffff1642106118e65760405163311388dd60e21b815260048101839052602401610d69565b610bd66118f38583611746565b843361195f565b805160209091012090565b5f8061191083612630565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff8316421061194157505f610727565b6001600160a01b03821661195757506001610727565b506002610727565b61196a8383836114a3565b6119b9576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610d69565b505050565b5f610a09620100008361115c565b5f610a0983835b5f8281526002602090815260408083206001600160a01b03851684529091529020548215610727575f611a0584611444565b90506001600160a01b03811615801590611a315750826001600160a01b0316816001600160a01b031614155b8015611a6157506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b15611a8d575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b5f8383611aa282823361159a565b85611ac057604051631850848b60e31b815260040160405180910390fd5b611acd86868660016115e8565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990611b3e908b90600401612df9565b5f604051808303815f87803b158015611b55575f80fd5b505af1158015611b67573d5f803e3d5ffd5b5050895160208b012091505f9050611b928263ffffffff8116185f9081526101086020526040902090565b9050611b9e8282611728565b5f8181526020819052604090205460018301549194506001600160a01b03169067ffffffffffffffff164210611c28578415611be057611be05f60013361195f565b6001600160a01b038a16158015611bf657508615155b15611c235760405163d1a3b35560e01b81525f600482015260248101889052336044820152606401610d69565b611ced565b6001600160a01b03811615611c6b578a6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610d699190612df9565b6001600160a01b038a16611cad578a6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610d699190612df9565b8415611cbf57611cbf5f60103361195f565b8567ffffffffffffffff165f03611ce257600182015467ffffffffffffffff1695505b640100000000871796505b6001600160a01b038a1615611d0f5767ffffffffffffffff8616421015611d1c565b67ffffffffffffffff8616155b15611d5f576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602401610d69565b6001600160a01b03811615611df757611d7a8185600161200d565b815482905f90611d8f9063ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff16611dcc9061378f565b91906101000a81548163ffffffff021916908363ffffffff160217905550611df48483611728565b93505b60018201805483546001600160a01b03808d16680100000000000000009081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921786558b81169091026001600160e01b031990921667ffffffffffffffff8a1617919091179091558a16611eb857336001600160a01b0316835f1b857f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88e8a604051611eab9291906137ce565b60405180910390a4611f71565b336001600160a01b0316835f1b857f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8e8e8b604051611ef9939291906137f9565b60405180910390a4611f1c8a85600160405180602001604052805f81525061264a565b5f611f278584611746565b905080611f3657611f36613834565b604051819086907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a3611f6e81898d5f6115e8565b50505b6001600160a01b03891615611fb85760405133906001600160a01b038b169086907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a45b6001600160a01b03881615611fff5760405133906001600160a01b038a169086907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a45b505050979650505050505050565b6001600160a01b03831661203557604051626a0d4560e21b81525f6004820152602401610d69565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291610a7591879185908590836125d9565b6001600160a01b0382166120b6576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610d69565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101610e94565b5f61212584836126a6565b905080198316156115e2576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610d69565b5f612185846123db565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611705575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906116a0908990839061243b565b5f82836121f486856126e1565b1614949350505050565b5f838361220c82823361211a565b8561222a57604051631850848b60e31b815260040160405180910390fd5b611acd868686600161217b565b6001600160a01b03841661226057604051632bfa23e760e11b81525f6004820152602401610d69565b6001600160a01b03851661228857604051626a0d4560e21b81525f6004820152602401610d69565b604080516001808252602082018690528183019081526060820185905260808201909252906122bb87878484875f6125d9565b50505050505050565b5f6001600160e01b031982167fd9b67a2600000000000000000000000000000000000000000000000000000000148061232657506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b8061235a57506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061072757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610727565b5f82158015906123b257505f6123a784611444565b6001600160a01b0316145b156123be57505f610727565b5f6123c984846126a6565b90508315610a0957608081901c610bb5565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612438576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610d69565b50565b5f61244583612630565b9050811561250e575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156124e6576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610d69565b5f8481526003602052604081208054859290612503908490613848565b909155506115e29050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156125a8576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610d69565b5f84815260036020526040812080548592906125c590849061385b565b909155505050505050565b610a75856126fe565b6125e5868686866127de565b6001600160a01b0385161561262857801561260d576126083387878787876128dc565b612628565b602084810151908401516126253389898585896129fd565b50505b505050505050565b5f61263a826123db565b50600181901b17600281901b1790565b6001600160a01b03841661267357604051632bfa23e760e11b81525f6004820152602401610d69565b604080516001808252602082018690528183019081526060820185905260808201909252906126285f87848487846125d9565b5f610a096126b484846126e1565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000811660809190911c1790565b5f6126ec83836119d3565b6126f65f846119d3565b179392505050565b80156124385763ffffffff811681185f90815261010860205260408120906127268383611728565b5f818152602081905260409020549091506001600160a01b031661274c8183600161200d565b8254839060049061276a90640100000000900463ffffffff1661378f565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6127938385611728565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3610a758282600160405180602001604052805f81525061264a565b6127ea84848484612ae4565b6001600160a01b0383161580159061280a57506001600160a01b03841615155b156115e2575f5b8251811015610a75575f83828151811061282d5761282d6136ab565b6020026020010151905061285681731000000000000000000000000000000000000000886114a3565b61289e576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610d69565b5f8383815181106128b1576128b16136ab565b602002602001015111156128d3576128d36128cb82610a37565b87875f612cd7565b50600101612811565b6001600160a01b0384163b156126285760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190612920908990899088908890889060040161386e565b6020604051808303815f875af192505050801561295a575060408051601f3d908101601f19168201909252612957918101906138cb565b60015b6129c1573d808015612987576040519150601f19603f3d011682016040523d82523d5f602084013e61298c565b606091505b5080515f036129b957604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b146122bb57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b6001600160a01b0384163b156126285760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190612a4190899089908890889088906004016138e6565b6020604051808303815f875af1925050508015612a7b575060408051601f3d908101601f19168201909252612a78918101906138cb565b60015b612aa8573d808015612987576040519150601f19603f3d011682016040523d82523d5f602084013e61298c565b6001600160e01b0319811663f23a6e6160e01b146122bb57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610d69565b8051825114612b135781518151604051635b05999160e01b815260048101929092526024820152604401610d69565b5f5b8251811015612c11576020818102848101820151908401909101518015612c07575f828152602081905260409020546001600160a01b039081169088168114612b90576040516303dee4c560e01b81526001600160a01b03891660048201525f60248201526044810183905260648101849052608401610d69565b6001821115612bd2576040516303dee4c560e01b81526001600160a01b0389166004820152600160248201526044810183905260648101849052608401610d69565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388161790555b5050600101612b15565b508151600103612c7a576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450506115e2565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051612cc992919061391d565b60405180910390a450505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015610a7557612d0b8582868561217b565b50612628858285856115e8565b6001600160a01b0381168114612438575f80fd5b5f8060408385031215612d3d575f80fd5b8235612d4881612d18565b946020939093013593505050565b6001600160e01b031981168114612438575f80fd5b5f60208284031215612d7b575f80fd5b8135610a0981612d56565b5f8060408385031215612d97575f80fd5b823591506020830135612da981612d18565b809150509250929050565b5f60208284031215612dc4575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610a096020830184612dcb565b5f8060408385031215612e1c575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e6857612e68612e2b565b604052919050565b5f67ffffffffffffffff821115612e8957612e89612e2b565b5060051b60200190565b5f82601f830112612ea2575f80fd5b81356020612eb7612eb283612e70565b612e3f565b8083825260208201915060208460051b870101935086841115612ed8575f80fd5b602086015b84811015612ef45780358352918301918301612edd565b509695505050505050565b5f67ffffffffffffffff821115612f1857612f18612e2b565b50601f01601f191660200190565b5f82601f830112612f35575f80fd5b8135612f43612eb282612eff565b818152846020838601011115612f57575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a08688031215612f87575f80fd5b8535612f9281612d18565b94506020860135612fa281612d18565b9350604086013567ffffffffffffffff80821115612fbe575f80fd5b612fca89838a01612e93565b94506060880135915080821115612fdf575f80fd5b612feb89838a01612e93565b93506080880135915080821115613000575f80fd5b5061300d88828901612f26565b9150509295509295909350565b5f8083601f84011261302a575f80fd5b50813567ffffffffffffffff811115613041575f80fd5b602083019150836020828501011115610bd6575f80fd5b5f8060208385031215613069575f80fd5b823567ffffffffffffffff81111561307f575f80fd5b61308b8582860161301a565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600381106130c757634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506130dd8284516130ab565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f60408486031215613130575f80fd5b833567ffffffffffffffff811115613146575f80fd5b6131528682870161301a565b909450925050602084013561316681612d18565b809150509250925092565b5f8060408385031215613182575f80fd5b823567ffffffffffffffff80821115613199575f80fd5b818501915085601f8301126131ac575f80fd5b813560206131bc612eb283612e70565b82815260059290921b840181019181810190898411156131da575f80fd5b948201945b838610156132015785356131f281612d18565b825294820194908201906131df565b96505086013592505080821115613216575f80fd5b5061322385828601612e93565b9150509250929050565b5f815180845260208085019450602084015f5b8381101561325c57815187529582019590820190600101613240565b509495945050505050565b602081525f610a09602083018461322d565b5f806040838503121561328a575f80fd5b823561329581612d18565b9150602083013567ffffffffffffffff8111156132b0575f80fd5b61322385828601612f26565b803567ffffffffffffffff811681146132d3575f80fd5b919050565b5f80604083850312156132e9575f80fd5b823591506132f9602084016132bc565b90509250929050565b6020810161072782846130ab565b5f60208284031215613320575f80fd5b8135610a0981612d18565b5f805f6060848603121561333d575f80fd5b8335925060208401359150604084013561316681612d18565b6001600160a01b0383168152604060208201525f610bb56040830184612dcb565b5f805f805f8060c0878903121561338c575f80fd5b863567ffffffffffffffff8111156133a2575f80fd5b6133ae89828a01612f26565b96505060208701356133bf81612d18565b945060408701356133cf81612d18565b935060608701356133df81612d18565b9250608087013591506133f460a088016132bc565b90509295509295509295565b5f8060408385031215613411575f80fd5b823561341c81612d18565b915060208301358015158114612da9575f80fd5b5f8060408385031215613441575f80fd5b823561344c81612d18565b91506020830135612da981612d18565b5f805f805f60a08688031215613470575f80fd5b853561347b81612d18565b9450602086013561348b81612d18565b93506040860135925060608601359150608086013567ffffffffffffffff8111156134b4575f80fd5b61300d88828901612f26565b600181811c908216806134d457607f821691505b6020821081036134f257634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613508575f80fd5b815167ffffffffffffffff81111561351e575f80fd5b8201601f8101841361352e575f80fd5b805161353c612eb282612eff565b818152856020838501011115613550575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b601f8211156119b957805f5260205f20601f840160051c810160208510156135925750805b601f840160051c820191505b81811015610a75575f815560010161359e565b67ffffffffffffffff8311156135c9576135c9612e2b565b6135dd836135d783546134c0565b8361356d565b5f601f84116001811461360e575f85156135f75750838201355b5f19600387901b1c1916600186901b178355610a75565b5f83815260208120601f198716915b8281101561363d578685013582556020948501946001909201910161361d565b5086821015613659575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff8111156136d9576136d9612e2b565b6136ed816136e784546134c0565b8461356d565b602080601f831160018114613720575f84156137095750858301515b5f19600386901b1c1916600185901b178555612628565b5f85815260208120601f198616915b8281101561374e5788860151825594840194600190910190840161372f565b508582101561376b57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036137a7576137a761377b565b6001019392505050565b63ffffffff818116838216019080821115611a8d57611a8d61377b565b604081525f6137e06040830185612dcb565b905067ffffffffffffffff831660208301529392505050565b606081525f61380b6060830186612dcb565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b808201808211156107275761072761377b565b818103818111156107275761072761377b565b5f6001600160a01b03808816835280871660208401525060a0604083015261389960a083018661322d565b82810360608401526138ab818661322d565b905082810360808401526138bf8185612dcb565b98975050505050505050565b5f602082840312156138db575f80fd5b8151610a0981612d56565b5f6001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261124260a0830184612dcb565b604081525f61392f604083018561322d565b82810360208401526108bd818561322d56fea2646970667358221220d5c76270adee32355114bf29e4bad3cec273a3f6ceb196bf34b709a3beebecc164736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "28814": [ + { + "length": 32, + "start": 1479 + }, + { + "length": 32, + "start": 6921 + } + ] + }, + "inputSourceName": "project/src/registry/PermissionedRegistry.sol", + "devdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "details": "Error selector: `0x68c1425a`" + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "details": "Error selector: `0xf1d446c3`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1155InsufficientBalance(address,uint256,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred.", + "tokenId": "Identifier number of a token." + } + } + ], + "ERC1155InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "ERC1155InvalidOperator(address)": [ + { + "details": "Indicates a failure with the `operator` to be approved. Used in approvals.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC1155InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC1155InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC1155MissingApprovalForAll(address,address)": [ + { + "details": "Indicates a failure with the `operator`’s approval. Used in transfers.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner.", + "owner": "Address of the current owner of a token." + } + } + ], + "LabelAlreadyRegistered(string)": [ + { + "details": "Error selector: `0xdef545a4`" + } + ], + "LabelAlreadyReserved(string)": [ + { + "details": "Error selector: `0xf60759e0`" + } + ], + "LabelExpired(uint256)": [ + { + "details": "Error selector: `0xc44e2374`" + } + ], + "TransferDisallowed(uint256,address)": [ + { + "details": "Error selector: `0xe58f6d5a`" + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "ExpiryUpdated(uint256,uint64,address)": { + "params": { + "newExpiry": "The new expiry of the label.", + "sender": "The sender of the call to update the expiry.", + "tokenId": "The token ID of the label." + } + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label registered.", + "labelHash": "The label hash registered.", + "owner": "The owner of the label.", + "sender": "The sender of the call to register.", + "tokenId": "The token ID registered." + } + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label reserved.", + "labelHash": "The label hash reserved.", + "sender": "The sender of the call to reserve.", + "tokenId": "The token ID reserved." + } + }, + "LabelUnregistered(uint256,address)": { + "params": { + "sender": "The sender of the call to unregister.", + "tokenId": "The token ID unregistered." + } + }, + "ParentUpdated(address,string,address)": { + "params": { + "label": "The new label.", + "parent": "The new parent.", + "sender": "The sender of the call to update the parent." + } + }, + "ResolverUpdated(uint256,address,address)": { + "params": { + "resolver": "The new resolver.", + "sender": "The sender of the call to update the resolver.", + "tokenId": "The token ID of the label." + } + }, + "SubregistryUpdated(uint256,address,address)": { + "params": { + "sender": "The sender of the call to update the subregistry.", + "subregistry": "The new subregistry.", + "tokenId": "The token ID of the label." + } + }, + "TokenRegenerated(uint256,uint256)": { + "params": { + "newTokenId": "The new token ID.", + "oldTokenId": "The old token ID." + } + }, + "TokenResource(uint256,uint256)": { + "params": { + "resource": "The EAC resource.", + "tokenId": "The token ID." + } + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + }, + "URIUpdated(string,address,address)": { + "params": { + "renderer": "The new render address.", + "sender": "The sender of the call to update the URI.", + "uri": "The new URI." + } + } + }, + "kind": "dev", + "methods": { + "balanceOf(address,uint256)": { + "params": { + "account": "The account to get the balance for.", + "id": "The token ID." + }, + "returns": { + "_0": "balance The balance of the token for the account. This will only ever be 1 or 0." + } + }, + "balanceOfBatch(address[],uint256[])": { + "details": "`accounts` and `ids` must have the same length.", + "params": { + "accounts": "The accounts to get the balances for.", + "ids": "The token IDs." + }, + "returns": { + "_0": "batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0." + } + }, + "constructor": { + "params": { + "labelStore": "The shared label database.", + "roleBitmap": "The role bitmap granted to `rootAccount`.", + "rootAccount": "Account granted root roles." + } + }, + "findExpiry(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The expiry of the label." + } + }, + "findOwner(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The owner of the label." + } + }, + "findTokenId(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The token ID of the label." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getExpiry(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The expiry of the label, in seconds." + } + }, + "getOwner(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token owner." + } + }, + "getParent()": { + "returns": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "getResolver(string)": { + "params": { + "label": "The label to fetch a resolver for." + }, + "returns": { + "_0": "resolver The address of a resolver responsible for this label, or `address(0)` if none exists." + } + }, + "getResource(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The resource." + } + }, + "getState(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "state": "The state of the label." + } + }, + "getStatus(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The status of the label." + } + }, + "getSubregistry(string)": { + "params": { + "label": "The label to resolve." + }, + "returns": { + "_0": "The address of the registry for this label, or `address(0)` if none exists." + } + }, + "getTokenId(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token ID." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "account": "The account to get the approval for.", + "operator": "The operator to get the approval for." + }, + "returns": { + "_0": "approved The approval status." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "latestOwnerOf(uint256)": { + "params": { + "tokenId": "The token ID to query." + }, + "returns": { + "_0": "The latest owner address." + } + }, + "ownerOf(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The owner of the token." + } + }, + "register(string,address,address,address,uint256,uint64)": { + "params": { + "expiry": "The expiry of the label, in seconds.", + "label": "The label to register.", + "owner": "The address of the owner of the label.", + "registry": "The registry to set as the label.", + "resolver": "The resolver to set for the label.", + "roleBitmap": "The role bitmap to set for the label." + }, + "returns": { + "_0": "The token ID." + } + }, + "renew(uint256,uint64)": { + "details": "If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.", + "params": { + "anyId": "The labelhash, token ID, or resource.", + "newExpiry": "The new expiry, in seconds." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the tokens from.", + "ids": "The token IDs.", + "to": "The address to transfer the tokens to.", + "values": "The amounts of tokens to transfer." + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the token from.", + "id": "The token ID.", + "to": "The address to transfer the token to.", + "value": "The amount of tokens to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "The approval status.", + "operator": "The operator to set the approval for." + } + }, + "setParent(address,string)": { + "details": "Should emit `ParentUpdated`.", + "params": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "setResolver(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "resolver": "The new resolver." + } + }, + "setSubregistry(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "registry": "The new registry." + } + }, + "setURI(string,address)": { + "params": { + "renderer": "The new renderer address.", + "uri_": "The new URI." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "unregister(uint256)": { + "details": "Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.", + "params": { + "anyId": "The labelhash, token ID, or resource." + } + }, + "uri(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The URI for the token." + } + } + }, + "stateVariables": { + "__gap": { + "details": "Storage gap for future changes." + }, + "_childLabel": { + "details": "The child label of this registry." + }, + "_entries": { + "details": "The entries of this registry." + }, + "_parentRegistry": { + "details": "The parent registry of this registry." + }, + "_uri": { + "details": "The metadata URI." + }, + "_uriRenderer": { + "details": "The metadata renderer." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "2942200", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "LABEL_STORE()": "infinite", + "ROOT_RESOURCE()": "250", + "balanceOf(address,uint256)": "infinite", + "balanceOfBatch(address[],uint256[])": "infinite", + "findExpiry(string)": "infinite", + "findOwner(string)": "infinite", + "findTokenId(string)": "infinite", + "getAssigneeCount(uint256,uint256)": "7372", + "getExpiry(uint256)": "2537", + "getOwner(uint256)": "infinite", + "getParent()": "infinite", + "getResolver(string)": "infinite", + "getResource(uint256)": "4918", + "getState(uint256)": "infinite", + "getStatus(uint256)": "infinite", + "getSubregistry(string)": "infinite", + "getTokenId(uint256)": "2663", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "infinite", + "hasRoles(uint256,uint256,address)": "infinite", + "hasRootRoles(uint256,address)": "2843", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "infinite", + "latestOwnerOf(uint256)": "2597", + "ownerOf(uint256)": "infinite", + "register(string,address,address,address,uint256,uint64)": "infinite", + "renew(uint256,uint64)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "infinite", + "roles(uint256,address)": "infinite", + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": "infinite", + "safeTransferFrom(address,address,uint256,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "26752", + "setParent(address,string)": "infinite", + "setResolver(uint256,address)": "infinite", + "setSubregistry(uint256,address)": "infinite", + "setURI(string,address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "unregister(uint256)": "infinite", + "uri(uint256)": "infinite" + }, + "internal": { + "_canRevive(uint256,address)": "2402", + "_checkExpiryAndTokenRoles(uint256,uint256)": "infinite", + "_constructResource(uint256,struct PermissionedRegistry.Entry storage pointer)": "4435", + "_constructStatus(uint64,address)": "101", + "_constructTokenId(uint256,struct PermissionedRegistry.Entry storage pointer)": "2179", + "_entry(uint256)": "infinite", + "_getRoles(uint256,address)": "infinite", + "_getSettableRoles(uint256,address)": "infinite", + "_isExpired(uint64)": "infinite", + "_onRolesGranted(uint256,address,uint256,uint256,uint256)": "infinite", + "_onRolesRevoked(uint256,address,uint256,uint256,uint256)": "infinite", + "_regenerate(uint256)": "infinite", + "_register(string memory,address,contract IRegistry,address,uint256,uint64,bool)": "infinite", + "_update(address,address,uint256[] memory,uint256[] memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"labelStore\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"oldExpiry\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"CannotReduceExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"CannotSetPastExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyReserved\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"LabelExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"TransferDisallowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ExpiryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelReserved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelUnregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ParentUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RegistryCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ResolverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SubregistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldTokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newTokenId\",\"type\":\"uint256\"}],\"name\":\"TokenRegenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"TokenResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"renderer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"URIUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"LABEL_STORE\",\"outputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getParent\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getResource\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"latestOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"internalType\":\"struct IPermissionedRegistry.State\",\"name\":\"state\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getSubregistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"latestOwnerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setParent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"setSubregistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"},{\"internalType\":\"contract IRegistryURIRenderer\",\"name\":\"renderer\",\"type\":\"address\"}],\"name\":\"setURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"details\":\"Error selector: `0x68c1425a`\"}],\"CannotSetPastExpiry(uint64)\":[{\"details\":\"Error selector: `0xf1d446c3`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1155InsufficientBalance(address,uint256,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\",\"tokenId\":\"Identifier number of a token.\"}}],\"ERC1155InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"ERC1155InvalidOperator(address)\":[{\"details\":\"Indicates a failure with the `operator` to be approved. Used in approvals.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC1155InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC1155InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC1155MissingApprovalForAll(address,address)\":[{\"details\":\"Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\",\"owner\":\"Address of the current owner of a token.\"}}],\"LabelAlreadyRegistered(string)\":[{\"details\":\"Error selector: `0xdef545a4`\"}],\"LabelAlreadyReserved(string)\":[{\"details\":\"Error selector: `0xf60759e0`\"}],\"LabelExpired(uint256)\":[{\"details\":\"Error selector: `0xc44e2374`\"}],\"TransferDisallowed(uint256,address)\":[{\"details\":\"Error selector: `0xe58f6d5a`\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"ExpiryUpdated(uint256,uint64,address)\":{\"params\":{\"newExpiry\":\"The new expiry of the label.\",\"sender\":\"The sender of the call to update the expiry.\",\"tokenId\":\"The token ID of the label.\"}},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label registered.\",\"labelHash\":\"The label hash registered.\",\"owner\":\"The owner of the label.\",\"sender\":\"The sender of the call to register.\",\"tokenId\":\"The token ID registered.\"}},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label reserved.\",\"labelHash\":\"The label hash reserved.\",\"sender\":\"The sender of the call to reserve.\",\"tokenId\":\"The token ID reserved.\"}},\"LabelUnregistered(uint256,address)\":{\"params\":{\"sender\":\"The sender of the call to unregister.\",\"tokenId\":\"The token ID unregistered.\"}},\"ParentUpdated(address,string,address)\":{\"params\":{\"label\":\"The new label.\",\"parent\":\"The new parent.\",\"sender\":\"The sender of the call to update the parent.\"}},\"ResolverUpdated(uint256,address,address)\":{\"params\":{\"resolver\":\"The new resolver.\",\"sender\":\"The sender of the call to update the resolver.\",\"tokenId\":\"The token ID of the label.\"}},\"SubregistryUpdated(uint256,address,address)\":{\"params\":{\"sender\":\"The sender of the call to update the subregistry.\",\"subregistry\":\"The new subregistry.\",\"tokenId\":\"The token ID of the label.\"}},\"TokenRegenerated(uint256,uint256)\":{\"params\":{\"newTokenId\":\"The new token ID.\",\"oldTokenId\":\"The old token ID.\"}},\"TokenResource(uint256,uint256)\":{\"params\":{\"resource\":\"The EAC resource.\",\"tokenId\":\"The token ID.\"}},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"},\"URIUpdated(string,address,address)\":{\"params\":{\"renderer\":\"The new render address.\",\"sender\":\"The sender of the call to update the URI.\",\"uri\":\"The new URI.\"}}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"params\":{\"account\":\"The account to get the balance for.\",\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"balance The balance of the token for the account. This will only ever be 1 or 0.\"}},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"`accounts` and `ids` must have the same length.\",\"params\":{\"accounts\":\"The accounts to get the balances for.\",\"ids\":\"The token IDs.\"},\"returns\":{\"_0\":\"batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\"}},\"constructor\":{\"params\":{\"labelStore\":\"The shared label database.\",\"roleBitmap\":\"The role bitmap granted to `rootAccount`.\",\"rootAccount\":\"Account granted root roles.\"}},\"findExpiry(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The expiry of the label.\"}},\"findOwner(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The owner of the label.\"}},\"findTokenId(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The token ID of the label.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getExpiry(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The expiry of the label, in seconds.\"}},\"getOwner(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token owner.\"}},\"getParent()\":{\"returns\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"getResolver(string)\":{\"params\":{\"label\":\"The label to fetch a resolver for.\"},\"returns\":{\"_0\":\"resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\"}},\"getResource(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The resource.\"}},\"getState(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"state\":\"The state of the label.\"}},\"getStatus(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The status of the label.\"}},\"getSubregistry(string)\":{\"params\":{\"label\":\"The label to resolve.\"},\"returns\":{\"_0\":\"The address of the registry for this label, or `address(0)` if none exists.\"}},\"getTokenId(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"account\":\"The account to get the approval for.\",\"operator\":\"The operator to get the approval for.\"},\"returns\":{\"_0\":\"approved The approval status.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"latestOwnerOf(uint256)\":{\"params\":{\"tokenId\":\"The token ID to query.\"},\"returns\":{\"_0\":\"The latest owner address.\"}},\"ownerOf(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The owner of the token.\"}},\"register(string,address,address,address,uint256,uint64)\":{\"params\":{\"expiry\":\"The expiry of the label, in seconds.\",\"label\":\"The label to register.\",\"owner\":\"The address of the owner of the label.\",\"registry\":\"The registry to set as the label.\",\"resolver\":\"The resolver to set for the label.\",\"roleBitmap\":\"The role bitmap to set for the label.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"renew(uint256,uint64)\":{\"details\":\"If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"newExpiry\":\"The new expiry, in seconds.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the tokens from.\",\"ids\":\"The token IDs.\",\"to\":\"The address to transfer the tokens to.\",\"values\":\"The amounts of tokens to transfer.\"}},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the token from.\",\"id\":\"The token ID.\",\"to\":\"The address to transfer the token to.\",\"value\":\"The amount of tokens to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"The approval status.\",\"operator\":\"The operator to set the approval for.\"}},\"setParent(address,string)\":{\"details\":\"Should emit `ParentUpdated`.\",\"params\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"setResolver(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"resolver\":\"The new resolver.\"}},\"setSubregistry(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"registry\":\"The new registry.\"}},\"setURI(string,address)\":{\"params\":{\"renderer\":\"The new renderer address.\",\"uri_\":\"The new URI.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"unregister(uint256)\":{\"details\":\"Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"}},\"uri(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The URI for the token.\"}}},\"stateVariables\":{\"__gap\":{\"details\":\"Storage gap for future changes.\"},\"_childLabel\":{\"details\":\"The child label of this registry.\"},\"_entries\":{\"details\":\"The entries of this registry.\"},\"_parentRegistry\":{\"details\":\"The parent registry of this registry.\"},\"_uri\":{\"details\":\"The metadata URI.\"},\"_uriRenderer\":{\"details\":\"The metadata renderer.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"notice\":\"Label expiry cannot be reduced.\"}],\"CannotSetPastExpiry(uint64)\":[{\"notice\":\"Label expiry cannot be before now.\"}],\"LabelAlreadyRegistered(string)\":[{\"notice\":\"Label is already registered.\"}],\"LabelAlreadyReserved(string)\":[{\"notice\":\"Label cannot be reserved again.\"}],\"LabelExpired(uint256)\":[{\"notice\":\"Label is expired/unregistered.\"}],\"TransferDisallowed(uint256,address)\":[{\"notice\":\"Transfer is not allowed due to missing transfer admin role.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"ExpiryUpdated(uint256,uint64,address)\":{\"notice\":\"Expiry of label was changed.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"notice\":\"A label was registered.\"},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"notice\":\"A label was reserved.\"},\"LabelUnregistered(uint256,address)\":{\"notice\":\"A label was unregistered.\"},\"ParentUpdated(address,string,address)\":{\"notice\":\"Parent was changed.\"},\"RegistryCreated()\":{\"notice\":\"A registry was created/initialized.\"},\"ResolverUpdated(uint256,address,address)\":{\"notice\":\"Resolver of label was changed.\"},\"SubregistryUpdated(uint256,address,address)\":{\"notice\":\"Subregistry of label was changed.\"},\"TokenRegenerated(uint256,uint256)\":{\"notice\":\"Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance.\"},\"TokenResource(uint256,uint256)\":{\"notice\":\"Associate a token with an EAC resource.\"},\"URIUpdated(string,address,address)\":{\"notice\":\"URI was changed.\"}},\"kind\":\"user\",\"methods\":{\"LABEL_STORE()\":{\"notice\":\"The shared label database.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"balanceOf(address,uint256)\":{\"notice\":\"Returns the balance of a token for an account.\"},\"balanceOfBatch(address[],uint256[])\":{\"notice\":\"Returns the balances of a batch of tokens for an account.\"},\"findExpiry(string)\":{\"notice\":\"Fetches the label expiry.\"},\"findOwner(string)\":{\"notice\":\"Fetches the label owner.\"},\"findTokenId(string)\":{\"notice\":\"Fetches the token ID for a label.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getExpiry(uint256)\":{\"notice\":\"Get expiry of label.\"},\"getOwner(uint256)\":{\"notice\":\"Get token owner from `anyId`.\"},\"getParent()\":{\"notice\":\"Get canonical \\\"location\\\" of this registry.\"},\"getResolver(string)\":{\"notice\":\"Fetches the resolver responsible for the specified label.\"},\"getResource(uint256)\":{\"notice\":\"Get `resource` from `anyId`.\"},\"getState(uint256)\":{\"notice\":\"Get the state of a label.\"},\"getStatus(uint256)\":{\"notice\":\"Get `Status` from `anyId`.\"},\"getSubregistry(string)\":{\"notice\":\"Fetches the registry for a label.\"},\"getTokenId(uint256)\":{\"notice\":\"Get `tokenId` from `anyId`.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Returns the approval for all operator.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"latestOwnerOf(uint256)\":{\"notice\":\"Get the latest owner of a token. If the token was burned, returns null.\"},\"ownerOf(uint256)\":{\"notice\":\"Returns the owner of a token.\"},\"register(string,address,address,address,uint256,uint64)\":{\"notice\":\"Registers a new label.\"},\"renew(uint256,uint64)\":{\"notice\":\"Renew a label.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Transfers multiple tokens from one address to another.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"notice\":\"Transfers a single token from one address to another.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Sets the approval for all operator.\"},\"setParent(address,string)\":{\"notice\":\"Change canonical \\\"location\\\".\"},\"setResolver(uint256,address)\":{\"notice\":\"Change resolver of label.\"},\"setSubregistry(uint256,address)\":{\"notice\":\"Change registry of label.\"},\"setURI(string,address)\":{\"notice\":\"Set the URI for the registry.\"},\"unregister(uint256)\":{\"notice\":\"Delete a label.\"},\"uri(uint256)\":{\"notice\":\"Returns the URI for a token.\"}},\"notice\":\"A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`) to resolve any of these to the canonical storage slot for the name. The registry maintains two independent version counters per name: - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form the EAC resource ID. This means a re-registered name gets a fresh permission scope. - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint) due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring changes to roles create new tokens and prevent frontrunning a transfer with a role revocation. Names are treated as `AVAILABLE` once `block.timestamp >= expiry`. State diagram: register() +ROLE_REGISTRAR +------------------->----------------------+ | | | renew() | renew() | +ROLE_RENEW | +ROLE_RENEW | +------+ | +------+ | | | | | | \\u028c \\u028c v v v | AVAILABLE --------> RESERVED -------------> REGISTERED >--+ \\u028c register() v register() v | w/owner=0 | +ROLE_REGISTER_RESERVED | | +ROLE_REGISTRAR | | | | | +--------<---------+------------<------------+ unregister() +ROLE_UNREGISTER\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/PermissionedRegistry.sol\":\"PermissionedRegistry\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155} from \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x35d120c427299af1525aaf07955314d9e36a62f14408eb93dec71a2e001f74d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/utils/ERC1155Utils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\nimport {IERC1155Errors} from \\\"../../../interfaces/draft-IERC6093.sol\\\";\\n\\n/**\\n * @dev Library that provide common ERC-1155 utility functions.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].\\n *\\n * _Available since v5.1._\\n */\\nlibrary ERC1155Utils {\\n /**\\n * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155Received(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver.onERC1155Received.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155BatchReceived(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x22f099c02c252dd1f6ddc464916ce683294a63b23b3c6ee3d290b77398e2474b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)\\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\\n\\npragma solidity ^0.8.20;\\n\\nimport {Comparators} from \\\"./Comparators.sol\\\";\\nimport {SlotDerivation} from \\\"./SlotDerivation.sol\\\";\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\nimport {Math} from \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to array types.\\n */\\nlibrary Arrays {\\n using SlotDerivation for bytes32;\\n using StorageSlot for bytes32;\\n\\n /**\\n * @dev Sort an array of uint256 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n uint256[] memory array,\\n function(uint256, uint256) pure returns (bool) comp\\n ) internal pure returns (uint256[] memory) {\\n _quickSort(_begin(array), _end(array), comp);\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\\n */\\n function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\\n sort(array, Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of address (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n address[] memory array,\\n function(address, address) pure returns (bool) comp\\n ) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of address in increasing order.\\n */\\n function sort(address[] memory array) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n bytes32[] memory array,\\n function(bytes32, bytes32) pure returns (bool) comp\\n ) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\\n */\\n function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\\n * at end (exclusive). Sorting follows the `comp` comparator.\\n *\\n * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\\n *\\n * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\\n * be used only if the limits are within a memory array.\\n */\\n function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\\n unchecked {\\n if (end - begin < 0x40) return;\\n\\n // Use first element as pivot\\n uint256 pivot = _mload(begin);\\n // Position where the pivot should be at the end of the loop\\n uint256 pos = begin;\\n\\n for (uint256 it = begin + 0x20; it < end; it += 0x20) {\\n if (comp(_mload(it), pivot)) {\\n // If the value stored at the iterator's position comes before the pivot, we increment the\\n // position of the pivot and move the value there.\\n pos += 0x20;\\n _swap(pos, it);\\n }\\n }\\n\\n _swap(begin, pos); // Swap pivot into place\\n _quickSort(begin, pos, comp); // Sort the left side of the pivot\\n _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first element of `array`.\\n */\\n function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\\n assembly (\\\"memory-safe\\\") {\\n ptr := add(array, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\\n * that comes just after the last element of the array.\\n */\\n function _end(uint256[] memory array) private pure returns (uint256 ptr) {\\n unchecked {\\n return _begin(array) + array.length * 0x20;\\n }\\n }\\n\\n /**\\n * @dev Load memory word (as a uint256) at location `ptr`.\\n */\\n function _mload(uint256 ptr) private pure returns (uint256 value) {\\n assembly {\\n value := mload(ptr)\\n }\\n }\\n\\n /**\\n * @dev Swaps the elements memory location `ptr1` and `ptr2`.\\n */\\n function _swap(uint256 ptr1, uint256 ptr2) private pure {\\n assembly {\\n let value1 := mload(ptr1)\\n let value2 := mload(ptr2)\\n mstore(ptr1, value2)\\n mstore(ptr2, value1)\\n }\\n }\\n\\n /// @dev Helper: low level cast address memory array to uint256 memory array\\n function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\\n function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast address comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(address, address) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(bytes32, bytes32) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /**\\n * @dev Searches a sorted `array` and returns the first index that contains\\n * a value greater or equal to `element`. If no such index exists (i.e. all\\n * values in the array are strictly less than `element`), the array length is\\n * returned. Time complexity O(log n).\\n *\\n * NOTE: The `array` is expected to be sorted in ascending order, and to\\n * contain no repeated elements.\\n *\\n * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\\n * support for repeated elements in the array. The {lowerBound} function should\\n * be used instead.\\n */\\n function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n low = mid + 1;\\n }\\n }\\n\\n // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\\n if (low > 0 && unsafeAccess(array, low - 1).value == element) {\\n return low - 1;\\n } else {\\n return low;\\n }\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value greater or equal than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\\n */\\n function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value strictly greater than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\\n */\\n function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {lowerBound}, but with an array in memory.\\n */\\n function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {upperBound}, but with an array in memory.\\n */\\n function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getAddressSlot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getBytes32Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getUint256Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(address[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(uint256[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55a4fdb408e3db950b48f4a6131e538980be8c5f48ee59829d92d66477140cd6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides a set of functions to compare values.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Comparators {\\n function lt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a < b;\\n }\\n\\n function gt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a > b;\\n }\\n}\\n\",\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\\n * the solidity language / compiler.\\n *\\n * 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.].\\n *\\n * Example usage:\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using StorageSlot for bytes32;\\n * using SlotDerivation for bytes32;\\n *\\n * // Declare a namespace\\n * string private constant _NAMESPACE = \\\"\\\"; // eg. OpenZeppelin.Slot\\n *\\n * function setValueInNamespace(uint256 key, address newValue) internal {\\n * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\\n * }\\n *\\n * function getValueInNamespace(uint256 key) internal view returns (address) {\\n * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {StorageSlot}.\\n *\\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\\n * upgrade safety will ignore the slots accessed through this library.\\n *\\n * _Available since v5.1._\\n */\\nlibrary SlotDerivation {\\n /**\\n * @dev Derive an ERC-7201 slot from a string (namespace).\\n */\\n function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\\n slot := and(keccak256(0x00, 0x20), not(0xff))\\n }\\n }\\n\\n /**\\n * @dev Add an offset to a slot to get the n-th element of a structure or an array.\\n */\\n function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\\n unchecked {\\n return bytes32(uint256(slot) + pos);\\n }\\n }\\n\\n /**\\n * @dev Derive the location of the first element in an array from the slot where the length is stored.\\n */\\n function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, slot)\\n result := keccak256(0x00, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, and(key, shr(96, not(0))))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, iszero(iszero(key)))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x67672e4ca1dafdcc661d4eba8475cfac631fa0933309258e3af7644b92e1fb26\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, msg.sender);\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _getRoles(resource, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _getRoles(ROOT_RESOURCE, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return _effectiveRoles(resource, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the roles bitmap for an account for permission checks.\\n function _getRoles(uint256 resource, address account) internal view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the effective roles bitmap for an account for permission checks.\\n function _effectiveRoles(uint256 resource, address account) private view returns (uint256) {\\n return _getRoles(ROOT_RESOURCE, account) | _getRoles(resource, account);\\n }\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n}\\n\",\"keccak256\":\"0x934655016f502e7a2f8e5cbd294ef48e85f238821f5608de5675c023f48037af\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Admin roles imply their corresponding regular roles.\\n function withAdminRolesApplied(uint256 roleBitmap) internal pure returns (uint256) {\\n roleBitmap >>= 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Derive roles bitmap from assignee counts.\\n /// @param counts Packed role counts (0-15) as `uint4x64`.\\n function fromCounts(uint256 counts) internal pure returns (uint256) {\\n return (counts | (counts >> 1) | (counts >> 2) | (counts >> 3)) & ALL_ROLES;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function hasZeroNybbles(uint256 value) internal pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 zeroNybbles;\\n unchecked {\\n zeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return zeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xc14f05abd508e75c9f16a35e31d0fb9f1f1dd904b65d058201c788a9ddd562eb\",\"license\":\"MIT\"},\"project/src/erc1155/ERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {\\n IERC1155MetadataURI\\n} from \\\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\\\";\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport {ERC1155Utils} from \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol\\\";\\nimport {Arrays} from \\\"@openzeppelin/contracts/utils/Arrays.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {IERC1155Singleton} from \\\"./interfaces/IERC1155Singleton.sol\\\";\\n\\n/// @notice ERC1155 variant enforcing exactly one owner per token ID.\\n///\\n/// Instead of the standard nested balance mapping (`id \\u2192 address \\u2192 balance`), uses a flat\\n/// `id \\u2192 address` ownership mapping. `balanceOf` returns 1 if the account is the owner,\\n/// 0 otherwise. Transferring value > 1 reverts.\\n///\\n/// Used by `PermissionedRegistry` to represent domain name ownership as non-divisible tokens.\\n/// The registry overrides `ownerOf` to add expiry and version validation on top of raw ownership.\\n///\\n/// @author OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC1155/ERC1155.sol)\\n/// @dev This contract has been modified from the implementation at the above link.\\nabstract contract ERC1155Singleton is\\n ERC165,\\n IERC1155Singleton,\\n IERC1155Errors,\\n IERC1155MetadataURI\\n{\\n using Arrays for uint256[];\\n\\n using Arrays for address[];\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Maps each token ID to its single owner address.\\n mapping(uint256 id => address account) private _owners;\\n\\n /// @dev Standard ERC1155 operator approval mapping.\\n mapping(address account => mapping(address operator => bool)) private _operatorApprovals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155Singleton).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Sets the approval for all operator.\\n /// @param operator The operator to set the approval for.\\n /// @param approved The approval status.\\n function setApprovalForAll(address operator, bool approved) public virtual {\\n _setApprovalForAll(msg.sender, operator, approved);\\n }\\n\\n /// @notice Transfers a single token from one address to another.\\n /// @param from The address to transfer the token from.\\n /// @param to The address to transfer the token to.\\n /// @param id The token ID.\\n /// @param value The amount of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `to` cannot be the zero address.\\n /// @dev If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.\\n /// @dev `from` must have a balance of tokens of type `id` of at least `value` amount.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the\\n /// acceptance magic value.\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data)\\n public\\n virtual\\n {\\n _checkApproval(from, msg.sender);\\n _safeTransferFrom(from, to, id, value, data);\\n }\\n\\n /// @notice Transfers multiple tokens from one address to another.\\n /// @param from The address to transfer the tokens from.\\n /// @param to The address to transfer the tokens to.\\n /// @param ids The token IDs.\\n /// @param values The amounts of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `ids` and `values` must have the same length.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the\\n /// acceptance magic value.\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n public\\n virtual\\n {\\n _checkApproval(from, msg.sender);\\n _safeBatchTransferFrom(from, to, ids, values, data);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 id) public view virtual returns (address owner) {\\n return _owners[id];\\n }\\n\\n /// @notice Returns the URI for a token.\\n /// @param id The token ID.\\n /// @return uri The URI for the token.\\n function uri(uint256 id) public view virtual returns (string memory uri);\\n\\n /// @notice Returns the balance of a token for an account.\\n /// @param account The account to get the balance for.\\n /// @param id The token ID.\\n /// @return balance The balance of the token for the account. This will only ever be 1 or 0.\\n function balanceOf(address account, uint256 id) public view virtual returns (uint256) {\\n return account != address(0) && ownerOf(id) == account ? 1 : 0;\\n }\\n\\n /// @notice Returns the balances of a batch of tokens for an account.\\n /// @param accounts The accounts to get the balances for.\\n /// @param ids The token IDs.\\n /// @return batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\\n /// @dev `accounts` and `ids` must have the same length.\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n returns (uint256[] memory)\\n {\\n if (accounts.length != ids.length) {\\n revert ERC1155InvalidArrayLength(ids.length, accounts.length);\\n }\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));\\n }\\n\\n return batchBalances;\\n }\\n\\n /// @notice Returns the approval for all operator.\\n /// @param account The account to get the approval for.\\n /// @param operator The operator to get the approval for.\\n /// @return approved The approval status.\\n function isApprovedForAll(address account, address operator) public view virtual returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Apply token updates for each pair in `ids` and `values`.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not the current owner or `value > 1`.\\n /// @dev This function does not perform ERC-1155 receiver acceptance checks.\\n /// @dev Emits `TransferSingle` when one token ID is updated, otherwise emits `TransferBatch`.\\n function _update(address from, address to, uint256[] memory ids, uint256[] memory values)\\n internal\\n virtual\\n {\\n if (ids.length != values.length) {\\n revert ERC1155InvalidArrayLength(ids.length, values.length);\\n }\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids.unsafeMemoryAccess(i);\\n uint256 value = values.unsafeMemoryAccess(i);\\n\\n if (value > 0) {\\n address owner = _owners[id];\\n if (owner != from) {\\n revert ERC1155InsufficientBalance(from, 0, value, id);\\n } else if (value > 1) {\\n revert ERC1155InsufficientBalance(from, 1, value, id);\\n }\\n _owners[id] = to;\\n }\\n }\\n\\n if (ids.length == 1) {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n emit TransferSingle(msg.sender, from, to, id, value);\\n } else {\\n emit TransferBatch(msg.sender, from, to, ids, values);\\n }\\n }\\n\\n /// @notice Apply token updates and run ERC-1155 receiver acceptance checks.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @param batch `true` if a batch operation.\\n /// @dev Calls `_update` before external receiver callbacks.\\n /// @dev If `to` is a contract, this calls `onERC1155Received` or `onERC1155BatchReceived`.\\n /// @dev Overriding is discouraged because post-callback state writes can introduce reentrancy bugs.\\n function _updateWithAcceptanceCheck(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data,\\n bool batch\\n )\\n internal\\n virtual\\n {\\n _update(from, to, ids, values);\\n if (to != address(0)) {\\n if (batch) {\\n ERC1155Utils.checkOnERC1155BatchReceived(msg.sender, from, to, ids, values, data);\\n } else {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n ERC1155Utils.checkOnERC1155Received(msg.sender, from, to, id, value, data);\\n }\\n }\\n }\\n\\n /// @notice Safely transfer `value` tokens of token ID `id` from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param id Token ID to transfer.\\n /// @param value Amount to transfer.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, to, ids, values, data, false);\\n }\\n\\n /// @notice Safely transfer multiple token IDs from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param ids Token IDs to transfer.\\n /// @param values Amounts to transfer for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferBatch`.\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n _updateWithAcceptanceCheck(from, to, ids, values, data, true);\\n }\\n\\n /// @notice Mint `value` tokens of token ID `id` to `to`.\\n /// @param to Address receiving the minted token.\\n /// @param id Token ID to mint.\\n /// @param value Amount to mint.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(address(0), to, ids, values, data, false);\\n }\\n\\n /// @notice Burn `value` tokens of token ID `id` from `from`.\\n /// @param from Address to burn from.\\n /// @param id Token ID to burn.\\n /// @param value Amount to burn.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not current owner or `value > 1`.\\n /// @dev Emits `TransferSingle`.\\n function _burn(address from, uint256 id, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, address(0), ids, values, \\\"\\\", false);\\n }\\n\\n /// @notice Set or clear approval for `operator` to manage all tokens owned by `owner`.\\n /// @param owner Token owner granting or revoking approval.\\n /// @param operator Operator receiving approval.\\n /// @param approved Approval status to set.\\n /// @dev Reverts with `ERC1155InvalidOperator` if `operator` is the zero address.\\n /// @dev Emits `ApprovalForAll`.\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n if (operator == address(0)) {\\n revert ERC1155InvalidOperator(address(0));\\n }\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Ensure operator is approved.\\n function _checkApproval(address from, address operator) private view {\\n if (from != operator && !isApprovedForAll(from, operator)) {\\n revert ERC1155MissingApprovalForAll(operator, from);\\n }\\n }\\n\\n /// @dev Gas-optimized assembly helper that creates two length-1 memory arrays without Solidity's\\n /// default zero-initialization overhead. Used to adapt single-token operations (`_mint`,\\n /// `_burn`, `_safeTransferFrom`) to the array-based `_update` function.\\n function _asSingletonArrays(uint256 element1, uint256 element2)\\n private\\n pure\\n returns (uint256[] memory array1, uint256[] memory array2)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Load the free memory pointer\\n array1 := mload(0x40)\\n // Set array length to 1\\n mstore(array1, 1)\\n // Store the single element at the next word after the length (where content starts)\\n mstore(add(array1, 0x20), element1)\\n\\n // Repeat for next array locating it right after the first array\\n array2 := add(array1, 0x40)\\n mstore(array2, 1)\\n mstore(add(array2, 0x20), element2)\\n\\n // Update the free memory pointer by pointing after the second array\\n mstore(0x40, add(array2, 0x40))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7e1c260a1b1791a63a658f049251b2b5390d9e11cdb20d99a2d115083251d37e\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/PermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IEnhancedAccessControl} from \\\"../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {ERC1155Singleton} from \\\"../erc1155/ERC1155Singleton.sol\\\";\\nimport {IERC1155Singleton} from \\\"../erc1155/interfaces/IERC1155Singleton.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {ILabelStore} from \\\"../utils/interfaces/ILabelStore.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./interfaces/IOwnedRegistry.sol\\\";\\nimport {IPermissionedRegistry} from \\\"./interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"./interfaces/IRegistry.sol\\\";\\nimport {IRegistryURIRenderer} from \\\"./interfaces/IRegistryURIRenderer.sol\\\";\\nimport {IStandardRegistry} from \\\"./interfaces/IStandardRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./interfaces/ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./interfaces/ITokenizedRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"./libraries/RegistryRolesLib.sol\\\";\\n\\n/// @notice A tokenized (ERC1155) registry with resource-scoped access control for subdomain management.\\n///\\n/// Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource\\n/// interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`)\\n/// to resolve any of these to the canonical storage slot for the name.\\n///\\n/// The registry maintains two independent version counters per name:\\n/// - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form\\n/// the EAC resource ID. This means a re-registered name gets a fresh permission scope.\\n/// - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint)\\n/// due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring\\n/// changes to roles create new tokens and prevent frontrunning a transfer with a role revocation.\\n///\\n/// Names are treated as `AVAILABLE` once `block.timestamp >= expiry`.\\n///\\n/// State diagram:\\n///\\n/// register()\\n/// +ROLE_REGISTRAR\\n/// +------------------->----------------------+\\n/// | |\\n/// | renew() | renew()\\n/// | +ROLE_RENEW | +ROLE_RENEW\\n/// | +------+ | +------+\\n/// | | | | | |\\n/// \\u028c \\u028c v v v |\\n/// AVAILABLE --------> RESERVED -------------> REGISTERED >--+\\n/// \\u028c register() v register() v\\n/// | w/owner=0 | +ROLE_REGISTER_RESERVED |\\n/// | +ROLE_REGISTRAR | |\\n/// | | |\\n/// +--------<---------+------------<------------+\\n/// unregister()\\n/// +ROLE_UNREGISTER\\n///\\ncontract PermissionedRegistry is ERC1155Singleton, EnhancedAccessControl, IPermissionedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n struct Entry {\\n /// @dev Incremented on unregister; combined with labelhash to form the EAC resource ID.\\n uint32 eacVersionId;\\n /// @dev Incremented on unregister and on token regeneration; combined with labelhash to form the ERC1155 token ID.\\n uint32 tokenVersionId;\\n /// @dev Child registry for this name.\\n IRegistry subregistry;\\n /// @dev Timestamp at or after which the name is considered expired/available.\\n uint64 expiry;\\n /// @dev Resolver address for this name.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The shared label database.\\n ILabelStore public immutable LABEL_STORE;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The parent registry of this registry.\\n IRegistry internal _parentRegistry;\\n\\n /// @dev The child label of this registry.\\n string internal _childLabel;\\n\\n /// @dev The metadata URI.\\n string internal _uri;\\n\\n /// @dev The metadata renderer.\\n IRegistryURIRenderer internal _uriRenderer;\\n\\n /// @dev The entries of this registry.\\n mapping(uint256 storageId => Entry entry) internal _entries;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param labelStore The shared label database.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n constructor(ILabelStore labelStore, address rootAccount, uint256 roleBitmap) {\\n emit RegistryCreated();\\n LABEL_STORE = labelStore;\\n _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false);\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(IERC165, ERC1155Singleton, EnhancedAccessControl)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IPermissionedRegistry).interfaceId ||\\n interfaceId == type(IStandardRegistry).interfaceId ||\\n interfaceId == type(ITokenizedRegistry).interfaceId ||\\n interfaceId == type(ITemporalRegistry).interfaceId ||\\n interfaceId == type(IOwnedRegistry).interfaceId ||\\n interfaceId == type(IRegistry).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IStandardRegistry\\n function setSubregistry(uint256 anyId, IRegistry registry) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_SUBREGISTRY);\\n entry.subregistry = registry;\\n emit SubregistryUpdated(tokenId, registry, msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setResolver(uint256 anyId, address resolver) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_RESOLVER);\\n entry.resolver = resolver;\\n emit ResolverUpdated(tokenId, resolver, msg.sender);\\n }\\n\\n /// @notice Set the URI for the registry.\\n /// @param uri_ The new URI.\\n /// @param renderer The new renderer address.\\n function setURI(string calldata uri_, IRegistryURIRenderer renderer)\\n public\\n virtual\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_URI)\\n {\\n _uri = uri_;\\n _uriRenderer = renderer;\\n emit URIUpdated(uri_, address(renderer), msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setParent(IRegistry parent, string memory label)\\n public\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_PARENT)\\n {\\n _parentRegistry = parent;\\n _childLabel = label;\\n emit ParentUpdated(parent, label, msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n public\\n virtual\\n returns (uint256)\\n {\\n return _register(label, owner, registry, resolver, roleBitmap, expiry, true);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\\n function unregister(uint256 anyId) public {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_UNREGISTER);\\n emit LabelUnregistered(tokenId, msg.sender);\\n address owner = super.ownerOf(tokenId);\\n if (owner != address(0)) {\\n _burn(owner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n }\\n entry.expiry = uint64(block.timestamp);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev If `REGISTERED | RESERVED`, requires `ROLE_RENEW`.\\n /// If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\\n function renew(uint256 anyId, uint64 newExpiry) public override {\\n Entry storage entry = _entry(anyId);\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n uint64 expiry = entry.expiry;\\n if (_isExpired(expiry)) {\\n if (expiry == 0 || !_canRevive(tokenId, msg.sender)) {\\n revert LabelExpired(tokenId); // never registered OR cannot revive\\n }\\n } else {\\n _checkRoles(_constructResource(anyId, entry), RegistryRolesLib.ROLE_RENEW, msg.sender);\\n }\\n if (newExpiry < expiry) {\\n revert CannotReduceExpiry(expiry, newExpiry);\\n }\\n entry.expiry = newExpiry;\\n emit ExpiryUpdated(tokenId, newExpiry, msg.sender);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function grantRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.grantRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function revokeRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.revokeRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IRegistry\\n function getSubregistry(string calldata label) public view virtual returns (IRegistry) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? IRegistry(address(0)) : entry.subregistry;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getResolver(string calldata label) public view virtual returns (address) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? address(0) : entry.resolver;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getParent() public view returns (IRegistry parent, string memory label) {\\n return (_parentRegistry, _childLabel);\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) public view virtual returns (bool) {\\n return hasRootRoles(RegistryRolesLib.ROLE_CAN_NAME, namer);\\n }\\n\\n /// @inheritdoc ITemporalRegistry\\n function findExpiry(string calldata label) public view returns (uint64) {\\n return getExpiry(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc IOwnedRegistry\\n function findOwner(string calldata label) public view returns (address) {\\n return getOwner(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ITokenizedRegistry\\n function findTokenId(string calldata label) public view returns (uint256) {\\n return getTokenId(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ERC1155Singleton\\n function uri(uint256 tokenId) public view override returns (string memory) {\\n return\\n address(_uriRenderer) != address(0)\\n ? _uriRenderer.renderURI(this, tokenId)\\n : _uri;\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function getExpiry(uint256 anyId) public view returns (uint64) {\\n return _entry(anyId).expiry;\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getResource(uint256 anyId) public view returns (uint256) {\\n return _constructResource(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getTokenId(uint256 anyId) public view returns (uint256) {\\n return _constructTokenId(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getOwner(uint256 anyId) public view returns (address) {\\n return _isExpired(getExpiry(anyId)) ? address(0) : super.ownerOf(getTokenId(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getStatus(uint256 anyId) public view returns (Status) {\\n Entry storage entry = _entry(anyId);\\n return _constructStatus(entry.expiry, super.ownerOf(_constructTokenId(anyId, entry)));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getState(uint256 anyId) public view returns (State memory state) {\\n Entry storage entry = _entry(anyId);\\n uint64 expiry = entry.expiry;\\n state.expiry = expiry;\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n state.tokenId = tokenId;\\n state.resource = _constructResource(anyId, entry);\\n address owner = super.ownerOf(tokenId);\\n state.latestOwner = owner;\\n state.status = _constructStatus(expiry, owner);\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function latestOwnerOf(uint256 tokenId) public view returns (address) {\\n return super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 tokenId)\\n public\\n view\\n override(ERC1155Singleton, IERC1155Singleton)\\n returns (address)\\n {\\n Entry storage entry = _entry(tokenId);\\n return\\n tokenId != _constructTokenId(tokenId, entry) || _isExpired(entry.expiry)\\n ? address(0)\\n : super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 anyId, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roles(getResource(anyId), account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 anyId)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roleCount(getResource(anyId));\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasAssignees(getResource(anyId), roleBitmap);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256 counts, uint256 mask)\\n {\\n return super.getAssigneeCount(getResource(anyId), roleBitmap);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev If `AVAILABLE`, requires `ROLE_REGISTRAR` on root and status becomes `REGISTERED`.\\n /// * If `owner` is null (`roleBitmap` must be 0), status becomes `RESERVED`.\\n /// If `RESERVED`, requires `ROLE_REGISTER_RESERVED` on root and status becomes `REGISTERED`.\\n /// * If `expiry` is 0, uses current expiry.\\n function _register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry,\\n bool checkRoles\\n )\\n internal\\n returns (uint256 tokenId)\\n {\\n LABEL_STORE.setLabel(label);\\n uint256 labelId = LibLabel.id(label);\\n Entry storage entry = _entry(labelId);\\n tokenId = _constructTokenId(labelId, entry);\\n address prevOwner = super.ownerOf(tokenId);\\n if (_isExpired(entry.expiry)) {\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTRAR, msg.sender);\\n }\\n if (owner == address(0) && roleBitmap != 0) {\\n revert EACCannotGrantRoles(ROOT_RESOURCE, roleBitmap, msg.sender); // strict\\n }\\n } else {\\n if (prevOwner != address(0)) {\\n revert LabelAlreadyRegistered(label); // cannot overwrite REGISTERED\\n } else if (owner == address(0)) {\\n revert LabelAlreadyReserved(label); // cannot overwrite RESERVED\\n }\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTER_RESERVED, msg.sender);\\n }\\n if (expiry == 0) {\\n expiry = entry.expiry; // use RESERVED expiry\\n }\\n roleBitmap |= RegistryRolesLib.ROLE_WAS_RESERVED; // remember\\n }\\n if (owner == address(0) ? expiry == 0 : _isExpired(expiry)) {\\n revert CannotSetPastExpiry(expiry);\\n }\\n if (prevOwner != address(0)) {\\n _burn(prevOwner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n tokenId = _constructTokenId(tokenId, entry);\\n }\\n entry.expiry = expiry;\\n entry.subregistry = registry;\\n entry.resolver = resolver;\\n if (owner == address(0)) {\\n emit LabelReserved(tokenId, bytes32(labelId), label, expiry, msg.sender);\\n } else {\\n emit LabelRegistered(tokenId, bytes32(labelId), label, owner, expiry, msg.sender);\\n _mint(owner, tokenId, 1, \\\"\\\");\\n uint256 resource = _constructResource(tokenId, entry);\\n assert(resource != ROOT_RESOURCE);\\n emit TokenResource(tokenId, resource);\\n _grantRoles(resource, roleBitmap, owner, false);\\n }\\n if (address(registry) != address(0)) {\\n emit SubregistryUpdated(tokenId, registry, msg.sender);\\n }\\n if (address(resolver) != address(0)) {\\n emit ResolverUpdated(tokenId, resolver, msg.sender);\\n }\\n }\\n\\n /// @dev Override `ERC1155Singleton._update()` to transfer the roles to the new owner if the token is transferred.\\n function _update(address from, address to, uint256[] memory tokenIds, uint256[] memory amounts)\\n internal\\n override\\n {\\n super._update(from, to, tokenIds, amounts); // ensures amounts[i] is 0 or 1\\n if (to != address(0) && from != address(0)) {\\n // only transfers (skip mint and burn)\\n for (uint256 i; i < tokenIds.length; ++i) {\\n uint256 tokenId = tokenIds[i];\\n // only check ROLE_CAN_TRANSFER_ADMIN on original owner (from)\\n // ROLE_CAN_TRANSFER_ADMIN is technically a property of the token\\n if (!hasRoles(tokenId, RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, from)) {\\n revert TransferDisallowed(tokenId, from);\\n } else if (amounts[i] > 0) {\\n _transferRoles(getResource(tokenId), from, to, false);\\n }\\n }\\n }\\n }\\n\\n /// @dev Override the base registry _onRolesGranted function to regenerate the token when the roles are granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Override the base registry _onRolesRevoked function to regenerate the token when the roles are revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Bump `tokenVersionId` via burn+mint if token is not expired.\\n function _regenerate(uint256 resource) internal {\\n if (resource != ROOT_RESOURCE) {\\n Entry storage entry = _entry(resource);\\n uint256 tokenId = _constructTokenId(resource, entry);\\n address owner = super.ownerOf(tokenId); // grant/revoke only on registered\\n _burn(owner, tokenId, 1);\\n ++entry.tokenVersionId;\\n uint256 newTokenId = _constructTokenId(tokenId, entry);\\n emit TokenRegenerated(tokenId, newTokenId); // resource is unchanged\\n _mint(owner, newTokenId, 1, \\\"\\\");\\n }\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token non-admin roles can only be granted to registered tokens.\\n ///\\n /// Token admin roles are only assigned during name registration to maintain\\n /// controlled permission management. This ensures that role delegation\\n /// follows the intended security model where admin privileges are granted at\\n /// registration time and cannot be arbitrarily granted afterward.\\n ///\\n /// Root admin roles are unaffected.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles (regular roles only, not admin roles).\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n if (resource != ROOT_RESOURCE && getOwner(resource) == address(0)) {\\n return 0;\\n }\\n uint256 roleBitmap = super._getSettableRoles(resource, account);\\n return resource == ROOT_RESOURCE ? roleBitmap : roleBitmap >> 128;\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// * if caller is approved by token owner, combine the caller's roles with the owner's roles\\n ///\\n function _getRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n override\\n returns (uint256 roleBitmap)\\n {\\n roleBitmap = super._getRoles(resource, account);\\n if (resource != ROOT_RESOURCE) {\\n address owner = getOwner(resource);\\n if (owner != address(0) && owner != account && isApprovedForAll(owner, account)) {\\n roleBitmap |= super._getRoles(resource, owner);\\n }\\n }\\n }\\n\\n /// @dev Zeroes version bits in `anyId` to return the canonical storage entry for the name.\\n function _entry(uint256 anyId) internal view returns (Entry storage) {\\n return _entries[LibLabel.withVersion(anyId, 0)];\\n }\\n\\n /// @dev Determine if token can be revived.\\n function _canRevive(\\n uint256 /*tokenId*/,\\n address sender\\n )\\n internal\\n view\\n virtual\\n returns (bool)\\n {\\n return hasRootRoles(RegistryRolesLib.ROLE_RENEW, sender);\\n }\\n\\n /// @dev Assert token is not expired and caller has necessary roles.\\n function _checkExpiryAndTokenRoles(uint256 anyId, uint256 roleBitmap)\\n internal\\n view\\n returns (uint256 tokenId, Entry storage entry)\\n {\\n entry = _entry(anyId);\\n tokenId = _constructTokenId(anyId, entry);\\n if (_isExpired(entry.expiry)) {\\n revert LabelExpired(tokenId);\\n }\\n _checkRoles(_constructResource(anyId, entry), roleBitmap, msg.sender);\\n }\\n\\n /// @dev Internal logic for expired status.\\n function _isExpired(uint64 expiry) internal view returns (bool) {\\n return block.timestamp >= expiry;\\n }\\n\\n /// @dev Create `resource` from parts.\\n /// Does nothing if `ROOT_RESOURCE`.\\n /// Returns next resource if expired.\\n function _constructResource(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n if (anyId == ROOT_RESOURCE) {\\n return anyId;\\n }\\n return\\n LibLabel.withVersion(\\n anyId,\\n _isExpired(entry.expiry)\\n ? entry.eacVersionId + 1\\n : entry.eacVersionId\\n );\\n }\\n\\n /// @dev Create `tokenId` from parts.\\n function _constructTokenId(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n return LibLabel.withVersion(anyId, entry.tokenVersionId);\\n }\\n\\n /// @dev Create `Status` from parts.\\n function _constructStatus(uint64 expiry, address owner) internal view returns (Status) {\\n if (_isExpired(expiry)) {\\n return Status.AVAILABLE;\\n } else if (owner == address(0)) {\\n return Status.RESERVED;\\n } else {\\n return Status.REGISTERED;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7df0d16fb74e67612b88f2143f142410c70a4079a21c0980b2063824e291942b\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryURIRenderer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6c55e19b`\\ninterface IRegistryURIRenderer {\\n /// @notice Generate URI for `tokenId` from `registry`.\\n /// @param registry The registry.\\n /// @param tokenId The token ID in the registry.\\n /// @return The generated URI.\\n function renderURI(IRegistry registry, uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa6ea64ff73d10fa58118ae9c0d0c2caa72f2f3488776227a22bd0cd9cd6586f6\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 39: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 62: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x01771816c1c5b16c10f29b33083dbd1cc2eb64dbfec60fb45a1a1969cec06624\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/interfaces/ILabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @notice Interface for a shared label database.\\n/// @dev Interface selector: `0x0d48fe93`\\ninterface ILabelStore {\\n /// @notice A label was recorded.\\n /// @param labelHash The hash of `label`.\\n /// @param label The recorded label.\\n event Label(bytes32 indexed labelHash, string label);\\n\\n /// @notice Ensure `label` can be inverted from `anyId`.\\n /// @param label The label.\\n function setLabel(string calldata label) external;\\n\\n /// @notice Invert `anyId` to the corresponding label.\\n /// @param anyId The truncated labelhash.\\n /// @return The label or null if unknown.\\n function getLabel(uint256 anyId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 24185, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_owners", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 24192, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 21770, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_roles", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 21775, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_roleCount", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 21780, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "__gap", + "offset": 0, + "slot": "4", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 28818, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_parentRegistry", + "offset": 0, + "slot": "260", + "type": "t_contract(IRegistry)30865" + }, + { + "astId": 28821, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_childLabel", + "offset": 0, + "slot": "261", + "type": "t_string_storage" + }, + { + "astId": 28824, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_uri", + "offset": 0, + "slot": "262", + "type": "t_string_storage" + }, + { + "astId": 28828, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_uriRenderer", + "offset": 0, + "slot": "263", + "type": "t_contract(IRegistryURIRenderer)30980" + }, + { + "astId": 28834, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "_entries", + "offset": 0, + "slot": "264", + "type": "t_mapping(t_uint256,t_struct(Entry)28810_storage)" + }, + { + "astId": 28839, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "__gap", + "offset": 0, + "slot": "265", + "type": "t_array(t_uint256)256_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRegistry)30865": { + "encoding": "inplace", + "label": "contract IRegistry", + "numberOfBytes": "20" + }, + "t_contract(IRegistryURIRenderer)30980": { + "encoding": "inplace", + "label": "contract IRegistryURIRenderer", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "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_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_struct(Entry)28810_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct PermissionedRegistry.Entry)", + "numberOfBytes": "32", + "value": "t_struct(Entry)28810_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Entry)28810_storage": { + "encoding": "inplace", + "label": "struct PermissionedRegistry.Entry", + "members": [ + { + "astId": 28796, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "eacVersionId", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 28799, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "tokenVersionId", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 28803, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "subregistry", + "offset": 8, + "slot": "0", + "type": "t_contract(IRegistry)30865" + }, + { + "astId": 28806, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "expiry", + "offset": 0, + "slot": "1", + "type": "t_uint64" + }, + { + "astId": 28809, + "contract": "project/src/registry/PermissionedRegistry.sol:PermissionedRegistry", + "label": "resolver", + "offset": 8, + "slot": "1", + "type": "t_address" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "notice": "Label expiry cannot be reduced." + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "notice": "Label expiry cannot be before now." + } + ], + "LabelAlreadyRegistered(string)": [ + { + "notice": "Label is already registered." + } + ], + "LabelAlreadyReserved(string)": [ + { + "notice": "Label cannot be reserved again." + } + ], + "LabelExpired(uint256)": [ + { + "notice": "Label is expired/unregistered." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "notice": "Transfer is not allowed due to missing transfer admin role." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "ExpiryUpdated(uint256,uint64,address)": { + "notice": "Expiry of label was changed." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "notice": "A label was registered." + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "notice": "A label was reserved." + }, + "LabelUnregistered(uint256,address)": { + "notice": "A label was unregistered." + }, + "ParentUpdated(address,string,address)": { + "notice": "Parent was changed." + }, + "RegistryCreated()": { + "notice": "A registry was created/initialized." + }, + "ResolverUpdated(uint256,address,address)": { + "notice": "Resolver of label was changed." + }, + "SubregistryUpdated(uint256,address,address)": { + "notice": "Subregistry of label was changed." + }, + "TokenRegenerated(uint256,uint256)": { + "notice": "Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance." + }, + "TokenResource(uint256,uint256)": { + "notice": "Associate a token with an EAC resource." + }, + "URIUpdated(string,address,address)": { + "notice": "URI was changed." + } + }, + "kind": "user", + "methods": { + "LABEL_STORE()": { + "notice": "The shared label database." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "balanceOf(address,uint256)": { + "notice": "Returns the balance of a token for an account." + }, + "balanceOfBatch(address[],uint256[])": { + "notice": "Returns the balances of a batch of tokens for an account." + }, + "findExpiry(string)": { + "notice": "Fetches the label expiry." + }, + "findOwner(string)": { + "notice": "Fetches the label owner." + }, + "findTokenId(string)": { + "notice": "Fetches the token ID for a label." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getExpiry(uint256)": { + "notice": "Get expiry of label." + }, + "getOwner(uint256)": { + "notice": "Get token owner from `anyId`." + }, + "getParent()": { + "notice": "Get canonical \"location\" of this registry." + }, + "getResolver(string)": { + "notice": "Fetches the resolver responsible for the specified label." + }, + "getResource(uint256)": { + "notice": "Get `resource` from `anyId`." + }, + "getState(uint256)": { + "notice": "Get the state of a label." + }, + "getStatus(uint256)": { + "notice": "Get `Status` from `anyId`." + }, + "getSubregistry(string)": { + "notice": "Fetches the registry for a label." + }, + "getTokenId(uint256)": { + "notice": "Get `tokenId` from `anyId`." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "isApprovedForAll(address,address)": { + "notice": "Returns the approval for all operator." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "latestOwnerOf(uint256)": { + "notice": "Get the latest owner of a token. If the token was burned, returns null." + }, + "ownerOf(uint256)": { + "notice": "Returns the owner of a token." + }, + "register(string,address,address,address,uint256,uint64)": { + "notice": "Registers a new label." + }, + "renew(uint256,uint64)": { + "notice": "Renew a label." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "notice": "Transfers multiple tokens from one address to another." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "notice": "Transfers a single token from one address to another." + }, + "setApprovalForAll(address,bool)": { + "notice": "Sets the approval for all operator." + }, + "setParent(address,string)": { + "notice": "Change canonical \"location\"." + }, + "setResolver(uint256,address)": { + "notice": "Change resolver of label." + }, + "setSubregistry(uint256,address)": { + "notice": "Change registry of label." + }, + "setURI(string,address)": { + "notice": "Set the URI for the registry." + }, + "unregister(uint256)": { + "notice": "Delete a label." + }, + "uri(uint256)": { + "notice": "Returns the URI for a token." + } + }, + "notice": "A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`) to resolve any of these to the canonical storage slot for the name. The registry maintains two independent version counters per name: - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form the EAC resource ID. This means a re-registered name gets a fresh permission scope. - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint) due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring changes to roles create new tokens and prevent frontrunning a transfer with a role revocation. Names are treated as `AVAILABLE` once `block.timestamp >= expiry`. State diagram: register() +ROLE_REGISTRAR +------------------->----------------------+ | | | renew() | renew() | +ROLE_RENEW | +ROLE_RENEW | +------+ | +------+ | | | | | | ʌ ʌ v v v | AVAILABLE --------> RESERVED -------------> REGISTERED >--+ ʌ register() v register() v | w/owner=0 | +ROLE_REGISTER_RESERVED | | +ROLE_REGISTRAR | | | | | +--------<---------+------------<------------+ unregister() +ROLE_UNREGISTER", + "version": 1 + }, + "argsData": "0x000000000000000000000000b03524289c16424f71802a1794c29c7bd1b9f57700000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d30100000000000000000000100001011101000000000000000000001000010111", + "transaction": { + "hash": "0xaaa9c3f6693488c95105f1bd6ce43c9bfbff6cda9ec9a2b4256ca56d9bd844fb", + "nonce": "0xe", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xca37d5f79c727aaaef02d8077d7f2373040e272e9ff4decff36734ee89a188b0", + "blockNumber": "0xaa56b7", + "transactionIndex": "0x54" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/StandardRentPriceOracle.json b/contracts/deployments/sepolia/StandardRentPriceOracle.json new file mode 100644 index 000000000..6e04490b3 --- /dev/null +++ b/contracts/deployments/sepolia/StandardRentPriceOracle.json @@ -0,0 +1,1729 @@ +{ + "address": "0x09340d50a6489e7bfb2959acc4e32bcbc401e203", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "baseRatePerCp", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + } + ], + "internalType": "struct DiscountPoint[]", + "name": "discountPoints", + "type": "tuple[]" + }, + { + "internalType": "uint128", + "name": "discountDenominator", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "premiumPriceInitial", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "premiumHalvingPeriod", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "premiumPeriod", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "denom", + "type": "uint128" + } + ], + "internalType": "struct PaymentRatio[]", + "name": "paymentRatios", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBaseRates", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDiscount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRatio", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "NotValid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "PaymentTokenNotSupported", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "numer", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "denom", + "type": "uint128" + } + ], + "name": "PaymentTokenUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DISCOUNT_DENOMINATOR", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIUM_HALVING_PERIOD", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIUM_PERIOD", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIUM_PRICE_INITIAL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PREMIUM_PRICE_OFFSET", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + } + ], + "name": "applyDiscount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "convertUnits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "disablePaymentToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + } + ], + "name": "getBasePrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBaseRates", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDiscountPoints", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + } + ], + "internalType": "struct DiscountPoint[]", + "name": "v", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getPaymentTokenRatio", + "outputs": [ + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "denom", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + } + ], + "name": "getPremiumPriceAfter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "available", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRegisterPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "base", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "premium", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "duration", + "type": "uint64" + }, + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "getRenewPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + } + ], + "name": "isPaymentToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "isValid", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "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": [ + { + "internalType": "contract IERC20", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "uint128", + "name": "numer", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "denom", + "type": "uint128" + } + ], + "name": "updatePaymentToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "contractName": "StandardRentPriceOracle", + "sourceName": "src/registrar/StandardRentPriceOracle.sol", + "bytecode": "0x610120604052348015610010575f80fd5b50604051612ef6380380612ef683398101604081905261002f91610c7e565b61004d5f710111000000000000000000000000000001118a8261032c565b5086515f0361006f5760405163de27644760e01b815260040160405180910390fd5b8651610083906101029060208a0190610987565b50855180156101cc575f86815b83811015610192575f8a82815181106100ab576100ab610d4b565b60200260200101519050836001600160401b0316815f01516001600160401b03161115806100ef5750826001600160801b031681602001516001600160801b031610155b1561010d576040516304cbf51b60e51b815260040160405180910390fd5b80516020820180516101038054600181810183555f9290925294517f02c297ab74aad0aede3a1895c857b1f2c71e6a203feb727bec95ac752998cb78909501805493516001600160801b031668010000000000000000026001600160c01b03199094166001600160401b03909616959095179290921790935590945090925001610090565b50806001600160801b03165f036101bc576040516304cbf51b60e51b815260040160405180910390fd5b50506001600160801b0386166080525b60a08590526001600160401b0380851660c081905290841660e08190526101f4918791610427565b610100525f5b825181101561031d575f83828151811061021657610216610d4b565b6020026020010151905080602001516001600160801b03165f1480610246575060408101516001600160801b0316155b156102645760405163648564d360e01b815260040160405180910390fd5b604080518082018252602080840180516001600160801b0390811684528585018051821684860190815287516001600160a01b039081165f90815261010490965294879020955190518316600160801b0292169190911790935584519051925193519116927f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede49261030c929091906001600160801b0392831681529116602082015260400190565b60405180910390a2506001016101fa565b50505050505050505050610dcf565b5f835f0361033b57505f61041f565b610344846104cf565b6001600160a01b03831661036b5760405163761fe2c960e11b815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214610419575f878152602081815260408083206001600160a01b03891684529091529020819055811986166103c78882600161051b565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a36001935050505061041f565b5f925050505b949350505050565b5f831580610433575082155b1561043f57505f6104c8565b815f0361044d5750826104c8565b5f83610461670de0b6b3a764000085610d73565b61046b9190610d8a565b90505f610480670de0b6b3a764000083610d8a565b90505f610495670de0b6b3a764000083610d73565b61049f9084610da9565b90506104c287831c6104bd670de0b6b3a7640000601085901b610d8a565b61064b565b93505050505b9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561051857604051630153d96960e51b8152600481018290526024015b60405180910390fd5b50565b5f6105258361096d565b905081156105bb575f8481526001602052604090205461056b9082161980195f80516020612ed683398151915291909101165f80516020612eb683398151915216151590565b1561059357604051631f22ca6960e31b8152600481018590526024810184905260440161050f565b5f84815260016020526040812080548592906105b0908490610dbc565b909155506106459050565b5f848152600160205260409020546105fa901982161980195f80516020612ed683398151915291909101165f80516020612eb683398151915216151590565b1561062257604051631f80c19b60e01b8152600481018590526024810184905260440161050f565b5f848152600160205260408120805485929061063f908490610da9565b90915550505b50505050565b5f600182161561067d57670de0b6b3a7640000610670670de0ad151d09418085610d73565b61067a9190610d8a565b92505b60028216156106ae57670de0b6b3a76400006106a1670de0a3769959680085610d73565b6106ab9190610d8a565b92505b60048216156106df57670de0b6b3a76400006106d2670de09039a5fa510085610d73565b6106dc9190610d8a565b92505b600882161561071057670de0b6b3a7640000610703670de069c00f3e120085610d73565b61070d9190610d8a565b92505b601082161561074157670de0b6b3a7640000610734670de01cce21c9440085610d73565b61073e9190610d8a565b92505b602082161561077257670de0b6b3a7640000610765670ddf82ef46ce100085610d73565b61076f9190610d8a565b92505b60408216156107a357670de0b6b3a7640000610796670dde4f458f8e8d8085610d73565b6107a09190610d8a565b92505b60808216156107d457670de0b6b3a76400006107c7670ddbe84213d5f08085610d73565b6107d19190610d8a565b92505b61010082161561080657670de0b6b3a76400006107f9670dd71b7aa6df5b8085610d73565b6108039190610d8a565b92505b61020082161561083857670de0b6b3a764000061082b670dcd86e7f28cde0085610d73565b6108359190610d8a565b92505b61040082161561086a57670de0b6b3a764000061085d670dba71a3084ad68085610d73565b6108679190610d8a565b92505b61080082161561089c57670de0b6b3a764000061088f670d94961b13dbde8085610d73565b6108999190610d8a565b92505b6110008216156108ce57670de0b6b3a76400006108c1670d4a171c35c9838085610d73565b6108cb9190610d8a565b92505b61200082161561090057670de0b6b3a76400006108f3670cb9da519ccfb70085610d73565b6108fd9190610d8a565b92505b61400082161561093257670de0b6b3a7640000610925670bab76d59c18d68085610d73565b61092f9190610d8a565b92505b61800082161561096457670de0b6b3a76400006109576709d025defee4df8085610d73565b6109619190610d8a565b92505b50815b92915050565b5f610977826104cf565b50600181901b17600281901b1790565b828054828255905f5260205f209081019282156109c0579160200282015b828111156109c05782518255916020019190600101906109a5565b506109cc9291506109d0565b5090565b5b808211156109cc575f81556001016109d1565b6001600160a01b0381168114610518575f80fd5b8051610a03816109e4565b919050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715610a3e57610a3e610a08565b60405290565b604051606081016001600160401b0381118282101715610a3e57610a3e610a08565b604051601f8201601f191681016001600160401b0381118282101715610a8e57610a8e610a08565b604052919050565b5f6001600160401b03821115610aae57610aae610a08565b5060051b60200190565b5f82601f830112610ac7575f80fd5b81516020610adc610ad783610a96565b610a66565b8083825260208201915060208460051b870101935086841115610afd575f80fd5b602086015b84811015610b195780518352918301918301610b02565b509695505050505050565b80516001600160401b0381168114610a03575f80fd5b80516001600160801b0381168114610a03575f80fd5b5f82601f830112610b5f575f80fd5b81516020610b6f610ad783610a96565b82815260069290921b84018101918181019086841115610b8d575f80fd5b8286015b84811015610b195760408189031215610ba8575f80fd5b610bb0610a1c565b610bb982610b24565b8152610bc6858301610b3a565b81860152835291830191604001610b91565b5f82601f830112610be7575f80fd5b81516020610bf7610ad783610a96565b82815260609283028501820192828201919087851115610c15575f80fd5b8387015b85811015610c715781818a031215610c2f575f80fd5b610c37610a44565b8151610c42816109e4565b8152610c4f828701610b3a565b868201526040610c60818401610b3a565b908201528452928401928101610c19565b5090979650505050505050565b5f805f805f805f80610100898b031215610c96575f80fd5b610c9f896109f8565b60208a01519098506001600160401b0380821115610cbb575f80fd5b610cc78c838d01610ab8565b985060408b0151915080821115610cdc575f80fd5b610ce88c838d01610b50565b9750610cf660608c01610b3a565b965060808b01519550610d0b60a08c01610b24565b9450610d1960c08c01610b24565b935060e08b0151915080821115610d2e575f80fd5b50610d3b8b828c01610bd8565b9150509295985092959890939650565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761096757610967610d5f565b5f82610da457634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561096757610967610d5f565b8082018082111561096757610967610d5f565b60805160a05160c05160e05161010051612087610e2f5f395f81816103720152610aa401525f81816103bf0152610a6301525f818161055d0152610ae901525f81816105360152610ac801525f8181610333015261079601526120875ff3fe608060405234801561000f575f80fd5b50600436106101e7575f3560e01c80636f3ff72611610109578063b553630e1161009e578063dfa70d8b1161006e578063dfa70d8b14610608578063dff521a81461061b578063e1de9c831461062e578063f1dfaefb14610641575f80fd5b8063b553630e14610558578063c50f093b1461057f578063ce156e8214610594578063d3bf89b1146105a7575f80fd5b8063930eaddc116100d9578063930eaddc146104ce5780639c7aa7f8146105095780639e6d1a931461051e578063ac0d63d014610531575f80fd5b80636f3ff7261461040d578063781ef8db1461045e5780637c300586146104a85780638b59de43146104bb575f80fd5b806339ac7a2a1161017f5780635adf47241161014f5780635adf4724146103945780636981b5f4146103a75780636bab30b7146103ba5780636e455111146103fa575f80fd5b806339ac7a2a146103065780633ad860831461031b578063415175bb1461032e57806348b6781f1461036d575f80fd5b80632f27fa24116101ba5780632f27fa241461024e57806330897dba1461026d57806334d82622146102cb5780633634f911146102de575f80fd5b806301ffc9a7146101eb578063072d5d771461021357806311b8e00a146102265780631c3fc3eb14610239575b5f80fd5b6101fe6101f9366004611bc3565b610654565b60405190151581526020015b60405180910390f35b6101fe610221366004611bfe565b6106cb565b6101fe610234366004611c2c565b6106ef565b6102405f81565b60405190815260200161020a565b61024061025c366004611c4c565b5f9081526001602052604090205490565b6102ab61027b366004611c63565b6001600160a01b03165f90815261010460205260409020546001600160801b0380821692600160801b9092041690565b604080516001600160801b0393841681529290911660208301520161020a565b6102406102d9366004611c95565b610706565b6102f16102ec366004611c2c565b6107d1565b6040805192835260208301919091520161020a565b61030e6107f4565b60405161020a9190611cbf565b610240610329366004611d65565b610875565b6103557f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160801b03909116815260200161020a565b6102407f000000000000000000000000000000000000000000000000000000000000000081565b6102406103a2366004611bfe565b61089c565b6102406103b5366004611dda565b6108c4565b6103e17f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff909116815260200161020a565b610240610408366004611e19565b610903565b6101fe61041b366004611c63565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020526040812054610100908116146106c5565b6101fe61046c366004611bfe565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b6101fe6104b6366004611e69565b610984565b6102406104c9366004611bfe565b6109bd565b6101fe6104dc366004611c63565b6001600160a01b03165f9081526101046020526040902054600160801b90046001600160801b0316151590565b61051c610517366004611c63565b6109cb565b005b61024061052c366004611e9f565b610a60565b6102407f000000000000000000000000000000000000000000000000000000000000000081565b6103e17f000000000000000000000000000000000000000000000000000000000000000081565b610587610b2c565b60405161020a9190611eb8565b6101fe6105a2366004611bfe565b610b83565b6101fe6105b5366004611e69565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b6101fe610616366004611e69565b610b9e565b61051c610629366004611f11565b610bd7565b6102f161063c366004611d65565b610da9565b6101fe61064f366004611dda565b610e10565b5f6001600160e01b031982167fdb06fc000000000000000000000000000000000000000000000000000000000014806106b657506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b806106c557506106c582610e26565b92915050565b5f80836106d9828233610e8c565b6106e65f86866001610ef8565b95945050505050565b5f806106fb84846107d1565b501515949350505050565b610103545f9081805b82811015610776575f610103828154811061072c5761072c611f4a565b5f918252602090912001805490915067ffffffffffffffff90811690871610156107565750610776565b546801000000000000000090046001600160801b0316915060010161070f565b506001600160801b038116156107c8576107c385826001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160801b031661100c565b6106e6565b50929392505050565b5f806107dc836110bc565b5f948552600160205260409094205484169492505050565b6060610103805480602002602001604051908101604052809291908181526020015f905b8282101561086c575f848152602090819020604080518082019091529084015467ffffffffffffffff811682526801000000000000000090046001600160801b031681830152825260019092019101610818565b50505050905090565b5f6108926108848787866110d6565b61088d84611121565b6111b6565b9695505050505050565b5f828152602081815260408083206001600160a01b03851684529091528120545b9392505050565b5f6108bd83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061120992505050565b5f82801580610912575060ff81115b15610920575f9150506108bd565b5f61092b86866108c4565b6101025490915081111561093f5750610102545b61089267ffffffffffffffff851661010261095b600185611f72565b8154811061096b5761096b611f4a565b905f5260205f20015461097e9190611f85565b85610706565b5f8383610992828233610e8c565b856109b057604051631850848b60e31b815260040160405180910390fd5b6108928686866001610ef8565b5f6108bd8361088d84611121565b60106109d85f8233611396565b6001600160a01b0382165f9081526101046020526040902054600160801b90046001600160801b031615610a5c576001600160a01b0382165f818152610104602090815260408083208390558051838152918201929092527f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff1610610aa2575f6106c5565b7f0000000000000000000000000000000000000000000000000000000000000000610b227f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168567ffffffffffffffff16611437565b6106c59190611f72565b6060610102805480602002602001604051908101604052809291908181526020018280548015610b7957602002820191905f5260205f20905b815481526020019060010190808311610b65575b5050505050905090565b5f8083610b918282336114dd565b6106e65f8686600161153e565b5f8383610bac8282336114dd565b85610bca57604051631850848b60e31b815260040160405180910390fd5b610892868686600161153e565b6001610be45f8233611396565b6001600160a01b0384165f90815261010460209081526040918290208251808401909352546001600160801b038082168452600160801b909104811691830191909152831615610d3957836001600160801b03165f03610c70576040517f648564d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001600160801b0316815f01516001600160801b0316141580610caa5750826001600160801b031681602001516001600160801b031614155b15610d34576040805180820182526001600160801b0386811680835286821660208085018281526001600160a01b038c165f8181526101048452889020965191518616600160801b029190951617909455845191825292810192909252917f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b610da2565b60208101516001600160801b031615610da2576001600160a01b0385165f818152610104602090815260408083208390558051838152918201929092527f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b5050505050565b5f80610db68787866110d6565b91505f610dc284611121565b9050610dcd86610a60565b91508115610dee57610ddf8284611f9c565b9250610deb82826111b6565b91505b81610df984836111b6565b610e039190611f72565b9250509550959350505050565b5f80610e1e84846001610903565b119392505050565b5f6001600160e01b031982167f8f452d620000000000000000000000000000000000000000000000000000000014806106c557507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316146106c5565b5f610e9784836115a6565b90508019831615610ef2576040517fd1a3b35500000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b03831660448201526064015b60405180910390fd5b50505050565b5f835f03610f0757505f611004565b610f108461161d565b6001600160a01b038316610f50576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214610ffe575f878152602081815260408083206001600160a01b0389168452909152902081905581198616610fac8882600161167d565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050611004565b5f925050505b949350505050565b5f805f6110198686611812565b91509150815f0361103d5783818161103357611033611faf565b04925050506108bd565b81841161105457611054600385150260111861182e565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010185841190960395909502919093039390930492909217029150509392505050565b5f6110c68261161d565b50600181901b17600281901b1790565b5f6110e2848484610903565b9050805f036108bd5783836040517fdbfa2886000000000000000000000000000000000000000000000000000000008152600401610ee9929190611fc3565b6040805180820182525f80825260209182018190526001600160a01b038416815261010482528281208351808501909452546001600160801b038082168552600160801b90910416918301829052036111b1576040517f02e2ae9e0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610ee9565b919050565b5f81602001516001600160801b0316825f01516001600160801b031614611202576111fd83835f01516001600160801b031684602001516001600160801b0316600161183f565b6108bd565b5090919050565b80515f90819081905b8082101561138d575f85838151811061122d5761122d611f4a565b01602001516001600160f81b03191690507f800000000000000000000000000000000000000000000000000000000000000081101561127857611271600184611f9c565b925061137a565b7fe0000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156112b557611271600284611f9c565b7ff0000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156112f257611271600384611f9c565b7ff8000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561132f57611271600484611f9c565b7ffc000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561136c57611271600584611f9c565b611377600684611f9c565b92505b508261138581611ff1565b935050611212565b50909392505050565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5909252909120541782168214611432576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610ee9565b505050565b5f831580611443575082155b1561144f57505f6108bd565b815f0361145d5750826108bd565b5f83611471670de0b6b3a764000085611f85565b61147b9190612009565b90505f611490670de0b6b3a764000083612009565b90505f6114a5670de0b6b3a764000083611f85565b6114af9084611f72565b90506114d287831c6114cd670de0b6b3a7640000601085901b612009565b611881565b979650505050505050565b5f6114e884836115a6565b90508019831615610ef2576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610ee9565b5f6115488461161d565b5f858152602081815260408083206001600160a01b038716845290915290205484198116808214610ffe575f878152602081815260408083206001600160a01b0389168452909152812082905586831690610fac908990839061167d565b5f828152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925282205417608081901c7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176108bd565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561167a576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610ee9565b50565b5f611687836110bc565b90508115611750575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615611728576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610ee9565b5f8481526001602052604081208054859290611745908490611f9c565b90915550610ef29050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156117ea576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610ee9565b5f8481526001602052604081208054859290611807908490611f72565b909155505050505050565b5f805f1983850993909202808410938190039390930393915050565b634e487b715f52806020526024601cfd5b5f61186c61184c83611b97565b801561186757505f848061186257611862611faf565b868809115b151590565b61187786868661100c565b6106e69190611f9c565b5f60018216156118b357670de0b6b3a76400006118a6670de0ad151d09418085611f85565b6118b09190612009565b92505b60028216156118e457670de0b6b3a76400006118d7670de0a3769959680085611f85565b6118e19190612009565b92505b600482161561191557670de0b6b3a7640000611908670de09039a5fa510085611f85565b6119129190612009565b92505b600882161561194657670de0b6b3a7640000611939670de069c00f3e120085611f85565b6119439190612009565b92505b601082161561197757670de0b6b3a764000061196a670de01cce21c9440085611f85565b6119749190612009565b92505b60208216156119a857670de0b6b3a764000061199b670ddf82ef46ce100085611f85565b6119a59190612009565b92505b60408216156119d957670de0b6b3a76400006119cc670dde4f458f8e8d8085611f85565b6119d69190612009565b92505b6080821615611a0a57670de0b6b3a76400006119fd670ddbe84213d5f08085611f85565b611a079190612009565b92505b610100821615611a3c57670de0b6b3a7640000611a2f670dd71b7aa6df5b8085611f85565b611a399190612009565b92505b610200821615611a6e57670de0b6b3a7640000611a61670dcd86e7f28cde0085611f85565b611a6b9190612009565b92505b610400821615611aa057670de0b6b3a7640000611a93670dba71a3084ad68085611f85565b611a9d9190612009565b92505b610800821615611ad257670de0b6b3a7640000611ac5670d94961b13dbde8085611f85565b611acf9190612009565b92505b611000821615611b0457670de0b6b3a7640000611af7670d4a171c35c9838085611f85565b611b019190612009565b92505b612000821615611b3657670de0b6b3a7640000611b29670cb9da519ccfb70085611f85565b611b339190612009565b92505b614000821615611b6857670de0b6b3a7640000611b5b670bab76d59c18d68085611f85565b611b659190612009565b92505b61800082161561120257670de0b6b3a7640000611b8d6709d025defee4df8085611f85565b6108bd9190612009565b5f6002826003811115611bac57611bac61201c565b611bb69190612030565b60ff166001149050919050565b5f60208284031215611bd3575f80fd5b81356001600160e01b0319811681146108bd575f80fd5b6001600160a01b038116811461167a575f80fd5b5f8060408385031215611c0f575f80fd5b823591506020830135611c2181611bea565b809150509250929050565b5f8060408385031215611c3d575f80fd5b50508035926020909101359150565b5f60208284031215611c5c575f80fd5b5035919050565b5f60208284031215611c73575f80fd5b81356108bd81611bea565b803567ffffffffffffffff811681146111b1575f80fd5b5f8060408385031215611ca6575f80fd5b82359150611cb660208401611c7e565b90509250929050565b602080825282518282018190525f919060409081850190868401855b82811015611d13578151805167ffffffffffffffff1685528601516001600160801b0316868501529284019290850190600101611cdb565b5091979650505050505050565b5f8083601f840112611d30575f80fd5b50813567ffffffffffffffff811115611d47575f80fd5b602083019150836020828501011115611d5e575f80fd5b9250929050565b5f805f805f60808688031215611d79575f80fd5b853567ffffffffffffffff811115611d8f575f80fd5b611d9b88828901611d20565b9096509450611dae905060208701611c7e565b9250611dbc60408701611c7e565b91506060860135611dcc81611bea565b809150509295509295909350565b5f8060208385031215611deb575f80fd5b823567ffffffffffffffff811115611e01575f80fd5b611e0d85828601611d20565b90969095509350505050565b5f805f60408486031215611e2b575f80fd5b833567ffffffffffffffff811115611e41575f80fd5b611e4d86828701611d20565b9094509250611e60905060208501611c7e565b90509250925092565b5f805f60608486031215611e7b575f80fd5b83359250602084013591506040840135611e9481611bea565b809150509250925092565b5f60208284031215611eaf575f80fd5b6108bd82611c7e565b602080825282518282018190525f9190848201906040850190845b81811015611eef57835183529284019291840191600101611ed3565b50909695505050505050565b80356001600160801b03811681146111b1575f80fd5b5f805f60608486031215611f23575f80fd5b8335611f2e81611bea565b9250611f3c60208501611efb565b9150611e6060408501611efb565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b818103818111156106c5576106c5611f5e565b80820281158282048414176106c5576106c5611f5e565b808201808211156106c5576106c5611f5e565b634e487b7160e01b5f52601260045260245ffd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f6001820161200257612002611f5e565b5060010190565b5f8261201757612017611faf565b500490565b634e487b7160e01b5f52602160045260245ffd5b5f60ff83168061204257612042611faf565b8060ff8416069150509291505056fea2646970667358221220149d85dd817ae3b3f32aaa794260c55e82e3303959ca021a7688d95e58bbc91d64736f6c634300081900338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106101e7575f3560e01c80636f3ff72611610109578063b553630e1161009e578063dfa70d8b1161006e578063dfa70d8b14610608578063dff521a81461061b578063e1de9c831461062e578063f1dfaefb14610641575f80fd5b8063b553630e14610558578063c50f093b1461057f578063ce156e8214610594578063d3bf89b1146105a7575f80fd5b8063930eaddc116100d9578063930eaddc146104ce5780639c7aa7f8146105095780639e6d1a931461051e578063ac0d63d014610531575f80fd5b80636f3ff7261461040d578063781ef8db1461045e5780637c300586146104a85780638b59de43146104bb575f80fd5b806339ac7a2a1161017f5780635adf47241161014f5780635adf4724146103945780636981b5f4146103a75780636bab30b7146103ba5780636e455111146103fa575f80fd5b806339ac7a2a146103065780633ad860831461031b578063415175bb1461032e57806348b6781f1461036d575f80fd5b80632f27fa24116101ba5780632f27fa241461024e57806330897dba1461026d57806334d82622146102cb5780633634f911146102de575f80fd5b806301ffc9a7146101eb578063072d5d771461021357806311b8e00a146102265780631c3fc3eb14610239575b5f80fd5b6101fe6101f9366004611bc3565b610654565b60405190151581526020015b60405180910390f35b6101fe610221366004611bfe565b6106cb565b6101fe610234366004611c2c565b6106ef565b6102405f81565b60405190815260200161020a565b61024061025c366004611c4c565b5f9081526001602052604090205490565b6102ab61027b366004611c63565b6001600160a01b03165f90815261010460205260409020546001600160801b0380821692600160801b9092041690565b604080516001600160801b0393841681529290911660208301520161020a565b6102406102d9366004611c95565b610706565b6102f16102ec366004611c2c565b6107d1565b6040805192835260208301919091520161020a565b61030e6107f4565b60405161020a9190611cbf565b610240610329366004611d65565b610875565b6103557f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160801b03909116815260200161020a565b6102407f000000000000000000000000000000000000000000000000000000000000000081565b6102406103a2366004611bfe565b61089c565b6102406103b5366004611dda565b6108c4565b6103e17f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff909116815260200161020a565b610240610408366004611e19565b610903565b6101fe61041b366004611c63565b6001600160a01b0381165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb56020526040812054610100908116146106c5565b6101fe61046c366004611bfe565b6001600160a01b03165f9081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205481161490565b6101fe6104b6366004611e69565b610984565b6102406104c9366004611bfe565b6109bd565b6101fe6104dc366004611c63565b6001600160a01b03165f9081526101046020526040902054600160801b90046001600160801b0316151590565b61051c610517366004611c63565b6109cb565b005b61024061052c366004611e9f565b610a60565b6102407f000000000000000000000000000000000000000000000000000000000000000081565b6103e17f000000000000000000000000000000000000000000000000000000000000000081565b610587610b2c565b60405161020a9190611eb8565b6101fe6105a2366004611bfe565b610b83565b6101fe6105b5366004611e69565b5f928352602083815260408085206001600160a01b03939093168552918152818420547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590915292205490911781161490565b6101fe610616366004611e69565b610b9e565b61051c610629366004611f11565b610bd7565b6102f161063c366004611d65565b610da9565b6101fe61064f366004611dda565b610e10565b5f6001600160e01b031982167fdb06fc000000000000000000000000000000000000000000000000000000000014806106b657506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b806106c557506106c582610e26565b92915050565b5f80836106d9828233610e8c565b6106e65f86866001610ef8565b95945050505050565b5f806106fb84846107d1565b501515949350505050565b610103545f9081805b82811015610776575f610103828154811061072c5761072c611f4a565b5f918252602090912001805490915067ffffffffffffffff90811690871610156107565750610776565b546801000000000000000090046001600160801b0316915060010161070f565b506001600160801b038116156107c8576107c385826001600160801b03167f00000000000000000000000000000000000000000000000000000000000000006001600160801b031661100c565b6106e6565b50929392505050565b5f806107dc836110bc565b5f948552600160205260409094205484169492505050565b6060610103805480602002602001604051908101604052809291908181526020015f905b8282101561086c575f848152602090819020604080518082019091529084015467ffffffffffffffff811682526801000000000000000090046001600160801b031681830152825260019092019101610818565b50505050905090565b5f6108926108848787866110d6565b61088d84611121565b6111b6565b9695505050505050565b5f828152602081815260408083206001600160a01b03851684529091528120545b9392505050565b5f6108bd83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061120992505050565b5f82801580610912575060ff81115b15610920575f9150506108bd565b5f61092b86866108c4565b6101025490915081111561093f5750610102545b61089267ffffffffffffffff851661010261095b600185611f72565b8154811061096b5761096b611f4a565b905f5260205f20015461097e9190611f85565b85610706565b5f8383610992828233610e8c565b856109b057604051631850848b60e31b815260040160405180910390fd5b6108928686866001610ef8565b5f6108bd8361088d84611121565b60106109d85f8233611396565b6001600160a01b0382165f9081526101046020526040902054600160801b90046001600160801b031615610a5c576001600160a01b0382165f818152610104602090815260408083208390558051838152918201929092527f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b5050565b5f7f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168267ffffffffffffffff1610610aa2575f6106c5565b7f0000000000000000000000000000000000000000000000000000000000000000610b227f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff168567ffffffffffffffff16611437565b6106c59190611f72565b6060610102805480602002602001604051908101604052809291908181526020018280548015610b7957602002820191905f5260205f20905b815481526020019060010190808311610b65575b5050505050905090565b5f8083610b918282336114dd565b6106e65f8686600161153e565b5f8383610bac8282336114dd565b85610bca57604051631850848b60e31b815260040160405180910390fd5b610892868686600161153e565b6001610be45f8233611396565b6001600160a01b0384165f90815261010460209081526040918290208251808401909352546001600160801b038082168452600160801b909104811691830191909152831615610d3957836001600160801b03165f03610c70576040517f648564d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001600160801b0316815f01516001600160801b0316141580610caa5750826001600160801b031681602001516001600160801b031614155b15610d34576040805180820182526001600160801b0386811680835286821660208085018281526001600160a01b038c165f8181526101048452889020965191518616600160801b029190951617909455845191825292810192909252917f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b610da2565b60208101516001600160801b031615610da2576001600160a01b0385165f818152610104602090815260408083208390558051838152918201929092527f2d9461f4916036390b11b47e528b3b051e2f8faa661e2a410dec33c82012ede4910160405180910390a25b5050505050565b5f80610db68787866110d6565b91505f610dc284611121565b9050610dcd86610a60565b91508115610dee57610ddf8284611f9c565b9250610deb82826111b6565b91505b81610df984836111b6565b610e039190611f72565b9250509550959350505050565b5f80610e1e84846001610903565b119392505050565b5f6001600160e01b031982167f8f452d620000000000000000000000000000000000000000000000000000000014806106c557507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316146106c5565b5f610e9784836115a6565b90508019831615610ef2576040517fd1a3b35500000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b03831660448201526064015b60405180910390fd5b50505050565b5f835f03610f0757505f611004565b610f108461161d565b6001600160a01b038316610f50576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f858152602081815260408083206001600160a01b0387168452909152902054848117808214610ffe575f878152602081815260408083206001600160a01b0389168452909152902081905581198616610fac8882600161167d565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a360019350505050611004565b5f925050505b949350505050565b5f805f6110198686611812565b91509150815f0361103d5783818161103357611033611faf565b04925050506108bd565b81841161105457611054600385150260111861182e565b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010185841190960395909502919093039390930492909217029150509392505050565b5f6110c68261161d565b50600181901b17600281901b1790565b5f6110e2848484610903565b9050805f036108bd5783836040517fdbfa2886000000000000000000000000000000000000000000000000000000008152600401610ee9929190611fc3565b6040805180820182525f80825260209182018190526001600160a01b038416815261010482528281208351808501909452546001600160801b038082168552600160801b90910416918301829052036111b1576040517f02e2ae9e0000000000000000000000000000000000000000000000000000000081526001600160a01b0383166004820152602401610ee9565b919050565b5f81602001516001600160801b0316825f01516001600160801b031614611202576111fd83835f01516001600160801b031684602001516001600160801b0316600161183f565b6108bd565b5090919050565b80515f90819081905b8082101561138d575f85838151811061122d5761122d611f4a565b01602001516001600160f81b03191690507f800000000000000000000000000000000000000000000000000000000000000081101561127857611271600184611f9c565b925061137a565b7fe0000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156112b557611271600284611f9c565b7ff0000000000000000000000000000000000000000000000000000000000000006001600160f81b0319821610156112f257611271600384611f9c565b7ff8000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561132f57611271600484611f9c565b7ffc000000000000000000000000000000000000000000000000000000000000006001600160f81b03198216101561136c57611271600584611f9c565b611377600684611f9c565b92505b508261138581611ff1565b935050611212565b50909392505050565b5f838152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5909252909120541782168214611432576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610ee9565b505050565b5f831580611443575082155b1561144f57505f6108bd565b815f0361145d5750826108bd565b5f83611471670de0b6b3a764000085611f85565b61147b9190612009565b90505f611490670de0b6b3a764000083612009565b90505f6114a5670de0b6b3a764000083611f85565b6114af9084611f72565b90506114d287831c6114cd670de0b6b3a7640000601085901b612009565b611881565b979650505050505050565b5f6114e884836115a6565b90508019831615610ef2576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610ee9565b5f6115488461161d565b5f858152602081815260408083206001600160a01b038716845290915290205484198116808214610ffe575f878152602081815260408083206001600160a01b0389168452909152812082905586831690610fac908990839061167d565b5f828152602081815260408083206001600160a01b03851684528252808320547fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb590925282205417608081901c7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176108bd565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561167a576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610ee9565b50565b5f611687836110bc565b90508115611750575f848152600160205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615611728576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610ee9565b5f8481526001602052604081208054859290611745908490611f9c565b90915550610ef29050565b5f848152600160205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef011616156117ea576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610ee9565b5f8481526001602052604081208054859290611807908490611f72565b909155505050505050565b5f805f1983850993909202808410938190039390930393915050565b634e487b715f52806020526024601cfd5b5f61186c61184c83611b97565b801561186757505f848061186257611862611faf565b868809115b151590565b61187786868661100c565b6106e69190611f9c565b5f60018216156118b357670de0b6b3a76400006118a6670de0ad151d09418085611f85565b6118b09190612009565b92505b60028216156118e457670de0b6b3a76400006118d7670de0a3769959680085611f85565b6118e19190612009565b92505b600482161561191557670de0b6b3a7640000611908670de09039a5fa510085611f85565b6119129190612009565b92505b600882161561194657670de0b6b3a7640000611939670de069c00f3e120085611f85565b6119439190612009565b92505b601082161561197757670de0b6b3a764000061196a670de01cce21c9440085611f85565b6119749190612009565b92505b60208216156119a857670de0b6b3a764000061199b670ddf82ef46ce100085611f85565b6119a59190612009565b92505b60408216156119d957670de0b6b3a76400006119cc670dde4f458f8e8d8085611f85565b6119d69190612009565b92505b6080821615611a0a57670de0b6b3a76400006119fd670ddbe84213d5f08085611f85565b611a079190612009565b92505b610100821615611a3c57670de0b6b3a7640000611a2f670dd71b7aa6df5b8085611f85565b611a399190612009565b92505b610200821615611a6e57670de0b6b3a7640000611a61670dcd86e7f28cde0085611f85565b611a6b9190612009565b92505b610400821615611aa057670de0b6b3a7640000611a93670dba71a3084ad68085611f85565b611a9d9190612009565b92505b610800821615611ad257670de0b6b3a7640000611ac5670d94961b13dbde8085611f85565b611acf9190612009565b92505b611000821615611b0457670de0b6b3a7640000611af7670d4a171c35c9838085611f85565b611b019190612009565b92505b612000821615611b3657670de0b6b3a7640000611b29670cb9da519ccfb70085611f85565b611b339190612009565b92505b614000821615611b6857670de0b6b3a7640000611b5b670bab76d59c18d68085611f85565b611b659190612009565b92505b61800082161561120257670de0b6b3a7640000611b8d6709d025defee4df8085611f85565b6108bd9190612009565b5f6002826003811115611bac57611bac61201c565b611bb69190612030565b60ff166001149050919050565b5f60208284031215611bd3575f80fd5b81356001600160e01b0319811681146108bd575f80fd5b6001600160a01b038116811461167a575f80fd5b5f8060408385031215611c0f575f80fd5b823591506020830135611c2181611bea565b809150509250929050565b5f8060408385031215611c3d575f80fd5b50508035926020909101359150565b5f60208284031215611c5c575f80fd5b5035919050565b5f60208284031215611c73575f80fd5b81356108bd81611bea565b803567ffffffffffffffff811681146111b1575f80fd5b5f8060408385031215611ca6575f80fd5b82359150611cb660208401611c7e565b90509250929050565b602080825282518282018190525f919060409081850190868401855b82811015611d13578151805167ffffffffffffffff1685528601516001600160801b0316868501529284019290850190600101611cdb565b5091979650505050505050565b5f8083601f840112611d30575f80fd5b50813567ffffffffffffffff811115611d47575f80fd5b602083019150836020828501011115611d5e575f80fd5b9250929050565b5f805f805f60808688031215611d79575f80fd5b853567ffffffffffffffff811115611d8f575f80fd5b611d9b88828901611d20565b9096509450611dae905060208701611c7e565b9250611dbc60408701611c7e565b91506060860135611dcc81611bea565b809150509295509295909350565b5f8060208385031215611deb575f80fd5b823567ffffffffffffffff811115611e01575f80fd5b611e0d85828601611d20565b90969095509350505050565b5f805f60408486031215611e2b575f80fd5b833567ffffffffffffffff811115611e41575f80fd5b611e4d86828701611d20565b9094509250611e60905060208501611c7e565b90509250925092565b5f805f60608486031215611e7b575f80fd5b83359250602084013591506040840135611e9481611bea565b809150509250925092565b5f60208284031215611eaf575f80fd5b6108bd82611c7e565b602080825282518282018190525f9190848201906040850190845b81811015611eef57835183529284019291840191600101611ed3565b50909695505050505050565b80356001600160801b03811681146111b1575f80fd5b5f805f60608486031215611f23575f80fd5b8335611f2e81611bea565b9250611f3c60208501611efb565b9150611e6060408501611efb565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b818103818111156106c5576106c5611f5e565b80820281158282048414176106c5576106c5611f5e565b808201808211156106c5576106c5611f5e565b634e487b7160e01b5f52601260045260245ffd5b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f6001820161200257612002611f5e565b5060010190565b5f8261201757612017611faf565b500490565b634e487b7160e01b5f52602160045260245ffd5b5f60ff83168061204257612042611faf565b8060ff8416069150509291505056fea2646970667358221220149d85dd817ae3b3f32aaa794260c55e82e3303959ca021a7688d95e58bbc91d64736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "65165": [ + { + "length": 32, + "start": 819 + }, + { + "length": 32, + "start": 1942 + } + ], + "65168": [ + { + "length": 32, + "start": 1334 + }, + { + "length": 32, + "start": 2760 + } + ], + "65171": [ + { + "length": 32, + "start": 1373 + }, + { + "length": 32, + "start": 2793 + } + ], + "65174": [ + { + "length": 32, + "start": 959 + }, + { + "length": 32, + "start": 2659 + } + ], + "65177": [ + { + "length": 32, + "start": 882 + }, + { + "length": 32, + "start": 2724 + } + ] + }, + "inputSourceName": "project/src/registrar/StandardRentPriceOracle.sol", + "devdoc": { + "errors": { + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "InvalidBaseRates()": [ + { + "details": "Error selector: `0xde276447`" + } + ], + "InvalidDiscount()": [ + { + "details": "Error selector: `0x997ea360`" + } + ], + "InvalidRatio()": [ + { + "details": "Error selector: `0x648564d3`" + } + ], + "NotValid(string)": [ + { + "details": "Error selector: `0xdbfa2886`" + } + ], + "PaymentTokenNotSupported(address)": [ + { + "details": "Error selector: `0x02e2ae9e`" + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "PaymentTokenUpdated(address,uint128,uint128)": { + "params": { + "denom": "Exchange rate denominator, relative to base units, or 0 if disabled.", + "numer": "Exchange rate numerator, relative to base units.", + "paymentToken": "The payment token." + } + } + }, + "kind": "dev", + "methods": { + "applyDiscount(uint256,uint64)": { + "params": { + "duration": "The duration, in seconds.", + "value": "An arbitrary value." + }, + "returns": { + "_0": "`value` reduced by discount." + } + }, + "constructor": { + "params": { + "baseRatePerCp": "Base rates, in standard units per second.", + "discountDenominator": "Denominator for discounts.", + "discountPoints": "List of discount points.", + "paymentRatios": "List of payment tokens with exchange rates.", + "premiumHalvingPeriod": "Premium halving period, in seconds.", + "premiumPeriod": "Premium period, in seconds.", + "premiumPriceInitial": "Premium initial price, in standard units.", + "rootAccount": "Account granted root roles." + } + }, + "convertUnits(uint256,address)": { + "params": { + "paymentToken": "The payment token.", + "value": "An arbitrary value, in standard units." + }, + "returns": { + "_0": "The amount of payment token." + } + }, + "disablePaymentToken(address)": { + "params": { + "paymentToken": "The payment token." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getBasePrice(string,uint64)": { + "params": { + "duration": "The duration, in seconds.", + "label": "The name to price." + }, + "returns": { + "_0": "The base price, in standard units, or 0 if not valid." + } + }, + "getLength(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "The number of Unicode codepoints." + } + }, + "getPaymentTokenRatio(address)": { + "params": { + "paymentToken": "The payment token." + }, + "returns": { + "denom": "The denominator of the exchange rate.", + "numer": "The numerator of the exchange rate." + } + }, + "getPremiumPriceAfter(uint64)": { + "details": "Defined over `[0, premiumPeriod)`.", + "params": { + "duration": "The time after expiration, in seconds." + }, + "returns": { + "_0": "The premium price, in standard units." + } + }, + "getRegisterPrice(string,uint64,uint64,address)": { + "params": { + "available": "The duration the name has been available, in seconds.", + "duration": "The duration to register for, in seconds.", + "label": "The name to price.", + "paymentToken": "The payment token." + }, + "returns": { + "base": "The amount of `paymentToken` for the registration.", + "premium": "The amount of `paymentToken` due to premium." + } + }, + "getRenewPrice(string,uint64,uint64,address)": { + "params": { + "duration": "The extension to price, in seconds.", + "expiry": "The current expiry, in seconds.", + "label": "The name to price.", + "paymentToken": "The payment token." + }, + "returns": { + "_0": "The amount of `paymentToken`." + } + }, + "grantRoles(uint256,uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted. Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.", + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "isPaymentToken(address)": { + "params": { + "paymentToken": "The payment token." + }, + "returns": { + "_0": "`true` if `paymentToken` is supported." + } + }, + "isValid(string)": { + "params": { + "label": "The name to check." + }, + "returns": { + "_0": "`true` if the `label` is valid." + } + }, + "revokeRoles(uint256,uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked. Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.", + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + }, + "updatePaymentToken(address,uint128,uint128)": { + "params": { + "denom": "The denominator of the exchange rate, or 0 to disable.", + "numer": "The numerator of the exchange rate.", + "paymentToken": "The payment token." + } + } + }, + "stateVariables": { + "_baseRatePerCp": { + "details": "Per-second base rates indexed by codepoint count; `_baseRatePerCp[i]` prices labels with `i+1` codepoints." + }, + "_discountPoints": { + "details": "Ordered discount points, relative to `DISCOUNT_DENOMINATOR`." + }, + "_paymentRatios": { + "details": "Exchange rates for each accepted payment token, mapping token address to its numerator/denominator ratio." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1665400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "DISCOUNT_DENOMINATOR()": "infinite", + "PREMIUM_HALVING_PERIOD()": "infinite", + "PREMIUM_PERIOD()": "infinite", + "PREMIUM_PRICE_INITIAL()": "infinite", + "PREMIUM_PRICE_OFFSET()": "infinite", + "ROOT_RESOURCE()": "306", + "applyDiscount(uint256,uint64)": "infinite", + "convertUnits(uint256,address)": "infinite", + "disablePaymentToken(address)": "13903", + "getAssigneeCount(uint256,uint256)": "2748", + "getBasePrice(string,uint64)": "infinite", + "getBaseRates()": "infinite", + "getDiscountPoints()": "infinite", + "getLength(string)": "infinite", + "getPaymentTokenRatio(address)": "2694", + "getPremiumPriceAfter(uint64)": "infinite", + "getRegisterPrice(string,uint64,uint64,address)": "infinite", + "getRenewPrice(string,uint64,uint64,address)": "infinite", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "2755", + "hasRoles(uint256,uint256,address)": "4937", + "hasRootRoles(uint256,address)": "2631", + "isContractNamer(address)": "2606", + "isPaymentToken(address)": "2609", + "isValid(string)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "2481", + "roles(uint256,address)": "2695", + "supportsInterface(bytes4)": "infinite", + "updatePaymentToken(address,uint128,uint128)": "infinite" + }, + "internal": { + "_requireBasePrice(string calldata,uint64)": "infinite", + "_requirePaymentToken(contract IERC20)": "infinite", + "_toAmount(uint256,struct StandardRentPriceOracle.Ratio memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"baseRatePerCp\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"}],\"internalType\":\"struct DiscountPoint[]\",\"name\":\"discountPoints\",\"type\":\"tuple[]\"},{\"internalType\":\"uint128\",\"name\":\"discountDenominator\",\"type\":\"uint128\"},{\"internalType\":\"uint256\",\"name\":\"premiumPriceInitial\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"premiumHalvingPeriod\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"premiumPeriod\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"denom\",\"type\":\"uint128\"}],\"internalType\":\"struct PaymentRatio[]\",\"name\":\"paymentRatios\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBaseRates\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDiscount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRatio\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"NotValid\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"PaymentTokenNotSupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"},{\"indexed\":false,\"internalType\":\"uint128\",\"name\":\"denom\",\"type\":\"uint128\"}],\"name\":\"PaymentTokenUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DISCOUNT_DENOMINATOR\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIUM_HALVING_PERIOD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIUM_PERIOD\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIUM_PRICE_INITIAL\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PREMIUM_PRICE_OFFSET\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"}],\"name\":\"applyDiscount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"convertUnits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"disablePaymentToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"}],\"name\":\"getBasePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBaseRates\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDiscountPoints\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"}],\"internalType\":\"struct DiscountPoint[]\",\"name\":\"v\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getPaymentTokenRatio\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"denom\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"}],\"name\":\"getPremiumPriceAfter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"available\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRegisterPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"base\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"premium\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"duration\",\"type\":\"uint64\"},{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"getRenewPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"}],\"name\":\"isPaymentToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"isValid\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"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\":[{\"internalType\":\"contract IERC20\",\"name\":\"paymentToken\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"numer\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"denom\",\"type\":\"uint128\"}],\"name\":\"updatePaymentToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"InvalidBaseRates()\":[{\"details\":\"Error selector: `0xde276447`\"}],\"InvalidDiscount()\":[{\"details\":\"Error selector: `0x997ea360`\"}],\"InvalidRatio()\":[{\"details\":\"Error selector: `0x648564d3`\"}],\"NotValid(string)\":[{\"details\":\"Error selector: `0xdbfa2886`\"}],\"PaymentTokenNotSupported(address)\":[{\"details\":\"Error selector: `0x02e2ae9e`\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"PaymentTokenUpdated(address,uint128,uint128)\":{\"params\":{\"denom\":\"Exchange rate denominator, relative to base units, or 0 if disabled.\",\"numer\":\"Exchange rate numerator, relative to base units.\",\"paymentToken\":\"The payment token.\"}}},\"kind\":\"dev\",\"methods\":{\"applyDiscount(uint256,uint64)\":{\"params\":{\"duration\":\"The duration, in seconds.\",\"value\":\"An arbitrary value.\"},\"returns\":{\"_0\":\"`value` reduced by discount.\"}},\"constructor\":{\"params\":{\"baseRatePerCp\":\"Base rates, in standard units per second.\",\"discountDenominator\":\"Denominator for discounts.\",\"discountPoints\":\"List of discount points.\",\"paymentRatios\":\"List of payment tokens with exchange rates.\",\"premiumHalvingPeriod\":\"Premium halving period, in seconds.\",\"premiumPeriod\":\"Premium period, in seconds.\",\"premiumPriceInitial\":\"Premium initial price, in standard units.\",\"rootAccount\":\"Account granted root roles.\"}},\"convertUnits(uint256,address)\":{\"params\":{\"paymentToken\":\"The payment token.\",\"value\":\"An arbitrary value, in standard units.\"},\"returns\":{\"_0\":\"The amount of payment token.\"}},\"disablePaymentToken(address)\":{\"params\":{\"paymentToken\":\"The payment token.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getBasePrice(string,uint64)\":{\"params\":{\"duration\":\"The duration, in seconds.\",\"label\":\"The name to price.\"},\"returns\":{\"_0\":\"The base price, in standard units, or 0 if not valid.\"}},\"getLength(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"The number of Unicode codepoints.\"}},\"getPaymentTokenRatio(address)\":{\"params\":{\"paymentToken\":\"The payment token.\"},\"returns\":{\"denom\":\"The denominator of the exchange rate.\",\"numer\":\"The numerator of the exchange rate.\"}},\"getPremiumPriceAfter(uint64)\":{\"details\":\"Defined over `[0, premiumPeriod)`.\",\"params\":{\"duration\":\"The time after expiration, in seconds.\"},\"returns\":{\"_0\":\"The premium price, in standard units.\"}},\"getRegisterPrice(string,uint64,uint64,address)\":{\"params\":{\"available\":\"The duration the name has been available, in seconds.\",\"duration\":\"The duration to register for, in seconds.\",\"label\":\"The name to price.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"base\":\"The amount of `paymentToken` for the registration.\",\"premium\":\"The amount of `paymentToken` due to premium.\"}},\"getRenewPrice(string,uint64,uint64,address)\":{\"params\":{\"duration\":\"The extension to price, in seconds.\",\"expiry\":\"The current expiry, in seconds.\",\"label\":\"The name to price.\",\"paymentToken\":\"The payment token.\"},\"returns\":{\"_0\":\"The amount of `paymentToken`.\"}},\"grantRoles(uint256,uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted. Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\",\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"isPaymentToken(address)\":{\"params\":{\"paymentToken\":\"The payment token.\"},\"returns\":{\"_0\":\"`true` if `paymentToken` is supported.\"}},\"isValid(string)\":{\"params\":{\"label\":\"The name to check.\"},\"returns\":{\"_0\":\"`true` if the `label` is valid.\"}},\"revokeRoles(uint256,uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked. Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"updatePaymentToken(address,uint128,uint128)\":{\"params\":{\"denom\":\"The denominator of the exchange rate, or 0 to disable.\",\"numer\":\"The numerator of the exchange rate.\",\"paymentToken\":\"The payment token.\"}}},\"stateVariables\":{\"_baseRatePerCp\":{\"details\":\"Per-second base rates indexed by codepoint count; `_baseRatePerCp[i]` prices labels with `i+1` codepoints.\"},\"_discountPoints\":{\"details\":\"Ordered discount points, relative to `DISCOUNT_DENOMINATOR`.\"},\"_paymentRatios\":{\"details\":\"Exchange rates for each accepted payment token, mapping token address to its numerator/denominator ratio.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBaseRates()\":[{\"notice\":\"Invalid base rates.\"}],\"InvalidDiscount()\":[{\"notice\":\"Invalid discount configuration.\"}],\"InvalidRatio()\":[{\"notice\":\"Invalid payment token exchange rate.\"}],\"NotValid(string)\":[{\"notice\":\"`label` is not valid.\"}],\"PaymentTokenNotSupported(address)\":[{\"notice\":\"`paymentToken` is not supported for payment.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"PaymentTokenUpdated(address,uint128,uint128)\":{\"notice\":\"`paymentToken` has changed.\"}},\"kind\":\"user\",\"methods\":{\"DISCOUNT_DENOMINATOR()\":{\"notice\":\"Denominator for discounts.\"},\"PREMIUM_HALVING_PERIOD()\":{\"notice\":\"Number of seconds for the premium to halve in value.\"},\"PREMIUM_PERIOD()\":{\"notice\":\"Total duration of the premium window; the premium reaches zero at this offset from expiry.\"},\"PREMIUM_PRICE_INITIAL()\":{\"notice\":\"Starting value of the exponential decay premium for recently expired names, in base pricing units.\"},\"PREMIUM_PRICE_OFFSET()\":{\"notice\":\"Precomputed premium halving at end of period.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"applyDiscount(uint256,uint64)\":{\"notice\":\"Apply discount function to an arbitrary value.\"},\"convertUnits(uint256,address)\":{\"notice\":\"Convert arbitrary standard units to payment token amount.\"},\"disablePaymentToken(address)\":{\"notice\":\"Disable `paymentToken` support.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getBasePrice(string,uint64)\":{\"notice\":\"Get base price to register or renew `label` for `duration` seconds.\"},\"getBaseRates()\":{\"notice\":\"Get all base rates, in standard units per second.\"},\"getDiscountPoints()\":{\"notice\":\"Get all discount durations, in seconds.\"},\"getLength(string)\":{\"notice\":\"Check length of a name.\"},\"getPaymentTokenRatio(address)\":{\"notice\":\"Get numerator/denominator for `paymentToken`.\"},\"getPremiumPriceAfter(uint64)\":{\"notice\":\"Get premium price for a duration after expiry.\"},\"getRegisterPrice(string,uint64,uint64,address)\":{\"notice\":\"Determine registration price for `label`.\"},\"getRenewPrice(string,uint64,uint64,address)\":{\"notice\":\"Determine renewal price for `label`.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"isPaymentToken(address)\":{\"notice\":\"Check if `paymentToken` is supported for payment.\"},\"isValid(string)\":{\"notice\":\"Check if a `label` is valid. Does not check if normalized.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"updatePaymentToken(address,uint128,uint128)\":{\"notice\":\"Update `paymentToken` support and/or exchange rate.\"}},\"notice\":\"Rent pricing oracle with (4) components: 1. Base rates: per-second cost indexed by label codepoint count. Shorter names cost more. Rates are stored in an array where index `i` corresponds to `i+1` codepoints; labels longer than the array use the last entry. 2. Duration discounts: increasing expiry reduce costs. Each dicount point specifies a duration and a numerator. `1 - numerator / DISCOUNT_DENOMINATOR` determines the discount percentage. Rewards longer registrations. 3. Expiry premium: exponential decay from an initial premium with a configurable halving period, reaching zero at the end of the premium period. Only charged to new owners of recently expired names; renewals are exempt. 4. Configurable payment tokens: payment tokens and their exchange rates can be managed with `ROLE_UPDATE_TOKEN`. The exchange rate converts the token to standard units. Since no external oracle is consulted, only stablecoins. Accounts with `ROLE_DISABLE_TOKEN` can only disable payment tokens.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registrar/StandardRentPriceOracle.sol\":\"StandardRentPriceOracle\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/utils/StringUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\nlibrary StringUtils {\\n /// @dev Returns the length of a given string\\n /// @param s The string to measure the length of\\n /// @return The length of the input string\\n function strlen(string memory s) internal pure returns (uint256) {\\n uint256 len;\\n uint256 i = 0;\\n uint256 bytelength = bytes(s).length;\\n for (len = 0; i < bytelength; len++) {\\n bytes1 b = bytes(s)[i];\\n if (b < 0x80) {\\n i += 1;\\n } else if (b < 0xE0) {\\n i += 2;\\n } else if (b < 0xF0) {\\n i += 3;\\n } else if (b < 0xF8) {\\n i += 4;\\n } else if (b < 0xFC) {\\n i += 5;\\n } else {\\n i += 6;\\n }\\n }\\n return len;\\n }\\n\\n /// @dev Escapes special characters in a given string\\n /// @param str The string to escape\\n /// @return The escaped string\\n function escape(string memory str) internal pure returns (string memory) {\\n bytes memory strBytes = bytes(str);\\n uint extraChars = 0;\\n\\n // count extra space needed for escaping\\n for (uint i = 0; i < strBytes.length; i++) {\\n if (_needsEscaping(strBytes[i])) {\\n extraChars++;\\n }\\n }\\n\\n // allocate buffer with the exact size needed\\n bytes memory buffer = new bytes(strBytes.length + extraChars);\\n uint index = 0;\\n\\n // escape characters\\n for (uint i = 0; i < strBytes.length; i++) {\\n if (_needsEscaping(strBytes[i])) {\\n buffer[index++] = \\\"\\\\\\\\\\\";\\n buffer[index++] = _getEscapedChar(strBytes[i]);\\n } else {\\n buffer[index++] = strBytes[i];\\n }\\n }\\n\\n return string(buffer);\\n }\\n\\n // determine if a character needs escaping\\n function _needsEscaping(bytes1 char) private pure returns (bool) {\\n return\\n char == '\\\"' ||\\n char == \\\"/\\\" ||\\n char == \\\"\\\\\\\\\\\" ||\\n char == \\\"\\\\n\\\" ||\\n char == \\\"\\\\r\\\" ||\\n char == \\\"\\\\t\\\";\\n }\\n\\n // get the escaped character\\n function _getEscapedChar(bytes1 char) private pure returns (bytes1) {\\n if (char == \\\"\\\\n\\\") return \\\"n\\\";\\n if (char == \\\"\\\\r\\\") return \\\"r\\\";\\n if (char == \\\"\\\\t\\\") return \\\"t\\\";\\n return char;\\n }\\n}\\n\",\"keccak256\":\"0x0bfe56e70297eb274d45dccd1dab1fe1904f7802fdb27d0b5ff102cec3defb85\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, msg.sender);\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _getRoles(resource, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _getRoles(ROOT_RESOURCE, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return _effectiveRoles(resource, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the roles bitmap for an account for permission checks.\\n function _getRoles(uint256 resource, address account) internal view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the effective roles bitmap for an account for permission checks.\\n function _effectiveRoles(uint256 resource, address account) private view returns (uint256) {\\n return _getRoles(ROOT_RESOURCE, account) | _getRoles(resource, account);\\n }\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n}\\n\",\"keccak256\":\"0x934655016f502e7a2f8e5cbd294ef48e85f238821f5608de5675c023f48037af\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Admin roles imply their corresponding regular roles.\\n function withAdminRolesApplied(uint256 roleBitmap) internal pure returns (uint256) {\\n roleBitmap >>= 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Derive roles bitmap from assignee counts.\\n /// @param counts Packed role counts (0-15) as `uint4x64`.\\n function fromCounts(uint256 counts) internal pure returns (uint256) {\\n return (counts | (counts >> 1) | (counts >> 2) | (counts >> 3)) & ALL_ROLES;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function hasZeroNybbles(uint256 value) internal pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 zeroNybbles;\\n unchecked {\\n zeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return zeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xc14f05abd508e75c9f16a35e31d0fb9f1f1dd904b65d058201c788a9ddd562eb\",\"license\":\"MIT\"},\"project/src/registrar/StandardRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {StringUtils} from \\\"@ens/contracts/utils/StringUtils.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {Math} from \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\nimport {LibHalving} from \\\"./libraries/LibHalving.sol\\\";\\n\\n/// @dev Nybble 0: authorizes updating tokens. Root only.\\nuint256 constant ROLE_UPDATE_TOKEN = 1 << 0;\\n\\n/// @dev Nybble 32: authorizes setting `ROLE_UPDATE_TOKEN`.\\nuint256 constant ROLE_UPDATE_TOKEN_ADMIN = ROLE_UPDATE_TOKEN << 128;\\n\\n/// @dev Nybble 1: authorizes disabling tokens. Root only.\\nuint256 constant ROLE_DISABLE_TOKEN = 1 << 4;\\n\\n/// @dev Nybble 33: authorizes setting `ROLE_DISABLE_TOKEN`.\\nuint256 constant ROLE_DISABLE_TOKEN_ADMIN = ROLE_DISABLE_TOKEN << 128;\\n\\n/// @dev Nybble 2: authorizes contract naming. Root only.\\nuint256 constant ROLE_CAN_NAME = 1 << 8;\\n\\n/// @dev Nybble 34: authorizes setting `ROLE_CAN_NAME`.\\nuint256 constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n/// @dev Default root roles assigned at construction.\\nuint256 constant DEFAULT_ROLE_BITMAP =\\n ROLE_UPDATE_TOKEN |\\n ROLE_UPDATE_TOKEN_ADMIN |\\n ROLE_DISABLE_TOKEN |\\n ROLE_DISABLE_TOKEN_ADMIN |\\n ROLE_CAN_NAME |\\n ROLE_CAN_NAME_ADMIN;\\n\\n/// @dev Initialization-time structure for a discount point.\\n/// @param duration Duration threshold, in seconds.\\n/// @param numer Discount numerator, relative to `DISCOUNT_DENOMINATOR`.\\nstruct DiscountPoint {\\n uint64 duration;\\n uint128 numer;\\n}\\n\\n/// @dev Initialization-time structure for a payment token and exchange rate.\\n/// @param paymenToken The payment token.\\n/// @param numer Exchange rate numerator, relative to base units.\\n/// @param denom Exchange rate denominator, relative to base units.\\nstruct PaymentRatio {\\n IERC20 paymentToken;\\n uint128 numer;\\n uint128 denom;\\n}\\n\\n/// @notice Rent pricing oracle with (4) components:\\n///\\n/// 1. Base rates: per-second cost indexed by label codepoint count. Shorter names cost more.\\n/// Rates are stored in an array where index `i` corresponds to `i+1` codepoints; labels\\n/// longer than the array use the last entry.\\n/// 2. Duration discounts: increasing expiry reduce costs. Each dicount point specifies a\\n/// duration and a numerator. `1 - numerator / DISCOUNT_DENOMINATOR` determines the\\n/// discount percentage. Rewards longer registrations.\\n/// 3. Expiry premium: exponential decay from an initial premium with a configurable halving\\n/// period, reaching zero at the end of the premium period. Only charged to new owners of\\n/// recently expired names; renewals are exempt.\\n/// 4. Configurable payment tokens: payment tokens and their exchange rates can be managed\\n/// with `ROLE_UPDATE_TOKEN`. The exchange rate converts the token to standard units.\\n/// Since no external oracle is consulted, only stablecoins.\\n/// Accounts with `ROLE_DISABLE_TOKEN` can only disable payment tokens.\\n///\\ncontract StandardRentPriceOracle is EnhancedAccessControl, IRentPriceOracle, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Internal numerator/denominator pair representing a payment token's exchange rate relative to base pricing units.\\n struct Ratio {\\n uint128 numer;\\n uint128 denom;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Denominator for discounts.\\n uint128 public immutable DISCOUNT_DENOMINATOR;\\n\\n /// @notice Starting value of the exponential decay premium for recently expired names, in base pricing units.\\n uint256 public immutable PREMIUM_PRICE_INITIAL;\\n\\n /// @notice Number of seconds for the premium to halve in value.\\n uint64 public immutable PREMIUM_HALVING_PERIOD;\\n\\n /// @notice Total duration of the premium window; the premium reaches zero at this offset from expiry.\\n uint64 public immutable PREMIUM_PERIOD;\\n\\n /// @notice Precomputed premium halving at end of period.\\n uint256 public immutable PREMIUM_PRICE_OFFSET;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Per-second base rates indexed by codepoint count; `_baseRatePerCp[i]` prices labels with `i+1` codepoints.\\n uint256[] internal _baseRatePerCp;\\n\\n /// @dev Ordered discount points, relative to `DISCOUNT_DENOMINATOR`.\\n DiscountPoint[] internal _discountPoints;\\n\\n /// @dev Exchange rates for each accepted payment token, mapping token address to its numerator/denominator ratio.\\n mapping(IERC20 paymentToken => Ratio ratio) internal _paymentRatios;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `paymentToken` has changed.\\n /// @param paymentToken The payment token.\\n /// @param numer Exchange rate numerator, relative to base units.\\n /// @param denom Exchange rate denominator, relative to base units, or 0 if disabled.\\n event PaymentTokenUpdated(IERC20 indexed paymentToken, uint128 numer, uint128 denom);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Invalid base rates.\\n /// @dev Error selector: `0xde276447`\\n error InvalidBaseRates();\\n\\n /// @notice Invalid payment token exchange rate.\\n /// @dev Error selector: `0x648564d3`\\n error InvalidRatio();\\n\\n /// @notice Invalid discount configuration.\\n /// @dev Error selector: `0x997ea360`\\n error InvalidDiscount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param rootAccount Account granted root roles.\\n /// @param baseRatePerCp Base rates, in standard units per second.\\n /// @param discountPoints List of discount points.\\n /// @param discountDenominator Denominator for discounts.\\n /// @param premiumPriceInitial Premium initial price, in standard units.\\n /// @param premiumHalvingPeriod Premium halving period, in seconds.\\n /// @param premiumPeriod Premium period, in seconds.\\n /// @param paymentRatios List of payment tokens with exchange rates.\\n constructor(\\n address rootAccount,\\n uint256[] memory baseRatePerCp,\\n DiscountPoint[] memory discountPoints,\\n uint128 discountDenominator,\\n uint256 premiumPriceInitial,\\n uint64 premiumHalvingPeriod,\\n uint64 premiumPeriod,\\n PaymentRatio[] memory paymentRatios\\n )\\n {\\n _grantRoles(ROOT_RESOURCE, DEFAULT_ROLE_BITMAP, rootAccount, false);\\n\\n if (baseRatePerCp.length == 0) {\\n revert InvalidBaseRates();\\n }\\n _baseRatePerCp = baseRatePerCp;\\n\\n uint256 n = discountPoints.length;\\n if (n > 0) {\\n uint64 duration; // must increase\\n uint128 numer = discountDenominator; // must decrease\\n for (uint256 i; i < n; ++i) {\\n DiscountPoint memory p = discountPoints[i];\\n if (p.duration <= duration || p.numer >= numer) {\\n revert InvalidDiscount(); // not strictly monotonic\\n }\\n duration = p.duration;\\n numer = p.numer;\\n _discountPoints.push(p);\\n }\\n if (numer == 0) {\\n revert InvalidDiscount(); // free\\n }\\n DISCOUNT_DENOMINATOR = discountDenominator;\\n }\\n\\n PREMIUM_PRICE_INITIAL = premiumPriceInitial;\\n PREMIUM_HALVING_PERIOD = premiumHalvingPeriod;\\n PREMIUM_PERIOD = premiumPeriod;\\n PREMIUM_PRICE_OFFSET = LibHalving.halving(\\n premiumPriceInitial,\\n premiumHalvingPeriod,\\n premiumPeriod\\n );\\n\\n for (uint256 i; i < paymentRatios.length; ++i) {\\n PaymentRatio memory pr = paymentRatios[i];\\n if (pr.numer == 0 || pr.denom == 0) {\\n revert InvalidRatio();\\n }\\n _paymentRatios[pr.paymentToken] = Ratio(pr.numer, pr.denom);\\n emit PaymentTokenUpdated(pr.paymentToken, pr.numer, pr.denom);\\n }\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return\\n interfaceId == type(IRentPriceOracle).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Update `paymentToken` support and/or exchange rate.\\n /// @param paymentToken The payment token.\\n /// @param numer The numerator of the exchange rate.\\n /// @param denom The denominator of the exchange rate, or 0 to disable.\\n function updatePaymentToken(IERC20 paymentToken, uint128 numer, uint128 denom)\\n external\\n onlyRootRoles(ROLE_UPDATE_TOKEN)\\n {\\n Ratio memory ratio = _paymentRatios[paymentToken];\\n if (denom > 0) {\\n if (numer == 0) {\\n revert InvalidRatio();\\n }\\n if (ratio.numer != numer || ratio.denom != denom) {\\n _paymentRatios[paymentToken] = Ratio(numer, denom);\\n emit PaymentTokenUpdated(paymentToken, numer, denom);\\n }\\n } else if (ratio.denom > 0) {\\n delete _paymentRatios[paymentToken];\\n emit PaymentTokenUpdated(paymentToken, 0, 0);\\n }\\n }\\n\\n /// @notice Disable `paymentToken` support.\\n /// @param paymentToken The payment token.\\n function disablePaymentToken(IERC20 paymentToken) external onlyRootRoles(ROLE_DISABLE_TOKEN) {\\n if (_paymentRatios[paymentToken].denom > 0) {\\n delete _paymentRatios[paymentToken];\\n emit PaymentTokenUpdated(paymentToken, 0, 0);\\n }\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return hasRootRoles(ROLE_CAN_NAME, namer);\\n }\\n\\n /// @notice Get all base rates, in standard units per second.\\n function getBaseRates() external view returns (uint256[] memory) {\\n return _baseRatePerCp;\\n }\\n\\n /// @notice Get all discount durations, in seconds.\\n function getDiscountPoints() external view returns (DiscountPoint[] memory v) {\\n return _discountPoints;\\n }\\n\\n /// @notice Check if a `label` is valid. Does not check if normalized.\\n /// @param label The name to check.\\n /// @return `true` if the `label` is valid.\\n function isValid(string calldata label) external view returns (bool) {\\n return getBasePrice(label, 1) > 0;\\n }\\n\\n /// @notice Get numerator/denominator for `paymentToken`.\\n /// @param paymentToken The payment token.\\n /// @return numer The numerator of the exchange rate.\\n /// @return denom The denominator of the exchange rate.\\n function getPaymentTokenRatio(IERC20 paymentToken)\\n external\\n view\\n returns (uint128 numer, uint128 denom)\\n {\\n Ratio storage ratio = _paymentRatios[paymentToken];\\n return (ratio.numer, ratio.denom);\\n }\\n\\n /// @notice Check if `paymentToken` is supported for payment.\\n /// @param paymentToken The payment token.\\n /// @return `true` if `paymentToken` is supported.\\n function isPaymentToken(IERC20 paymentToken) external view returns (bool) {\\n return _paymentRatios[paymentToken].denom > 0;\\n }\\n\\n /// @inheritdoc IRentPriceOracle\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium)\\n {\\n base = _requireBasePrice(label, duration);\\n Ratio memory ratio = _requirePaymentToken(paymentToken);\\n premium = getPremiumPriceAfter(available);\\n if (premium > 0) {\\n base += premium; // total\\n premium = _toAmount(premium, ratio);\\n }\\n base = _toAmount(base, ratio) - premium; // ensure: f(a+b) - f(a) == f(b)\\n }\\n\\n /// @inheritdoc IRentPriceOracle\\n function getRenewPrice(\\n string calldata label,\\n uint64 /*expiry*/,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256)\\n {\\n return _toAmount(_requireBasePrice(label, duration), _requirePaymentToken(paymentToken));\\n }\\n\\n /// @notice Convert arbitrary standard units to payment token amount.\\n /// @param value An arbitrary value, in standard units.\\n /// @param paymentToken The payment token.\\n /// @return The amount of payment token.\\n function convertUnits(uint256 value, IERC20 paymentToken) external view returns (uint256) {\\n return _toAmount(value, _requirePaymentToken(paymentToken));\\n }\\n\\n /// @notice Apply discount function to an arbitrary value.\\n /// @param value An arbitrary value.\\n /// @param duration The duration, in seconds.\\n /// @return `value` reduced by discount.\\n function applyDiscount(uint256 value, uint64 duration) public view returns (uint256) {\\n uint256 n = _discountPoints.length;\\n uint128 numer;\\n for (uint256 i; i < n; ++i) {\\n DiscountPoint storage p = _discountPoints[i];\\n if (duration < p.duration)\\n break;\\n numer = p.numer;\\n }\\n return\\n numer == 0\\n ? value\\n : Math.mulDiv(value, numer, DISCOUNT_DENOMINATOR);\\n }\\n\\n /// @notice Get base price to register or renew `label` for `duration` seconds.\\n /// @param label The name to price.\\n /// @param duration The duration, in seconds.\\n /// @return The base price, in standard units, or 0 if not valid.\\n function getBasePrice(string calldata label, uint64 duration) public view returns (uint256) {\\n uint256 n = bytes(label).length;\\n if (n == 0 || n > 255)\\n return 0; // too long or too short\\n uint256 i = getLength(label);\\n if (i > _baseRatePerCp.length) {\\n i = _baseRatePerCp.length;\\n }\\n return applyDiscount(_baseRatePerCp[i - 1] * duration, duration);\\n }\\n\\n /// @notice Get premium price for a duration after expiry.\\n /// @dev Defined over `[0, premiumPeriod)`.\\n /// @param duration The time after expiration, in seconds.\\n /// @return The premium price, in standard units.\\n function getPremiumPriceAfter(uint64 duration) public view returns (uint256) {\\n return\\n duration < PREMIUM_PERIOD\\n ? LibHalving.halving(PREMIUM_PRICE_INITIAL, PREMIUM_HALVING_PERIOD, duration) -\\n PREMIUM_PRICE_OFFSET\\n : 0;\\n }\\n\\n /// @notice Check length of a name.\\n /// @param label The name to check.\\n /// @return The number of Unicode codepoints.\\n function getLength(string calldata label) public pure returns (uint256) {\\n return StringUtils.strlen(label);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Compute `rate * duration` and apply discount.\\n function _requireBasePrice(string calldata label, uint64 duration)\\n internal\\n view\\n returns (uint256 rate)\\n {\\n rate = getBasePrice(label, duration);\\n if (rate == 0) {\\n revert NotValid(label);\\n }\\n }\\n\\n /// @dev Ensure `paymentToken` is supported.\\n function _requirePaymentToken(IERC20 paymentToken) internal view returns (Ratio memory ratio) {\\n ratio = _paymentRatios[paymentToken];\\n if (ratio.denom == 0) {\\n revert PaymentTokenNotSupported(paymentToken);\\n }\\n }\\n\\n /// @dev Convert standard units to token amount.\\n function _toAmount(uint256 value, Ratio memory ratio) internal pure returns (uint256) {\\n return\\n ratio.numer == ratio.denom\\n ? value\\n : Math.mulDiv(value, ratio.numer, ratio.denom, Math.Rounding.Ceil);\\n }\\n}\\n\",\"keccak256\":\"0xdc93b3393fed7b46378728ec6a7e37333d45c7937d129222aa9977772d22ddc8\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registrar/libraries/LibHalving.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Computes exponential decay `initial / 2^(elapsed / half)` using fixed-point arithmetic\\n/// with 18-decimal precision. The elapsed/half ratio is decomposed into integer and fractional\\n/// parts: the integer part is applied via right-shift, the fractional part via multiplication\\n/// with precomputed constants.\\nlibrary LibHalving {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Fixed-point scale factor (10^18).\\n uint256 private constant PRECISION = 1e18;\\n\\n // solgrid-disable docs/natspec\\n\\n /// @dev Precomputed values of `0.5^(2^k / 65536) * 10^18` for the corresponding power-of-two\\n /// bit position. Together they compose any fractional power of 0.5 in 16-bit resolution\\n /// via binary decomposition.\\n uint256 private constant BIT1 = 999989423469314432; // 0.5 ^ 1/65536 * (10 ** 18)\\n uint256 private constant BIT2 = 999978847050491904; // 0.5 ^ 2/65536 * (10 ** 18)\\n uint256 private constant BIT3 = 999957694548431104;\\n uint256 private constant BIT4 = 999915390886613504;\\n uint256 private constant BIT5 = 999830788931929088;\\n uint256 private constant BIT6 = 999661606496243712;\\n uint256 private constant BIT7 = 999323327502650752;\\n uint256 private constant BIT8 = 998647112890970240;\\n uint256 private constant BIT9 = 997296056085470080;\\n uint256 private constant BIT10 = 994599423483633152;\\n uint256 private constant BIT11 = 989228013193975424;\\n uint256 private constant BIT12 = 978572062087700096;\\n uint256 private constant BIT13 = 957603280698573696;\\n uint256 private constant BIT14 = 917004043204671232;\\n uint256 private constant BIT15 = 840896415253714560;\\n uint256 private constant BIT16 = 707106781186547584;\\n\\n // solgrid-enable docs/natspec\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Library Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Compute `initial / 2 ** (elapsed / half)`.\\n /// @param initial The initial value.\\n /// @param half The halving period.\\n /// @param elapsed The elapsed duration.\\n function halving(uint256 initial, uint256 half, uint256 elapsed)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (initial == 0 || half == 0)\\n return 0;\\n if (elapsed == 0)\\n return initial;\\n uint256 x = (elapsed * PRECISION) / half;\\n uint256 i = x / PRECISION;\\n uint256 f = x - i * PRECISION;\\n return _addFraction(initial >> i, (f << 16) / PRECISION);\\n }\\n\\n /// @dev Applies the fractional part of the exponent by multiplying `x` with each precomputed\\n /// constant whose corresponding bit is set in the 16-bit fraction, implementing\\n /// `x * 0.5^(fraction / 65536)`.\\n function _addFraction(uint256 x, uint256 fraction) private pure returns (uint256) {\\n if (fraction & (1 << 0) != 0) {\\n x = (x * BIT1) / PRECISION;\\n }\\n if (fraction & (1 << 1) != 0) {\\n x = (x * BIT2) / PRECISION;\\n }\\n if (fraction & (1 << 2) != 0) {\\n x = (x * BIT3) / PRECISION;\\n }\\n if (fraction & (1 << 3) != 0) {\\n x = (x * BIT4) / PRECISION;\\n }\\n if (fraction & (1 << 4) != 0) {\\n x = (x * BIT5) / PRECISION;\\n }\\n if (fraction & (1 << 5) != 0) {\\n x = (x * BIT6) / PRECISION;\\n }\\n if (fraction & (1 << 6) != 0) {\\n x = (x * BIT7) / PRECISION;\\n }\\n if (fraction & (1 << 7) != 0) {\\n x = (x * BIT8) / PRECISION;\\n }\\n if (fraction & (1 << 8) != 0) {\\n x = (x * BIT9) / PRECISION;\\n }\\n if (fraction & (1 << 9) != 0) {\\n x = (x * BIT10) / PRECISION;\\n }\\n if (fraction & (1 << 10) != 0) {\\n x = (x * BIT11) / PRECISION;\\n }\\n if (fraction & (1 << 11) != 0) {\\n x = (x * BIT12) / PRECISION;\\n }\\n if (fraction & (1 << 12) != 0) {\\n x = (x * BIT13) / PRECISION;\\n }\\n if (fraction & (1 << 13) != 0) {\\n x = (x * BIT14) / PRECISION;\\n }\\n if (fraction & (1 << 14) != 0) {\\n x = (x * BIT15) / PRECISION;\\n }\\n if (fraction & (1 << 15) != 0) {\\n x = (x * BIT16) / PRECISION;\\n }\\n return x;\\n }\\n}\\n\",\"keccak256\":\"0xee476242b69612db26589dfa47817c4381e7dd5a3713a961a2bf2ac656aff67d\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 56727, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_roles", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 56732, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_roleCount", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 56737, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 65181, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_baseRatePerCp", + "offset": 0, + "slot": "258", + "type": "t_array(t_uint256)dyn_storage" + }, + { + "astId": 65186, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_discountPoints", + "offset": 0, + "slot": "259", + "type": "t_array(t_struct(DiscountPoint)65140_storage)dyn_storage" + }, + { + "astId": 65193, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "_paymentRatios", + "offset": 0, + "slot": "260", + "type": "t_mapping(t_contract(IERC20)39090,t_struct(Ratio)65162_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(DiscountPoint)65140_storage)dyn_storage": { + "base": "t_struct(DiscountPoint)65140_storage", + "encoding": "dynamic_array", + "label": "struct DiscountPoint[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_array(t_uint256)dyn_storage": { + "base": "t_uint256", + "encoding": "dynamic_array", + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_contract(IERC20)39090": { + "encoding": "inplace", + "label": "contract IERC20", + "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_contract(IERC20)39090,t_struct(Ratio)65162_storage)": { + "encoding": "mapping", + "key": "t_contract(IERC20)39090", + "label": "mapping(contract IERC20 => struct StandardRentPriceOracle.Ratio)", + "numberOfBytes": "32", + "value": "t_struct(Ratio)65162_storage" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_struct(DiscountPoint)65140_storage": { + "encoding": "inplace", + "label": "struct DiscountPoint", + "members": [ + { + "astId": 65137, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "duration", + "offset": 0, + "slot": "0", + "type": "t_uint64" + }, + { + "astId": 65139, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "numer", + "offset": 8, + "slot": "0", + "type": "t_uint128" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Ratio)65162_storage": { + "encoding": "inplace", + "label": "struct StandardRentPriceOracle.Ratio", + "members": [ + { + "astId": 65159, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "numer", + "offset": 0, + "slot": "0", + "type": "t_uint128" + }, + { + "astId": 65161, + "contract": "project/src/registrar/StandardRentPriceOracle.sol:StandardRentPriceOracle", + "label": "denom", + "offset": 16, + "slot": "0", + "type": "t_uint128" + } + ], + "numberOfBytes": "32" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "InvalidBaseRates()": [ + { + "notice": "Invalid base rates." + } + ], + "InvalidDiscount()": [ + { + "notice": "Invalid discount configuration." + } + ], + "InvalidRatio()": [ + { + "notice": "Invalid payment token exchange rate." + } + ], + "NotValid(string)": [ + { + "notice": "`label` is not valid." + } + ], + "PaymentTokenNotSupported(address)": [ + { + "notice": "`paymentToken` is not supported for payment." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "PaymentTokenUpdated(address,uint128,uint128)": { + "notice": "`paymentToken` has changed." + } + }, + "kind": "user", + "methods": { + "DISCOUNT_DENOMINATOR()": { + "notice": "Denominator for discounts." + }, + "PREMIUM_HALVING_PERIOD()": { + "notice": "Number of seconds for the premium to halve in value." + }, + "PREMIUM_PERIOD()": { + "notice": "Total duration of the premium window; the premium reaches zero at this offset from expiry." + }, + "PREMIUM_PRICE_INITIAL()": { + "notice": "Starting value of the exponential decay premium for recently expired names, in base pricing units." + }, + "PREMIUM_PRICE_OFFSET()": { + "notice": "Precomputed premium halving at end of period." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "applyDiscount(uint256,uint64)": { + "notice": "Apply discount function to an arbitrary value." + }, + "convertUnits(uint256,address)": { + "notice": "Convert arbitrary standard units to payment token amount." + }, + "disablePaymentToken(address)": { + "notice": "Disable `paymentToken` support." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getBasePrice(string,uint64)": { + "notice": "Get base price to register or renew `label` for `duration` seconds." + }, + "getBaseRates()": { + "notice": "Get all base rates, in standard units per second." + }, + "getDiscountPoints()": { + "notice": "Get all discount durations, in seconds." + }, + "getLength(string)": { + "notice": "Check length of a name." + }, + "getPaymentTokenRatio(address)": { + "notice": "Get numerator/denominator for `paymentToken`." + }, + "getPremiumPriceAfter(uint64)": { + "notice": "Get premium price for a duration after expiry." + }, + "getRegisterPrice(string,uint64,uint64,address)": { + "notice": "Determine registration price for `label`." + }, + "getRenewPrice(string,uint64,uint64,address)": { + "notice": "Determine renewal price for `label`." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "isPaymentToken(address)": { + "notice": "Check if `paymentToken` is supported for payment." + }, + "isValid(string)": { + "notice": "Check if a `label` is valid. Does not check if normalized." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "updatePaymentToken(address,uint128,uint128)": { + "notice": "Update `paymentToken` support and/or exchange rate." + } + }, + "notice": "Rent pricing oracle with (4) components: 1. Base rates: per-second cost indexed by label codepoint count. Shorter names cost more. Rates are stored in an array where index `i` corresponds to `i+1` codepoints; labels longer than the array use the last entry. 2. Duration discounts: increasing expiry reduce costs. Each dicount point specifies a duration and a numerator. `1 - numerator / DISCOUNT_DENOMINATOR` determines the discount percentage. Rewards longer registrations. 3. Expiry premium: exponential decay from an initial premium with a configurable halving period, reaching zero at the end of the premium period. Only charged to new owners of recently expired names; renewals are exempt. 4. Configurable payment tokens: payment tokens and their exchange rates can be managed with `ROLE_UPDATE_TOKEN`. The exchange rate converts the token to standard units. Since no external oracle is consulted, only stablecoins. Accounts with `ROLE_DISABLE_TOKEN` can only disable payment tokens.", + "version": 1 + }, + "argsData": "0x00000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d3000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000004b3b4ca85a86c47a098a2240000000000000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000000000000000000000000000000000000001518000000000000000000000000000000000000000000000000000000000001baf8000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000135aa7b00000000000000000000000000000000000000000000000000000000004d6a9f000000000000000000000000000000000000000000000000000000000003deef00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000003c267000000000000000000000000000000000041d3e3134f35ebeac858ddf8000000000000000000000000000000000000000000000000000000000000000005a39a800000000000000000000000000000000033b8c4b3be3ca713e68ef78c00000000000000000000000000000000000000000000000000000000000000000b473500000000000000000000000000000000002a515b1eb2ebce84a55db344000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d3322b29a7bdee707d1684676f149bf41aa3422f000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000e33a01a41ee4a68616b5278183aa88808326ed8e00000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001c7d4b196cb0c7b01d743fbc6116a902379c7238000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000f4240", + "transaction": { + "hash": "0x83ad5befdad194cffc46c9cf06bb432974f1b63545bdc8452d21b2dca31b224e", + "nonce": "0x50", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x4eb2f891ce30fb12d5ab3df5cdcbc8a220d49111f5bb56c759033a746bd53533", + "blockNumber": "0xaa5704", + "transactionIndex": "0xd3" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/UniversalResolverV2.json b/contracts/deployments/sepolia/UniversalResolverV2.json new file mode 100644 index 000000000..cbb633112 --- /dev/null +++ b/contracts/deployments/sepolia/UniversalResolverV2.json @@ -0,0 +1,1406 @@ +{ + "address": "0x85edf8b6b7d4211e2b07aa687506b746357b92cf", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "rootRegistry", + "type": "address" + }, + { + "internalType": "contract IGatewayProvider", + "name": "batchGatewayProvider", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "dns", + "type": "bytes" + } + ], + "name": "DNSDecodingFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "ens", + "type": "string" + } + ], + "name": "DNSEncodingFailed", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "status", + "type": "uint16" + }, + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "HttpError", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBatchGatewayResponse", + "type": "error" + }, + { + "inputs": [], + "name": "LabelIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelIsTooLong", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "errorData", + "type": "bytes" + } + ], + "name": "ResolverError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "ResolverNotContract", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "ResolverNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "primary", + "type": "string" + }, + { + "internalType": "bytes", + "name": "primaryAddress", + "type": "bytes" + } + ], + "name": "ReverseAddressMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "selector", + "type": "bytes4" + } + ], + "name": "UnsupportedResolverProfile", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchGatewayProvider", + "outputs": [ + { + "internalType": "contract IGatewayProvider", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "name": "ccipBatch", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipBatchCallback", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "call", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "flags", + "type": "uint256" + } + ], + "internalType": "struct CCIPBatcher.Lookup[]", + "name": "lookups", + "type": "tuple[]" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "internalType": "struct CCIPBatcher.Batch", + "name": "batch", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ccipReadCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "findCanonicalName", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findCanonicalRegistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findExactRegistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findParentRegistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findRegistries", + "outputs": [ + { + "internalType": "contract IRegistry[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "findResolver", + "outputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "requireResolver", + "outputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bool", + "name": "extended", + "type": "bool" + } + ], + "internalType": "struct AbstractUniversalResolver.ResolverInfo", + "name": "info", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "resolve", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveBatchCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveCallback", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "resolveDirectCallback", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "resolveDirectCallbackError", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "name": "resolveWithGateways", + "outputs": [ + { + "internalType": "bytes", + "name": "result", + "type": "bytes" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "name": "resolveWithResolver", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "lookupAddress", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + } + ], + "name": "reverse", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "reverseAddressCallback", + "outputs": [ + { + "internalType": "string", + "name": "primary", + "type": "string" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "address", + "name": "reverseResolver", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "reverseNameCallback", + "outputs": [ + { + "internalType": "string", + "name": "primary", + "type": "string" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "lookupAddress", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "coinType", + "type": "uint256" + }, + { + "internalType": "string[]", + "name": "gateways", + "type": "string[]" + } + ], + "name": "reverseWithGateways", + "outputs": [ + { + "internalType": "string", + "name": "primary", + "type": "string" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "address", + "name": "reverseResolver", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "UniversalResolverV2", + "sourceName": "src/universalResolver/UniversalResolverV2.sol", + "bytecode": "0x610100604052348015610010575f80fd5b506040516148dd3803806148dd83398101604081905261002f91610068565b61c3506080526001600160a01b0391821660a052811660c0521660e0526100b2565b6001600160a01b0381168114610065575f80fd5b50565b5f805f6060848603121561007a575f80fd5b835161008581610051565b602085015190935061009681610051565b60408501519092506100a781610051565b809150509250925092565b60805160a05160c05160e0516147b261012b5f395f818161042e0152818161053201528181610b4901528181610d1501528181610fea01528181611024015281816114b6015261159c01525f81816102480152610ad701525f81816101e101528181610a270152610b7a01525f61223d01526147b25ff3fe608060405234801561000f575f80fd5b50600436106101b0575f3560e01c806394fbfa87116100f3578063b536af7611610093578063c92cc49a1161006e578063c92cc49a14610429578063e4f8ce0514610450578063ef46c0b814610463578063f272e2af14610476575f80fd5b8063b536af76146103e3578063b7d6ca64146103f6578063c285238a14610409575f80fd5b8063a1472844116100ce578063a147284414610372578063a1cbcbaf14610385578063b363cc73146103bd578063b4a85801146103d0575f80fd5b806394fbfa871461032c57806397ad3b3b1461033f5780639f28e99d14610352575f80fd5b80634a3e39941161015e5780635d78a217116101395780635d78a217146102d25780636f3ff726146102e557806383a64339146102f85780639061b9231461030b575f80fd5b80634a3e39941461027d57806355391bb81461029d578063575de750146102b0575f80fd5b80634878c6dd1161018e5780634878c6dd1461023057806348ee1bcc14610243578063491fc4f91461026a575f80fd5b806301ffc9a7146101b457806302cf2578146101dc5780633c6cbda81461021b575b5f80fd5b6101c76101c236600461331a565b610496565b60405190151581526020015b60405180910390f35b6102037f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101d3565b61022e610229366004613373565b6104e8565b005b61020361023e3660046133da565b61052c565b6102037f000000000000000000000000000000000000000000000000000000000000000081565b61022e610278366004613373565b610593565b61029061028b3660046135f8565b610703565b6040516101d391906136c4565b61022e6102ab3660046136d6565b610837565b6102c36102be366004613373565b6108ba565b6040516101d39392919061373a565b6102c36102e036600461376c565b610a1b565b6101c76102f33660046137b4565b610ab6565b6102906103063660046137b4565b610b42565b61031e610319366004613373565b610b6e565b6040516101d39291906137cf565b6102c361033a366004613373565b610c07565b61020361034d3660046133da565b610d0f565b6103656103603660046137f9565b610d6f565b6040516101d391906139b9565b61031e610380366004613a82565b610f30565b610398610393366004613b0f565b610fe2565b604080516001600160a01b0390941684526020840192909252908201526060016101d3565b6102036103cb3660046133da565b61101e565b61031e6103de366004613373565b61107e565b6103656103f1366004613373565b6110d4565b6102c3610404366004613b41565b61132e565b61041c610417366004613b0f565b611454565b6040516101d39190613baf565b6102037f000000000000000000000000000000000000000000000000000000000000000081565b61020361045e3660046133da565b6114b0565b61022e610471366004613c09565b611510565b6104896104843660046133da565b611595565b6040516101d39190613c69565b5f7ff99a5e06000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806104d357506104d3826115f6565b806104e257506104e282611643565b92915050565b61052684848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061167792505050565b50505050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506116d6915050565b9392505050565b5f6105a0848601866137f9565b5190505f8080806105b386880188613cc2565b9350935093509350606083156105f3576105cd868661179c565b6040516020016105dd9190613d27565b60405160208183030381529060405290506106a8565b5f865f8151811061060657610606613d89565b602002602001015190508060400151915060048160600151165f1461062d57815160208301fd5b6060810151600216156106485761064382611677565b610689565b81515f0361068957806020015161065e90613d9d565b604051637b1c461b60e01b81526001600160e01b031990911660048201526024015b60405180910390fd5b85156106a657818060200190518101906106a39190613e1d565b91505b505b6106f7308483856040516024016106c0929190613e4f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526118fe565b50505050505050505050565b6040805160a08101825260608082525f60208301819052928201839052818101839052608082019290925286868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250604080516020601f89018190048102820181019092528781526107a29189908990819084018382808284375f9201829052509250611923915050565b60408201526001600160a01b03881660608201526107bf81611954565b61082c8186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516001600160a01b038f16602082015289935063b4a8580160e01b9250015b604051602081830303815290604052611a1c565b509695505050505050565b5f80808061084785870187613e7c565b935093509350935086515f0361087c57604051637b1c461b60e01b81526001600160e01b031984166004820152602401610680565b831561089957868060200190518101906108969190613e1d565b96505b6108b1308389846040516024016106c0929190613e4f565b50505050505050565b60605f80806108cb85870187613f32565b90506108d987890189613b0f565b935083515f03610902576060015160408051602081019091525f80825290945092509050610a11565b5f61090f61041786611d88565b9050610a0e81603c84602001511461098d5782604001518460200151604051602401610945929190918252602082015260400190565b60408051601f198184030181529190526020810180516001600160e01b03167ff1cb7e06000000000000000000000000000000000000000000000000000000001790526109e8565b82604001516040516024016109a491815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f3b3b57de000000000000000000000000000000000000000000000000000000001790525b84604001516394fbfa8760e01b868a876060015160405160200161081893929190613fbb565b50505b9450945094915050565b60605f80610aa78686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663093a86d36040518163ffffffff1660e01b81526004015f60405180830381865afa158015610a80573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104049190810190614074565b92509250925093509350939050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610b1e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e291906140a6565b60606104e27f000000000000000000000000000000000000000000000000000000000000000083611f46565b60605f610bfa868686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663093a86d36040518163ffffffff1660e01b81526004015f60405180830381865afa158015610bd3573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526103809190810190614074565b9150915094509492505050565b60605f80610c3d6040518060800160405280606081526020015f8152602001606081526020015f6001600160a01b031681525090565b610c49858701876140c1565b60208301519196509450909150606090603b1901610ca7575f610c6e898b018b6137b4565b6040516bffffffffffffffffffffffff19606083901b166020820152909150603401604051602081830303815290604052915050610cb6565b610cb3888a018a613b0f565b90505b8151610cc29082612115565b610cfc5784816040517fef9c03ce000000000000000000000000000000000000000000000000000000008152600401610680929190613e4f565b8160600151925050509450945094915050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612139915050565b60408051808201909152606080825260208201525f5b825151811015610f22575f835f01518281518110610da557610da5613d89565b6020026020010151905060408160600151165f14610dc35750610f1a565b60608101516030165f03610e6d575f610dde825f01516121f7565b610de9576010610dec565b60205b9050825b855151811015610e6a57825f01516001600160a01b0316865f01518281518110610e1c57610e1c613d89565b60200260200101515f01516001600160a01b031603610e625781865f01518281518110610e4b57610e4b613d89565b602002602001015160600181815117915081815250505b600101610df0565b50505b5f60208260600151165f1490505f80610e8f8315855f01518660200151612229565b9150915081158015610eb95750630556f18360e41b610ead82613d9d565b6001600160e01b031916145b15610ece576060840180516001179052610f0e565b6060840180516040179052828015610ee557508051155b610efa5781610efa5760608401805160021790525b80515f03610f0e5760608401805160081790525b60409093019290925250505b600101610d85565b50610f2c826122bc565b5090565b60605f80610f7288888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061145492505050565b9050610fd78187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050506060840151604080516001600160a01b039092166020830152889163b4a8580160e01b9101610818565b509550959350505050565b5f805f6110107f0000000000000000000000000000000000000000000000000000000000000000855f6124a7565b919790965090945092505050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061261392505050565b60605f858561108f858701876137b4565b82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929c939b50929950505050505050505050565b60408051808201909152606080825260208201525f806110f686880188614134565b91509150805182511461111c5760405163252e18f560e11b815260040160405180910390fd5b611128848601866137f9565b92505f805b8451518110156112f8575f855f0151828151811061114d5761114d613d89565b6020026020010151905060408160600151165f036112ef5783518310156112e3575f84848151811061118157611181613d89565b6020026020010151905085848151811061119d5761119d613d89565b6020026020010151156111ba5760608201805160441790526112dd565b5f6111c88360400151612663565b90505f815f01516001600160a01b031682606001518484608001516040516024016111f4929190613e4f565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161123291906141fd565b5f60405180830381855afa9150503d805f811461126a576040519150601f19603f3d011682016040523d82523d5f602084013e61126f565b606091505b509350905080806112995750630556f18360e41b61128c84613d9d565b6001600160e01b03191614155b156112da5760608401805160401790528015806112b557508251155b156112c65760608401805160021790525b82515f036112da5760608401805160081790525b50505b60408201525b6112ec8361421c565b92505b5060010161112d565b508151811461131a5760405163252e18f560e11b815260040160405180910390fd5b611323846122bc565b505050949350505050565b60605f805f61137e6104176113798a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c92506126a7915050565b611d88565b905061144981826040015160405160240161139b91815260200190565b60405160208183030381529060405263691f343160e01b6020820180516001600160e01b0383818316178352505050508763575de75060e01b60405180608001604052808e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060208082018e905260408083018e905260608a8101516001600160a01b03169301929092529051610818929101614234565b509450945094915050565b6040805160a08101825260608082525f602083018190529282018390528101829052608081019190915261148782610fe2565b602084015260408301526001600160a01b031660608201528181526114ab81611954565b919050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506127ec915050565b5f81806020019051810190611525919061425c565b9050611590815f0151826020015185846040015160405160240161154a929190613e4f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a0860151612818565b505050565b606061058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506129db915050565b5f7f6cd2d09b000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806104e257506301ffc9a760e01b6001600160e01b03198316146104e2565b5f6001600160e01b0319821663379ffb9360e11b14806104e257506301ffc9a760e01b6001600160e01b03198316146104e2565b637b1c461b60e01b61168882613d9d565b6001600160e01b0319160361169f57805160208201fd5b806040517f95c0c75200000000000000000000000000000000000000000000000000000000815260040161068091906136c4565b50565b5f805f6116e38585612a82565b9092509050816116f757859250505061058c565b5f6117038787846116d6565b90506001600160a01b03811615611792575f61171f8787612aaf565b50604051631ad7b10b60e11b81529091506001600160a01b038316906335af62169061174f9084906004016136c4565b602060405180830381865afa15801561176a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178e919061432b565b9450505b5050509392505050565b6060825167ffffffffffffffff8111156117b8576117b861342d565b6040519080825280602002602001820160405280156117eb57816020015b60608152602001906001900390816117d65790505b5090505f5b83518110156118f7575f84828151811061180c5761180c613d89565b60209081029190910101516040810151606082015191925090600e165f0361185057841561184b57808060200190518101906118489190613e1d565b90505b6118cf565b8051156118cf578051600403601f1680156118cd57818167ffffffffffffffff81111561187f5761187f61342d565b6040519080825280601f01601f1916602001820160405280156118a9576020820181803683370190505b506040516020016118bb929190614346565b60405160208183030381529060405291505b505b808484815181106118e2576118e2613d89565b602090810291909101015250506001016117f0565b5092915050565b61191f82825f60e01b5f60e01b60405180602001604052805f815250612818565b5050565b5f61192e8383612a82565b9250905080156104e25761058c6119458484611923565b825f9182526020526040902090565b60608101516001600160a01b0316611982578051604051630ee413fd60e31b815261068091906004016136c4565b6119978160600151639061b92360e01b612b2c565b156119a6576001608082015250565b6020810151156119cc578051604051630ee413fd60e31b815261068091906004016136c4565b80606001516001600160a01b03163b5f036116d357805160608201516040517f1e9535f20000000000000000000000000000000000000000000000000000000081526106809291906004016137cf565b5f7fac9650d800000000000000000000000000000000000000000000000000000000611a4786613d9d565b6001600160e01b031916149050611a69866060015163582de3e760e01b612b2c565b8015611b105750801580611b10575085608001518015611b105750606086015160405163582de3e760e01b81527f96b62db80000000000000000000000000000000000000000000000000000000060048201526001600160a01b039091169063582de3e790602401602060405180830381865afa158015611aec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b1091906140a6565b15611be657611be686606001518760800151611b2c5786611b6b565b8751604051611b4091908990602401613e4f565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b1790525b60808901517f55391bb800000000000000000000000000000000000000000000000000000000907f3c6cbda80000000000000000000000000000000000000000000000000000000090611bbd8b613d9d565b8989604051602001611bd2949392919061435a565b604051602081830303815290604052612818565b60608115611c2057611c06866004808951611c019190614398565b612bb2565b806020019051810190611c1991906143ab565b9050611c6b565b60408051600180825281830190925290816020015b6060815260200190600190039081611c3557905050905085815f81518110611c5f57611c5f613d89565b60200260200101819052505b866080015115611d02575f5b8151811015611d0057875f0151828281518110611c9657611c96613d89565b6020026020010151604051602401611caf929190613e4f565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b1790528251839083908110611ced57611ced613d89565b6020908102919091010152600101611c77565b505b6108b130306001600160a01b0316639f28e99d611d248b60600151868b612c07565b604051602401611d3491906139b9565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505063491fc4f960e01b5f60e01b8b60800151878a8a604051602001611bd29493929190614455565b80516060905f819003611db057505060408051808201909152600181525f6020820152919050565b8060020167ffffffffffffffff811115611dcc57611dcc61342d565b6040519080825280601f01601f191660200182016040528015611df6576020820181803683370190505b509150611e0a602183016020850183612d1c565b5f805f5b83811015611ec757858181518110611e2857611e28613d89565b01602001516001600160f81b031916601760f91b03611ebf578281039150815f1480611e54575060ff82115b15611e745785604051639a4c3e3b60e01b815260040161068091906136c4565b8160f81b858481518110611e8a57611e8a613d89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053508060010192505b600101611e0e565b505080820382821480611eda575060ff81115b15611efa5784604051639a4c3e3b60e01b815260040161068091906136c4565b8060f81b848381518110611f1057611f10613d89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350505050919050565b60606001600160a01b038216611f6a575060408051602081019091525f81526104e2565b826001600160a01b0316826001600160a01b031603611fac57805f604051602001611f96929190614487565b60405160208183030381529060405290506104e2565b5f80836001600160a01b03166380f760216040518163ffffffff1660e01b81526004015f60405180830381865afa158015611fe9573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261201091908101906144ae565b90925090506001600160a01b03821661203b5760405180602001604052805f815250925050506104e2565b604051631ad7b10b60e11b81525f906001600160a01b038416906335af6216906120699085906004016136c4565b602060405180830381865afa158015612084573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120a8919061432b565b9050846001600160a01b0316816001600160a01b0316146120dc5760405180602001604052805f81525093505050506104e2565b836120e683612d65565b836040516020016120f9939291906144f2565b6040516020818303038152906040529350829450505050611f6a565b5f8151835114801561058c5750508051602091820120825192909101919091201490565b5f806121468585856127ec565b90506001600160a01b0381161580159061216c575061216c816331ab054760e11b612ddf565b156121ef575f61217c8585612aaf565b506040516331ab054760e11b81529091506001600160a01b038316906363560a8e906121ac9084906004016136c4565b602060405180830381865afa1580156121c7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121eb919061432b565b9250505b509392505050565b5f306001600160a01b0383160361221057506001919050565b6113885a5f805f808786fa50815a909103109392505050565b5f6060836001600160a01b031685612261577f0000000000000000000000000000000000000000000000000000000000000000612263565b5a5b8460405161227191906141fd565b5f604051808303818686fa925050503d805f81146122aa576040519150601f19603f3d011682016040523d82523d5f602084013e6122af565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff8111156122d9576122d961342d565b60405190808252806020026020018201604052801561233657816020015b61232360405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816122f75790505b5090505f805b8351518110156123e7575f845f0151828151811061235c5761235c613d89565b6020026020010151905060408160600151165f036123de575f6123828260400151612663565b90506040518060600160405280825f01516001600160a01b031681526020018260200151815260200182604001518152508585806123bf9061421c565b9650815181106123d1576123d1613d89565b6020026020010181905250505b5060010161233c565b5080156115905780825230836020015183604051602401612408919061451a565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af76000000000000000000000000000000000000000000000000000000009161247c918991016139b9565b60408051601f1981840301815290829052630556f18360e41b825261068095949392916004016145b4565b5f805f805f806124b78888612a82565b9092509050816124d557508794505f935083925085915061260a9050565b6124e08989836124a7565b929850909650945092506001600160a01b038616156125fb575f6125048989612aaf565b5090505f876001600160a01b031663e4ae7d77836040518263ffffffff1660e01b815260040161253491906136c4565b602060405180830381865afa15801561254f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612573919061432b565b90506001600160a01b0381161561258b578096508894505b604051631ad7b10b60e11b81526001600160a01b038916906335af6216906125b79085906004016136c4565b602060405180830381865afa1580156125d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125f6919061432b565b975050505b505f9283526020526040909120905b93509350935093565b5f8061262084845f6116d6565b90506001600160a01b0381161580159061264f5750825160208401206126468583611f46565b80519060200120145b612659575f61265b565b805b949350505050565b6040805160a0810182525f8082526060602083018190529282018390528282015260808101919091526104e26126a2836004808651611c019190614398565b612dfa565b606082515f036126e3576040517f7138356f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6126ec83612e65565b601760f91b603c841461274f57638000000084146127145761270f846001612ece565b612786565b6040518060400160405280600781526020017f64656661756c7400000000000000000000000000000000000000000000000000815250612786565b6040518060400160405280600481526020017f61646472000000000000000000000000000000000000000000000000000000008152505b601760f91b6040518060400160405280600781526020017f72657665727365000000000000000000000000000000000000000000000000008152506040516020016127d5959493929190614617565b604051602081830303815290604052905092915050565b5f805f6127f98585612a82565b9092509050811561280f576121eb8686836116d6565b50509392505050565b5f8061282d612826886121f7565b8888612229565b91509150811580156128575750630556f18360e41b61284b82613d9d565b6001600160e01b031916145b15612905575f61286682612663565b9050876001600160a01b0316815f01516001600160a01b03160361290357308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b03191681526020018981525060405160200161247c9190614651565b505b5f826129115784612913565b855b90506001600160e01b03198116156129c557306001600160a01b0316818386604051602401612943929190613e4f565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161298191906141fd565b5f60405180830381855afa9150503d805f81146129b9576040519150601f19603f3d011682016040523d82523d5f602084013e6129be565b606091505b5090935091505b82156129d357815160208301f35b815160208301fd5b60606129e78383612fa0565b6129f29060016146cd565b67ffffffffffffffff811115612a0a57612a0a61342d565b604051908082528060200260200182016040528015612a33578160200160208202803683370190505b509050838160018351612a469190614398565b81518110612a5657612a56613d89565b60200260200101906001600160a01b031690816001600160a01b0316815250506121ef8383835f612fca565b5f805f612a8f85856130e5565b9250905060ff811615612aa757806021858701012092505b509250929050565b60605f80612abd85856130e5565b925090505f60ff821667ffffffffffffffff811115612ade57612ade61342d565b6040519080825280601f01601f191660200182016040528015612b08576020820181803683370190505b509050612b216020820160218888010160ff8516612d1c565b959194509092505050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f519050828015612b9c575060208210155b8015612ba757505f81115b979650505050505050565b60608167ffffffffffffffff811115612bcd57612bcd61342d565b6040519080825280601f01601f191660200182016040528015612bf7576020820181803683370190505b50905061058c8484835f86613169565b60408051808201909152606080825260208201525f835167ffffffffffffffff811115612c3657612c3661342d565b604051908082528060200260200182016040528015612c9957816020015b612c8660405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b815260200190600190039081612c545790505b5090505f5b8451811015612cff575f828281518110612cba57612cba613d89565b60209081029190910101516001600160a01b03881681528651909150869083908110612ce857612ce8613d89565b602090810291909101810151910152600101612c9e565b506040805180820190915290815260208101929092525092915050565b5b601f811115612d3d578151835260209283019290910190601f1901612d1d565b80156115905790518251600160209390930360031b9290921b5f190180199091169116179052565b80515f90808203612da2576040517fbf9a274000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff8111156104e257826040517fdab6c73c00000000000000000000000000000000000000000000000000000000815260040161068091906136c4565b5f612de9836131a6565b801561058c575061058c83836131d8565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915281806020019051810190612e3791906146e0565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b805160609060011b8067ffffffffffffffff811115612e8657612e8661342d565b6040519080825280601f01601f191660200182016040528015612eb0576020820181803683370190505b5091506020838101908301612ec682828561325a565b505050919050565b6060825f60805b60088110612f06576001811b831015612ef957612ef281836146cd565b9150612efe565b91821c915b60011c612ed5565b50838015612f145750601082105b15612f2757612f246004826146cd565b90505b5f612f37600283901c6040614398565b90508067ffffffffffffffff811115612f5257612f5261342d565b6040519080825280601f01601f191660200182016040528015612f7c576020820181803683370190505b5093505f86831b5f52602085019050612f965f828461325a565b5050505092915050565b5f805b612fad84846130e5565b9350905060ff8116156118f757612fc38261421c565b9150612fa3565b5f805f612fd78787612aaf565b9150915081515f03613013578460018651612ff29190614398565b8151811061300257613002613d89565b60200260200101519250505061265b565b6130298782876130248860016146cd565b612fca565b92506001600160a01b038316156130db57604051631ad7b10b60e11b81526001600160a01b038416906335af6216906130669085906004016136c4565b602060405180830381865afa158015613081573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130a5919061432b565b9250828585815181106130ba576130ba613d89565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050949350505050565b5f808351831061310a578360405163ba4adc2360e01b815260040161068091906136c4565b83838151811061311c5761311c613d89565b016020015160f81c9150508181016001018161313c578351811415613142565b83518110155b15613162578360405163ba4adc2360e01b815260040161068091906136c4565b9250929050565b61317c8561317783876146cd565b6132bd565b61318a8361317783856146cd565b61319f82602085010185602088010183612d1c565b5050505050565b5f6131b8826301ffc9a760e01b6131d8565b80156104e257506131d1826001600160e01b03196131d8565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015612b9c575060208210158015612ba7575015159695505050505050565b8181015b808310156105265783516101005b828510801561327a57505f81115b156132b05760031901600f82821c16600a811061329a578060570161329f565b806030015b90508086535060019094019361326c565b505060208401935061325e565b815181111561191f5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610680918391600401918252602082015260400190565b6001600160e01b0319811681146116d3575f80fd5b5f6020828403121561332a575f80fd5b813561265981613305565b5f8083601f840112613345575f80fd5b50813567ffffffffffffffff81111561335c575f80fd5b602083019150836020828501011115613162575f80fd5b5f805f8060408587031215613386575f80fd5b843567ffffffffffffffff8082111561339d575f80fd5b6133a988838901613335565b909650945060208701359150808211156133c1575f80fd5b506133ce87828801613335565b95989497509550505050565b5f80602083850312156133eb575f80fd5b823567ffffffffffffffff811115613401575f80fd5b61340d85828601613335565b90969095509350505050565b6001600160a01b03811681146116d3575f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff811182821017156134645761346461342d565b60405290565b6040516080810167ffffffffffffffff811182821017156134645761346461342d565b60405160c0810167ffffffffffffffff811182821017156134645761346461342d565b604051601f8201601f1916810167ffffffffffffffff811182821017156134d9576134d961342d565b604052919050565b5f67ffffffffffffffff8211156134fa576134fa61342d565b5060051b60200190565b5f67ffffffffffffffff82111561351d5761351d61342d565b50601f01601f191660200190565b5f82601f83011261353a575f80fd5b813561354d61354882613504565b6134b0565b818152846020838601011115613561575f80fd5b816020850160208301375f918101602001919091529392505050565b5f82601f83011261358c575f80fd5b8135602061359c613548836134e1565b82815260059290921b840181019181810190868411156135ba575f80fd5b8286015b8481101561082c57803567ffffffffffffffff8111156135dc575f80fd5b6135ea8986838b010161352b565b8452509183019183016135be565b5f805f805f806080878903121561360d575f80fd5b863561361881613419565b9550602087013567ffffffffffffffff80821115613634575f80fd5b6136408a838b01613335565b90975095506040890135915080821115613658575f80fd5b6136648a838b01613335565b9095509350606089013591508082111561367c575f80fd5b5061368989828a0161357d565b9150509295509295509295565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61058c6020830184613696565b5f805f604084860312156136e8575f80fd5b833567ffffffffffffffff808211156136ff575f80fd5b61370b8783880161352b565b94506020860135915080821115613720575f80fd5b5061372d86828701613335565b9497909650939450505050565b606081525f61374c6060830186613696565b6001600160a01b0394851660208401529290931660409091015292915050565b5f805f6040848603121561377e575f80fd5b833567ffffffffffffffff811115613794575f80fd5b6137a086828701613335565b909790965060209590950135949350505050565b5f602082840312156137c4575f80fd5b813561265981613419565b604081525f6137e16040830185613696565b90506001600160a01b03831660208301529392505050565b5f602080838503121561380a575f80fd5b823567ffffffffffffffff80821115613821575f80fd5b9084019060408287031215613834575f80fd5b61383c613441565b82358281111561384a575f80fd5b8301601f8101881361385a575f80fd5b8035613868613548826134e1565b81815260059190911b8201860190868101908a831115613886575f80fd5b8784015b8381101561392e578035878111156138a0575f80fd5b85016080818e03601f190112156138b5575f80fd5b6138bd61346a565b8a8201356138ca81613419565b81526040820135898111156138dd575f80fd5b6138eb8f8d8386010161352b565b8c83015250606082013589811115613901575f80fd5b61390f8f8d8386010161352b565b604083015250608091909101356060820152835291880191880161388a565b5084525050508284013582811115613944575f80fd5b6139508882860161357d565b948201949094529695505050505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156139ac57601f1986840301895261399a838351613696565b9884019892509083019060010161397e565b5090979650505050505050565b5f602080835260608084018551604080858801528282518085526080945060808901915060808160051b8a010187850194505f5b82811015613a5757607f198b830301845285516001600160a01b03815116835289810151888b850152613a2289850182613696565b90508682015184820388860152613a398282613696565b928b0151948b019490945250958901959389019391506001016139ed565b50968a0151898803601f190160408b015296613a738189613961565b9b9a5050505050505050505050565b5f805f805f60608688031215613a96575f80fd5b853567ffffffffffffffff80821115613aad575f80fd5b613ab989838a01613335565b90975095506020880135915080821115613ad1575f80fd5b613add89838a01613335565b90955093506040880135915080821115613af5575f80fd5b50613b028882890161357d565b9150509295509295909350565b5f60208284031215613b1f575f80fd5b813567ffffffffffffffff811115613b35575f80fd5b61265b8482850161352b565b5f805f8060608587031215613b54575f80fd5b843567ffffffffffffffff80821115613b6b575f80fd5b613b7788838901613335565b9096509450602087013593506040870135915080821115613b96575f80fd5b50613ba38782880161357d565b91505092959194509250565b602081525f825160a06020840152613bca60c0840182613696565b905060208401516040840152604084015160608401526001600160a01b0360608501511660808401526080840151151560a08401528091505092915050565b5f8060408385031215613c1a575f80fd5b823567ffffffffffffffff80821115613c31575f80fd5b613c3d8683870161352b565b93506020850135915080821115613c52575f80fd5b50613c5f8582860161352b565b9150509250929050565b602080825282518282018190525f9190848201906040850190845b81811015613ca95783516001600160a01b031683529284019291840191600101613c84565b50909695505050505050565b80151581146116d3575f80fd5b5f805f8060808587031215613cd5575f80fd5b8435613ce081613cb5565b93506020850135613cf081613cb5565b92506040850135613d0081613305565b9150606085013567ffffffffffffffff811115613d1b575f80fd5b613ba38782880161352b565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015613d7c57603f19888603018452613d6a858351613696565b94509285019290850190600101613d4e565b5092979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f815160208301516001600160e01b031980821693506004831015612ec65760049290920360031b82901b161692915050565b5f82601f830112613ddf575f80fd5b8151613ded61354882613504565b818152846020838601011115613e01575f80fd5b8160208501602083015e5f918101602001919091529392505050565b5f60208284031215613e2d575f80fd5b815167ffffffffffffffff811115613e43575f80fd5b61265b84828501613dd0565b604081525f613e616040830185613696565b8281036020840152613e738185613696565b95945050505050565b5f805f8060808587031215613e8f575f80fd5b8435613e9a81613cb5565b93506020850135613cf081613305565b5f60808284031215613eba575f80fd5b613ec261346a565b9050813567ffffffffffffffff80821115613edb575f80fd5b613ee78583860161352b565b8352602084013560208401526040840135915080821115613f06575f80fd5b50613f138482850161357d565b6040830152506060820135613f2781613419565b606082015292915050565b5f60208284031215613f42575f80fd5b813567ffffffffffffffff811115613f58575f80fd5b61265b84828501613eaa565b5f815160808452613f786080850182613696565b90506020830151602085015260408301518482036040860152613f9b8282613961565b9150506001600160a01b0360608401511660608501528091505092915050565b606081525f613fcd6060830186613f64565b8281036020840152613fdf8186613696565b9150506001600160a01b0383166040830152949350505050565b5f82601f830112614008575f80fd5b81516020614018613548836134e1565b82815260059290921b84018101918181019086841115614036575f80fd5b8286015b8481101561082c57805167ffffffffffffffff811115614058575f80fd5b6140668986838b0101613dd0565b84525091830191830161403a565b5f60208284031215614084575f80fd5b815167ffffffffffffffff81111561409a575f80fd5b61265b84828501613ff9565b5f602082840312156140b6575f80fd5b815161265981613cb5565b5f805f606084860312156140d3575f80fd5b833567ffffffffffffffff808211156140ea575f80fd5b6140f687838801613eaa565b9450602086013591508082111561410b575f80fd5b506141188682870161352b565b925050604084013561412981613419565b809150509250925092565b5f8060408385031215614145575f80fd5b823567ffffffffffffffff8082111561415c575f80fd5b818501915085601f83011261416f575f80fd5b8135602061417f613548836134e1565b82815260059290921b8401810191818101908984111561419d575f80fd5b948201945b838610156141c45785356141b581613cb5565b825294820194908201906141a2565b965050860135925050808211156141d9575f80fd5b50613c5f8582860161357d565b5f81518060208401855e5f93019283525090919050565b5f61058c82846141e6565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161422d5761422d614208565b5060010190565b602081525f61058c6020830184613f64565b80516114ab81613419565b80516114ab81613305565b5f6020828403121561426c575f80fd5b815167ffffffffffffffff80821115614283575f80fd5b9083019060c08286031215614296575f80fd5b61429e61348d565b6142a783614246565b81526142b560208401614251565b60208201526040830151828111156142cb575f80fd5b6142d787828601613dd0565b6040830152506142e960608401614251565b60608201526142fa60808401614251565b608082015260a083015182811115614310575f80fd5b61431c87828601613dd0565b60a08301525095945050505050565b5f6020828403121561433b575f80fd5b815161265981613419565b5f61265b61435483866141e6565b846141e6565b84151581525f6001600160e01b031980861660208401528085166040840152506080606083015261438e6080830184613696565b9695505050505050565b818103818111156104e2576104e2614208565b5f60208083850312156143bc575f80fd5b825167ffffffffffffffff808211156143d3575f80fd5b818501915085601f8301126143e6575f80fd5b81516143f4613548826134e1565b81815260059190911b83018401908481019088831115614412575f80fd5b8585015b838110156144485780518581111561442c575f80fd5b61443a8b89838a0101613dd0565b845250918601918601614416565b5098975050505050505050565b841515815283151560208201526001600160e01b031983166040820152608060608201525f61438e6080830184613696565b5f61449282856141e6565b60f89390931b6001600160f81b03191683525050600101919050565b5f80604083850312156144bf575f80fd5b82516144ca81613419565b602084015190925067ffffffffffffffff8111156144e6575f80fd5b613c5f85828601613dd0565b5f6144fd82866141e6565b6001600160f81b03198560f81b16815261438e60018201856141e6565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b838110156145a657603f19898403018552815160606001600160a01b03825116855288820151818a87015261457882870182613961565b915050878201519150848103888601526145928183613696565b968901969450505090860190600101614541565b509098975050505050505050565b6001600160a01b038616815260a060208201525f6145d560a0830187613961565b82810360408401526145e78187613696565b90506001600160e01b031985166060840152828103608084015261460b8185613696565b98975050505050505050565b5f61462282886141e6565b6001600160f81b0319808816825261463d60018301886141e6565b9086168152905061460b60018201856141e6565b602081526001600160a01b0382511660208201525f60208301516001600160e01b031980821660408501526040850151915060c0606085015261469760e0850183613696565b91508060608601511660808501528060808601511660a08501525060a0840151601f198483030160c0850152613e738282613696565b808201808211156104e2576104e2614208565b5f805f805f60a086880312156146f4575f80fd5b85516146ff81613419565b602087015190955067ffffffffffffffff8082111561471c575f80fd5b61472889838a01613ff9565b9550604088015191508082111561473d575f80fd5b61474989838a01613dd0565b94506060880151915061475b82613305565b60808801519193508082111561476f575f80fd5b50613b0288828901613dd056fea2646970667358221220b5f04554ce6c30ed434ffce71874eb611f9274ab10b3b0fe2621b7121916cfa964736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106101b0575f3560e01c806394fbfa87116100f3578063b536af7611610093578063c92cc49a1161006e578063c92cc49a14610429578063e4f8ce0514610450578063ef46c0b814610463578063f272e2af14610476575f80fd5b8063b536af76146103e3578063b7d6ca64146103f6578063c285238a14610409575f80fd5b8063a1472844116100ce578063a147284414610372578063a1cbcbaf14610385578063b363cc73146103bd578063b4a85801146103d0575f80fd5b806394fbfa871461032c57806397ad3b3b1461033f5780639f28e99d14610352575f80fd5b80634a3e39941161015e5780635d78a217116101395780635d78a217146102d25780636f3ff726146102e557806383a64339146102f85780639061b9231461030b575f80fd5b80634a3e39941461027d57806355391bb81461029d578063575de750146102b0575f80fd5b80634878c6dd1161018e5780634878c6dd1461023057806348ee1bcc14610243578063491fc4f91461026a575f80fd5b806301ffc9a7146101b457806302cf2578146101dc5780633c6cbda81461021b575b5f80fd5b6101c76101c236600461331a565b610496565b60405190151581526020015b60405180910390f35b6102037f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016101d3565b61022e610229366004613373565b6104e8565b005b61020361023e3660046133da565b61052c565b6102037f000000000000000000000000000000000000000000000000000000000000000081565b61022e610278366004613373565b610593565b61029061028b3660046135f8565b610703565b6040516101d391906136c4565b61022e6102ab3660046136d6565b610837565b6102c36102be366004613373565b6108ba565b6040516101d39392919061373a565b6102c36102e036600461376c565b610a1b565b6101c76102f33660046137b4565b610ab6565b6102906103063660046137b4565b610b42565b61031e610319366004613373565b610b6e565b6040516101d39291906137cf565b6102c361033a366004613373565b610c07565b61020361034d3660046133da565b610d0f565b6103656103603660046137f9565b610d6f565b6040516101d391906139b9565b61031e610380366004613a82565b610f30565b610398610393366004613b0f565b610fe2565b604080516001600160a01b0390941684526020840192909252908201526060016101d3565b6102036103cb3660046133da565b61101e565b61031e6103de366004613373565b61107e565b6103656103f1366004613373565b6110d4565b6102c3610404366004613b41565b61132e565b61041c610417366004613b0f565b611454565b6040516101d39190613baf565b6102037f000000000000000000000000000000000000000000000000000000000000000081565b61020361045e3660046133da565b6114b0565b61022e610471366004613c09565b611510565b6104896104843660046133da565b611595565b6040516101d39190613c69565b5f7ff99a5e06000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806104d357506104d3826115f6565b806104e257506104e282611643565b92915050565b61052684848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061167792505050565b50505050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506116d6915050565b9392505050565b5f6105a0848601866137f9565b5190505f8080806105b386880188613cc2565b9350935093509350606083156105f3576105cd868661179c565b6040516020016105dd9190613d27565b60405160208183030381529060405290506106a8565b5f865f8151811061060657610606613d89565b602002602001015190508060400151915060048160600151165f1461062d57815160208301fd5b6060810151600216156106485761064382611677565b610689565b81515f0361068957806020015161065e90613d9d565b604051637b1c461b60e01b81526001600160e01b031990911660048201526024015b60405180910390fd5b85156106a657818060200190518101906106a39190613e1d565b91505b505b6106f7308483856040516024016106c0929190613e4f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526118fe565b50505050505050505050565b6040805160a08101825260608082525f60208301819052928201839052818101839052608082019290925286868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250505090825250604080516020601f89018190048102820181019092528781526107a29189908990819084018382808284375f9201829052509250611923915050565b60408201526001600160a01b03881660608201526107bf81611954565b61082c8186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516001600160a01b038f16602082015289935063b4a8580160e01b9250015b604051602081830303815290604052611a1c565b509695505050505050565b5f80808061084785870187613e7c565b935093509350935086515f0361087c57604051637b1c461b60e01b81526001600160e01b031984166004820152602401610680565b831561089957868060200190518101906108969190613e1d565b96505b6108b1308389846040516024016106c0929190613e4f565b50505050505050565b60605f80806108cb85870187613f32565b90506108d987890189613b0f565b935083515f03610902576060015160408051602081019091525f80825290945092509050610a11565b5f61090f61041786611d88565b9050610a0e81603c84602001511461098d5782604001518460200151604051602401610945929190918252602082015260400190565b60408051601f198184030181529190526020810180516001600160e01b03167ff1cb7e06000000000000000000000000000000000000000000000000000000001790526109e8565b82604001516040516024016109a491815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f3b3b57de000000000000000000000000000000000000000000000000000000001790525b84604001516394fbfa8760e01b868a876060015160405160200161081893929190613fbb565b50505b9450945094915050565b60605f80610aa78686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663093a86d36040518163ffffffff1660e01b81526004015f60405180830381865afa158015610a80573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104049190810190614074565b92509250925093509350939050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610b1e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104e291906140a6565b60606104e27f000000000000000000000000000000000000000000000000000000000000000083611f46565b60605f610bfa868686867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663093a86d36040518163ffffffff1660e01b81526004015f60405180830381865afa158015610bd3573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526103809190810190614074565b9150915094509492505050565b60605f80610c3d6040518060800160405280606081526020015f8152602001606081526020015f6001600160a01b031681525090565b610c49858701876140c1565b60208301519196509450909150606090603b1901610ca7575f610c6e898b018b6137b4565b6040516bffffffffffffffffffffffff19606083901b166020820152909150603401604051602081830303815290604052915050610cb6565b610cb3888a018a613b0f565b90505b8151610cc29082612115565b610cfc5784816040517fef9c03ce000000000000000000000000000000000000000000000000000000008152600401610680929190613e4f565b8160600151925050509450945094915050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052509250612139915050565b60408051808201909152606080825260208201525f5b825151811015610f22575f835f01518281518110610da557610da5613d89565b6020026020010151905060408160600151165f14610dc35750610f1a565b60608101516030165f03610e6d575f610dde825f01516121f7565b610de9576010610dec565b60205b9050825b855151811015610e6a57825f01516001600160a01b0316865f01518281518110610e1c57610e1c613d89565b60200260200101515f01516001600160a01b031603610e625781865f01518281518110610e4b57610e4b613d89565b602002602001015160600181815117915081815250505b600101610df0565b50505b5f60208260600151165f1490505f80610e8f8315855f01518660200151612229565b9150915081158015610eb95750630556f18360e41b610ead82613d9d565b6001600160e01b031916145b15610ece576060840180516001179052610f0e565b6060840180516040179052828015610ee557508051155b610efa5781610efa5760608401805160021790525b80515f03610f0e5760608401805160081790525b60409093019290925250505b600101610d85565b50610f2c826122bc565b5090565b60605f80610f7288888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061145492505050565b9050610fd78187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050506060840151604080516001600160a01b039092166020830152889163b4a8580160e01b9101610818565b509550959350505050565b5f805f6110107f0000000000000000000000000000000000000000000000000000000000000000855f6124a7565b919790965090945092505050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061261392505050565b60605f858561108f858701876137b4565b82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250929c939b50929950505050505050505050565b60408051808201909152606080825260208201525f806110f686880188614134565b91509150805182511461111c5760405163252e18f560e11b815260040160405180910390fd5b611128848601866137f9565b92505f805b8451518110156112f8575f855f0151828151811061114d5761114d613d89565b6020026020010151905060408160600151165f036112ef5783518310156112e3575f84848151811061118157611181613d89565b6020026020010151905085848151811061119d5761119d613d89565b6020026020010151156111ba5760608201805160441790526112dd565b5f6111c88360400151612663565b90505f815f01516001600160a01b031682606001518484608001516040516024016111f4929190613e4f565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161123291906141fd565b5f60405180830381855afa9150503d805f811461126a576040519150601f19603f3d011682016040523d82523d5f602084013e61126f565b606091505b509350905080806112995750630556f18360e41b61128c84613d9d565b6001600160e01b03191614155b156112da5760608401805160401790528015806112b557508251155b156112c65760608401805160021790525b82515f036112da5760608401805160081790525b50505b60408201525b6112ec8361421c565b92505b5060010161112d565b508151811461131a5760405163252e18f560e11b815260040160405180910390fd5b611323846122bc565b505050949350505050565b60605f805f61137e6104176113798a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152508c92506126a7915050565b611d88565b905061144981826040015160405160240161139b91815260200190565b60405160208183030381529060405263691f343160e01b6020820180516001600160e01b0383818316178352505050508763575de75060e01b60405180608001604052808e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050509082525060208082018e905260408083018e905260608a8101516001600160a01b03169301929092529051610818929101614234565b509450945094915050565b6040805160a08101825260608082525f602083018190529282018390528101829052608081019190915261148782610fe2565b602084015260408301526001600160a01b031660608201528181526114ab81611954565b919050565b5f61058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506127ec915050565b5f81806020019051810190611525919061425c565b9050611590815f0151826020015185846040015160405160240161154a929190613e4f565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526060840151608085015160a0860151612818565b505050565b606061058c7f000000000000000000000000000000000000000000000000000000000000000084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525092506129db915050565b5f7f6cd2d09b000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806104e257506301ffc9a760e01b6001600160e01b03198316146104e2565b5f6001600160e01b0319821663379ffb9360e11b14806104e257506301ffc9a760e01b6001600160e01b03198316146104e2565b637b1c461b60e01b61168882613d9d565b6001600160e01b0319160361169f57805160208201fd5b806040517f95c0c75200000000000000000000000000000000000000000000000000000000815260040161068091906136c4565b50565b5f805f6116e38585612a82565b9092509050816116f757859250505061058c565b5f6117038787846116d6565b90506001600160a01b03811615611792575f61171f8787612aaf565b50604051631ad7b10b60e11b81529091506001600160a01b038316906335af62169061174f9084906004016136c4565b602060405180830381865afa15801561176a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178e919061432b565b9450505b5050509392505050565b6060825167ffffffffffffffff8111156117b8576117b861342d565b6040519080825280602002602001820160405280156117eb57816020015b60608152602001906001900390816117d65790505b5090505f5b83518110156118f7575f84828151811061180c5761180c613d89565b60209081029190910101516040810151606082015191925090600e165f0361185057841561184b57808060200190518101906118489190613e1d565b90505b6118cf565b8051156118cf578051600403601f1680156118cd57818167ffffffffffffffff81111561187f5761187f61342d565b6040519080825280601f01601f1916602001820160405280156118a9576020820181803683370190505b506040516020016118bb929190614346565b60405160208183030381529060405291505b505b808484815181106118e2576118e2613d89565b602090810291909101015250506001016117f0565b5092915050565b61191f82825f60e01b5f60e01b60405180602001604052805f815250612818565b5050565b5f61192e8383612a82565b9250905080156104e25761058c6119458484611923565b825f9182526020526040902090565b60608101516001600160a01b0316611982578051604051630ee413fd60e31b815261068091906004016136c4565b6119978160600151639061b92360e01b612b2c565b156119a6576001608082015250565b6020810151156119cc578051604051630ee413fd60e31b815261068091906004016136c4565b80606001516001600160a01b03163b5f036116d357805160608201516040517f1e9535f20000000000000000000000000000000000000000000000000000000081526106809291906004016137cf565b5f7fac9650d800000000000000000000000000000000000000000000000000000000611a4786613d9d565b6001600160e01b031916149050611a69866060015163582de3e760e01b612b2c565b8015611b105750801580611b10575085608001518015611b105750606086015160405163582de3e760e01b81527f96b62db80000000000000000000000000000000000000000000000000000000060048201526001600160a01b039091169063582de3e790602401602060405180830381865afa158015611aec573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b1091906140a6565b15611be657611be686606001518760800151611b2c5786611b6b565b8751604051611b4091908990602401613e4f565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b1790525b60808901517f55391bb800000000000000000000000000000000000000000000000000000000907f3c6cbda80000000000000000000000000000000000000000000000000000000090611bbd8b613d9d565b8989604051602001611bd2949392919061435a565b604051602081830303815290604052612818565b60608115611c2057611c06866004808951611c019190614398565b612bb2565b806020019051810190611c1991906143ab565b9050611c6b565b60408051600180825281830190925290816020015b6060815260200190600190039081611c3557905050905085815f81518110611c5f57611c5f613d89565b60200260200101819052505b866080015115611d02575f5b8151811015611d0057875f0151828281518110611c9657611c96613d89565b6020026020010151604051602401611caf929190613e4f565b60408051601f198184030181529190526020810180516001600160e01b0316639061b92360e01b1790528251839083908110611ced57611ced613d89565b6020908102919091010152600101611c77565b505b6108b130306001600160a01b0316639f28e99d611d248b60600151868b612c07565b604051602401611d3491906139b9565b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505063491fc4f960e01b5f60e01b8b60800151878a8a604051602001611bd29493929190614455565b80516060905f819003611db057505060408051808201909152600181525f6020820152919050565b8060020167ffffffffffffffff811115611dcc57611dcc61342d565b6040519080825280601f01601f191660200182016040528015611df6576020820181803683370190505b509150611e0a602183016020850183612d1c565b5f805f5b83811015611ec757858181518110611e2857611e28613d89565b01602001516001600160f81b031916601760f91b03611ebf578281039150815f1480611e54575060ff82115b15611e745785604051639a4c3e3b60e01b815260040161068091906136c4565b8160f81b858481518110611e8a57611e8a613d89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053508060010192505b600101611e0e565b505080820382821480611eda575060ff81115b15611efa5784604051639a4c3e3b60e01b815260040161068091906136c4565b8060f81b848381518110611f1057611f10613d89565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350505050919050565b60606001600160a01b038216611f6a575060408051602081019091525f81526104e2565b826001600160a01b0316826001600160a01b031603611fac57805f604051602001611f96929190614487565b60405160208183030381529060405290506104e2565b5f80836001600160a01b03166380f760216040518163ffffffff1660e01b81526004015f60405180830381865afa158015611fe9573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261201091908101906144ae565b90925090506001600160a01b03821661203b5760405180602001604052805f815250925050506104e2565b604051631ad7b10b60e11b81525f906001600160a01b038416906335af6216906120699085906004016136c4565b602060405180830381865afa158015612084573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120a8919061432b565b9050846001600160a01b0316816001600160a01b0316146120dc5760405180602001604052805f81525093505050506104e2565b836120e683612d65565b836040516020016120f9939291906144f2565b6040516020818303038152906040529350829450505050611f6a565b5f8151835114801561058c5750508051602091820120825192909101919091201490565b5f806121468585856127ec565b90506001600160a01b0381161580159061216c575061216c816331ab054760e11b612ddf565b156121ef575f61217c8585612aaf565b506040516331ab054760e11b81529091506001600160a01b038316906363560a8e906121ac9084906004016136c4565b602060405180830381865afa1580156121c7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121eb919061432b565b9250505b509392505050565b5f306001600160a01b0383160361221057506001919050565b6113885a5f805f808786fa50815a909103109392505050565b5f6060836001600160a01b031685612261577f0000000000000000000000000000000000000000000000000000000000000000612263565b5a5b8460405161227191906141fd565b5f604051808303818686fa925050503d805f81146122aa576040519150601f19603f3d011682016040523d82523d5f602084013e6122af565b606091505b5090969095509350505050565b8051515f9067ffffffffffffffff8111156122d9576122d961342d565b60405190808252806020026020018201604052801561233657816020015b61232360405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b8152602001906001900390816122f75790505b5090505f805b8351518110156123e7575f845f0151828151811061235c5761235c613d89565b6020026020010151905060408160600151165f036123de575f6123828260400151612663565b90506040518060600160405280825f01516001600160a01b031681526020018260200151815260200182604001518152508585806123bf9061421c565b9650815181106123d1576123d1613d89565b6020026020010181905250505b5060010161233c565b5080156115905780825230836020015183604051602401612408919061451a565b60408051601f19818403018152918152602080830180516001600160e01b03167fa780bab60000000000000000000000000000000000000000000000000000000017905290517fb536af76000000000000000000000000000000000000000000000000000000009161247c918991016139b9565b60408051601f1981840301815290829052630556f18360e41b825261068095949392916004016145b4565b5f805f805f806124b78888612a82565b9092509050816124d557508794505f935083925085915061260a9050565b6124e08989836124a7565b929850909650945092506001600160a01b038616156125fb575f6125048989612aaf565b5090505f876001600160a01b031663e4ae7d77836040518263ffffffff1660e01b815260040161253491906136c4565b602060405180830381865afa15801561254f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612573919061432b565b90506001600160a01b0381161561258b578096508894505b604051631ad7b10b60e11b81526001600160a01b038916906335af6216906125b79085906004016136c4565b602060405180830381865afa1580156125d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125f6919061432b565b975050505b505f9283526020526040909120905b93509350935093565b5f8061262084845f6116d6565b90506001600160a01b0381161580159061264f5750825160208401206126468583611f46565b80519060200120145b612659575f61265b565b805b949350505050565b6040805160a0810182525f8082526060602083018190529282018390528282015260808101919091526104e26126a2836004808651611c019190614398565b612dfa565b606082515f036126e3576040517f7138356f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6126ec83612e65565b601760f91b603c841461274f57638000000084146127145761270f846001612ece565b612786565b6040518060400160405280600781526020017f64656661756c7400000000000000000000000000000000000000000000000000815250612786565b6040518060400160405280600481526020017f61646472000000000000000000000000000000000000000000000000000000008152505b601760f91b6040518060400160405280600781526020017f72657665727365000000000000000000000000000000000000000000000000008152506040516020016127d5959493929190614617565b604051602081830303815290604052905092915050565b5f805f6127f98585612a82565b9092509050811561280f576121eb8686836116d6565b50509392505050565b5f8061282d612826886121f7565b8888612229565b91509150811580156128575750630556f18360e41b61284b82613d9d565b6001600160e01b031916145b15612905575f61286682612663565b9050876001600160a01b0316815f01516001600160a01b03160361290357308160200151826040015163ef46c0b860e01b6040518060c001604052808d6001600160a01b0316815260200186606001516001600160e01b0319168152602001866080015181526020018b6001600160e01b03191681526020018a6001600160e01b03191681526020018981525060405160200161247c9190614651565b505b5f826129115784612913565b855b90506001600160e01b03198116156129c557306001600160a01b0316818386604051602401612943929190613e4f565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161298191906141fd565b5f60405180830381855afa9150503d805f81146129b9576040519150601f19603f3d011682016040523d82523d5f602084013e6129be565b606091505b5090935091505b82156129d357815160208301f35b815160208301fd5b60606129e78383612fa0565b6129f29060016146cd565b67ffffffffffffffff811115612a0a57612a0a61342d565b604051908082528060200260200182016040528015612a33578160200160208202803683370190505b509050838160018351612a469190614398565b81518110612a5657612a56613d89565b60200260200101906001600160a01b031690816001600160a01b0316815250506121ef8383835f612fca565b5f805f612a8f85856130e5565b9250905060ff811615612aa757806021858701012092505b509250929050565b60605f80612abd85856130e5565b925090505f60ff821667ffffffffffffffff811115612ade57612ade61342d565b6040519080825280601f01601f191660200182016040528015612b08576020820181803683370190505b509050612b216020820160218888010160ff8516612d1c565b959194509092505050565b604080516001600160e01b03198316602480830191909152825180830390910181526044909101909152602080820180516001600160e01b03166301ffc9a760e01b17815282515f9392849283928392918391908a617530fa92503d91505f519050828015612b9c575060208210155b8015612ba757505f81115b979650505050505050565b60608167ffffffffffffffff811115612bcd57612bcd61342d565b6040519080825280601f01601f191660200182016040528015612bf7576020820181803683370190505b50905061058c8484835f86613169565b60408051808201909152606080825260208201525f835167ffffffffffffffff811115612c3657612c3661342d565b604051908082528060200260200182016040528015612c9957816020015b612c8660405180608001604052805f6001600160a01b0316815260200160608152602001606081526020015f81525090565b815260200190600190039081612c545790505b5090505f5b8451811015612cff575f828281518110612cba57612cba613d89565b60209081029190910101516001600160a01b03881681528651909150869083908110612ce857612ce8613d89565b602090810291909101810151910152600101612c9e565b506040805180820190915290815260208101929092525092915050565b5b601f811115612d3d578151835260209283019290910190601f1901612d1d565b80156115905790518251600160209390930360031b9290921b5f190180199091169116179052565b80515f90808203612da2576040517fbf9a274000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff8111156104e257826040517fdab6c73c00000000000000000000000000000000000000000000000000000000815260040161068091906136c4565b5f612de9836131a6565b801561058c575061058c83836131d8565b6040805160a0810182525f80825260606020830181905292820183905282820152608081019190915281806020019051810190612e3791906146e0565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b805160609060011b8067ffffffffffffffff811115612e8657612e8661342d565b6040519080825280601f01601f191660200182016040528015612eb0576020820181803683370190505b5091506020838101908301612ec682828561325a565b505050919050565b6060825f60805b60088110612f06576001811b831015612ef957612ef281836146cd565b9150612efe565b91821c915b60011c612ed5565b50838015612f145750601082105b15612f2757612f246004826146cd565b90505b5f612f37600283901c6040614398565b90508067ffffffffffffffff811115612f5257612f5261342d565b6040519080825280601f01601f191660200182016040528015612f7c576020820181803683370190505b5093505f86831b5f52602085019050612f965f828461325a565b5050505092915050565b5f805b612fad84846130e5565b9350905060ff8116156118f757612fc38261421c565b9150612fa3565b5f805f612fd78787612aaf565b9150915081515f03613013578460018651612ff29190614398565b8151811061300257613002613d89565b60200260200101519250505061265b565b6130298782876130248860016146cd565b612fca565b92506001600160a01b038316156130db57604051631ad7b10b60e11b81526001600160a01b038416906335af6216906130669085906004016136c4565b602060405180830381865afa158015613081573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130a5919061432b565b9250828585815181106130ba576130ba613d89565b60200260200101906001600160a01b031690816001600160a01b0316815250505b5050949350505050565b5f808351831061310a578360405163ba4adc2360e01b815260040161068091906136c4565b83838151811061311c5761311c613d89565b016020015160f81c9150508181016001018161313c578351811415613142565b83518110155b15613162578360405163ba4adc2360e01b815260040161068091906136c4565b9250929050565b61317c8561317783876146cd565b6132bd565b61318a8361317783856146cd565b61319f82602085010185602088010183612d1c565b5050505050565b5f6131b8826301ffc9a760e01b6131d8565b80156104e257506131d1826001600160e01b03196131d8565b1592915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f519050828015612b9c575060208210158015612ba7575015159695505050505050565b8181015b808310156105265783516101005b828510801561327a57505f81115b156132b05760031901600f82821c16600a811061329a578060570161329f565b806030015b90508086535060019094019361326c565b505060208401935061325e565b815181111561191f5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610680918391600401918252602082015260400190565b6001600160e01b0319811681146116d3575f80fd5b5f6020828403121561332a575f80fd5b813561265981613305565b5f8083601f840112613345575f80fd5b50813567ffffffffffffffff81111561335c575f80fd5b602083019150836020828501011115613162575f80fd5b5f805f8060408587031215613386575f80fd5b843567ffffffffffffffff8082111561339d575f80fd5b6133a988838901613335565b909650945060208701359150808211156133c1575f80fd5b506133ce87828801613335565b95989497509550505050565b5f80602083850312156133eb575f80fd5b823567ffffffffffffffff811115613401575f80fd5b61340d85828601613335565b90969095509350505050565b6001600160a01b03811681146116d3575f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040805190810167ffffffffffffffff811182821017156134645761346461342d565b60405290565b6040516080810167ffffffffffffffff811182821017156134645761346461342d565b60405160c0810167ffffffffffffffff811182821017156134645761346461342d565b604051601f8201601f1916810167ffffffffffffffff811182821017156134d9576134d961342d565b604052919050565b5f67ffffffffffffffff8211156134fa576134fa61342d565b5060051b60200190565b5f67ffffffffffffffff82111561351d5761351d61342d565b50601f01601f191660200190565b5f82601f83011261353a575f80fd5b813561354d61354882613504565b6134b0565b818152846020838601011115613561575f80fd5b816020850160208301375f918101602001919091529392505050565b5f82601f83011261358c575f80fd5b8135602061359c613548836134e1565b82815260059290921b840181019181810190868411156135ba575f80fd5b8286015b8481101561082c57803567ffffffffffffffff8111156135dc575f80fd5b6135ea8986838b010161352b565b8452509183019183016135be565b5f805f805f806080878903121561360d575f80fd5b863561361881613419565b9550602087013567ffffffffffffffff80821115613634575f80fd5b6136408a838b01613335565b90975095506040890135915080821115613658575f80fd5b6136648a838b01613335565b9095509350606089013591508082111561367c575f80fd5b5061368989828a0161357d565b9150509295509295509295565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61058c6020830184613696565b5f805f604084860312156136e8575f80fd5b833567ffffffffffffffff808211156136ff575f80fd5b61370b8783880161352b565b94506020860135915080821115613720575f80fd5b5061372d86828701613335565b9497909650939450505050565b606081525f61374c6060830186613696565b6001600160a01b0394851660208401529290931660409091015292915050565b5f805f6040848603121561377e575f80fd5b833567ffffffffffffffff811115613794575f80fd5b6137a086828701613335565b909790965060209590950135949350505050565b5f602082840312156137c4575f80fd5b813561265981613419565b604081525f6137e16040830185613696565b90506001600160a01b03831660208301529392505050565b5f602080838503121561380a575f80fd5b823567ffffffffffffffff80821115613821575f80fd5b9084019060408287031215613834575f80fd5b61383c613441565b82358281111561384a575f80fd5b8301601f8101881361385a575f80fd5b8035613868613548826134e1565b81815260059190911b8201860190868101908a831115613886575f80fd5b8784015b8381101561392e578035878111156138a0575f80fd5b85016080818e03601f190112156138b5575f80fd5b6138bd61346a565b8a8201356138ca81613419565b81526040820135898111156138dd575f80fd5b6138eb8f8d8386010161352b565b8c83015250606082013589811115613901575f80fd5b61390f8f8d8386010161352b565b604083015250608091909101356060820152835291880191880161388a565b5084525050508284013582811115613944575f80fd5b6139508882860161357d565b948201949094529695505050505050565b5f8282518085526020808601955060208260051b840101602086015f5b848110156139ac57601f1986840301895261399a838351613696565b9884019892509083019060010161397e565b5090979650505050505050565b5f602080835260608084018551604080858801528282518085526080945060808901915060808160051b8a010187850194505f5b82811015613a5757607f198b830301845285516001600160a01b03815116835289810151888b850152613a2289850182613696565b90508682015184820388860152613a398282613696565b928b0151948b019490945250958901959389019391506001016139ed565b50968a0151898803601f190160408b015296613a738189613961565b9b9a5050505050505050505050565b5f805f805f60608688031215613a96575f80fd5b853567ffffffffffffffff80821115613aad575f80fd5b613ab989838a01613335565b90975095506020880135915080821115613ad1575f80fd5b613add89838a01613335565b90955093506040880135915080821115613af5575f80fd5b50613b028882890161357d565b9150509295509295909350565b5f60208284031215613b1f575f80fd5b813567ffffffffffffffff811115613b35575f80fd5b61265b8482850161352b565b5f805f8060608587031215613b54575f80fd5b843567ffffffffffffffff80821115613b6b575f80fd5b613b7788838901613335565b9096509450602087013593506040870135915080821115613b96575f80fd5b50613ba38782880161357d565b91505092959194509250565b602081525f825160a06020840152613bca60c0840182613696565b905060208401516040840152604084015160608401526001600160a01b0360608501511660808401526080840151151560a08401528091505092915050565b5f8060408385031215613c1a575f80fd5b823567ffffffffffffffff80821115613c31575f80fd5b613c3d8683870161352b565b93506020850135915080821115613c52575f80fd5b50613c5f8582860161352b565b9150509250929050565b602080825282518282018190525f9190848201906040850190845b81811015613ca95783516001600160a01b031683529284019291840191600101613c84565b50909695505050505050565b80151581146116d3575f80fd5b5f805f8060808587031215613cd5575f80fd5b8435613ce081613cb5565b93506020850135613cf081613cb5565b92506040850135613d0081613305565b9150606085013567ffffffffffffffff811115613d1b575f80fd5b613ba38782880161352b565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015613d7c57603f19888603018452613d6a858351613696565b94509285019290850190600101613d4e565b5092979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f815160208301516001600160e01b031980821693506004831015612ec65760049290920360031b82901b161692915050565b5f82601f830112613ddf575f80fd5b8151613ded61354882613504565b818152846020838601011115613e01575f80fd5b8160208501602083015e5f918101602001919091529392505050565b5f60208284031215613e2d575f80fd5b815167ffffffffffffffff811115613e43575f80fd5b61265b84828501613dd0565b604081525f613e616040830185613696565b8281036020840152613e738185613696565b95945050505050565b5f805f8060808587031215613e8f575f80fd5b8435613e9a81613cb5565b93506020850135613cf081613305565b5f60808284031215613eba575f80fd5b613ec261346a565b9050813567ffffffffffffffff80821115613edb575f80fd5b613ee78583860161352b565b8352602084013560208401526040840135915080821115613f06575f80fd5b50613f138482850161357d565b6040830152506060820135613f2781613419565b606082015292915050565b5f60208284031215613f42575f80fd5b813567ffffffffffffffff811115613f58575f80fd5b61265b84828501613eaa565b5f815160808452613f786080850182613696565b90506020830151602085015260408301518482036040860152613f9b8282613961565b9150506001600160a01b0360608401511660608501528091505092915050565b606081525f613fcd6060830186613f64565b8281036020840152613fdf8186613696565b9150506001600160a01b0383166040830152949350505050565b5f82601f830112614008575f80fd5b81516020614018613548836134e1565b82815260059290921b84018101918181019086841115614036575f80fd5b8286015b8481101561082c57805167ffffffffffffffff811115614058575f80fd5b6140668986838b0101613dd0565b84525091830191830161403a565b5f60208284031215614084575f80fd5b815167ffffffffffffffff81111561409a575f80fd5b61265b84828501613ff9565b5f602082840312156140b6575f80fd5b815161265981613cb5565b5f805f606084860312156140d3575f80fd5b833567ffffffffffffffff808211156140ea575f80fd5b6140f687838801613eaa565b9450602086013591508082111561410b575f80fd5b506141188682870161352b565b925050604084013561412981613419565b809150509250925092565b5f8060408385031215614145575f80fd5b823567ffffffffffffffff8082111561415c575f80fd5b818501915085601f83011261416f575f80fd5b8135602061417f613548836134e1565b82815260059290921b8401810191818101908984111561419d575f80fd5b948201945b838610156141c45785356141b581613cb5565b825294820194908201906141a2565b965050860135925050808211156141d9575f80fd5b50613c5f8582860161357d565b5f81518060208401855e5f93019283525090919050565b5f61058c82846141e6565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161422d5761422d614208565b5060010190565b602081525f61058c6020830184613f64565b80516114ab81613419565b80516114ab81613305565b5f6020828403121561426c575f80fd5b815167ffffffffffffffff80821115614283575f80fd5b9083019060c08286031215614296575f80fd5b61429e61348d565b6142a783614246565b81526142b560208401614251565b60208201526040830151828111156142cb575f80fd5b6142d787828601613dd0565b6040830152506142e960608401614251565b60608201526142fa60808401614251565b608082015260a083015182811115614310575f80fd5b61431c87828601613dd0565b60a08301525095945050505050565b5f6020828403121561433b575f80fd5b815161265981613419565b5f61265b61435483866141e6565b846141e6565b84151581525f6001600160e01b031980861660208401528085166040840152506080606083015261438e6080830184613696565b9695505050505050565b818103818111156104e2576104e2614208565b5f60208083850312156143bc575f80fd5b825167ffffffffffffffff808211156143d3575f80fd5b818501915085601f8301126143e6575f80fd5b81516143f4613548826134e1565b81815260059190911b83018401908481019088831115614412575f80fd5b8585015b838110156144485780518581111561442c575f80fd5b61443a8b89838a0101613dd0565b845250918601918601614416565b5098975050505050505050565b841515815283151560208201526001600160e01b031983166040820152608060608201525f61438e6080830184613696565b5f61449282856141e6565b60f89390931b6001600160f81b03191683525050600101919050565b5f80604083850312156144bf575f80fd5b82516144ca81613419565b602084015190925067ffffffffffffffff8111156144e6575f80fd5b613c5f85828601613dd0565b5f6144fd82866141e6565b6001600160f81b03198560f81b16815261438e60018201856141e6565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b838110156145a657603f19898403018552815160606001600160a01b03825116855288820151818a87015261457882870182613961565b915050878201519150848103888601526145928183613696565b968901969450505090860190600101614541565b509098975050505050505050565b6001600160a01b038616815260a060208201525f6145d560a0830187613961565b82810360408401526145e78187613696565b90506001600160e01b031985166060840152828103608084015261460b8185613696565b98975050505050505050565b5f61462282886141e6565b6001600160f81b0319808816825261463d60018301886141e6565b9086168152905061460b60018201856141e6565b602081526001600160a01b0382511660208201525f60208301516001600160e01b031980821660408501526040850151915060c0606085015261469760e0850183613696565b91508060608601511660808501528060808601511660a08501525060a0840151601f198483030160c0850152613e738282613696565b808201808211156104e2576104e2614208565b5f805f805f60a086880312156146f4575f80fd5b85516146ff81613419565b602087015190955067ffffffffffffffff8082111561471c575f80fd5b61472889838a01613ff9565b9550604088015191508082111561473d575f80fd5b61474989838a01613dd0565b94506060880151915061475b82613305565b60808801519193508082111561476f575f80fd5b50613b0288828901613dd056fea2646970667358221220b5f04554ce6c30ed434ffce71874eb611f9274ab10b3b0fe2621b7121916cfa964736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "1201": [ + { + "length": 32, + "start": 8765 + } + ], + "6082": [ + { + "length": 32, + "start": 481 + }, + { + "length": 32, + "start": 2599 + }, + { + "length": 32, + "start": 2938 + } + ], + "32557": [ + { + "length": 32, + "start": 1070 + }, + { + "length": 32, + "start": 1330 + }, + { + "length": 32, + "start": 2889 + }, + { + "length": 32, + "start": 3349 + }, + { + "length": 32, + "start": 4074 + }, + { + "length": 32, + "start": 4132 + }, + { + "length": 32, + "start": 5302 + }, + { + "length": 32, + "start": 5532 + } + ], + "33410": [ + { + "length": 32, + "start": 584 + }, + { + "length": 32, + "start": 2775 + } + ] + }, + "inputSourceName": "project/src/universalResolver/UniversalResolverV2.sol", + "devdoc": { + "errors": { + "DNSDecodingFailed(bytes)": [ + { + "details": "The DNS-encoded name is malformed. Error selector: `0xba4adc23`" + } + ], + "DNSEncodingFailed(string)": [ + { + "details": "A label of the ENS name has an invalid size. Error selector: `0x9a4c3e3b`" + } + ], + "EmptyAddress()": [ + { + "details": "The supplied address was `0x`. Error selector: `0x7138356f`" + } + ], + "HttpError(uint16,string)": [ + { + "details": "Error selector: `0x01800152`" + } + ], + "InvalidBatchGatewayResponse()": [ + { + "details": "Error selector: `0x4a5c31ea`" + } + ], + "LabelIsEmpty()": [ + { + "details": "The label was empty. Error selector: `0xbf9a2740`" + } + ], + "LabelIsTooLong(string)": [ + { + "details": "The label was more than 255 bytes. Error selector: `0xdab6c73c`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "ResolverError(bytes)": [ + { + "details": "Error selector: `0x95c0c752`" + } + ], + "ResolverNotContract(bytes,address)": [ + { + "details": "Error selector: `0x1e9535f2`" + } + ], + "ResolverNotFound(bytes)": [ + { + "details": "Error selector: `0x77209fe8`" + } + ], + "ReverseAddressMismatch(string,bytes)": [ + { + "details": "Error selector: `0xef9c03ce`" + } + ], + "UnsupportedResolverProfile(bytes4)": [ + { + "details": "Error selector: `0x7b1c461b`" + } + ] + }, + "kind": "dev", + "methods": { + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": { + "details": "Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`." + }, + "ccipBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \"done\".", + "params": { + "extraData": "The contextual data passed from `ccipBatch()`.", + "response": "The response from the batch gateway." + }, + "returns": { + "batch": "The batch where every lookup is \"done\"." + } + }, + "ccipReadCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.", + "params": { + "extraData": "The contextual data passed from `ccipRead()`.", + "response": "The response from offchain." + } + }, + "constructor": { + "params": { + "batchGatewayProvider": "The batch gateway provider.", + "contractNamer": "Delegated contract namer.", + "rootRegistry": "The root registry." + } + }, + "findCanonicalName(address)": { + "params": { + "registry": "The registry to name." + }, + "returns": { + "_0": "The DNS-encoded name or empty if not canonical." + } + }, + "findCanonicalRegistry(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The canonical registry or null if not canonical." + } + }, + "findExactRegistry(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The registry or null if not found." + } + }, + "findOwner(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The owner address or null if unowned or not found." + } + }, + "findParentRegistry(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "The parent registry or null if not found." + } + }, + "findRegistries(bytes)": { + "params": { + "name": "The DNS-encoded name." + }, + "returns": { + "_0": "Array of registries in label-order." + } + }, + "findResolver(bytes)": { + "params": { + "name": "The name to search." + }, + "returns": { + "node": "The namehash of `name`.", + "offset": "The offset into `name` corresponding to `resolver`.", + "resolver": "The found resolver, or null if not found." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "requireResolver(bytes)": { + "details": "Returns a valid resolver for `name` or reverts.", + "params": { + "name": "The name to search." + }, + "returns": { + "info": "The resolver information." + } + }, + "resolveBatchCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `_callResolver()` from calling the batch gateway successfully." + }, + "resolveCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `resolveWithGateways()`.", + "params": { + "extraData": "The contextual data passed from `resolveWith*()`.", + "response": "The response from the resolver." + } + }, + "resolveDirectCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `_callResolver()` from calling the resolver successfully." + }, + "resolveDirectCallbackError(bytes,bytes)": { + "details": "CCIP-Read callback for `_callResolver()` from calling the resolver unsuccessfully." + }, + "resolveWithGateways(bytes,bytes,string[])": { + "details": "This function executes over multiple steps.", + "params": { + "data": "The ABI-encoded resolver calldata.", + "gateways": "The list of batch gateway URLs to use.", + "name": "The DNS-encoded name to resolve." + }, + "returns": { + "resolver": "The resolver that was used to resolve the name.", + "result": "The ABI-encoded response for the calldata." + } + }, + "reverseAddressCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `reverseNameCallback()`. Reverts `ReverseAddressMismatch`.", + "params": { + "extraData": "The contextual data passed from `reverseNameCallback()`.", + "response": "The abi-encoded `addr()` response from the forward resolver." + } + }, + "reverseNameCallback(bytes,bytes)": { + "details": "CCIP-Read callback for `reverseWithGateways()`.", + "params": { + "extraData": "The contextual data passed from `reverseWithGateways()`.", + "response": "The abi-encoded `name()` response from the reverse resolver." + } + }, + "reverseWithGateways(bytes,uint256,string[])": { + "details": "This function executes over multiple steps.", + "params": { + "coinType": "The coin type.", + "gateways": "The list of batch gateway URLs to use.", + "lookupAddress": "The input address." + }, + "returns": { + "primary": "The resolved primary name.", + "resolver": "The resolver address for primary name.", + "reverseResolver": "The resolver address for the reverse name." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "3670800", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "ROOT_REGISTRY()": "infinite", + "batchGatewayProvider()": "infinite", + "ccipBatch(((address,bytes,bytes,uint256)[],string[]))": "infinite", + "ccipBatchCallback(bytes,bytes)": "infinite", + "ccipReadCallback(bytes,bytes)": "infinite", + "findCanonicalName(address)": "infinite", + "findCanonicalRegistry(bytes)": "infinite", + "findExactRegistry(bytes)": "infinite", + "findOwner(bytes)": "infinite", + "findParentRegistry(bytes)": "infinite", + "findRegistries(bytes)": "infinite", + "findResolver(bytes)": "infinite", + "isContractNamer(address)": "infinite", + "requireResolver(bytes)": "infinite", + "resolve(bytes,bytes)": "infinite", + "resolveBatchCallback(bytes,bytes)": "infinite", + "resolveCallback(bytes,bytes)": "infinite", + "resolveDirectCallback(bytes,bytes)": "infinite", + "resolveDirectCallbackError(bytes,bytes)": "infinite", + "resolveWithGateways(bytes,bytes,string[])": "infinite", + "resolveWithResolver(address,bytes,bytes,string[])": "infinite", + "reverse(bytes,uint256)": "infinite", + "reverseAddressCallback(bytes,bytes)": "infinite", + "reverseNameCallback(bytes,bytes)": "infinite", + "reverseWithGateways(bytes,uint256,string[])": "infinite", + "supportsInterface(bytes4)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"rootRegistry\",\"type\":\"address\"},{\"internalType\":\"contract IGatewayProvider\",\"name\":\"batchGatewayProvider\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"dns\",\"type\":\"bytes\"}],\"name\":\"DNSDecodingFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"ens\",\"type\":\"string\"}],\"name\":\"DNSEncodingFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"status\",\"type\":\"uint16\"},{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"HttpError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBatchGatewayResponse\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LabelIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelIsTooLong\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorData\",\"type\":\"bytes\"}],\"name\":\"ResolverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"ResolverNotContract\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"ResolverNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"primaryAddress\",\"type\":\"bytes\"}],\"name\":\"ReverseAddressMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"selector\",\"type\":\"bytes4\"}],\"name\":\"UnsupportedResolverProfile\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batchGatewayProvider\",\"outputs\":[{\"internalType\":\"contract IGatewayProvider\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"name\":\"ccipBatch\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipBatchCallback\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"call\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"flags\",\"type\":\"uint256\"}],\"internalType\":\"struct CCIPBatcher.Lookup[]\",\"name\":\"lookups\",\"type\":\"tuple[]\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"internalType\":\"struct CCIPBatcher.Batch\",\"name\":\"batch\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"ccipReadCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"findCanonicalName\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findCanonicalRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findExactRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findParentRegistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findRegistries\",\"outputs\":[{\"internalType\":\"contract IRegistry[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"findResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"requireResolver\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"extended\",\"type\":\"bool\"}],\"internalType\":\"struct AbstractUniversalResolver.ResolverInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveBatchCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveCallback\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"resolveDirectCallback\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"resolveDirectCallbackError\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"name\":\"resolveWithGateways\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"result\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"name\":\"resolveWithResolver\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"lookupAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"}],\"name\":\"reverse\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"reverseAddressCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"reverseResolver\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"response\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"reverseNameCallback\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"lookupAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"coinType\",\"type\":\"uint256\"},{\"internalType\":\"string[]\",\"name\":\"gateways\",\"type\":\"string[]\"}],\"name\":\"reverseWithGateways\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"primary\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"reverseResolver\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DNSDecodingFailed(bytes)\":[{\"details\":\"The DNS-encoded name is malformed. Error selector: `0xba4adc23`\"}],\"DNSEncodingFailed(string)\":[{\"details\":\"A label of the ENS name has an invalid size. Error selector: `0x9a4c3e3b`\"}],\"EmptyAddress()\":[{\"details\":\"The supplied address was `0x`. Error selector: `0x7138356f`\"}],\"HttpError(uint16,string)\":[{\"details\":\"Error selector: `0x01800152`\"}],\"InvalidBatchGatewayResponse()\":[{\"details\":\"Error selector: `0x4a5c31ea`\"}],\"LabelIsEmpty()\":[{\"details\":\"The label was empty. Error selector: `0xbf9a2740`\"}],\"LabelIsTooLong(string)\":[{\"details\":\"The label was more than 255 bytes. Error selector: `0xdab6c73c`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"ResolverError(bytes)\":[{\"details\":\"Error selector: `0x95c0c752`\"}],\"ResolverNotContract(bytes,address)\":[{\"details\":\"Error selector: `0x1e9535f2`\"}],\"ResolverNotFound(bytes)\":[{\"details\":\"Error selector: `0x77209fe8`\"}],\"ReverseAddressMismatch(string,bytes)\":[{\"details\":\"Error selector: `0xef9c03ce`\"}],\"UnsupportedResolverProfile(bytes4)\":[{\"details\":\"Error selector: `0x7b1c461b`\"}]},\"kind\":\"dev\",\"methods\":{\"ccipBatch(((address,bytes,bytes,uint256)[],string[]))\":{\"details\":\"Use `ccipRead()` to call this function with a batch. The callback response will be `abi.encode(batch)`.\"},\"ccipBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipBatch()`. Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\",\"params\":{\"extraData\":\"The contextual data passed from `ccipBatch()`.\",\"response\":\"The response from the batch gateway.\"},\"returns\":{\"batch\":\"The batch where every lookup is \\\"done\\\".\"}},\"ccipReadCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `ccipRead()`.The return type of this function is polymorphic depending on the caller.\",\"params\":{\"extraData\":\"The contextual data passed from `ccipRead()`.\",\"response\":\"The response from offchain.\"}},\"constructor\":{\"params\":{\"batchGatewayProvider\":\"The batch gateway provider.\",\"contractNamer\":\"Delegated contract namer.\",\"rootRegistry\":\"The root registry.\"}},\"findCanonicalName(address)\":{\"params\":{\"registry\":\"The registry to name.\"},\"returns\":{\"_0\":\"The DNS-encoded name or empty if not canonical.\"}},\"findCanonicalRegistry(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The canonical registry or null if not canonical.\"}},\"findExactRegistry(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The registry or null if not found.\"}},\"findOwner(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The owner address or null if unowned or not found.\"}},\"findParentRegistry(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"The parent registry or null if not found.\"}},\"findRegistries(bytes)\":{\"params\":{\"name\":\"The DNS-encoded name.\"},\"returns\":{\"_0\":\"Array of registries in label-order.\"}},\"findResolver(bytes)\":{\"params\":{\"name\":\"The name to search.\"},\"returns\":{\"node\":\"The namehash of `name`.\",\"offset\":\"The offset into `name` corresponding to `resolver`.\",\"resolver\":\"The found resolver, or null if not found.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"requireResolver(bytes)\":{\"details\":\"Returns a valid resolver for `name` or reverts.\",\"params\":{\"name\":\"The name to search.\"},\"returns\":{\"info\":\"The resolver information.\"}},\"resolveBatchCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `_callResolver()` from calling the batch gateway successfully.\"},\"resolveCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `resolveWithGateways()`.\",\"params\":{\"extraData\":\"The contextual data passed from `resolveWith*()`.\",\"response\":\"The response from the resolver.\"}},\"resolveDirectCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `_callResolver()` from calling the resolver successfully.\"},\"resolveDirectCallbackError(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `_callResolver()` from calling the resolver unsuccessfully.\"},\"resolveWithGateways(bytes,bytes,string[])\":{\"details\":\"This function executes over multiple steps.\",\"params\":{\"data\":\"The ABI-encoded resolver calldata.\",\"gateways\":\"The list of batch gateway URLs to use.\",\"name\":\"The DNS-encoded name to resolve.\"},\"returns\":{\"resolver\":\"The resolver that was used to resolve the name.\",\"result\":\"The ABI-encoded response for the calldata.\"}},\"reverseAddressCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `reverseNameCallback()`. Reverts `ReverseAddressMismatch`.\",\"params\":{\"extraData\":\"The contextual data passed from `reverseNameCallback()`.\",\"response\":\"The abi-encoded `addr()` response from the forward resolver.\"}},\"reverseNameCallback(bytes,bytes)\":{\"details\":\"CCIP-Read callback for `reverseWithGateways()`.\",\"params\":{\"extraData\":\"The contextual data passed from `reverseWithGateways()`.\",\"response\":\"The abi-encoded `name()` response from the reverse resolver.\"}},\"reverseWithGateways(bytes,uint256,string[])\":{\"details\":\"This function executes over multiple steps.\",\"params\":{\"coinType\":\"The coin type.\",\"gateways\":\"The list of batch gateway URLs to use.\",\"lookupAddress\":\"The input address.\"},\"returns\":{\"primary\":\"The resolved primary name.\",\"resolver\":\"The resolver address for primary name.\",\"reverseResolver\":\"The resolver address for the reverse name.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"HttpError(uint16,string)\":[{\"notice\":\"An HTTP error occurred on a resolving gateway.\"}],\"InvalidBatchGatewayResponse()\":[{\"notice\":\"The batch gateway supplied an incorrect number of responses.\"}],\"ResolverError(bytes)\":[{\"notice\":\"The resolver returned an error.\"}],\"ResolverNotContract(bytes,address)\":[{\"notice\":\"The resolver is not a contract.\"}],\"ResolverNotFound(bytes)\":[{\"notice\":\"A resolver could not be found for the supplied name.\"}],\"ReverseAddressMismatch(string,bytes)\":[{\"notice\":\"The resolved address from reverse resolution does not match the supplied address.\"}],\"UnsupportedResolverProfile(bytes4)\":[{\"notice\":\"The resolver did not respond.\"}]},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"ROOT_REGISTRY()\":{\"notice\":\"The ENSv2 root registry.\"},\"findCanonicalName(address)\":{\"notice\":\"Construct the canonical name for `registry`.\"},\"findCanonicalRegistry(bytes)\":{\"notice\":\"Find the canonical registry for `name`.\"},\"findExactRegistry(bytes)\":{\"notice\":\"Find the exact registry for `name`.\"},\"findOwner(bytes)\":{\"notice\":\"Find the owner for `name`.\"},\"findParentRegistry(bytes)\":{\"notice\":\"Find the parent registry for `name`.\"},\"findRegistries(bytes)\":{\"notice\":\"Find all registries in the ancestry of `name`. * `findRegistries(\\\"\\\") = []` * `findRegistries(\\\"eth\\\") = [, ]` * `findRegistries(\\\"nick.eth\\\") = [, , ]` * `findRegistries(\\\"sub.nick.eth\\\") = [null, , , ]`\"},\"findResolver(bytes)\":{\"notice\":\"Find the resolver address for `name`. Does not perform any validity checks on the resolver.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"resolve(bytes,bytes)\":{\"notice\":\"Same as `resolveWithGateways()` but uses default batch gateways.\"},\"resolveWithGateways(bytes,bytes,string[])\":{\"notice\":\"Performs ENS forward resolution for the supplied name and data. Caller should enable EIP-3668.\"},\"resolveWithResolver(address,bytes,bytes,string[])\":{\"notice\":\"Same as `resolveWithGateways()` but uses the supplied resolver.\"},\"reverse(bytes,uint256)\":{\"notice\":\"Same as `reverseWithGateways()` but uses default batch gateways.\"},\"reverseWithGateways(bytes,uint256,string[])\":{\"notice\":\"Performs ENS reverse resolution for the supplied address and coin type. Caller should enable EIP-3668.\"}},\"notice\":\"Universal Resolver that traverses the namechain registry hierarchy to locate resolvers and registries for any DNS-encoded name.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/universalResolver/UniversalResolverV2.sol\":\"UniversalResolverV2\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/CCIPBatcher.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {IBatchGateway} from \\\"./IBatchGateway.sol\\\";\\nimport {CCIPReader, EIP3668, OffchainLookup} from \\\"./CCIPReader.sol\\\";\\n\\n/// @dev CCIP-Read batch gateway client implementation.\\n///\\n/// Since requests are read-only, empty responses are considered an error.\\n///\\n/// Usage: `ccipRead(address(this), abi.encodeCall(this.ccipBatch, (createBatch(...))), ...)`\\n///\\nabstract contract CCIPBatcher is CCIPReader {\\n /// @notice The batch gateway supplied an incorrect number of responses.\\n /// @dev Error selector: `0x4a5c31ea`\\n error InvalidBatchGatewayResponse();\\n\\n uint256 constant FLAG_OFFCHAIN = 1 << 0; // the lookup reverted `OffchainLookup`\\n uint256 constant FLAG_CALL_ERROR = 1 << 1; // the initial call or callback reverted\\n uint256 constant FLAG_BATCH_ERROR = 1 << 2; // `OffchainLookup` failed on the batch gateway\\n uint256 constant FLAG_EMPTY_RESPONSE = 1 << 3; // the initial call or callback returned `0x`\\n uint256 constant FLAG_EIP140_BEFORE = 1 << 4; // does not have revert op code\\n uint256 constant FLAG_EIP140_AFTER = 1 << 5; // has revert op code\\n uint256 constant FLAG_DONE = 1 << 6; // the lookup has finished processing (private)\\n\\n uint256 constant FLAGS_ANY_ERROR =\\n FLAG_CALL_ERROR | FLAG_BATCH_ERROR | FLAG_EMPTY_RESPONSE;\\n uint256 constant FLAGS_ANY_EIP140 = FLAG_EIP140_BEFORE | FLAG_EIP140_AFTER;\\n\\n /// @dev An independent `OffchainLookup` session.\\n struct Lookup {\\n address target; // contract to call\\n bytes call; // initial calldata\\n bytes data; // response or error\\n uint256 flags; // see: FLAG_*\\n }\\n\\n /// @dev A batch gateway session.\\n struct Batch {\\n Lookup[] lookups;\\n string[] gateways;\\n }\\n\\n /// @dev Create a batch for a single target with multiple calls.\\n /// @param target The target contract.\\n /// @param calls The list of calldata.\\n /// @param gateways The batch gateway URLs.\\n function createBatch(\\n address target,\\n bytes[] memory calls,\\n string[] memory gateways\\n ) internal pure returns (Batch memory) {\\n Lookup[] memory lookups = new Lookup[](calls.length);\\n for (uint256 i; i < calls.length; ++i) {\\n Lookup memory lu = lookups[i];\\n lu.target = target;\\n lu.call = calls[i];\\n }\\n return Batch(lookups, gateways);\\n }\\n\\n /// @dev Use `ccipRead()` to call this function with a batch.\\n /// The callback response will be `abi.encode(batch)`.\\n function ccipBatch(\\n Batch memory batch\\n ) external view returns (Batch memory) {\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) != 0) {\\n continue; // don't call a lookup that's already done\\n }\\n if ((lu.flags & FLAGS_ANY_EIP140) == 0) {\\n uint256 flags = detectEIP140(lu.target)\\n ? FLAG_EIP140_AFTER\\n : FLAG_EIP140_BEFORE;\\n for (uint256 j = i; j < batch.lookups.length; ++j) {\\n if (batch.lookups[j].target == lu.target) {\\n batch.lookups[j].flags |= flags;\\n }\\n }\\n }\\n bool unsafe = (lu.flags & FLAG_EIP140_AFTER) == 0;\\n (bool ok, bytes memory v) = safeCall(!unsafe, lu.target, lu.call);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n lu.flags |= FLAG_OFFCHAIN;\\n } else {\\n lu.flags |= FLAG_DONE;\\n if (unsafe && v.length == 0) {\\n // unsafe contracts appear the same for throw and unimplemented fallback\\n // decision: interpret like an unimplemented function selector response\\n } else if (!ok) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n lu.data = v;\\n }\\n _revertBatchGateway(batch); // reverts if any offchain\\n return batch;\\n }\\n\\n /// @dev Check if the batch is \\\"done\\\". If not, revert `OffchainLookup` for batch gateway.\\n function _revertBatchGateway(Batch memory batch) internal view {\\n IBatchGateway.Request[] memory requests = new IBatchGateway.Request[](\\n batch.lookups.length\\n );\\n uint256 count;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n requests[count++] = IBatchGateway.Request(\\n p.sender,\\n p.urls,\\n p.callData\\n );\\n }\\n }\\n if (count > 0) {\\n assembly {\\n mstore(requests, count) // truncate to number of offchain requests\\n }\\n revert OffchainLookup(\\n address(this),\\n batch.gateways,\\n abi.encodeCall(IBatchGateway.query, (requests)),\\n this.ccipBatchCallback.selector,\\n abi.encode(batch)\\n );\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipBatch()`.\\n /// Updates `batch` using the batch gateway response. Reverts again if not \\\"done\\\".\\n /// @param response The response from the batch gateway.\\n /// @param extraData The contextual data passed from `ccipBatch()`.\\n /// @return batch The batch where every lookup is \\\"done\\\".\\n function ccipBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (Batch memory batch) {\\n (bool[] memory failures, bytes[] memory responses) = abi.decode(\\n response,\\n (bool[], bytes[])\\n );\\n if (failures.length != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n batch = abi.decode(extraData, (Batch));\\n uint256 expected;\\n for (uint256 i; i < batch.lookups.length; ++i) {\\n Lookup memory lu = batch.lookups[i];\\n if ((lu.flags & FLAG_DONE) == 0) {\\n if (expected < responses.length) {\\n bytes memory v = responses[expected];\\n if (failures[expected]) {\\n lu.flags |= FLAG_DONE | FLAG_BATCH_ERROR;\\n } else {\\n EIP3668.Params memory p = decodeOffchainLookup(lu.data);\\n bool ok;\\n // assumption: unsafe contracts don't revert OffchainLookup()\\n (ok, v) = p.sender.staticcall(\\n abi.encodeWithSelector(\\n p.callbackFunction,\\n v,\\n p.extraData\\n )\\n );\\n if (ok || bytes4(v) != OffchainLookup.selector) {\\n lu.flags |= FLAG_DONE;\\n // decision: promote empty response from the callback => call error\\n // ie. the initial function was implemented but the callback was not\\n // this can be detected via FLAG_OFFCHAIN\\n if (!ok || v.length == 0) {\\n lu.flags |= FLAG_CALL_ERROR;\\n }\\n if (v.length == 0) {\\n lu.flags |= FLAG_EMPTY_RESPONSE;\\n }\\n }\\n }\\n lu.data = v;\\n }\\n ++expected;\\n }\\n }\\n if (expected != responses.length) {\\n revert InvalidBatchGatewayResponse();\\n }\\n _revertBatchGateway(batch);\\n }\\n\\n /// @dev Safely collapse `Lookup[]` into `bytes[]`.\\n /// If `FLAGS_ANY_ERROR` and response is non-empty, the response is zero-padded so that `length % 32 == 4`.\\n /// @param lookups Array of completed lookups.\\n /// @param wrapped If `true`, successful responses are unwrapped as `bytes`.\\n /// @return arr Array of call responses.\\n function _toResponseArray(Lookup[] memory lookups, bool wrapped) internal pure returns (bytes[] memory arr) {\\n arr = new bytes[](lookups.length);\\n for (uint256 i; i < lookups.length; ++i) {\\n Lookup memory lu = lookups[i];\\n bytes memory v = lu.data;\\n if ((lu.flags & FLAGS_ANY_ERROR) == 0) {\\n if (wrapped) {\\n v = abi.decode(v, (bytes));\\n }\\n } else if (v.length != 0) {\\n // force pad error response to length mod 32 == 4\\n // prevents unverified data from passing as valid response \\n unchecked {\\n uint256 pad = (4 - v.length) & 31;\\n if (pad > 0) {\\n v = abi.encodePacked(v, new bytes(pad)); \\n }\\n }\\n }\\n arr[i] = v;\\n }\\n return arr;\\n }\\n}\",\"keccak256\":\"0xc7fe6929199a1019dd0c3faf9884b5250786fb77d3c3df3e772cfd4ed823d684\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/CCIPReader.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n/// @author Modified from https://github.com/unruggable-labs/CCIPReader.sol/blob/341576fe7ff2b6e0c93fc08f37740cf6439f5873/contracts/CCIPReader.sol\\n\\n/// MIT License\\n/// Portions Copyright (c) 2025 Unruggable\\n/// Portions Copyright (c) 2025 ENS Labs Ltd\\n\\n/// @dev Instructions:\\n/// 1. inherit this contract\\n/// 2. call `ccipRead()` similar to `staticcall()`\\n/// 3. do not put logic after this invocation\\n/// 4. implement all response logic in callback\\n/// 5. ensure that return type of calling function == callback function\\n\\nimport {EIP3668, OffchainLookup} from \\\"./EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\n\\ncontract CCIPReader {\\n /// @dev Default unsafe call gas (sufficient for legacy ENS resolver profiles).\\n uint256 constant DEFAULT_UNSAFE_CALL_GAS = 50000;\\n\\n /// @dev Special-purpose value for identity callback: `f(x) = x`.\\n bytes4 constant IDENTITY_FUNCTION = bytes4(0);\\n\\n /// @dev The gas limit for calling functions on unsafe contracts.\\n uint256 immutable unsafeCallGas;\\n\\n constructor(uint256 _unsafeCallGas) {\\n unsafeCallGas = _unsafeCallGas;\\n }\\n\\n /// @dev A recursive CCIP-Read session.\\n struct Context {\\n address target;\\n bytes4 callbackFunction;\\n bytes extraData;\\n bytes4 successCallbackFunction;\\n bytes4 failureCallbackFunction;\\n bytes myExtraData;\\n }\\n\\n /// @dev Same as `ccipRead()` but the callback function is the identity.\\n function ccipRead(address target, bytes memory call) internal view {\\n ccipRead(target, call, IDENTITY_FUNCTION, IDENTITY_FUNCTION, \\\"\\\");\\n }\\n\\n /// @dev Performs a CCIP-Read and handles internal recursion.\\n /// Reverts `OffchainLookup` if necessary.\\n /// Use `IDENTITY_FUNCTION` as the callback function selector for return/revert behavior.\\n /// @param target The contract address.\\n /// @param call The calldata to `staticcall()` on `target`.\\n /// @param successCallbackFunction The function selector of callback on success.\\n /// @param failureCallbackFunction The function selector of callback on failure.\\n /// @param extraData The contextual data relayed to callback function.\\n function ccipRead(\\n address target,\\n bytes memory call,\\n bytes4 successCallbackFunction,\\n bytes4 failureCallbackFunction,\\n bytes memory extraData\\n ) internal view {\\n // We call the intended function that **could** revert with an `OffchainLookup`\\n // We destructure the response into an execution status bool and our return bytes\\n (bool ok, bytes memory v) = safeCall(\\n detectEIP140(target),\\n target,\\n call\\n );\\n // IF the function reverted with an `OffchainLookup`\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n // We decode the response error into a tuple\\n // tuples allow flexibility noting stack too deep constraints\\n EIP3668.Params memory p = decodeOffchainLookup(v);\\n if (p.sender == target) {\\n // We then wrap the error data in an `OffchainLookup` sent/'owned' by this contract\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n this.ccipReadCallback.selector,\\n abi.encode(\\n Context(\\n target,\\n p.callbackFunction,\\n p.extraData,\\n successCallbackFunction,\\n failureCallbackFunction,\\n extraData\\n )\\n )\\n );\\n }\\n }\\n // IF we have gotten here, the 'real' target does not revert with an `OffchainLookup` error\\n // figure out what callback to call\\n bytes4 callbackFunction = ok\\n ? successCallbackFunction\\n : failureCallbackFunction;\\n if (callbackFunction != IDENTITY_FUNCTION) {\\n // The exit point of this architecture is OUR callback in the 'real'\\n // We pass through the response to that callback\\n (ok, v) = address(this).staticcall(\\n abi.encodeWithSelector(callbackFunction, v, extraData)\\n );\\n }\\n // OR the call to the 'real' target reverts with a different error selector\\n // OR the call to OUR callback reverts with ANY error selector\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @dev CCIP-Read callback for `ccipRead()`.\\n /// @param response The response from offchain.\\n /// @param extraData The contextual data passed from `ccipRead()`.\\n /// @dev The return type of this function is polymorphic depending on the caller.\\n function ccipReadCallback(\\n bytes memory response,\\n bytes memory extraData\\n ) external view {\\n Context memory ctx = abi.decode(extraData, (Context));\\n // Since the callback can revert too (but has the same return structure)\\n // We can reuse the calling infrastructure to call the callback\\n ccipRead(\\n ctx.target,\\n abi.encodeWithSelector(\\n ctx.callbackFunction,\\n response,\\n ctx.extraData\\n ),\\n ctx.successCallbackFunction,\\n ctx.failureCallbackFunction,\\n ctx.myExtraData\\n );\\n }\\n\\n /// @dev Decode `OffchainLookup` error data into a struct.\\n /// @param v The error data of the revert.\\n /// @return p The decoded `OffchainLookup` params.\\n function decodeOffchainLookup(\\n bytes memory v\\n ) internal pure returns (EIP3668.Params memory p) {\\n p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n }\\n\\n /// @dev Determine if `target` uses `revert()` instead of `invalid()`.\\n // Assumption: only newer contracts revert `OffchainLookup`.\\n /// @param target The contract to test.\\n /// @return safe True if safe to call.\\n function detectEIP140(address target) internal view returns (bool safe) {\\n if (target == address(this)) return true;\\n // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-140.md\\n assembly {\\n let G := 5000\\n let g := gas()\\n pop(staticcall(G, target, 0, 0, 0, 0))\\n safe := lt(sub(g, gas()), G)\\n }\\n }\\n\\n /// @dev Same as `staticcall()` but prevents OOG when not `safe`.\\n function safeCall(\\n bool safe,\\n address target,\\n bytes memory call\\n ) internal view returns (bool ok, bytes memory v) {\\n (ok, v) = target.staticcall{gas: safe ? gasleft() : unsafeCallGas}(\\n call\\n );\\n }\\n}\\n\",\"keccak256\":\"0xa6f483e89e779385c2b7ea6376d92cd3c05c98f91d1a3c7c43dc7422fe6b014f\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IBatchGateway.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for Batch Gateway Offchain Lookup Protocol.\\n/// https://docs.ens.domains/ensip/21/\\n/// @dev Interface selector: `0xa780bab6`\\ninterface IBatchGateway {\\n /// @notice An HTTP error occurred.\\n /// @dev Error selector: `0x01800152`\\n error HttpError(uint16 status, string message);\\n\\n /// @dev Information extracted from an `OffchainLookup` revert.\\n struct Request {\\n address sender;\\n string[] urls;\\n bytes data;\\n }\\n\\n /// @notice Perform multiple `OffchainLookup` in parallel.\\n /// Callers should enable EIP-3668.\\n /// @param requests The array of requests to lookup in parallel.\\n /// @return failures The failure status of the corresponding request.\\n /// @return responses The response or error data of the corresponding request.\\n function query(\\n Request[] memory requests\\n ) external view returns (bool[] memory failures, bytes[] memory responses);\\n}\\n\",\"keccak256\":\"0xfd7f0c7bdc29fc732ec54da2ebaea241873e55082e484729901811bc9374d6f6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/ccipRead/IGatewayProvider.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for shared gateway URLs.\\n/// @dev Interface selector: `0x093a86d3`\\ninterface IGatewayProvider {\\n /// @notice Get the gateways.\\n /// @return The gateway URLs.\\n function gateways() external view returns (string[] memory);\\n}\\n\",\"keccak256\":\"0x7c169843cfb65657a88fb4d5f7ec44612994d7d87cb7b1a67cbfdb18758823e0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/IMulticallable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IMulticallable {\\n function multicall(\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n\\n function multicallWithNodeCheck(\\n bytes32,\\n bytes[] calldata data\\n ) external returns (bytes[] memory results);\\n}\\n\",\"keccak256\":\"0x0334202e20bb11995997083d05963f5e8e7ed6194cba494e7f9371ab7bf4e2c3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/ResolverFeatures.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary ResolverFeatures {\\n /// @notice Implements `resolve(multicall([...]))`.\\n /// @dev Feature: `0x96b62db8`\\n bytes4 constant RESOLVE_MULTICALL =\\n bytes4(keccak256(\\\"eth.ens.resolver.extended.multicall\\\"));\\n\\n /// @notice Returns the same records independent of name or node.\\n /// @dev Feature: `0x86fb8da8`\\n bytes4 constant SINGULAR = bytes4(keccak256(\\\"eth.ens.resolver.singular\\\"));\\n}\\n\",\"keccak256\":\"0x87d131fcbdd7951a17b0a94f7f02470ec3f62c6004cf91c2d2acc54098373be6\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the legacy (ETH-only) addr function.\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /// Returns the address associated with an ENS node.\\n /// @param node The ENS node to query.\\n /// @return The associated address.\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x91dd0c350698c505d6c7e4c919da9f981d4b8d7ad062e25073fa1f6af7cb79d1\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/// Interface for the new (multicoin) addr function.\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x8da5dd0fc1c5ab4f47e03c23126976a86d4b2dbeac161e70e3af9e2a13330cf0\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/IExtendedResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x5d81521cfae7d9a4475d27533cd8ed0d3475d369eb0674fd90ffbdbdf292faa3\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/resolvers/profiles/INameResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface INameResolver {\\n event NameChanged(bytes32 indexed node, string name);\\n\\n /// Returns the name associated with an ENS node, for reverse records.\\n /// Defined in EIP181.\\n /// @param node The ENS node to query.\\n /// @return The associated name.\\n function name(bytes32 node) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x3ab986332e0baad7aeb4b426aace3aa1c235be5efff8db4b6f1ce501bcdd9e68\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/AbstractUniversalResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IUniversalResolver} from \\\"./IUniversalResolver.sol\\\";\\nimport {CCIPBatcher, CCIPReader} from \\\"../ccipRead/CCIPBatcher.sol\\\";\\nimport {IGatewayProvider} from \\\"../ccipRead/IGatewayProvider.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\nimport {BytesUtils} from \\\"../utils/BytesUtils.sol\\\";\\nimport {ENSIP19, COIN_TYPE_ETH, COIN_TYPE_DEFAULT} from \\\"../utils/ENSIP19.sol\\\";\\nimport {IERC7996} from \\\"../utils/IERC7996.sol\\\";\\nimport {ResolverFeatures} from \\\"../resolvers/ResolverFeatures.sol\\\";\\n\\n// resolver profiles\\nimport {IExtendedResolver} from \\\"../resolvers/profiles/IExtendedResolver.sol\\\";\\nimport {INameResolver} from \\\"../resolvers/profiles/INameResolver.sol\\\";\\nimport {IAddrResolver} from \\\"../resolvers/profiles/IAddrResolver.sol\\\";\\nimport {IAddressResolver} from \\\"../resolvers/profiles/IAddressResolver.sol\\\";\\nimport {IMulticallable} from \\\"../resolvers/IMulticallable.sol\\\";\\n\\nabstract contract AbstractUniversalResolver is\\n IUniversalResolver,\\n CCIPBatcher,\\n ERC165\\n{\\n /// @dev The default batch gateways.\\n IGatewayProvider public immutable batchGatewayProvider;\\n\\n constructor(\\n IGatewayProvider _batchGatewayProvider\\n ) CCIPReader(DEFAULT_UNSAFE_CALL_GAS) {\\n batchGatewayProvider = _batchGatewayProvider;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(\\n bytes4 interfaceId\\n ) public view virtual override(ERC165) returns (bool) {\\n return\\n type(IUniversalResolver).interfaceId == interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /// @inheritdoc IUniversalResolver\\n function findResolver(\\n bytes memory name\\n ) public view virtual returns (address, bytes32, uint256);\\n\\n /// @dev A valid resolver and its relevant properties.\\n struct ResolverInfo {\\n bytes name; // dns-encoded name (safe to decode)\\n uint256 offset; // byte offset into name used for resolver\\n bytes32 node; // namehash(name)\\n address resolver;\\n bool extended; // IExtendedResolver\\n }\\n\\n /// @dev Returns a valid resolver for `name` or reverts.\\n /// @param name The name to search.\\n /// @return info The resolver information.\\n function requireResolver(\\n bytes memory name\\n ) public view returns (ResolverInfo memory info) {\\n // https://docs.ens.domains/ensip/10\\n (info.resolver, info.node, info.offset) = findResolver(name);\\n info.name = name;\\n _checkResolver(info);\\n }\\n\\n /// @dev Asserts that the resolver information is valid.\\n function _checkResolver(ResolverInfo memory info) internal view {\\n if (info.resolver == address(0)) {\\n revert ResolverNotFound(info.name);\\n } else if (\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n info.resolver,\\n type(IExtendedResolver).interfaceId\\n )\\n ) {\\n info.extended = true;\\n } else if (info.offset != 0) {\\n revert ResolverNotFound(info.name); // immediate resolver requires exact match\\n } else if (info.resolver.code.length == 0) {\\n revert ResolverNotContract(info.name, info.resolver);\\n }\\n }\\n\\n /// @notice Same as `resolveWithGateways()` but uses default batch gateways.\\n function resolve(\\n bytes calldata name,\\n bytes calldata data\\n ) external view returns (bytes memory, address) {\\n return resolveWithGateways(name, data, batchGatewayProvider.gateways());\\n }\\n\\n /// @notice Performs ENS forward resolution for the supplied name and data.\\n /// Caller should enable EIP-3668.\\n /// @dev This function executes over multiple steps.\\n /// @param name The DNS-encoded name to resolve.\\n /// @param data The ABI-encoded resolver calldata.\\n /// @param gateways The list of batch gateway URLs to use.\\n /// @return result The ABI-encoded response for the calldata.\\n /// @return resolver The resolver that was used to resolve the name.\\n function resolveWithGateways(\\n bytes calldata name,\\n bytes calldata data,\\n string[] memory gateways\\n ) public view returns (bytes memory result, address resolver) {\\n result;\\n resolver;\\n ResolverInfo memory info = requireResolver(name);\\n _callResolver(\\n info,\\n data,\\n gateways,\\n this.resolveCallback.selector, // ==> step 2\\n abi.encode(info.resolver)\\n );\\n }\\n\\n /// @notice Same as `resolveWithGateways()` but uses the supplied resolver.\\n function resolveWithResolver(\\n address resolver,\\n bytes calldata name,\\n bytes calldata data,\\n string[] memory gateways\\n ) external view returns (bytes memory) {\\n ResolverInfo memory info;\\n info.name = name;\\n info.node = NameCoder.namehash(name, 0);\\n info.resolver = resolver;\\n _checkResolver(info);\\n _callResolver(\\n info,\\n data,\\n gateways,\\n this.resolveCallback.selector, // ==> step 2\\n abi.encode(resolver) // this value is ignored\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `resolveWithGateways()`.\\n /// @param response The response from the resolver.\\n /// @param extraData The contextual data passed from `resolveWith*()`.\\n function resolveCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external pure returns (bytes memory, address) {\\n return (response, abi.decode(extraData, (address)));\\n }\\n\\n /// @notice Same as `reverseWithGateways()` but uses default batch gateways.\\n function reverse(\\n bytes calldata lookupAddress,\\n uint256 coinType\\n ) external view returns (string memory, address, address) {\\n return\\n reverseWithGateways(\\n lookupAddress,\\n coinType,\\n batchGatewayProvider.gateways()\\n );\\n }\\n\\n struct ReverseArgs {\\n bytes lookupAddress; // parsed input address\\n uint256 coinType; // parsed coinType\\n string[] gateways; // supplied gateways\\n address resolver; // valid reverse resolver\\n }\\n\\n /// @notice Performs ENS reverse resolution for the supplied address and coin type.\\n /// Caller should enable EIP-3668.\\n /// @dev This function executes over multiple steps.\\n /// @param lookupAddress The input address.\\n /// @param coinType The coin type.\\n /// @param gateways The list of batch gateway URLs to use.\\n /// @return primary The resolved primary name.\\n /// @return resolver The resolver address for primary name.\\n /// @return reverseResolver The resolver address for the reverse name.\\n function reverseWithGateways(\\n bytes calldata lookupAddress,\\n uint256 coinType,\\n string[] memory gateways\\n )\\n public\\n view\\n returns (\\n string memory primary,\\n address resolver,\\n address reverseResolver\\n )\\n {\\n primary;\\n resolver;\\n reverseResolver;\\n // https://docs.ens.domains/ensip/19\\n ResolverInfo memory info = requireResolver(\\n NameCoder.encode(ENSIP19.reverseName(lookupAddress, coinType)) // reverts EmptyAddress\\n );\\n _callResolver(\\n info,\\n abi.encodeCall(INameResolver.name, (info.node)),\\n gateways,\\n this.reverseNameCallback.selector, // ==> step 2\\n abi.encode(\\n ReverseArgs(lookupAddress, coinType, gateways, info.resolver)\\n )\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `reverseWithGateways()`.\\n /// @param response The abi-encoded `name()` response from the reverse resolver.\\n /// @param extraData The contextual data passed from `reverseWithGateways()`.\\n function reverseNameCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view returns (string memory primary, address, address) {\\n ReverseArgs memory args = abi.decode(extraData, (ReverseArgs));\\n primary = abi.decode(response, (string));\\n if (bytes(primary).length == 0) {\\n return (\\\"\\\", address(0), args.resolver);\\n }\\n ResolverInfo memory info = requireResolver(NameCoder.encode(primary));\\n _callResolver(\\n info,\\n args.coinType == COIN_TYPE_ETH\\n ? abi.encodeCall(IAddrResolver.addr, (info.node))\\n : abi.encodeCall(\\n IAddressResolver.addr,\\n (info.node, args.coinType)\\n ),\\n args.gateways,\\n this.reverseAddressCallback.selector, // ==> step 3\\n abi.encode(args, primary, info.resolver)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `reverseNameCallback()`.\\n /// Reverts `ReverseAddressMismatch`.\\n /// @param response The abi-encoded `addr()` response from the forward resolver.\\n /// @param extraData The contextual data passed from `reverseNameCallback()`.\\n function reverseAddressCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n )\\n external\\n pure\\n returns (\\n string memory primary,\\n address resolver,\\n address reverseResolver\\n )\\n {\\n ReverseArgs memory args;\\n (args, primary, resolver) = abi.decode(\\n extraData,\\n (ReverseArgs, string, address)\\n );\\n bytes memory primaryAddress;\\n if (args.coinType == COIN_TYPE_ETH) {\\n address addr = abi.decode(response, (address));\\n primaryAddress = abi.encodePacked(addr);\\n } else {\\n primaryAddress = abi.decode(response, (bytes));\\n }\\n if (!BytesUtils.equals(args.lookupAddress, primaryAddress)) {\\n revert ReverseAddressMismatch(primary, primaryAddress);\\n }\\n reverseResolver = args.resolver;\\n }\\n\\n /// @dev Efficiently call a resolver.\\n /// If ENSIP-22 is supported, performs a direct call.\\n /// Otherwise, uses the batch gateway.\\n /// @param info The resolver to call.\\n /// @param call The resolution calldata.\\n /// @param gateways The list of batch gateway URLs to use.\\n /// @param callbackFunction The function selector to call after resolution.\\n /// @param extraData The contextual data passed to `callbackFunction`.\\n function _callResolver(\\n ResolverInfo memory info,\\n bytes memory call,\\n string[] memory gateways,\\n bytes4 callbackFunction,\\n bytes memory extraData\\n ) internal view {\\n bool multi = bytes4(call) == IMulticallable.multicall.selector;\\n if (\\n ERC165Checker.supportsERC165InterfaceUnchecked(\\n info.resolver,\\n type(IERC7996).interfaceId\\n ) &&\\n (!multi ||\\n (info.extended &&\\n IERC7996(info.resolver).supportsFeature(\\n ResolverFeatures.RESOLVE_MULTICALL\\n )))\\n ) {\\n ccipRead(\\n address(info.resolver),\\n info.extended\\n ? abi.encodeCall(\\n IExtendedResolver.resolve,\\n (info.name, call)\\n )\\n : call,\\n this.resolveDirectCallback.selector,\\n this.resolveDirectCallbackError.selector,\\n abi.encode(\\n info.extended,\\n bytes4(call),\\n callbackFunction,\\n extraData\\n )\\n );\\n }\\n bytes[] memory calls;\\n if (multi) {\\n calls = abi.decode(\\n BytesUtils.substring(call, 4, call.length - 4),\\n (bytes[])\\n );\\n } else {\\n calls = new bytes[](1);\\n calls[0] = call;\\n }\\n if (info.extended) {\\n for (uint256 i; i < calls.length; ++i) {\\n calls[i] = abi.encodeCall(\\n IExtendedResolver.resolve,\\n (info.name, calls[i])\\n );\\n }\\n }\\n ccipRead(\\n address(this),\\n abi.encodeCall(\\n this.ccipBatch,\\n (createBatch(info.resolver, calls, gateways))\\n ),\\n this.resolveBatchCallback.selector,\\n IDENTITY_FUNCTION,\\n abi.encode(info.extended, multi, callbackFunction, extraData)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `_callResolver()` from calling the resolver successfully.\\n function resolveDirectCallback(\\n bytes memory response,\\n bytes calldata extraData\\n ) external view {\\n (\\n bool extended,\\n bytes4 callSelector,\\n bytes4 callbackFunction,\\n bytes memory extraData_\\n ) = abi.decode(extraData, (bool, bytes4, bytes4, bytes));\\n if (response.length == 0) {\\n revert UnsupportedResolverProfile(callSelector);\\n }\\n if (extended) {\\n response = abi.decode(response, (bytes)); // unwrap resolve()\\n }\\n ccipRead(\\n address(this),\\n abi.encodeWithSelector(callbackFunction, response, extraData_)\\n );\\n }\\n\\n /// @dev CCIP-Read callback for `_callResolver()` from calling the resolver unsuccessfully.\\n function resolveDirectCallbackError(\\n bytes calldata response,\\n bytes calldata\\n ) external pure {\\n _propagateResolverError(response);\\n }\\n\\n /// @dev CCIP-Read callback for `_callResolver()` from calling the batch gateway successfully.\\n function resolveBatchCallback(\\n bytes calldata response,\\n bytes calldata extraData\\n ) external view {\\n Lookup[] memory lookups = abi.decode(response, (Batch)).lookups;\\n (\\n bool extended,\\n bool multi,\\n bytes4 callbackFunction,\\n bytes memory extraData_\\n ) = abi.decode(extraData, (bool, bool, bytes4, bytes));\\n bytes memory answer;\\n if (multi) {\\n answer = abi.encode(_toResponseArray(lookups, extended));\\n } else {\\n Lookup memory lu = lookups[0];\\n answer = lu.data;\\n if ((lu.flags & FLAG_BATCH_ERROR) != 0) {\\n assembly {\\n revert(add(answer, 32), mload(answer)) // propagate batch gateway errors\\n }\\n } else if ((lu.flags & FLAG_CALL_ERROR) != 0) {\\n _propagateResolverError(answer);\\n } else if (answer.length == 0) {\\n revert UnsupportedResolverProfile(bytes4(lu.call));\\n }\\n if (extended) {\\n answer = abi.decode(answer, (bytes)); // unwrap resolve()\\n }\\n }\\n ccipRead(\\n address(this),\\n abi.encodeWithSelector(callbackFunction, answer, extraData_)\\n );\\n }\\n\\n /// @dev Propagate the revert from the resolver.\\n /// @param v The error data.\\n function _propagateResolverError(bytes memory v) internal pure {\\n if (bytes4(v) == UnsupportedResolverProfile.selector) {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n } else {\\n revert ResolverError(v);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28ebdcf6a76a2c013ce3549d3ca711307e09765ee55bed190848641d3aac86df\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/universalResolver/IUniversalResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for the UniversalResolver.\\n/// @dev Interface selector: `0xcd191b34`\\ninterface IUniversalResolver {\\n /// @notice A resolver could not be found for the supplied name.\\n /// @dev Error selector: `0x77209fe8`\\n error ResolverNotFound(bytes name);\\n\\n /// @notice The resolver is not a contract.\\n /// @dev Error selector: `0x1e9535f2`\\n error ResolverNotContract(bytes name, address resolver);\\n\\n /// @notice The resolver did not respond.\\n /// @dev Error selector: `0x7b1c461b`\\n error UnsupportedResolverProfile(bytes4 selector);\\n\\n /// @notice The resolver returned an error.\\n /// @dev Error selector: `0x95c0c752`\\n error ResolverError(bytes errorData);\\n\\n /// @notice The resolved address from reverse resolution does not match the supplied address.\\n /// @dev Error selector: `0xef9c03ce`\\n error ReverseAddressMismatch(string primary, bytes primaryAddress);\\n\\n /// @notice An HTTP error occurred on a resolving gateway.\\n /// @dev Error selector: `0x01800152`\\n error HttpError(uint16 status, string message);\\n\\n /// @notice Find the resolver address for `name`.\\n /// Does not perform any validity checks on the resolver.\\n /// @param name The name to search.\\n /// @return resolver The found resolver, or null if not found.\\n /// @return node The namehash of `name`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(\\n bytes memory name\\n )\\n external\\n view\\n returns (address resolver, bytes32 node, uint256 resolverOffset);\\n\\n /// @notice Performs ENS forward resolution for the supplied name and data.\\n /// Caller should enable EIP-3668.\\n /// @param name The DNS-encoded name to resolve.\\n /// @param data The ABI-encoded resolver calldata.\\n /// For a multicall, encode as `multicall(bytes[])`.\\n /// @return result The ABI-encoded response for the calldata.\\n /// For a multicall, the results are encoded as `(bytes[])`.\\n /// @return resolver The resolver that was used to resolve the name.\\n function resolve(\\n bytes calldata name,\\n bytes calldata data\\n ) external view returns (bytes memory result, address resolver);\\n\\n /// @notice Performs ENS primary name resolution for the supplied address and coin type, as specified in ENSIP-19.\\n /// Caller should enable EIP-3668.\\n /// @param lookupAddress The byte-encoded address to resolve.\\n /// @param coinType The coin type of the address to resolve.\\n /// @return primary The verified primary name, or null if not set.\\n /// @return resolver The resolver that was used to resolve the primary name.\\n /// @return reverseResolver The resolver that was used to resolve the reverse name.\\n function reverse(\\n bytes calldata lookupAddress,\\n uint256 coinType\\n )\\n external\\n view\\n returns (\\n string memory primary,\\n address resolver,\\n address reverseResolver\\n );\\n}\\n\",\"keccak256\":\"0x61f9fe7140591d0ba238685d391c30ed00950e4b9c328229616ffc00eab6ac8a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/ENSIP19.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {HexUtils} from \\\"../utils/HexUtils.sol\\\";\\nimport {NameCoder} from \\\"../utils/NameCoder.sol\\\";\\n\\nuint32 constant CHAIN_ID_ETH = 1;\\n\\nuint256 constant COIN_TYPE_ETH = 60;\\nuint256 constant COIN_TYPE_DEFAULT = 1 << 31; // 0x8000_0000\\n\\nstring constant SLUG_ETH = \\\"addr\\\"; // <=> COIN_TYPE_ETH\\nstring constant SLUG_DEFAULT = \\\"default\\\"; // <=> COIN_TYPE_DEFAULT\\nstring constant TLD_REVERSE = \\\"reverse\\\";\\n\\n/// @dev Library for generating reverse names according to ENSIP-19.\\n/// https://docs.ens.domains/ensip/19\\nlibrary ENSIP19 {\\n /// @dev The supplied address was `0x`.\\n /// Error selector: `0x7138356f`\\n error EmptyAddress();\\n\\n /// @dev Extract Chain ID from `coinType`.\\n /// @param coinType The coin type.\\n /// @return The Chain ID or 0 if non-EVM Chain.\\n function chainFromCoinType(\\n uint256 coinType\\n ) internal pure returns (uint32) {\\n if (coinType == COIN_TYPE_ETH) return CHAIN_ID_ETH;\\n coinType ^= COIN_TYPE_DEFAULT;\\n return uint32(coinType < COIN_TYPE_DEFAULT ? coinType : 0);\\n }\\n\\n /// @dev Determine if Coin Type is for an EVM address.\\n /// @param coinType The coin type.\\n /// @return True if coin type represents an EVM address.\\n function isEVMCoinType(uint256 coinType) internal pure returns (bool) {\\n return coinType == COIN_TYPE_DEFAULT || chainFromCoinType(coinType) > 0;\\n }\\n\\n /// @dev Generate Reverse Name from Address + Coin Type.\\n /// Reverts `EmptyAddress` if `addressBytes` is `0x`.\\n /// @param addressBytes The input address.\\n /// @param coinType The coin type.\\n /// @return The ENS reverse name, eg. `1234abcd.addr.reverse`.\\n function reverseName(\\n bytes memory addressBytes,\\n uint256 coinType\\n ) internal pure returns (string memory) {\\n if (addressBytes.length == 0) {\\n revert EmptyAddress();\\n }\\n return\\n string(\\n abi.encodePacked(\\n HexUtils.bytesToHex(addressBytes),\\n bytes1(\\\".\\\"),\\n coinType == COIN_TYPE_ETH\\n ? SLUG_ETH\\n : coinType == COIN_TYPE_DEFAULT\\n ? SLUG_DEFAULT\\n : HexUtils.unpaddedUintToHex(coinType, true),\\n bytes1(\\\".\\\"),\\n TLD_REVERSE\\n )\\n );\\n }\\n\\n /// @dev Parse Reverse Name into Address + Coin Type.\\n /// Matches: `/^[0-9a-fA-F]+\\\\.([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @return addressBytes The address or empty if invalid.\\n /// @return coinType The coin type.\\n function parse(\\n bytes memory name\\n ) internal pure returns (bytes memory addressBytes, uint256 coinType) {\\n (, uint256 offset) = NameCoder.readLabel(name, 0);\\n bool valid;\\n (addressBytes, valid) = HexUtils.hexToBytes(name, 1, offset);\\n if (!valid || addressBytes.length == 0) return (\\\"\\\", 0); // addressBytes not 1+ hex\\n (valid, coinType) = parseNamespace(name, offset);\\n if (!valid) return (\\\"\\\", 0); // invalid namespace\\n }\\n\\n /// @dev Parse Reverse Namespace into Coin Type.\\n /// Matches: `/^([0-9a-f]{1,64}|addr|default)\\\\.reverse$/`.\\n /// Reverts `DNSDecodingFailed`.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset to begin parsing.\\n /// @return valid True if a valid reverse namespace.\\n /// @return coinType The coin type.\\n function parseNamespace(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bool valid, uint256 coinType) {\\n (bytes32 labelHash, uint256 offsetTLD) = NameCoder.readLabel(\\n name,\\n offset\\n );\\n if (labelHash == keccak256(bytes(SLUG_ETH))) {\\n coinType = COIN_TYPE_ETH;\\n } else if (labelHash == keccak256(bytes(SLUG_DEFAULT))) {\\n coinType = COIN_TYPE_DEFAULT;\\n } else if (labelHash == bytes32(0)) {\\n return (false, 0); // no slug\\n } else {\\n (bytes32 word, bool validHex) = HexUtils.hexStringToBytes32(\\n name,\\n 1 + offset,\\n offsetTLD\\n );\\n if (!validHex) return (false, 0); // invalid coinType or too long\\n coinType = uint256(word);\\n }\\n (labelHash, offset) = NameCoder.readLabel(name, offsetTLD);\\n if (labelHash != keccak256(bytes(TLD_REVERSE))) return (false, 0); // invalid tld\\n (labelHash, ) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) return (false, 0); // not tld\\n valid = true;\\n }\\n}\\n\",\"keccak256\":\"0xd1af09b014028de4c50489bd58ae424273180bb96d95353d8eefd14845f31824\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/IERC7996.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @notice Interface for expressing contract features not visible from the ABI.\\n/// @dev Interface selector: `0x582de3e7`\\ninterface IERC7996 {\\n /// @notice Check if a feature is supported.\\n /// @param featureId The feature identifier.\\n /// @return `true` if the feature is supported by the contract.\\n function supportsFeature(bytes4 featureId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xf499a48e4e879ec7775f375d2cb5af047720ab6ae4b6f89a40a578c4e0f51631\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x5a08ad61f4e82b8a3323562661a86fb10b10190848073fdc13d4ac43710ffba5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the ERC-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface.\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC-165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&\\n !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC-165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function getSupportedInterfaces(\\n address account,\\n bytes4[] memory interfaceIds\\n ) internal view returns (bool[] memory) {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC-165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC-165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC-165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC-165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n *\\n * Some precompiled contracts will falsely indicate support for a given interface, so caution\\n * should be exercised when using this function.\\n *\\n * Interface identification is specified in ERC-165.\\n */\\n function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {\\n // prepare call\\n bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));\\n\\n // perform static call\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0x00)\\n }\\n\\n return success && returnSize >= 0x20 && returnValue > 0;\\n }\\n}\\n\",\"keccak256\":\"0x27c3c648062924bd44cd6f38541c78e6de145dd49515ee62321e42fc1b72e5c2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/universalResolver/UniversalResolverV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IGatewayProvider} from \\\"@ens/contracts/ccipRead/IGatewayProvider.sol\\\";\\nimport {\\n AbstractUniversalResolver\\n} from \\\"@ens/contracts/universalResolver/AbstractUniversalResolver.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {IUniversalResolverV2} from \\\"./interfaces/IUniversalResolverV2.sol\\\";\\nimport {LibRegistry} from \\\"./libraries/LibRegistry.sol\\\";\\n\\n/// @notice Universal Resolver that traverses the namechain registry hierarchy to locate\\n/// resolvers and registries for any DNS-encoded name.\\ncontract UniversalResolverV2 is\\n AbstractUniversalResolver,\\n DelegatedContractNamer,\\n IUniversalResolverV2\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 root registry.\\n IPermissionedRegistry public immutable ROOT_REGISTRY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param rootRegistry The root registry.\\n /// @param batchGatewayProvider The batch gateway provider.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n IPermissionedRegistry rootRegistry,\\n IGatewayProvider batchGatewayProvider,\\n IContractNamer contractNamer\\n )\\n AbstractUniversalResolver(batchGatewayProvider)\\n DelegatedContractNamer(contractNamer)\\n {\\n ROOT_REGISTRY = rootRegistry;\\n }\\n\\n /// @inheritdoc AbstractUniversalResolver\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(AbstractUniversalResolver, DelegatedContractNamer)\\n returns (bool)\\n {\\n // note: this is some kind of compiler bug probably due to oz v4/v5\\n return\\n type(IUniversalResolverV2).interfaceId == interfaceId ||\\n AbstractUniversalResolver.supportsInterface(interfaceId) ||\\n DelegatedContractNamer.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findOwner(bytes calldata name) external view returns (address) {\\n return LibRegistry.findOwner(ROOT_REGISTRY, name, 0);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findCanonicalName(IRegistry registry) external view returns (bytes memory) {\\n return LibRegistry.findCanonicalName(ROOT_REGISTRY, registry);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findCanonicalRegistry(bytes calldata name) external view returns (IRegistry) {\\n return LibRegistry.findCanonicalRegistry(ROOT_REGISTRY, name);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findExactRegistry(bytes calldata name) external view returns (IRegistry) {\\n return LibRegistry.findExactRegistry(ROOT_REGISTRY, name, 0);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findParentRegistry(bytes calldata name) external view returns (IRegistry) {\\n return LibRegistry.findParentRegistry(ROOT_REGISTRY, name, 0);\\n }\\n\\n /// @inheritdoc IUniversalResolverV2\\n function findRegistries(bytes calldata name) external view returns (IRegistry[] memory) {\\n return LibRegistry.findRegistries(ROOT_REGISTRY, name, 0);\\n }\\n\\n /// @inheritdoc AbstractUniversalResolver\\n function findResolver(bytes memory name)\\n public\\n view\\n override\\n returns (address resolver, bytes32 node, uint256 offset)\\n {\\n (, resolver, node, offset) = LibRegistry.findResolver(ROOT_REGISTRY, name, 0);\\n }\\n}\\n\",\"keccak256\":\"0xb67ebee7a5c7d07725b4a5d1fa8fb3f71d819801f91528eba00f66c57e2844da\",\"license\":\"MIT\"},\"project/src/universalResolver/interfaces/IUniversalResolverV2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @notice Interface for ENSv2-specific UniversalResolver helper functions.\\n/// @dev Interface selector: `0xf99a5e06`\\ninterface IUniversalResolverV2 {\\n /// @notice Find the owner for `name`.\\n /// @param name The DNS-encoded name.\\n /// @return The owner address or null if unowned or not found.\\n function findOwner(bytes calldata name) external view returns (address);\\n\\n /// @notice Construct the canonical name for `registry`.\\n /// @param registry The registry to name.\\n /// @return The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry registry) external view returns (bytes memory);\\n\\n /// @notice Find the canonical registry for `name`.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(bytes calldata name) external view returns (IRegistry);\\n\\n /// @notice Find the exact registry for `name`.\\n /// @param name The DNS-encoded name.\\n /// @return The registry or null if not found.\\n function findExactRegistry(bytes calldata name) external view returns (IRegistry);\\n\\n /// @notice Find the parent registry for `name`.\\n /// @param name The DNS-encoded name.\\n /// @return The parent registry or null if not found.\\n function findParentRegistry(bytes calldata name) external view returns (IRegistry);\\n\\n /// @notice Find all registries in the ancestry of `name`.\\n /// * `findRegistries(\\\"\\\") = []`\\n /// * `findRegistries(\\\"eth\\\") = [, ]`\\n /// * `findRegistries(\\\"nick.eth\\\") = [, , ]`\\n /// * `findRegistries(\\\"sub.nick.eth\\\") = [null, , , ]`\\n ///\\n /// @param name The DNS-encoded name.\\n /// @return Array of registries in label-order.\\n function findRegistries(bytes calldata name) external view returns (IRegistry[] memory);\\n}\\n\",\"keccak256\":\"0x50933f37ecc0ec711b159aefdbd4cc66e951a9312c44ce66a28e3ca116dd2227\",\"license\":\"MIT\"},\"project/src/universalResolver/libraries/LibRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {ERC165Checker} from \\\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"../../registry/interfaces/IOwnedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Recursive traversal helpers for the namechain registry tree \\u2014 resolver lookup, registry\\n/// discovery, canonical name construction, and ancestry enumeration.\\nlibrary LibRegistry {\\n /// @dev Find the resolver address for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return exactRegistry The exact registry or null if not exact.\\n /// @return resolver The resolver or null if not found.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return resolverOffset The offset into `name` corresponding to `resolver`.\\n function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset)\\n {\\n // supply if end of name\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return (rootRegistry, address(0), bytes32(0), offset);\\n }\\n // lookup parent name\\n (exactRegistry, resolver, node, resolverOffset) = findResolver(rootRegistry, name, next);\\n // if there was a parent registry...\\n if (address(exactRegistry) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n // remember the resolver (if it exists)\\n address res = exactRegistry.getResolver(label);\\n if (res != address(0)) {\\n resolver = res;\\n resolverOffset = offset;\\n }\\n exactRegistry = exactRegistry.getSubregistry(label);\\n }\\n node = NameCoder.namehash(node, labelHash); // update namehash\\n }\\n\\n /// @dev Find the owner for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return owner The owner address or null if unowned or not found.\\n function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (address owner)\\n {\\n IRegistry registry = findParentRegistry(rootRegistry, name, offset);\\n if (\\n address(registry) != address(0) &&\\n ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId)\\n ) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n owner = IOwnedRegistry(address(registry)).findOwner(label);\\n }\\n }\\n\\n /// @dev Construct the canonical name for `registry`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param registry The registry to name.\\n /// @return name The DNS-encoded name or empty if not canonical.\\n function findCanonicalName(IRegistry rootRegistry, IRegistry registry)\\n internal\\n view\\n returns (bytes memory name)\\n {\\n if (address(registry) == address(0)) {\\n return \\\"\\\";\\n }\\n for (;;) {\\n if (address(registry) == address(rootRegistry)) {\\n return abi.encodePacked(name, uint8(0)); // add terminator\\n }\\n (IRegistry parent, string memory label) = registry.getParent();\\n if (address(parent) == address(0)) {\\n return \\\"\\\"; // no canonical parent\\n }\\n IRegistry child = parent.getSubregistry(label);\\n if (address(child) != address(registry)) {\\n return \\\"\\\"; // wrong canonical child\\n }\\n name = abi.encodePacked(name, NameCoder.assertLabelSize(label), label); // reverts if invalid label\\n registry = parent;\\n }\\n }\\n\\n /// @dev Find the registry for `name` and return it iff it is canonical for that name.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @return The canonical registry or null if not canonical.\\n function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name)\\n internal\\n view\\n returns (IRegistry)\\n {\\n IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0);\\n return\\n address(registry) != address(0) &&\\n keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) ==\\n keccak256(name)\\n ? registry\\n : IRegistry(address(0));\\n }\\n\\n /// @dev Find the exact registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return exactRegistry The exact registry or null if not found.\\n function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry exactRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash == bytes32(0)) {\\n return rootRegistry;\\n }\\n IRegistry parent = findExactRegistry(rootRegistry, name, next);\\n if (address(parent) != address(0)) {\\n (string memory label, ) = NameCoder.extractLabel(name, offset);\\n exactRegistry = parent.getSubregistry(label);\\n }\\n }\\n\\n /// @dev Find the parent registry for `name[offset:]`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name to search.\\n /// @return parentRegistry The parent registry or null if not found.\\n function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry parentRegistry)\\n {\\n (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n parentRegistry = findExactRegistry(rootRegistry, name, next);\\n }\\n }\\n\\n /// @dev Find all registries in the ancestry of `name`.\\n /// @param rootRegistry The root ENS registry.\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to begin the search.\\n /// @return registries Array of registries in label-order.\\n function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset)\\n internal\\n view\\n returns (IRegistry[] memory registries)\\n {\\n registries = new IRegistry[](1 + NameCoder.countLabels(name, offset));\\n registries[registries.length - 1] = rootRegistry;\\n _findRegistries(name, offset, registries, 0);\\n }\\n\\n /// @dev Recursive function for building ancestry.\\n function _findRegistries(\\n bytes memory name,\\n uint256 offset,\\n IRegistry[] memory registries,\\n uint256 index\\n )\\n private\\n view\\n returns (IRegistry registry)\\n {\\n (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset);\\n if (bytes(label).length == 0) {\\n return registries[registries.length - 1];\\n }\\n registry = _findRegistries(name, nextOffset, registries, index + 1);\\n if (address(registry) != address(0)) {\\n registry = registry.getSubregistry(label);\\n registries[index] = registry;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0b5f34bcc76ee3e49d300444fbcbe1ed152faee49a91c87eaea5f6d61ce6fb0b\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "HttpError(uint16,string)": [ + { + "notice": "An HTTP error occurred on a resolving gateway." + } + ], + "InvalidBatchGatewayResponse()": [ + { + "notice": "The batch gateway supplied an incorrect number of responses." + } + ], + "ResolverError(bytes)": [ + { + "notice": "The resolver returned an error." + } + ], + "ResolverNotContract(bytes,address)": [ + { + "notice": "The resolver is not a contract." + } + ], + "ResolverNotFound(bytes)": [ + { + "notice": "A resolver could not be found for the supplied name." + } + ], + "ReverseAddressMismatch(string,bytes)": [ + { + "notice": "The resolved address from reverse resolution does not match the supplied address." + } + ], + "UnsupportedResolverProfile(bytes4)": [ + { + "notice": "The resolver did not respond." + } + ] + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "ROOT_REGISTRY()": { + "notice": "The ENSv2 root registry." + }, + "findCanonicalName(address)": { + "notice": "Construct the canonical name for `registry`." + }, + "findCanonicalRegistry(bytes)": { + "notice": "Find the canonical registry for `name`." + }, + "findExactRegistry(bytes)": { + "notice": "Find the exact registry for `name`." + }, + "findOwner(bytes)": { + "notice": "Find the owner for `name`." + }, + "findParentRegistry(bytes)": { + "notice": "Find the parent registry for `name`." + }, + "findRegistries(bytes)": { + "notice": "Find all registries in the ancestry of `name`. * `findRegistries(\"\") = []` * `findRegistries(\"eth\") = [, ]` * `findRegistries(\"nick.eth\") = [, , ]` * `findRegistries(\"sub.nick.eth\") = [null, , , ]`" + }, + "findResolver(bytes)": { + "notice": "Find the resolver address for `name`. Does not perform any validity checks on the resolver." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "resolve(bytes,bytes)": { + "notice": "Same as `resolveWithGateways()` but uses default batch gateways." + }, + "resolveWithGateways(bytes,bytes,string[])": { + "notice": "Performs ENS forward resolution for the supplied name and data. Caller should enable EIP-3668." + }, + "resolveWithResolver(address,bytes,bytes,string[])": { + "notice": "Same as `resolveWithGateways()` but uses the supplied resolver." + }, + "reverse(bytes,uint256)": { + "notice": "Same as `reverseWithGateways()` but uses default batch gateways." + }, + "reverseWithGateways(bytes,uint256,string[])": { + "notice": "Performs ENS reverse resolution for the supplied address and coin type. Caller should enable EIP-3668." + } + }, + "notice": "Universal Resolver that traverses the namechain registry hierarchy to locate resolvers and registries for any DNS-encoded name.", + "version": 1 + }, + "argsData": "0x00000000000000000000000011b5bfbe9078d826b1edbdd1cfc12f5828d9f50c000000000000000000000000e4e7245716d12d0f6aea01dfe0e635c43d7d083c00000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0xc00750fdf4ec794592a19c9cad022c5c7f322e884b1f95121412128ac5215af0", + "nonce": "0x64", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x38309d023d7433e0c2006e480eafd04e613bed03ad606ca7307bbc1f366c19d1", + "blockNumber": "0xaa5718", + "transactionIndex": "0x4d" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/UnlockedMigrationController.json b/contracts/deployments/sepolia/UnlockedMigrationController.json new file mode 100644 index 000000000..2a5c0e5e1 --- /dev/null +++ b/contracts/deployments/sepolia/UnlockedMigrationController.json @@ -0,0 +1,634 @@ +{ + "address": "0xd021a69db7f9e276a59cbbccf06e7f1e5434215c", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "address", + "name": "graveyard", + "type": "address" + }, + { + "internalType": "contract IPermissionedRegistry", + "name": "ethRegistry", + "type": "address" + }, + { + "internalType": "contract IContractNamer", + "name": "contractNamer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameDataMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameIsLocked", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [], + "name": "CONTRACT_NAMER", + "outputs": [ + { + "internalType": "contract IContractNamer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH_REGISTRY", + "outputs": [ + { + "internalType": "contract IPermissionedRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GRAVEYARD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[]", + "name": "mds", + "type": "tuple[]" + } + ], + "name": "finishERC1155Migration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "UnlockedMigrationController", + "sourceName": "src/migration/UnlockedMigrationController.sol", + "bytecode": "0x610140604052348015610010575f80fd5b50604051611bf1380380611bf183398101604081905261002f91610154565b6001600160a01b03808516608081905290841660a05260408051633f15457f60e01b81529051839287928792633f15457f916004808201926020929091908290030181865afa158015610084573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100a891906101b0565b6001600160a01b0390811660c05292831660e05250508281166101005260408051632b20e39760e01b8152905191861691632b20e397916004808201926020929091908290030181865afa158015610102573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061012691906101b0565b6001600160a01b031661012052506101d292505050565b6001600160a01b0381168114610151575f80fd5b50565b5f805f8060808587031215610167575f80fd5b84516101728161013d565b60208601519094506101838161013d565b60408601519093506101948161013d565b60608601519092506101a58161013d565b939692955090935050565b5f602082840312156101c0575f80fd5b81516101cb8161013d565b9392505050565b60805160a05160c05160e051610100516101205161198461026d5f395f81816102490152818161032101526104cf01525f81816101550152610aaa01525f818161017c01526105dc01525f61038801525f81816101a30152818161040a015281816104a00152610d9c01525f8181610116015281816106530152818161080201528181610b6901528181610d080152610dcb01526119845ff3fe608060405234801561000f575f80fd5b50600436106100b9575f3560e01c80635c1a6b68116100725780636f3ff726116100585780636f3ff726146101da578063bc197c81146101ed578063f23a6e6114610200575f80fd5b80635c1a6b681461019e5780635d05f049146101c5575f80fd5b8063192cf07d116100a2578063192cf07d14610111578063475007081461015057806348ee1bcc14610177575f80fd5b806301ffc9a7146100bd578063150b7a02146100e5575b5f80fd5b6100d06100cb36600461107a565b610213565b60405190151581526020015b60405180910390f35b6100f86100f3366004611114565b61023d565b6040516001600160e01b031990911681526020016100dc565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100dc565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101d86101d33660046111c3565b610544565b005b6100d06101e836600461122a565b6105bb565b6100f86101fb366004611245565b610647565b6100f861020e3660046112fc565b6107f6565b5f6001600160e01b03198216630a85bd0160e11b1480610237575061023782610a01565b92915050565b5f336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461028e5760405163d86ad9cf60e01b81523360048201526024015b60405180910390fd5b60e08210156102b057604051635cb045db60e01b815260040160405180910390fd5b5f6102bd838501856114ad565b8051805160209091012090915085146102ec5760405163edec356960e01b815260048101869052602401610285565b6040517f28ed4f6c000000000000000000000000000000000000000000000000000000008152600481018690523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906328ed4f6c906044015f604051808303815f87803b15801561036a575f80fd5b505af115801561037c573d5f803e3d5ffd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063cf40882390506103e47f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae885f9182526020526040902090565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201525f6044820181905260648201526084015f604051808303815f87803b158015610456575f80fd5b505af1158015610468573d5f803e3d5ffd5b50506040517f42842e0e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018990527f00000000000000000000000000000000000000000000000000000000000000001692506342842e0e91506064015f604051808303815f87803b158015610512575f80fd5b505af1158015610524573d5f803e3d5ffd5b5050505061053181610a25565b50630a85bd0160e11b9695505050505050565b3330146105665760405163d86ad9cf60e01b8152336004820152602401610285565b8281146105a9576040517f5b0599910000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610285565b6105b584848484610b40565b50505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610623573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023791906114e7565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106c9576040513360248201526106c99063d86ad9cf60e01b906044015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610e6e565b82826106d660e08961151a565b6106e1906040611531565b8082101561071b576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261071b90610e6e565b5f61072886880188611544565b604051635d05f04960e01b81529091503090635d05f04990610752908e908e9086906004016116bc565b5f604051808303815f87803b158015610769575f80fd5b505af192505050801561077a575060015b6107bc573d8080156107a7576040519150601f19603f3d011682016040523d82523d5f602084013e6107ac565b606091505b506107b681610e6e565b506107e5565b507fbc197c810000000000000000000000000000000000000000000000000000000093506107e7565b505b50505098975050505050505050565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610845576040513360248201526108459063d86ad9cf60e01b90604401610692565b828260e080821015610883576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261088390610e6e565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f199092019101816108bb57905050905089825f8151811061090357610903611723565b602090810291909101015261091a878901896114ad565b815f8151811061092c5761092c611723565b6020908102919091010152604051635d05f04960e01b81523090635d05f0499061095c9085908590600401611737565b5f604051808303815f87803b158015610973575f80fd5b505af1925050508015610984575060015b6109c6573d8080156109b1576040519150601f19603f3d011682016040523d82523d5f602084013e6109b6565b606091505b506109c081610e6e565b506109f1565b507ff23a6e610000000000000000000000000000000000000000000000000000000094506109f49050565b50505b5050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b1480610237575061023782610e81565b60208101516001600160a01b0316610a69576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516020820151604080840151606085015191517f85f3e6430000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016946385f3e64394610afc9491939092909190731110000000000000000000000000000001100000905f90600401611784565b6020604051808303815f875af1158015610b18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3c91906117d7565b5050565b5f5b83811015610e67575f858583818110610b5d57610b5d611723565b9050602002013590505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630178fe3f836040518263ffffffff1660e01b8152600401610bb591815260200190565b606060405180830381865afa158015610bd0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf491906117ee565b509150506001811615610c36576040517fe7c290e200000000000000000000000000000000000000000000000000000000815260048101839052602401610285565b5f858585818110610c4957610c49611723565b9050602002810190610c5b919061184c565b610c65908061186a565b604051610c739291906118ad565b6040519081900390209050610cb17f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae825f9182526020526040902090565b8314610cd35760405163edec356960e01b815260048101849052602401610285565b6040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018490525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015610d51575f80fd5b505af1158015610d63573d5f803e3d5ffd5b50506040517f8b4dfa75000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830181905260448301527f0000000000000000000000000000000000000000000000000000000000000000169250638b4dfa7591506064015f604051808303815f87803b158015610e0e575f80fd5b505af1158015610e20573d5f803e3d5ffd5b50505050610e59868686818110610e3957610e39611723565b9050602002810190610e4b919061184c565b610e54906118bc565b610a25565b505050806001019050610b42565b5050505050565b610e7781610ee7565b9050805160208201fd5b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061023757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610237565b60605f8251118015610f11575062461bcd60e51b610f04836118c7565b6001600160e01b03191614155b15610faa5762461bcd60e51b7f577261707065644572726f723a3a307800000000000000000000000000000000610f4784610fae565b604051602001610f589291906118fa565b60408051601f1981840301815290829052610f759160240161193c565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b805160609060011b8067ffffffffffffffff811115610fcf57610fcf611373565b6040519080825280601f01601f191660200182016040528015610ff9576020820181803683370190505b509150602083810190830161100f828285611017565b505050919050565b8181015b808310156105b55783516101005b828510801561103757505f81115b1561106d5760031901600f82821c16600a8110611057578060570161105c565b806030015b905080865350600190940193611029565b505060208401935061101b565b5f6020828403121561108a575f80fd5b81356001600160e01b0319811681146110a1575f80fd5b9392505050565b6001600160a01b03811681146110bc575f80fd5b50565b80356110ca816110a8565b919050565b5f8083601f8401126110df575f80fd5b50813567ffffffffffffffff8111156110f6575f80fd5b60208301915083602082850101111561110d575f80fd5b9250929050565b5f805f805f60808688031215611128575f80fd5b8535611133816110a8565b94506020860135611143816110a8565b935060408601359250606086013567ffffffffffffffff811115611165575f80fd5b611171888289016110cf565b969995985093965092949392505050565b5f8083601f840112611192575f80fd5b50813567ffffffffffffffff8111156111a9575f80fd5b6020830191508360208260051b850101111561110d575f80fd5b5f805f80604085870312156111d6575f80fd5b843567ffffffffffffffff808211156111ed575f80fd5b6111f988838901611182565b90965094506020870135915080821115611211575f80fd5b5061121e87828801611182565b95989497509550505050565b5f6020828403121561123a575f80fd5b81356110a1816110a8565b5f805f805f805f8060a0898b03121561125c575f80fd5b8835611267816110a8565b97506020890135611277816110a8565b9650604089013567ffffffffffffffff80821115611293575f80fd5b61129f8c838d01611182565b909850965060608b01359150808211156112b7575f80fd5b6112c38c838d01611182565b909650945060808b01359150808211156112db575f80fd5b506112e88b828c016110cf565b999c989b5096995094979396929594505050565b5f805f805f8060a08789031215611311575f80fd5b863561131c816110a8565b9550602087013561132c816110a8565b94506040870135935060608701359250608087013567ffffffffffffffff811115611355575f80fd5b61136189828a016110cf565b979a9699509497509295939492505050565b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff811182821017156113aa576113aa611373565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156113d9576113d9611373565b604052919050565b5f608082840312156113f1575f80fd5b6113f9611387565b9050813567ffffffffffffffff80821115611412575f80fd5b818401915084601f830112611425575f80fd5b813560208282111561143957611439611373565b61144b601f8301601f191682016113b0565b92508183528681838601011115611460575f80fd5b81818501828501375f81838501015282855261147d8187016110bf565b8186015250505050611491604083016110bf565b60408201526114a2606083016110bf565b606082015292915050565b5f602082840312156114bd575f80fd5b813567ffffffffffffffff8111156114d3575f80fd5b6114df848285016113e1565b949350505050565b5f602082840312156114f7575f80fd5b815180151581146110a1575f80fd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761023757610237611506565b8082018082111561023757610237611506565b5f6020808385031215611555575f80fd5b823567ffffffffffffffff8082111561156c575f80fd5b818501915085601f83011261157f575f80fd5b81358181111561159157611591611373565b8060051b6115a08582016113b0565b91825283810185019185810190898411156115b9575f80fd5b86860192505b838310156115f3578235858111156115d5575f80fd5b6115e38b89838a01016113e1565b83525091860191908601906115bf565b9998505050505050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208086019550808260051b8401018186015f5b848110156116af57601f1986840301895281516080815181865261166f82870182611600565b838801516001600160a01b03908116888a015260408086015182169089015260609485015116939096019290925250509783019790830190600101611649565b5090979650505050505050565b604081528260408201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8411156116f3575f80fd5b8360051b808660608501378201828103606090810160208501526117199082018561162e565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b604080825283519082018190525f906020906060840190828701845b8281101561176f57815184529284019290840190600101611753565b5050508381036020850152611719818661162e565b60c081525f61179660c0830189611600565b6001600160a01b039788166020840152958716604083015250929094166060830152608082015267ffffffffffffffff90921660a090920191909152919050565b5f602082840312156117e7575f80fd5b5051919050565b5f805f60608486031215611800575f80fd5b835161180b816110a8565b602085015190935063ffffffff81168114611824575f80fd5b604085015190925067ffffffffffffffff81168114611841575f80fd5b809150509250925092565b5f8235607e19833603018112611860575f80fd5b9190910192915050565b5f808335601e1984360301811261187f575f80fd5b83018035915067ffffffffffffffff821115611899575f80fd5b60200191503681900382131561110d575f80fd5b818382375f9101908152919050565b5f61023736836113e1565b5f815160208301516001600160e01b03198082169350600483101561100f5760049290920360031b82901b161692915050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000831681525f82518060208501601085015e5f92016010019182525092915050565b602081525f6110a1602083018461160056fea264697066735822122020fa91b87be5519387eec9a360372d1078a07afea24e195560b379c8acbe356364736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100b9575f3560e01c80635c1a6b68116100725780636f3ff726116100585780636f3ff726146101da578063bc197c81146101ed578063f23a6e6114610200575f80fd5b80635c1a6b681461019e5780635d05f049146101c5575f80fd5b8063192cf07d116100a2578063192cf07d14610111578063475007081461015057806348ee1bcc14610177575f80fd5b806301ffc9a7146100bd578063150b7a02146100e5575b5f80fd5b6100d06100cb36600461107a565b610213565b60405190151581526020015b60405180910390f35b6100f86100f3366004611114565b61023d565b6040516001600160e01b031990911681526020016100dc565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100dc565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101387f000000000000000000000000000000000000000000000000000000000000000081565b6101d86101d33660046111c3565b610544565b005b6100d06101e836600461122a565b6105bb565b6100f86101fb366004611245565b610647565b6100f861020e3660046112fc565b6107f6565b5f6001600160e01b03198216630a85bd0160e11b1480610237575061023782610a01565b92915050565b5f336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461028e5760405163d86ad9cf60e01b81523360048201526024015b60405180910390fd5b60e08210156102b057604051635cb045db60e01b815260040160405180910390fd5b5f6102bd838501856114ad565b8051805160209091012090915085146102ec5760405163edec356960e01b815260048101869052602401610285565b6040517f28ed4f6c000000000000000000000000000000000000000000000000000000008152600481018690523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906328ed4f6c906044015f604051808303815f87803b15801561036a575f80fd5b505af115801561037c573d5f803e3d5ffd5b50506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915063cf40882390506103e47f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae885f9182526020526040902090565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201525f6044820181905260648201526084015f604051808303815f87803b158015610456575f80fd5b505af1158015610468573d5f803e3d5ffd5b50506040517f42842e0e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018990527f00000000000000000000000000000000000000000000000000000000000000001692506342842e0e91506064015f604051808303815f87803b158015610512575f80fd5b505af1158015610524573d5f803e3d5ffd5b5050505061053181610a25565b50630a85bd0160e11b9695505050505050565b3330146105665760405163d86ad9cf60e01b8152336004820152602401610285565b8281146105a9576040517f5b0599910000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610285565b6105b584848484610b40565b50505050565b60405163379ffb9360e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690636f3ff72690602401602060405180830381865afa158015610623573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023791906114e7565b5f336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106c9576040513360248201526106c99063d86ad9cf60e01b906044015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610e6e565b82826106d660e08961151a565b6106e1906040611531565b8082101561071b576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261071b90610e6e565b5f61072886880188611544565b604051635d05f04960e01b81529091503090635d05f04990610752908e908e9086906004016116bc565b5f604051808303815f87803b158015610769575f80fd5b505af192505050801561077a575060015b6107bc573d8080156107a7576040519150601f19603f3d011682016040523d82523d5f602084013e6107ac565b606091505b506107b681610e6e565b506107e5565b507fbc197c810000000000000000000000000000000000000000000000000000000093506107e7565b505b50505098975050505050505050565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610845576040513360248201526108459063d86ad9cf60e01b90604401610692565b828260e080821015610883576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261088390610e6e565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f199092019101816108bb57905050905089825f8151811061090357610903611723565b602090810291909101015261091a878901896114ad565b815f8151811061092c5761092c611723565b6020908102919091010152604051635d05f04960e01b81523090635d05f0499061095c9085908590600401611737565b5f604051808303815f87803b158015610973575f80fd5b505af1925050508015610984575060015b6109c6573d8080156109b1576040519150601f19603f3d011682016040523d82523d5f602084013e6109b6565b606091505b506109c081610e6e565b506109f1565b507ff23a6e610000000000000000000000000000000000000000000000000000000094506109f49050565b50505b5050509695505050505050565b5f6001600160e01b0319821663379ffb9360e11b1480610237575061023782610e81565b60208101516001600160a01b0316610a69576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516020820151604080840151606085015191517f85f3e6430000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016946385f3e64394610afc9491939092909190731110000000000000000000000000000001100000905f90600401611784565b6020604051808303815f875af1158015610b18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3c91906117d7565b5050565b5f5b83811015610e67575f858583818110610b5d57610b5d611723565b9050602002013590505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630178fe3f836040518263ffffffff1660e01b8152600401610bb591815260200190565b606060405180830381865afa158015610bd0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf491906117ee565b509150506001811615610c36576040517fe7c290e200000000000000000000000000000000000000000000000000000000815260048101839052602401610285565b5f858585818110610c4957610c49611723565b9050602002810190610c5b919061184c565b610c65908061186a565b604051610c739291906118ad565b6040519081900390209050610cb17f93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae825f9182526020526040902090565b8314610cd35760405163edec356960e01b815260048101849052602401610285565b6040517f1896f70a000000000000000000000000000000000000000000000000000000008152600481018490525f60248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631896f70a906044015f604051808303815f87803b158015610d51575f80fd5b505af1158015610d63573d5f803e3d5ffd5b50506040517f8b4dfa75000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830181905260448301527f0000000000000000000000000000000000000000000000000000000000000000169250638b4dfa7591506064015f604051808303815f87803b158015610e0e575f80fd5b505af1158015610e20573d5f803e3d5ffd5b50505050610e59868686818110610e3957610e39611723565b9050602002810190610e4b919061184c565b610e54906118bc565b610a25565b505050806001019050610b42565b5050505050565b610e7781610ee7565b9050805160208201fd5b5f6001600160e01b031982167f4e2312e000000000000000000000000000000000000000000000000000000000148061023757507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614610237565b60605f8251118015610f11575062461bcd60e51b610f04836118c7565b6001600160e01b03191614155b15610faa5762461bcd60e51b7f577261707065644572726f723a3a307800000000000000000000000000000000610f4784610fae565b604051602001610f589291906118fa565b60408051601f1981840301815290829052610f759160240161193c565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b805160609060011b8067ffffffffffffffff811115610fcf57610fcf611373565b6040519080825280601f01601f191660200182016040528015610ff9576020820181803683370190505b509150602083810190830161100f828285611017565b505050919050565b8181015b808310156105b55783516101005b828510801561103757505f81115b1561106d5760031901600f82821c16600a8110611057578060570161105c565b806030015b905080865350600190940193611029565b505060208401935061101b565b5f6020828403121561108a575f80fd5b81356001600160e01b0319811681146110a1575f80fd5b9392505050565b6001600160a01b03811681146110bc575f80fd5b50565b80356110ca816110a8565b919050565b5f8083601f8401126110df575f80fd5b50813567ffffffffffffffff8111156110f6575f80fd5b60208301915083602082850101111561110d575f80fd5b9250929050565b5f805f805f60808688031215611128575f80fd5b8535611133816110a8565b94506020860135611143816110a8565b935060408601359250606086013567ffffffffffffffff811115611165575f80fd5b611171888289016110cf565b969995985093965092949392505050565b5f8083601f840112611192575f80fd5b50813567ffffffffffffffff8111156111a9575f80fd5b6020830191508360208260051b850101111561110d575f80fd5b5f805f80604085870312156111d6575f80fd5b843567ffffffffffffffff808211156111ed575f80fd5b6111f988838901611182565b90965094506020870135915080821115611211575f80fd5b5061121e87828801611182565b95989497509550505050565b5f6020828403121561123a575f80fd5b81356110a1816110a8565b5f805f805f805f8060a0898b03121561125c575f80fd5b8835611267816110a8565b97506020890135611277816110a8565b9650604089013567ffffffffffffffff80821115611293575f80fd5b61129f8c838d01611182565b909850965060608b01359150808211156112b7575f80fd5b6112c38c838d01611182565b909650945060808b01359150808211156112db575f80fd5b506112e88b828c016110cf565b999c989b5096995094979396929594505050565b5f805f805f8060a08789031215611311575f80fd5b863561131c816110a8565b9550602087013561132c816110a8565b94506040870135935060608701359250608087013567ffffffffffffffff811115611355575f80fd5b61136189828a016110cf565b979a9699509497509295939492505050565b634e487b7160e01b5f52604160045260245ffd5b6040516080810167ffffffffffffffff811182821017156113aa576113aa611373565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156113d9576113d9611373565b604052919050565b5f608082840312156113f1575f80fd5b6113f9611387565b9050813567ffffffffffffffff80821115611412575f80fd5b818401915084601f830112611425575f80fd5b813560208282111561143957611439611373565b61144b601f8301601f191682016113b0565b92508183528681838601011115611460575f80fd5b81818501828501375f81838501015282855261147d8187016110bf565b8186015250505050611491604083016110bf565b60408201526114a2606083016110bf565b606082015292915050565b5f602082840312156114bd575f80fd5b813567ffffffffffffffff8111156114d3575f80fd5b6114df848285016113e1565b949350505050565b5f602082840312156114f7575f80fd5b815180151581146110a1575f80fd5b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761023757610237611506565b8082018082111561023757610237611506565b5f6020808385031215611555575f80fd5b823567ffffffffffffffff8082111561156c575f80fd5b818501915085601f83011261157f575f80fd5b81358181111561159157611591611373565b8060051b6115a08582016113b0565b91825283810185019185810190898411156115b9575f80fd5b86860192505b838310156115f3578235858111156115d5575f80fd5b6115e38b89838a01016113e1565b83525091860191908601906115bf565b9998505050505050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208086019550808260051b8401018186015f5b848110156116af57601f1986840301895281516080815181865261166f82870182611600565b838801516001600160a01b03908116888a015260408086015182169089015260609485015116939096019290925250509783019790830190600101611649565b5090979650505050505050565b604081528260408201525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8411156116f3575f80fd5b8360051b808660608501378201828103606090810160208501526117199082018561162e565b9695505050505050565b634e487b7160e01b5f52603260045260245ffd5b604080825283519082018190525f906020906060840190828701845b8281101561176f57815184529284019290840190600101611753565b5050508381036020850152611719818661162e565b60c081525f61179660c0830189611600565b6001600160a01b039788166020840152958716604083015250929094166060830152608082015267ffffffffffffffff90921660a090920191909152919050565b5f602082840312156117e7575f80fd5b5051919050565b5f805f60608486031215611800575f80fd5b835161180b816110a8565b602085015190935063ffffffff81168114611824575f80fd5b604085015190925067ffffffffffffffff81168114611841575f80fd5b809150509250925092565b5f8235607e19833603018112611860575f80fd5b9190910192915050565b5f808335601e1984360301811261187f575f80fd5b83018035915067ffffffffffffffff821115611899575f80fd5b60200191503681900382131561110d575f80fd5b818382375f9101908152919050565b5f61023736836113e1565b5f815160208301516001600160e01b03198082169350600483101561100f5760049290920360031b82901b161692915050565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000831681525f82518060208501601085015e5f92016010019182525092915050565b602081525f6110a1602083018461160056fea264697066735822122020fa91b87be5519387eec9a360372d1078a07afea24e195560b379c8acbe356364736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "25006": [ + { + "length": 32, + "start": 278 + }, + { + "length": 32, + "start": 1619 + }, + { + "length": 32, + "start": 2050 + }, + { + "length": 32, + "start": 2921 + }, + { + "length": 32, + "start": 3336 + }, + { + "length": 32, + "start": 3531 + } + ], + "25009": [ + { + "length": 32, + "start": 419 + }, + { + "length": 32, + "start": 1034 + }, + { + "length": 32, + "start": 1184 + }, + { + "length": 32, + "start": 3484 + } + ], + "25013": [ + { + "length": 32, + "start": 904 + } + ], + "26612": [ + { + "length": 32, + "start": 341 + }, + { + "length": 32, + "start": 2730 + } + ], + "26616": [ + { + "length": 32, + "start": 585 + }, + { + "length": 32, + "start": 801 + }, + { + "length": 32, + "start": 1231 + } + ], + "33410": [ + { + "length": 32, + "start": 380 + }, + { + "length": 32, + "start": 1500 + } + ] + }, + "inputSourceName": "project/src/migration/UnlockedMigrationController.sol", + "devdoc": { + "errors": { + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "InvalidData()": [ + { + "details": "Error selector: `0x5cb045db`" + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "NameDataMismatch(uint256)": [ + { + "details": "Error selector: `0xedec3569`" + } + ], + "NameIsLocked(uint256)": [ + { + "details": "Error selector: `0xe7c290e2`" + } + ], + "UnauthorizedCaller(address)": [ + { + "details": "Error selector: `0xd86ad9cf`", + "params": { + "caller": "The address that attempted the unauthorized operation" + } + } + ] + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "contractNamer": "Delegated contract namer.", + "ethRegistry": "The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.", + "graveyard": "The ENSv1 `BaseRegistrar` token graveyard.", + "nameWrapper": "The ENSv1 `NameWrapper` contract." + } + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "details": "Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts", + "params": { + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated.", + "mds": "The migration parameters for each name, indexed in parallel with `ids`." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.", + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed" + } + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data` struct containing migration parameters.", + "id": "The NameWrapper token ID (namehash) of the name being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed" + } + }, + "onERC721Received(address,address,uint256,bytes)": { + "params": { + "": "{from} Ignored.", + "data": "ABI-encoded `LibMigration.Data` struct containing migration parameters.", + "tokenId": "The BaseRegistrar token ID (labelhash) of the name being migrated." + }, + "returns": { + "_0": "The selector of the `onERC721Received` function." + } + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}." + } + }, + "stateVariables": { + "_BASE_REGISTRAR": { + "details": "The ENSv1 `BaseRegistrar` contract." + } + }, + "title": "UnlockedMigrationController", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "1306400", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "CONTRACT_NAMER()": "infinite", + "ETH_REGISTRY()": "infinite", + "GRAVEYARD()": "infinite", + "NAME_WRAPPER()": "infinite", + "finishERC1155Migration(uint256[],(string,address,address,address)[])": "infinite", + "isContractNamer(address)": "infinite", + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": "infinite", + "onERC1155Received(address,address,uint256,uint256,bytes)": "infinite", + "onERC721Received(address,address,uint256,bytes)": "infinite", + "supportsInterface(bytes4)": "infinite" + }, + "internal": { + "_inject(struct LibMigration.Data memory)": "infinite", + "_migrateWrapped(uint256[] calldata,struct LibMigration.Data calldata[] calldata)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"graveyard\",\"type\":\"address\"},{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"ethRegistry\",\"type\":\"address\"},{\"internalType\":\"contract IContractNamer\",\"name\":\"contractNamer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameIsLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CONTRACT_NAMER\",\"outputs\":[{\"internalType\":\"contract IContractNamer\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ETH_REGISTRY\",\"outputs\":[{\"internalType\":\"contract IPermissionedRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GRAVEYARD\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[]\",\"name\":\"mds\",\"type\":\"tuple[]\"}],\"name\":\"finishERC1155Migration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"InvalidData()\":[{\"details\":\"Error selector: `0x5cb045db`\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"NameDataMismatch(uint256)\":[{\"details\":\"Error selector: `0xedec3569`\"}],\"NameIsLocked(uint256)\":[{\"details\":\"Error selector: `0xe7c290e2`\"}],\"UnauthorizedCaller(address)\":[{\"details\":\"Error selector: `0xd86ad9cf`\",\"params\":{\"caller\":\"The address that attempted the unauthorized operation\"}}]},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"contractNamer\":\"Delegated contract namer.\",\"ethRegistry\":\"The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\",\"graveyard\":\"The ENSv1 `BaseRegistrar` token graveyard.\",\"nameWrapper\":\"The ENSv1 `NameWrapper` contract.\"}},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"details\":\"Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts\",\"params\":{\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\",\"mds\":\"The migration parameters for each name, indexed in parallel with `ids`.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\",\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\"}},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data` struct containing migration parameters.\",\"id\":\"The NameWrapper token ID (namehash) of the name being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\"}},\"onERC721Received(address,address,uint256,bytes)\":{\"params\":{\"\":\"{from} Ignored.\",\"data\":\"ABI-encoded `LibMigration.Data` struct containing migration parameters.\",\"tokenId\":\"The BaseRegistrar token ID (labelhash) of the name being migrated.\"},\"returns\":{\"_0\":\"The selector of the `onERC721Received` function.\"}},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"}},\"stateVariables\":{\"_BASE_REGISTRAR\":{\"details\":\"The ENSv1 `BaseRegistrar` contract.\"}},\"title\":\"UnlockedMigrationController\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidData()\":[{\"notice\":\"The encoded data is invalid.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"NameDataMismatch(uint256)\":[{\"notice\":\"NameWrapper or BaseRegistrar token does not match supplied data.\"}],\"NameIsLocked(uint256)\":[{\"notice\":\"NameWrapper token is locked.\"}],\"UnauthorizedCaller(address)\":[{\"notice\":\"Thrown when a caller is not authorized to perform the requested operation\"}]},\"kind\":\"user\",\"methods\":{\"CONTRACT_NAMER()\":{\"notice\":\"Delegated contract namer.\"},\"ETH_REGISTRY()\":{\"notice\":\"The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\"},\"GRAVEYARD()\":{\"notice\":\"The ENSv1 `BaseRegistrar` token graveyard.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\"},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"notice\":\"Convert NameWrapper tokens to their equivalent ENSv2 form.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"notice\":\"Migrate one NameWrapper token via `safeTransferFrom()`.\"},\"onERC721Received(address,address,uint256,bytes)\":{\"notice\":\"Receives an unwrapped .eth name via ERC721 `safeTransferFrom` from the `BaseRegistrar`. Decodes a single `LibMigration.Data` from `data` and registers the equivalent name in ENSv2.\"}},\"notice\":\"Migration controller for handling unwrapped and unlocked .eth names. Assumes premigration has `RESERVED` existing ENSv1 names. Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration. Supports (2) token sources: 1. NameWrapper (ERC-1155) but unlocked only. Reverts with `NameIsWrapped` if `LibMigration.isLocked()` => use LockedMigrationController instead. 2. BaseRegistrar (ERC-721) Unlike locked migration, no subregistry is deployed and no fuse-to-role translation is performed. The name is registered in the .eth registry with the roles and subregistry specified in the caller-provided `LibMigration.Data`.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/migration/UnlockedMigrationController.sol\":\"UnlockedMigrationController\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\ninterface IBaseRegistrar is IERC721 {\\n event ControllerAdded(address indexed controller);\\n event ControllerRemoved(address indexed controller);\\n event NameMigrated(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRegistered(\\n uint256 indexed id,\\n address indexed owner,\\n uint256 expires\\n );\\n event NameRenewed(uint256 indexed id, uint256 expires);\\n\\n // Authorises a controller, who can register and renew domains.\\n function addController(address controller) external;\\n\\n // Revoke controller permission for an address.\\n function removeController(address controller) external;\\n\\n // Set the resolver for the TLD this registrar manages.\\n function setResolver(address resolver) external;\\n\\n // Returns the expiration timestamp of the specified label hash.\\n function nameExpires(uint256 id) external view returns (uint256);\\n\\n // Returns true if the specified name is available for registration.\\n function available(uint256 id) external view returns (bool);\\n\\n /// @dev Register a name.\\n function register(\\n uint256 id,\\n address owner,\\n uint256 duration\\n ) external returns (uint256);\\n\\n function renew(uint256 id, uint256 duration) external returns (uint256);\\n\\n /// @dev Reclaim ownership of a name in ENS, if you own it in the registrar.\\n function reclaim(uint256 id, address owner) external;\\n}\\n\",\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\ninterface ENS {\\n // Logged when the owner of a node assigns a new owner to a subnode.\\n event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\\n\\n // Logged when the owner of a node transfers ownership to a new account.\\n event Transfer(bytes32 indexed node, address owner);\\n\\n // Logged when the resolver for a node changes.\\n event NewResolver(bytes32 indexed node, address resolver);\\n\\n // Logged when the TTL of a node changes\\n event NewTTL(bytes32 indexed node, uint64 ttl);\\n\\n // Logged when an operator is added or removed.\\n event ApprovalForAll(\\n address indexed owner,\\n address indexed operator,\\n bool approved\\n );\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n bytes32 label,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n bytes32 label,\\n address owner\\n ) external returns (bytes32);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setOwner(bytes32 node, address owner) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n function owner(bytes32 node) external view returns (address);\\n\\n function resolver(bytes32 node) external view returns (address);\\n\\n function ttl(bytes32 node) external view returns (uint64);\\n\\n function recordExists(bytes32 node) external view returns (bool);\\n\\n function isApprovedForAll(\\n address owner,\\n address operator\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /// @dev Convert `hexString[off:end]` to `bytes32`.\\n /// Accepts 0-64 hex-chars.\\n /// Uses right alignment: `1` → `0000000000000000000000000000000000000000000000000000000000000001`.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return word The parsed bytes32.\\n /// @return valid True if the parse was successful.\\n function hexStringToBytes32(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes32 word, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n if (nibbles > 64 || end > hexString.length) {\\n return (bytes32(0), false); // too large or out of bounds\\n }\\n uint256 src;\\n assembly {\\n src := add(add(hexString, 32), off)\\n }\\n valid = unsafeBytes(src, 0, nibbles);\\n assembly {\\n let pad := sub(32, shr(1, add(nibbles, 1))) // number of bytes\\n word := shr(shl(3, pad), mload(0)) // right align\\n }\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `address`.\\n /// Accepts exactly 40 hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return addr The parsed address.\\n /// @return valid True if the parse was successful.\\n function hexToAddress(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (address addr, bool valid) {\\n if (off + 40 != end) return (address(0), false); // wrong length\\n bytes32 word;\\n (word, valid) = hexStringToBytes32(hexString, off, end);\\n addr = address(uint160(uint256(word)));\\n }\\n\\n /// @dev Convert `hexString[off:end]` to `bytes`.\\n /// Accepts 0+ hex-chars.\\n /// @param hexString The string to parse.\\n /// @param off The index to start parsing.\\n /// @param end The (exclusive) index to stop parsing.\\n /// @return v The parsed bytes.\\n /// @return valid True if the parse was successful.\\n function hexToBytes(\\n bytes memory hexString,\\n uint256 off,\\n uint256 end\\n ) internal pure returns (bytes memory v, bool valid) {\\n if (end < off) return (\\\"\\\", false); // invalid range\\n uint256 nibbles = end - off;\\n v = new bytes((1 + nibbles) >> 1); // round up\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(add(hexString, 32), off)\\n dst := add(v, 32)\\n }\\n valid = unsafeBytes(src, dst, nibbles);\\n }\\n\\n /// @dev Convert arbitrary hex-encoded memory to bytes.\\n /// If nibbles is odd, leading hex-char is padded, eg. `F` → `0x0F`.\\n /// Matches: `/^[0-9a-f]*$/i`.\\n /// @param src The memory offset of first hex-char of input.\\n /// @param dst The memory offset of first byte of output (cannot alias `src`).\\n /// @param nibbles The number of hex-chars to convert.\\n /// @return valid True if all characters were hex.\\n function unsafeBytes(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure returns (bool valid) {\\n assembly {\\n function getHex(c, i) -> ascii {\\n c := byte(i, c)\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0x100\\n }\\n valid := true\\n let end := add(src, nibbles)\\n if and(nibbles, 1) {\\n let b := getHex(mload(src), 0) // \\\"f\\\" -> 15\\n mstore8(dst, b) // write ascii byte\\n src := add(src, 1) // update pointers\\n dst := add(dst, 1)\\n if gt(b, 255) {\\n valid := false\\n src := end // terminate loop\\n }\\n }\\n // prettier-ignore\\n for {} lt(src, end) {\\n src := add(src, 2) // 2 nibbles\\n dst := add(dst, 1) // per byte\\n } {\\n let word := mload(src) // read word (left aligned)\\n let b := or(shl(4, getHex(word, 0)), getHex(word, 1)) // \\\"ff\\\" -> 255\\n if gt(b, 255) {\\n valid := false\\n break\\n }\\n mstore8(dst, b) // write ascii byte\\n }\\n }\\n }\\n\\n /// @dev Format `address` as a hex string.\\n /// @param addr The address to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function addressToHex(\\n address addr\\n ) internal pure returns (string memory hexString) {\\n // return bytesToHex(abi.encodePacked(addr));\\n hexString = new string(40);\\n uint256 dst;\\n assembly {\\n mstore(0, addr)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(12, dst, 40);\\n }\\n\\n /// @dev Format `uint256` as a variable-length hex string without zero padding.\\n /// * unpaddedUintToHex(0, true) = \\\"0\\\"\\n /// * unpaddedUintToHex(1, true) = \\\"1\\\"\\n /// * unpaddedUintToHex(0, false) = \\\"00\\\"\\n /// * unpaddedUintToHex(1, false) = \\\"01\\\"\\n /// @param value The number to format.\\n /// @param dropZeroNibble If true, the leading byte will use one nibble if less than 16.\\n /// @return hexString The corresponding hex string w/o an 0x-prefix.\\n function unpaddedUintToHex(\\n uint256 value,\\n bool dropZeroNibble\\n ) internal pure returns (string memory hexString) {\\n uint256 temp = value;\\n uint256 shift;\\n for (uint256 b = 128; b >= 8; b >>= 1) {\\n if (temp < (1 << b)) {\\n shift += b; // number of zero upper bits\\n } else {\\n temp >>= b; // shift away lower half\\n }\\n }\\n if (dropZeroNibble && temp < 16) shift += 4;\\n uint256 nibbles = 64 - (shift >> 2);\\n hexString = new string(nibbles);\\n uint256 dst;\\n assembly {\\n mstore(0, shl(shift, value)) // left-align\\n dst := add(hexString, 32)\\n }\\n unsafeHex(0, dst, nibbles);\\n }\\n\\n /// @dev Format `bytes` as a hex string.\\n /// @param v The bytes to format.\\n /// @return hexString The corresponding hex string w/o a 0x-prefix.\\n function bytesToHex(\\n bytes memory v\\n ) internal pure returns (string memory hexString) {\\n uint256 nibbles = v.length << 1;\\n hexString = new string(nibbles);\\n uint256 src;\\n uint256 dst;\\n assembly {\\n src := add(v, 32)\\n dst := add(hexString, 32)\\n }\\n unsafeHex(src, dst, nibbles);\\n }\\n\\n /// @dev Converts arbitrary memory to a hex string.\\n /// @param src The memory offset of first nibble of input.\\n /// @param dst The memory offset of first hex-char of output (can alias `src`).\\n /// @param nibbles The number of nibbles to convert and the byte-length of the output.\\n function unsafeHex(\\n uint256 src,\\n uint256 dst,\\n uint256 nibbles\\n ) internal pure {\\n unchecked {\\n for (uint256 end = dst + nibbles; dst < end; src += 32) {\\n uint256 word;\\n assembly {\\n word := mload(src)\\n }\\n for (uint256 shift = 256; dst < end && shift > 0; dst++) {\\n uint256 b = (word >> (shift -= 4)) & 15; // each nibble\\n b = b < 10 ? b + 0x30 : b + 0x57; // (\\\"a\\\" - 10) => 0x57\\n assembly {\\n mstore8(dst, b)\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\nimport {BytesUtils} from \\\"./BytesUtils.sol\\\";\\n\\n/// @dev Library for encoding/decoding names.\\n///\\n/// An ENS name is stop-separated labels, eg. \\\"aaa.bb.c\\\".\\n///\\n/// A DNS-encoded name is composed of byte length-prefixed labels with a terminator byte.\\n/// eg. \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\".\\n///\\n/// * maximum label length is 255 bytes.\\n/// * length = 0 is reserved for the terminator (root).\\n/// * `dns.length == 2 + ens.length` and the mapping is injective.\\n///\\nlibrary NameCoder {\\n /// @dev The namehash of \\\"eth\\\".\\n bytes32 public constant ETH_NODE =\\n 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;\\n\\n /// @dev The label was empty.\\n /// Error selector: `0xbf9a2740`\\n error LabelIsEmpty();\\n\\n /// @dev The label was more than 255 bytes.\\n /// Error selector: `0xdab6c73c`\\n error LabelIsTooLong(string label);\\n\\n /// @dev The DNS-encoded name is malformed.\\n /// Error selector: `0xba4adc23`\\n error DNSDecodingFailed(bytes dns);\\n\\n /// @dev A label of the ENS name has an invalid size.\\n /// Error selector: `0x9a4c3e3b`\\n error DNSEncodingFailed(string ens);\\n\\n /// @dev The `name` did not end with `suffix`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param suffix The DNS-encoded suffix.\\n error NoSuffixMatch(bytes name, bytes suffix);\\n\\n /// @dev Read the `size` of the label at `offset`.\\n /// If `size = 0`, it must be the end of `name` (no junk at end).\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return size The size of the label in bytes.\\n /// @return nextOffset The offset into `name` of the next label.\\n function nextLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint8 size, uint256 nextOffset) {\\n unchecked {\\n if (offset >= name.length) {\\n revert DNSDecodingFailed(name);\\n }\\n size = uint8(name[offset]);\\n nextOffset = offset + 1 + size;\\n if (\\n size > 0 ? nextOffset >= name.length : nextOffset != name.length\\n ) {\\n revert DNSDecodingFailed(name);\\n }\\n }\\n }\\n\\n /// @dev Find the offset of the label before `offset` in `name`.\\n /// * `prevOffset(name, 0)` reverts\\n /// * `prevOffset(name, name.length + 1)` reverts\\n /// * `prevOffset(name, name.length) = name.length - 1`\\n /// * `prevOffset(name, name.length - 1) = `\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading backwards.\\n ///\\n /// @return prevOffset The offset into `name` of the previous label.\\n function prevLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 prevOffset) {\\n while (true) {\\n (, uint256 nextOffset) = nextLabel(name, prevOffset);\\n if (nextOffset == offset) break;\\n if (nextOffset > offset) {\\n revert DNSDecodingFailed(name);\\n }\\n prevOffset = nextOffset;\\n }\\n }\\n\\n /// @dev Count number of labels in `name`.\\n /// * `countLabels(\\\"\\\\x03eth\\\\x00\\\") = 1`\\n /// * `countLabels(\\\"\\\\x00\\\") = 0`\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return count The number of labels.\\n function countLabels(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (uint256 count) {\\n uint8 size;\\n while (true) {\\n (size, offset) = nextLabel(name, offset);\\n if (size == 0) break;\\n ++count;\\n }\\n }\\n\\n /// @dev Compute the ENS labelhash of the label at `offset` and the offset for the next label.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return labelHash The resulting labelhash.\\n /// @return nextOffset The offset into `name` of the next label.\\n function readLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 labelHash, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n if (size > 0) {\\n assembly {\\n labelHash := keccak256(add(add(name, offset), 33), size)\\n }\\n }\\n }\\n\\n /// @dev Read label at offset from a DNS-encoded name and the offset for the next label.\\n /// * `readLabel(\\\"\\\\x03abc\\\\x00\\\", 0) = (\\\"abc\\\", 4)`\\n /// * `readLabel(\\\"\\\\x00\\\", 0) = (\\\"\\\", 1)`\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start reading.\\n ///\\n /// @return label The label corresponding to `offset`.\\n /// @return nextOffset The offset into `name` of the next label.\\n function extractLabel(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (string memory label, uint256 nextOffset) {\\n uint8 size;\\n (size, nextOffset) = nextLabel(name, offset);\\n bytes memory v = new bytes(size);\\n unchecked {\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(name) + offset + 1, size);\\n }\\n label = string(v);\\n }\\n\\n /// @dev Reads first label from a DNS-encoded name.\\n /// Reverts `DNSDecodingFailed`.\\n /// Reverts `LabelIsEmpty` if the label was empty.\\n ///\\n /// @param name The DNS-encoded name.\\n ///\\n /// @return The first label.\\n function firstLabel(\\n bytes memory name\\n ) internal pure returns (string memory) {\\n (string memory label, ) = extractLabel(name, 0);\\n if (bytes(label).length == 0) {\\n revert LabelIsEmpty();\\n }\\n return label;\\n }\\n\\n /// @dev Compute the namehash of `name[:offset]`.\\n /// Reverts `DNSDecodingFailed`.\\n ///\\n /// @param name The DNS-encoded name.\\n /// @param offset The offset into `name` to start hashing.\\n ///\\n /// @return hash The namehash of `name[:offset]`.\\n function namehash(\\n bytes memory name,\\n uint256 offset\\n ) internal pure returns (bytes32 hash) {\\n (hash, offset) = readLabel(name, offset);\\n if (hash != bytes32(0)) {\\n hash = namehash(namehash(name, offset), hash);\\n }\\n }\\n\\n /// @dev Compute a child namehash from a parent namehash and child labelhash.\\n ///\\n /// @param parentNode The namehash of the parent.\\n /// @param labelHash The labelhash of the child.\\n ///\\n /// @return node The namehash of the child.\\n function namehash(\\n bytes32 parentNode,\\n bytes32 labelHash\\n ) internal pure returns (bytes32 node) {\\n // ~100 gas less than: keccak256(abi.encode(parentNode, labelHash))\\n assembly {\\n mstore(0, parentNode)\\n mstore(32, labelHash)\\n node := keccak256(0, 64)\\n }\\n }\\n\\n /// @dev Convert DNS-encoded name to ENS name.\\n /// * `decode(\\\"\\\\x00\\\") = \\\"\\\"`\\n /// * `decode(\\\"\\\\x03eth\\\\x00\\\") = \\\"eth\\\"`\\n /// * `decode(\\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\") = \\\"aa.bb.c\\\"`\\n /// * `decode(\\\"\\\\x03a.b\\\\x00\\\")` reverts\\n /// Reverts like `nextLabel()`.\\n ///\\n /// @param dns The DNS-encoded name to convert.\\n ///\\n /// @return ens The equivalent ENS name.\\n function decode(\\n bytes memory dns\\n ) internal pure returns (string memory ens) {\\n unchecked {\\n uint256 n = dns.length;\\n if (n == 1 && dns[0] == 0) return \\\"\\\"; // only valid answer is root\\n if (n < 3) revert DNSDecodingFailed(dns);\\n bytes memory v = new bytes(n - 2); // always 2-shorter\\n LibMem.copy(LibMem.ptr(v), LibMem.ptr(dns) + 1, n - 2); // shift by -1 byte\\n uint256 offset;\\n while (true) {\\n (uint8 size, uint256 nextOffset) = nextLabel(dns, offset);\\n if (size == 0) break;\\n if (BytesUtils.includes(v, offset, size, \\\".\\\")) {\\n revert DNSDecodingFailed(dns); // malicious label\\n }\\n if (offset > 0) {\\n v[offset - 1] = \\\".\\\";\\n }\\n offset = nextOffset;\\n }\\n return string(v);\\n }\\n }\\n\\n /// @dev Convert ENS name to DNS-encoded name.\\n /// * `encode(\\\"aaa.bb.c\\\") = \\\"\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00\\\"`\\n /// * `encode(\\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `encode(\\\"\\\") = \\\"\\\\x00\\\"`\\n /// Reverts `DNSEncodingFailed`.\\n ///\\n /// @param ens The ENS name to convert.\\n ///\\n /// @return dns The corresponding DNS-encoded name, eg. `\\\\x03aaa\\\\x02bb\\\\x01c\\\\x00`.\\n function encode(\\n string memory ens\\n ) internal pure returns (bytes memory dns) {\\n unchecked {\\n uint256 n = bytes(ens).length;\\n if (n == 0) return hex\\\"00\\\"; // root\\n dns = new bytes(n + 2); // always 2-longer\\n LibMem.copy(LibMem.ptr(dns) + 1, LibMem.ptr(bytes(ens)), n); // shift by +1 byte\\n uint256 start; // remember position to write length\\n uint256 size;\\n for (uint256 i; i < n; ++i) {\\n if (bytes(ens)[i] == \\\".\\\") {\\n size = i - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n start = i + 1;\\n }\\n }\\n size = n - start;\\n if (size == 0 || size > 255) {\\n revert DNSEncodingFailed(ens);\\n }\\n dns[start] = bytes1(uint8(size));\\n }\\n }\\n\\n /// @dev Find the offset into `name` that namehashes to `nodeSuffix`.\\n ///\\n /// @param name The DNS-encoded name to search.\\n /// @param nodeSuffix The namehash to match.\\n ///\\n /// @return matched True if `name` ends with `nodeSuffix`.\\n /// @return node The namehash of `name[offset:]`.\\n /// @return prevOffset The offset into `name` of the label before `nodeSuffix`, or `matchOffset` if no match or no prior label.\\n /// @return matchOffset The offset into `name` that namehashes to the `nodeSuffix`, or 0 if no match.\\n function matchSuffix(\\n bytes memory name,\\n uint256 offset,\\n bytes32 nodeSuffix\\n )\\n internal\\n pure\\n returns (\\n bool matched,\\n bytes32 node,\\n uint256 prevOffset,\\n uint256 matchOffset\\n )\\n {\\n (bytes32 labelHash, uint256 next) = readLabel(name, offset);\\n if (labelHash != bytes32(0)) {\\n (matched, node, prevOffset, matchOffset) = matchSuffix(\\n name,\\n next,\\n nodeSuffix\\n );\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = offset;\\n matchOffset = next;\\n }\\n node = namehash(node, labelHash);\\n }\\n if (node == nodeSuffix) {\\n matched = true;\\n prevOffset = matchOffset = offset;\\n }\\n }\\n\\n /// @dev Assert `label` is an encodable size.\\n ///\\n /// @param label The label to check.\\n ///\\n /// @return The size of the label.\\n function assertLabelSize(\\n string memory label\\n ) internal pure returns (uint8) {\\n uint256 n = bytes(label).length;\\n if (n == 0) revert LabelIsEmpty();\\n if (n > 255) revert LabelIsTooLong(label);\\n return uint8(n);\\n }\\n\\n /// @dev Prepend `label` to DNS-encoded `name`.\\n /// * `addLabel(\\\"\\\\x03eth\\\\x00\\\", \\\"test\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\\x00\\\", \\\"eth\\\") = \\\"\\\\x03eth\\\\x00\\\"`\\n /// * `addLabel(\\\"\\\", \\\"abc\\\") = \\\"\\\\x03abc\\\"` invalid\\n /// * `addLabel(\\\"\\\", \\\"\\\")` reverts\\n /// Assumes `name` is properly encoded.\\n /// Reverts like `assertLabelSize()`.\\n ///\\n /// @param name The DNS-encoded parent name.\\n /// @param label The child label to prepend.\\n ///\\n /// @return The DNS-encoded child name.\\n function addLabel(\\n bytes memory name,\\n string memory label\\n ) internal pure returns (bytes memory) {\\n return abi.encodePacked(assertLabelSize(label), label, name);\\n }\\n\\n /// @dev Transform `label` to DNS-encoded `{label}.eth`.\\n /// * `ethName(\\\"eth\\\") = \\\"\\\\x04test\\\\x03eth\\\\x00\\\"`\\n /// Behaves like `addLabel()`.\\n ///\\n /// @param label The label to encode.\\n ///\\n /// @return The DNS-encoded name.\\n function ethName(string memory label) internal pure returns (bytes memory) {\\n return addLabel(\\\"\\\\x03eth\\\\x00\\\", label);\\n }\\n}\\n\",\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface IMetadataService {\\n function uri(uint256) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\nimport \\\"../registry/ENS.sol\\\";\\nimport \\\"../ethregistrar/IBaseRegistrar.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport \\\"./IMetadataService.sol\\\";\\nimport \\\"./INameWrapperUpgrade.sol\\\";\\n\\nuint32 constant CANNOT_UNWRAP = 1;\\nuint32 constant CANNOT_BURN_FUSES = 2;\\nuint32 constant CANNOT_TRANSFER = 4;\\nuint32 constant CANNOT_SET_RESOLVER = 8;\\nuint32 constant CANNOT_SET_TTL = 16;\\nuint32 constant CANNOT_CREATE_SUBDOMAIN = 32;\\nuint32 constant CANNOT_APPROVE = 64;\\n//uint16 reserved for parent controlled fuses from bit 17 to bit 32\\nuint32 constant PARENT_CANNOT_CONTROL = 1 << 16;\\nuint32 constant IS_DOT_ETH = 1 << 17;\\nuint32 constant CAN_EXTEND_EXPIRY = 1 << 18;\\nuint32 constant CAN_DO_EVERYTHING = 0;\\nuint32 constant PARENT_CONTROLLED_FUSES = 0xFFFF0000;\\n// all fuses apart from IS_DOT_ETH\\nuint32 constant USER_SETTABLE_FUSES = 0xFFFDFFFF;\\n\\ninterface INameWrapper is IERC1155 {\\n event NameWrapped(\\n bytes32 indexed node,\\n bytes name,\\n address owner,\\n uint32 fuses,\\n uint64 expiry\\n );\\n\\n event NameUnwrapped(bytes32 indexed node, address owner);\\n\\n event FusesSet(bytes32 indexed node, uint32 fuses);\\n event ExpiryExtended(bytes32 indexed node, uint64 expiry);\\n\\n function ens() external view returns (ENS);\\n\\n function registrar() external view returns (IBaseRegistrar);\\n\\n function metadataService() external view returns (IMetadataService);\\n\\n function names(bytes32) external view returns (bytes memory);\\n\\n function name() external view returns (string memory);\\n\\n function upgradeContract() external view returns (INameWrapperUpgrade);\\n\\n function supportsInterface(bytes4 interfaceID) external view returns (bool);\\n\\n function wrap(\\n bytes calldata name,\\n address wrappedOwner,\\n address resolver\\n ) external;\\n\\n function wrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint16 ownerControlledFuses,\\n address resolver\\n ) external returns (uint64 expires);\\n\\n function registerAndWrapETH2LD(\\n string calldata label,\\n address wrappedOwner,\\n uint256 duration,\\n address resolver,\\n uint16 ownerControlledFuses\\n ) external returns (uint256 registrarExpiry);\\n\\n function renew(\\n uint256 labelHash,\\n uint256 duration\\n ) external returns (uint256 expires);\\n\\n function unwrap(bytes32 node, bytes32 label, address owner) external;\\n\\n function unwrapETH2LD(\\n bytes32 label,\\n address newRegistrant,\\n address newController\\n ) external;\\n\\n function upgrade(bytes calldata name, bytes calldata extraData) external;\\n\\n function setFuses(\\n bytes32 node,\\n uint16 ownerControlledFuses\\n ) external returns (uint32 newFuses);\\n\\n function setChildFuses(\\n bytes32 parentNode,\\n bytes32 labelhash,\\n uint32 fuses,\\n uint64 expiry\\n ) external;\\n\\n function setSubnodeRecord(\\n bytes32 node,\\n string calldata label,\\n address owner,\\n address resolver,\\n uint64 ttl,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function setRecord(\\n bytes32 node,\\n address owner,\\n address resolver,\\n uint64 ttl\\n ) external;\\n\\n function setSubnodeOwner(\\n bytes32 node,\\n string calldata label,\\n address newOwner,\\n uint32 fuses,\\n uint64 expiry\\n ) external returns (bytes32);\\n\\n function extendExpiry(\\n bytes32 node,\\n bytes32 labelhash,\\n uint64 expiry\\n ) external returns (uint64);\\n\\n function canModifyName(\\n bytes32 node,\\n address addr\\n ) external view returns (bool);\\n\\n function setResolver(bytes32 node, address resolver) external;\\n\\n function setTTL(bytes32 node, uint64 ttl) external;\\n\\n function ownerOf(uint256 id) external view returns (address owner);\\n\\n function approve(address to, uint256 tokenId) external;\\n\\n function getApproved(uint256 tokenId) external view returns (address);\\n\\n function getData(\\n uint256 id\\n ) external view returns (address, uint32, uint64);\\n\\n function setMetadataService(IMetadataService _metadataService) external;\\n\\n function uri(uint256 tokenId) external view returns (string memory);\\n\\n function setUpgradeContract(INameWrapperUpgrade _upgradeAddress) external;\\n\\n function allFusesBurned(\\n bytes32 node,\\n uint32 fuseMask\\n ) external view returns (bool);\\n\\n function isWrapped(bytes32) external view returns (bool);\\n\\n function isWrapped(bytes32, bytes32) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ~0.8.17;\\n\\ninterface INameWrapperUpgrade {\\n function wrapFromUpgrade(\\n bytes calldata name,\\n address wrappedOwner,\\n uint32 fuses,\\n uint64 expiry,\\n address approved,\\n bytes calldata extraData\\n ) external;\\n}\\n\",\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\\n *\\n * _Available since v3.1._\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the caller.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * Emits a {TransferBatch} event.\\n *\\n * Requirements:\\n *\\n * - `ids` and `amounts` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata amounts,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-v4/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\"},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Context} from \\\"../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 * The initial owner is set to the address provided by the deployer. This can\\n * 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 /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n constructor(address initialOwner) {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\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 if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling 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 if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\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\",\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"./IERC20.sol\\\";\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @title IERC1363\\n * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].\\n *\\n * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract\\n * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.\\n */\\ninterface IERC1363 is IERC20, IERC165 {\\n /*\\n * Note: the ERC-165 identifier for this interface is 0xb0202a11.\\n * 0xb0202a11 ===\\n * bytes4(keccak256('transferAndCall(address,uint256)')) ^\\n * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^\\n * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256)')) ^\\n * bytes4(keccak256('approveAndCall(address,uint256,bytes)'))\\n */\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from the caller's account to `to`\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism\\n * and then calls {IERC1363Receiver-onTransferReceived} on `to`.\\n * @param from The address which you want to send tokens from.\\n * @param to The address which you want to transfer to.\\n * @param value The amount of tokens to be transferred.\\n * @param data Additional data with no specified format, sent in call to `to`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value) external returns (bool);\\n\\n /**\\n * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\\n * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.\\n * @param spender The address which will spend the funds.\\n * @param value The amount of tokens to be spent.\\n * @param data Additional data with no specified format, sent in call to `spender`.\\n * @return A boolean value indicating whether the operation succeeded unless throwing.\\n */\\n function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../utils/introspection/IERC165.sol\\\";\\n\",\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../token/ERC20/IERC20.sol\\\";\\n\",\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-20 standard as defined in the ERC.\\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 value of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the value of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\\n * 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 value) external returns (bool);\\n\\n /**\\n * @dev Moves a `value` amount of tokens from `from` to `to` using the\\n * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\\n}\\n\",\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC20} from \\\"../IERC20.sol\\\";\\nimport {IERC1363} from \\\"../../../interfaces/IERC1363.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC-20 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 /**\\n * @dev An operation with an ERC-20 token failed.\\n */\\n error SafeERC20FailedOperation(address token);\\n\\n /**\\n * @dev Indicates a failed `decreaseAllowance` request.\\n */\\n error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));\\n }\\n\\n /**\\n * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.\\n */\\n function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {\\n return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n forceApprove(token, spender, oldAllowance + value);\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no\\n * value, non-reverting calls are assumed to be successful.\\n *\\n * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the \\\"client\\\"\\n * smart contract uses ERC-7674 to set temporary allowances, then the \\\"client\\\" smart contract should avoid using\\n * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract\\n * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {\\n unchecked {\\n uint256 currentAllowance = token.allowance(address(this), spender);\\n if (currentAllowance < requestedDecrease) {\\n revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);\\n }\\n forceApprove(token, spender, currentAllowance - requestedDecrease);\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n *\\n * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function\\n * only sets the \\\"standard\\\" allowance. Any temporary allowance will remain active, in addition to the value being\\n * set here.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n safeTransfer(token, to, value);\\n } else if (!token.transferAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target\\n * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function transferFromAndCallRelaxed(\\n IERC1363 token,\\n address from,\\n address to,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length == 0) {\\n safeTransferFrom(token, from, to, value);\\n } else if (!token.transferFromAndCall(from, to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\n }\\n\\n /**\\n * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no\\n * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when\\n * targeting contracts.\\n *\\n * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.\\n * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}\\n * once without retrying, and relies on the returned value to be true.\\n *\\n * Reverts if the returned value is other than `true`.\\n */\\n function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {\\n if (to.code.length == 0) {\\n forceApprove(token, to, value);\\n } else if (!token.approveAndCall(to, value, data)) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n // bubble errors\\n if iszero(success) {\\n let ptr := mload(0x40)\\n returndatacopy(ptr, 0, returndatasize())\\n revert(ptr, returndatasize())\\n }\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n\\n if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {\\n revert SafeERC20FailedOperation(address(token));\\n }\\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 * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n bool success;\\n uint256 returnSize;\\n uint256 returnValue;\\n assembly (\\\"memory-safe\\\") {\\n success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)\\n returnSize := returndatasize()\\n returnValue := mload(0)\\n }\\n return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);\\n }\\n}\\n\",\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @title ERC-721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC-721 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\\n * 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\":\"0xb5afb8e8eebc4d1c6404df2f5e1e6d2c3d24fd01e5dfc855314951ecfaae462d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\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 function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/migration/AbstractWrapperReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {ENS} from \\\"@ens/contracts/registry/ENS.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {IERC1155Receiver} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\nimport {ERC165, IERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {UnauthorizedCaller} from \\\"../CommonErrors.sol\\\";\\nimport {WrappedErrorLib} from \\\"../utils/WrappedErrorLib.sol\\\";\\n\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title AbstractWrapperReceiver\\n/// @dev Abstract IERC1155Receiver which handles NameWrapper token migration via transfer.\\n///\\n/// NameWrapper only allows `Error(string)` exceptions during transfer and squelches typed errors.\\n/// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L317-L335\\n/// This contract, with the aid of WrappedErrorLib, embeds errors that occur during migration into `Error(string)`.\\n///\\n/// There are (2) AbstractWrapperReceiver implementations:\\n/// 1. UnlockedMigrationController accepts unlocked tokens.\\n/// 2. LockedWrapperReceiver accepts locked tokens.\\n///\\n/// `LibMigration.isLocked()` determines lock status.\\n///\\nabstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\\n INameWrapper public immutable NAME_WRAPPER;\\n\\n /// @notice The ENSv1 `BaseRegistrar` token graveyard.\\n address public immutable GRAVEYARD;\\n\\n /// @dev The ENSv1 `ENSRegistry` contract.\\n ENS internal immutable _REGISTRY_V1;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Restrict `msg.sender` to NameWrapper.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier onlyWrapper() {\\n if (msg.sender != address(NAME_WRAPPER)) {\\n WrappedErrorLib.wrapAndRevert(\\n abi.encodeWithSelector(UnauthorizedCaller.selector, msg.sender)\\n );\\n }\\n _;\\n }\\n\\n /// @dev Avoid `abi.decode()` failure for obviously invalid data.\\n /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler.\\n modifier withData(bytes calldata data, uint256 minimumSize) {\\n if (data.length < minimumSize) {\\n WrappedErrorLib.wrapAndRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector));\\n }\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n constructor(INameWrapper nameWrapper, address graveyard) {\\n NAME_WRAPPER = nameWrapper;\\n GRAVEYARD = graveyard;\\n _REGISTRY_V1 = nameWrapper.ens();\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate one NameWrapper token via `safeTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param id The NameWrapper token ID (namehash) of the name being migrated.\\n /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters.\\n function onERC1155Received(\\n address /*operator*/,\\n address /*from*/,\\n uint256 id,\\n uint256 /*amount*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (amount != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L293\\n uint256[] memory ids = new uint256[](1);\\n LibMigration.Data[] memory mds = new LibMigration.Data[](1);\\n ids[0] = id;\\n mds[0] = abi.decode(data, (LibMigration.Data)); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155Received.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @inheritdoc IERC1155Receiver\\n /// @notice Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\\n /// @dev Only callable by NameWrapper.\\n /// Reverts require `WrappedErrorLib.unwrap()` before processing.\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param data ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\\n function onERC1155BatchReceived(\\n address /*operator*/,\\n address /*from*/,\\n uint256[] calldata ids,\\n uint256[] calldata /*amounts*/,\\n bytes calldata data\\n )\\n external\\n onlyWrapper\\n withData(data, 64 + ids.length * LibMigration.MIN_DATA_SIZE)\\n returns (bytes4)\\n {\\n // if (ids.length != amounts.length) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L162\\n // if (amounts[i] != 1) { ... } => never happens :: caught by ERC1155Fuse\\n // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L182\\n LibMigration.Data[] memory mds = abi.decode(data, (LibMigration.Data[])); // reverts if invalid\\n try this.finishERC1155Migration(ids, mds) {\\n return this.onERC1155BatchReceived.selector;\\n } catch (bytes memory reason) {\\n WrappedErrorLib.wrapAndRevert(reason); // convert all errors to wrapped\\n }\\n }\\n\\n /// @notice Convert NameWrapper tokens to their equivalent ENSv2 form.\\n /// @dev Only callable by ourself and invoked by our `IERC1155Receiver` handlers.\\n ///\\n /// TODO: gas analysis and optimization\\n /// NOTE: converting this to an internal call requires catching many reverts\\n ///\\n /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated.\\n /// @param mds The migration parameters for each name, indexed in parallel with `ids`.\\n function finishERC1155Migration(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n external\\n {\\n if (msg.sender != address(this)) {\\n revert UnauthorizedCaller(msg.sender);\\n }\\n if (ids.length != mds.length) {\\n revert IERC1155Errors.ERC1155InvalidArrayLength(ids.length, mds.length);\\n }\\n _migrateWrapped(ids, mds);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Migrate received NameWrapper tokens.\\n /// Token owner is this contract.\\n /// Token is not expired.\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n virtual;\\n}\\n\",\"keccak256\":\"0x0c15f9f657ba58bf5081cbff88c385c9e673ba87aed2032397ec2c5448d7fe1a\",\"license\":\"MIT\"},\"project/src/migration/UnlockedMigrationController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IBaseRegistrar} from \\\"@ens/contracts/ethregistrar/IBaseRegistrar.sol\\\";\\nimport {NameCoder} from \\\"@ens/contracts/utils/NameCoder.sol\\\";\\nimport {INameWrapper} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\nimport {InvalidOwner, UnauthorizedCaller} from \\\"../CommonErrors.sol\\\";\\nimport {REGISTRATION_ROLE_BITMAP} from \\\"../registrar/ETHRegistrar.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {DelegatedContractNamer} from \\\"../utils/DelegatedContractNamer.sol\\\";\\n\\nimport {AbstractWrapperReceiver} from \\\"./AbstractWrapperReceiver.sol\\\";\\nimport {LibMigration} from \\\"./libraries/LibMigration.sol\\\";\\n\\n/// @title UnlockedMigrationController\\n/// @notice Migration controller for handling unwrapped and unlocked .eth names.\\n///\\n/// Assumes premigration has `RESERVED` existing ENSv1 names.\\n/// Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration.\\n///\\n/// Supports (2) token sources:\\n/// 1. NameWrapper (ERC-1155) but unlocked only.\\n/// Reverts with `NameIsWrapped` if `LibMigration.isLocked()` => use LockedMigrationController instead.\\n/// 2. BaseRegistrar (ERC-721)\\n///\\n/// Unlike locked migration, no subregistry is deployed and no fuse-to-role translation is\\n/// performed. The name is registered in the .eth registry with the roles and subregistry\\n/// specified in the caller-provided `LibMigration.Data`.\\n///\\ncontract UnlockedMigrationController is\\n AbstractWrapperReceiver,\\n IERC721Receiver,\\n DelegatedContractNamer\\n{\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @dev The ENSv1 `BaseRegistrar` contract.\\n IBaseRegistrar internal immutable _BASE_REGISTRAR;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param nameWrapper The ENSv1 `NameWrapper` contract.\\n /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard.\\n /// @param ethRegistry The ENSv2 .eth `PermissionedRegistry` where migrated names are registered.\\n /// @param contractNamer Delegated contract namer.\\n constructor(\\n INameWrapper nameWrapper,\\n address graveyard,\\n IPermissionedRegistry ethRegistry,\\n IContractNamer contractNamer\\n )\\n AbstractWrapperReceiver(nameWrapper, graveyard)\\n DelegatedContractNamer(contractNamer)\\n {\\n ETH_REGISTRY = ethRegistry;\\n _BASE_REGISTRAR = nameWrapper.registrar();\\n }\\n\\n /// @inheritdoc DelegatedContractNamer\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(AbstractWrapperReceiver, DelegatedContractNamer)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC721Receiver).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Receives an unwrapped .eth name via ERC721 `safeTransferFrom` from the `BaseRegistrar`.\\n /// Decodes a single `LibMigration.Data` from `data` and registers the equivalent name in ENSv2.\\n /// @param {operator} Ignored.\\n /// @param {from} Ignored.\\n /// @param tokenId The BaseRegistrar token ID (labelhash) of the name being migrated.\\n /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters.\\n /// @return The selector of the `onERC721Received` function.\\n function onERC721Received(\\n address /*operator*/,\\n address /*from*/,\\n uint256 tokenId,\\n bytes calldata data\\n )\\n external\\n returns (bytes4)\\n {\\n if (msg.sender != address(_BASE_REGISTRAR)) {\\n revert UnauthorizedCaller(msg.sender);\\n }\\n if (data.length < LibMigration.MIN_DATA_SIZE) {\\n revert LibMigration.InvalidData();\\n }\\n LibMigration.Data memory md = abi.decode(data, (LibMigration.Data)); // reverts if invalid\\n if (tokenId != uint256(keccak256(bytes(md.label)))) {\\n revert LibMigration.NameDataMismatch(tokenId);\\n }\\n _BASE_REGISTRAR.reclaim(tokenId, address(this));\\n _REGISTRY_V1.setRecord(\\n NameCoder.namehash(NameCoder.ETH_NODE, bytes32(tokenId)),\\n GRAVEYARD, // transfer ownership to graveyard\\n address(0), // clear ENSv1 resolver\\n 0\\n );\\n _BASE_REGISTRAR.safeTransferFrom(address(this), GRAVEYARD, tokenId); // transfer token to graveyard\\n _inject(md);\\n return this.onERC721Received.selector;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc AbstractWrapperReceiver\\n /// @dev Reverts `NameIsLocked` if any token is locked.\\n /// Reverts `NameDataMismatch` if any token is mislabeled.\\n /// @param ids The NameWrapper token IDs (namehash) of the names to migrate.\\n /// @param mds The migration parameters for each name, indexed in parallel with `ids`.\\n function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds)\\n internal\\n override\\n {\\n for (uint256 i; i < ids.length; ++i) {\\n uint256 id = ids[i];\\n (, uint32 fuses, ) = NAME_WRAPPER.getData(id);\\n if (LibMigration.isLocked(fuses)) {\\n revert LibMigration.NameIsLocked(id);\\n }\\n bytes32 labelHash = keccak256(bytes(mds[i].label));\\n if (bytes32(id) != NameCoder.namehash(NameCoder.ETH_NODE, labelHash)) {\\n revert LibMigration.NameDataMismatch(id);\\n }\\n NAME_WRAPPER.setResolver(bytes32(id), address(0)); // clear ENSv1 resolver\\n NAME_WRAPPER.unwrapETH2LD(labelHash, GRAVEYARD, GRAVEYARD); // unwrap and transfer to graveyard\\n _inject(mds[i]);\\n }\\n }\\n\\n /// @dev Claim premigrated reservation.\\n function _inject(LibMigration.Data memory md) internal {\\n if (md.owner == address(0)) {\\n revert InvalidOwner();\\n }\\n // Register the name in the ETH registry\\n ETH_REGISTRY.register(\\n md.label,\\n md.owner,\\n md.subregistry,\\n md.resolver,\\n REGISTRATION_ROLE_BITMAP,\\n 0 // use reserved expiry\\n ); // reverts if not RESERVED\\n }\\n}\\n\",\"keccak256\":\"0x0045c5fc93efc668307847e587fc6c4d889309d6b5459d256c85a6fd6d0adca3\",\"license\":\"MIT\"},\"project/src/migration/libraries/LibMigration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {\\n CANNOT_BURN_FUSES,\\n CANNOT_UNWRAP,\\n IS_DOT_ETH,\\n PARENT_CANNOT_CONTROL\\n} from \\\"@ens/contracts/wrapper/INameWrapper.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\n/// @dev Primitives for migration.\\nlibrary LibMigration {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Typed arguments for migration via transfer payload.\\n struct Data {\\n /// @dev Subdomain being migrated.\\n string label;\\n /// @dev Address that will own the name in the v2 registry.\\n address owner;\\n /// @dev Address of the child registry.\\n /// Ignored by locked migration.\\n IRegistry subregistry;\\n /// @dev Resolver address to set for the migrated name.\\n /// Ignored if locked and `CANNOT_SET_RESOLVER`.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Minimum size of `abi.encode(Data({...}))`.\\n uint256 internal constant MIN_DATA_SIZE = 7 * 32;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Name cannot be registered because unmigrated NameWrapper token exists.\\n /// @dev Error selector: `0x408fa1b8`\\n error NameRequiresMigration();\\n\\n /// @notice NameWrapper token is unlocked.\\n /// @dev Error selector: `0x1bfe8f0a`\\n error NameNotLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper token is locked.\\n /// @dev Error selector: `0xe7c290e2`\\n error NameIsLocked(uint256 tokenId);\\n\\n /// @notice NameWrapper or BaseRegistrar token does not match supplied data.\\n /// @dev Error selector: `0xedec3569`\\n error NameDataMismatch(uint256 tokenId);\\n\\n /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\\n /// @dev Error selector: `0xa4f07713`\\n error FrozenTokenApproval(uint256 tokenId);\\n\\n /// @notice The encoded data is invalid.\\n /// @dev Error selector: `0x5cb045db`\\n error InvalidData();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns `true` if the NameWrapper token is locked.\\n function isLocked(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient\\n // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()`\\n return (fuses & CANNOT_UNWRAP) != 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token fuses are not frozen.\\n function notFrozen(uint32 fuses) internal pure returns (bool) {\\n return (fuses & CANNOT_BURN_FUSES) == 0;\\n }\\n\\n /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth.\\n function isEmancipatedChild(uint32 fuses) internal pure returns (bool) {\\n // PARENT_CANNOT_CONTROL must be set for the entire ancestory.\\n // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()`\\n return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL;\\n }\\n}\\n\",\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\"},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {Ownable} from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`.\\nabstract contract AbstractETHRegistrar is Ownable, ERC165, IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants & Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Minimum renew duration, in seconds.\\n uint64 public constant MIN_RENEW_DURATION = 1;\\n\\n /// @notice ENSv2 .eth `PermissionedRegistry`.\\n IPermissionedRegistry public immutable ETH_REGISTRY;\\n\\n /// @notice Address that receives payments.\\n address public immutable BENEFICIARY;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Oracle for registration and renewal costs.\\n IRentPriceOracle public rentPriceOracle;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `IRentPriceOracle` was replaced.\\n /// @param oracle The new `IRentPriceOracle` contract.\\n event RentPriceOracleUpdated(IRentPriceOracle oracle);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n constructor(\\n address owner_,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle\\n )\\n Ownable(owner_)\\n {\\n ETH_REGISTRY = ethRegistry;\\n BENEFICIARY = beneficiary;\\n\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Change the rent price oracle.\\n /// @param oracle The new `IRentPriceOracle` instance.\\n function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner {\\n rentPriceOracle = oracle;\\n emit RentPriceOracleUpdated(oracle);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external\\n {\\n IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not\\n uint64 newExpiry = state.expiry + duration; // reverts if overflow\\n uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, amount); // reverts if payment failed\\n ETH_REGISTRY.renew(state.tokenId, newExpiry);\\n _onRenew(label, duration);\\n emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount);\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function isRenewable(string calldata label) external view returns (bool) {\\n return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n public\\n view\\n returns (uint256)\\n {\\n return\\n rentPriceOracle.getRenewPrice(\\n label,\\n _requireRenewable(label, duration).expiry,\\n duration,\\n paymentToken\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Callback for when a name is renewed.\\n function _onRenew(string calldata label, uint64 duration) internal virtual {}\\n\\n /// @dev Returns whether the name is renewable by this contract.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n virtual\\n returns (bool);\\n\\n /// @dev Ensure name is renewable.\\n function _requireRenewable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isRenewable(state)) {\\n revert NameNotRenewable(label);\\n }\\n if (duration < MIN_RENEW_DURATION) {\\n revert DurationTooShort(duration, MIN_RENEW_DURATION);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x03c6381eaa4b6f36c842a32396b8f9a5a573a4257d7a9d263e77c015486a9458\",\"license\":\"MIT\"},\"project/src/registrar/ETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {SafeERC20, IERC20} from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {IPermissionedRegistry} from \\\"../registry/interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"../registry/interfaces/IRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"../registry/libraries/RegistryRolesLib.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {AbstractETHRegistrar} from \\\"./AbstractETHRegistrar.sol\\\";\\nimport {IETHRegistrar} from \\\"./interfaces/IETHRegistrar.sol\\\";\\nimport {IETHRenewer} from \\\"./interfaces/IETHRenewer.sol\\\";\\nimport {IRentPriceOracle} from \\\"./interfaces/IRentPriceOracle.sol\\\";\\n\\n/// @dev Roles assigned to owners at registration. Includes set-subregistry, set-resolver, and can-transfer (with admin variants).\\nuint256 constant REGISTRATION_ROLE_BITMAP =\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY |\\n RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN |\\n RegistryRolesLib.ROLE_SET_RESOLVER |\\n RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN |\\n RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN;\\n\\n/// @notice Commit-reveal registrar for .eth names. Registration requires two transactions: first\\n/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment\\n/// age but before the maximum commitment age has elapsed. The commitment hash binds all\\n/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer)\\n/// to prevent front-running.\\n///\\n/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed\\n/// set of roles (set subregistry, set resolver, and transfer \\u2014 each with their admin\\n/// counterpart).\\n///\\n/// Pricing and payment are delegated to a swappable `IRentPriceOracle`.\\n///\\ncontract ETHRegistrar is AbstractETHRegistrar, IETHRegistrar {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRenewer\\n uint64 public immutable GRACE_PERIOD;\\n\\n /// @notice Minimum seconds a commitment must age before registration can proceed.\\n /// @dev If zero, front-running protection is disabled.\\n uint64 public immutable MIN_COMMITMENT_AGE;\\n\\n /// @notice Maximum seconds a commitment remains valid; expired commitments are rejected.\\n uint64 public immutable MAX_COMMITMENT_AGE;\\n\\n /// @notice Minimum register duration, in seconds.\\n uint64 public immutable MIN_REGISTER_DURATION;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n mapping(bytes32 commitment => uint64 commitTime) public commitmentAt;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`.\\n /// @dev Error selector: `0x3e5aa838`\\n error MaxCommitmentAgeTooLow();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param owner_ Contract owner.\\n /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`.\\n /// @param beneficiary Address that receives payments.\\n /// @param oracle Initial oracle for registration and renewal costs.\\n /// @param gracePeriod Post-expiry period where still renewable and not available, in seconds.\\n /// @param minCommitmentAge Minimum seconds a commitment must age before registration can proceed.\\n /// @param maxCommitmentAge Maximum seconds a commitment remains valid; expired commitments are rejected.\\n /// @param minRegisterDuration Minimum register duration, in seconds.\\n constructor(\\n address owner_,\\n IPermissionedRegistry ethRegistry,\\n address beneficiary,\\n IRentPriceOracle oracle,\\n uint64 gracePeriod,\\n uint64 minCommitmentAge,\\n uint64 maxCommitmentAge,\\n uint64 minRegisterDuration\\n )\\n AbstractETHRegistrar(owner_, ethRegistry, beneficiary, oracle)\\n {\\n if (maxCommitmentAge <= minCommitmentAge) {\\n revert MaxCommitmentAgeTooLow();\\n }\\n GRACE_PERIOD = gracePeriod;\\n MIN_COMMITMENT_AGE = minCommitmentAge;\\n MAX_COMMITMENT_AGE = maxCommitmentAge;\\n MIN_REGISTER_DURATION = minRegisterDuration;\\n }\\n\\n /// @inheritdoc AbstractETHRegistrar\\n function supportsInterface(bytes4 interfaceId) public view override returns (bool) {\\n return\\n interfaceId == type(IETHRegistrar).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IETHRegistrar\\n function commit(bytes32 commitment) external {\\n if (commitmentAt[commitment] + MAX_COMMITMENT_AGE > block.timestamp) {\\n revert UnexpiredCommitmentExists(commitment);\\n }\\n commitmentAt[commitment] = uint64(block.timestamp);\\n emit CommitmentMade(commitment);\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function register(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256 tokenId)\\n {\\n if (owner == address(0)) {\\n revert InvalidOwner();\\n }\\n _consumeCommitment(\\n makeCommitment(label, owner, secret, subregistry, resolver, duration, referrer)\\n ); // reverts if no commitment\\n IPermissionedRegistry.State memory state = _requireAvailable(label, duration); // reverts if not\\n (uint256 base, uint256 premium) =\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(state.expiry),\\n duration,\\n paymentToken\\n ); // reverts if invalid\\n SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, base + premium); // reverts if payment failed\\n tokenId = ETH_REGISTRY.register(\\n label,\\n owner,\\n subregistry,\\n resolver,\\n REGISTRATION_ROLE_BITMAP,\\n uint64(block.timestamp) + duration // new expiry\\n ); // should not revert\\n emit NameRegistered(\\n tokenId,\\n label,\\n owner,\\n subregistry,\\n resolver,\\n duration,\\n paymentToken,\\n referrer,\\n base,\\n premium\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function isAvailable(string calldata label) external view returns (bool) {\\n return _isAvailable(ETH_REGISTRY.getState(LibLabel.id(label)));\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium)\\n {\\n return\\n rentPriceOracle.getRegisterPrice(\\n label,\\n _availablePeriod(_requireAvailable(label, duration).expiry),\\n duration,\\n paymentToken\\n );\\n }\\n\\n /// @inheritdoc IETHRenewer\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64) {\\n IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label));\\n return\\n uint64(\\n _isRenewableGrace(state)\\n ? GRACE_PERIOD - (block.timestamp - state.expiry)\\n : 0\\n );\\n }\\n\\n /// @inheritdoc IETHRegistrar\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n public\\n pure\\n override\\n returns (bytes32)\\n {\\n return\\n keccak256(abi.encode(label, owner, secret, subregistry, resolver, duration, referrer));\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates that the given `commitment` was recorded within the allowed time window\\n /// (between minimum and maximum commitment age), then deletes it so it cannot be reused.\\n /// @param commitment The commitment hash to validate and consume.\\n function _consumeCommitment(bytes32 commitment) internal {\\n uint64 t = uint64(block.timestamp);\\n uint64 t0 = commitmentAt[commitment];\\n uint64 tMin = t0 + MIN_COMMITMENT_AGE;\\n if (t < tMin) {\\n revert CommitmentTooNew(commitment, tMin, t);\\n }\\n uint64 tMax = t0 + MAX_COMMITMENT_AGE;\\n if (t >= tMax) {\\n revert CommitmentTooOld(commitment, tMax, t);\\n }\\n delete commitmentAt[commitment];\\n }\\n\\n /// @dev Ensure name is registerable.\\n function _requireAvailable(string calldata label, uint64 duration)\\n internal\\n view\\n returns (IPermissionedRegistry.State memory state)\\n {\\n state = ETH_REGISTRY.getState(LibLabel.id(label));\\n if (!_isAvailable(state)) {\\n revert NameNotAvailable(label);\\n }\\n if (duration < MIN_REGISTER_DURATION) {\\n revert DurationTooShort(duration, MIN_REGISTER_DURATION);\\n }\\n }\\n\\n /// @dev Determine if `AVAILABLE` and not in grace.\\n function _isAvailable(IPermissionedRegistry.State memory state) internal view returns (bool) {\\n return _checkGrace(state, false);\\n }\\n\\n /// @dev Determine if `REGISTERED` or in grace was `REGISTERED`.\\n function _isRenewable(IPermissionedRegistry.State memory state)\\n internal\\n view\\n override\\n returns (bool)\\n {\\n return state.status == IPermissionedRegistry.Status.REGISTERED || _isRenewableGrace(state);\\n }\\n\\n /// @dev Determine if was `REGISTERED` and in grace.\\n function _isRenewableGrace(IPermissionedRegistry.State memory state)\\n internal\\n view\\n returns (bool)\\n {\\n return state.latestOwner != address(0) && _checkGrace(state, true);\\n }\\n\\n /// @dev Check if `AVAILABLE` and conditionally in grace.\\n function _checkGrace(IPermissionedRegistry.State memory state, bool grace)\\n internal\\n view\\n returns (bool)\\n {\\n return\\n state.status == IPermissionedRegistry.Status.AVAILABLE &&\\n (grace == (block.timestamp - state.expiry) < GRACE_PERIOD);\\n }\\n\\n /// @dev Determine duration name has been available.\\n function _availablePeriod(uint64 expiry) internal view returns (uint64) {\\n uint64 t = uint64(block.timestamp);\\n if (expiry == 0) {\\n return t; // never registered\\n }\\n expiry += GRACE_PERIOD;\\n return t > expiry ? t - expiry : 0;\\n }\\n}\\n\",\"keccak256\":\"0x601a5929b1b2eba60dd566dd6967c3dba1a471d6b24ffe292f4aa660af1cd5f1\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRegistrar.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IRegistry} from \\\"../../registry/interfaces/IRegistry.sol\\\";\\n\\nimport {IETHRenewer} from \\\"./IETHRenewer.sol\\\";\\n\\n/// @notice Interface for registering \\\".eth\\\" names.\\n/// @dev Interface selector: `0xc1401b80`\\ninterface IETHRegistrar is IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` was recorded onchain at `block.timestamp`.\\n /// @param commitment The commitment hash from `makeCommitment()`.\\n event CommitmentMade(bytes32 commitment);\\n\\n /// @notice A name was registered.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the registration.\\n /// @param owner The owner address.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param base The amount of `paymentToken` for the registration.\\n /// @param premium The amount of `paymentToken` due to premium.\\n event NameRegistered(\\n uint256 indexed tokenId,\\n string label,\\n address owner,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 base,\\n uint256 premium\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `commitment` is still usable for registration.\\n /// @dev Error selector: `0x0a059d71`\\n error UnexpiredCommitmentExists(bytes32 commitment);\\n\\n /// @notice `commitment` cannot be consumed yet.\\n /// @dev Error selector: `0x6be614e3`\\n error CommitmentTooNew(bytes32 commitment, uint64 validFrom, uint64 blockTimestamp);\\n\\n /// @notice `commitment` has expired.\\n /// @dev Error selector: `0x0cb9df3f`\\n error CommitmentTooOld(bytes32 commitment, uint64 validTo, uint64 blockTimestamp);\\n\\n /// @notice `label` cannot be registered.\\n /// @dev Error selector: `0x477707e8`\\n error NameNotAvailable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registration step #1: record intent to register without revealing any information.\\n /// @dev Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`.\\n /// @param commitment The commitment hash.\\n function commit(bytes32 commitment) external;\\n\\n /// @notice Register a name.\\n /// @param label The name from commitment.\\n /// @param owner The owner from commitment.\\n /// @param secret The secret from commitment.\\n /// @param subregistry The registry from commitment.\\n /// @param resolver The resolver from commitment.\\n /// @param duration The registration from commitment.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @return The registered token ID.\\n function register(\\n string memory label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n IERC20 paymentToken,\\n bytes32 referrer\\n )\\n external\\n returns (uint256);\\n\\n /// @notice Get timestamp of a prior commitment.\\n /// @param commitment The commitment hash.\\n /// @return The commitment time, in seconds, or 0 if unknown.\\n function commitmentAt(bytes32 commitment) external view returns (uint64);\\n\\n /// @notice Determine register price for a name.\\n /// @param label The name to register.\\n /// @param duration The registration duration, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Check if name is available.\\n /// @param label The name to check.\\n /// @return `true` if registerable.\\n function isAvailable(string memory label) external view returns (bool);\\n\\n /// @notice Compute hash of registration parameters.\\n /// @param label The name to register.\\n /// @param owner The owner address.\\n /// @param secret The secret for the registration.\\n /// @param subregistry The initial registry address.\\n /// @param resolver The initial resolver address.\\n /// @param duration The registration duration, in seconds.\\n /// @param referrer The referrer hash.\\n /// @return The commitment hash.\\n function makeCommitment(\\n string calldata label,\\n address owner,\\n bytes32 secret,\\n IRegistry subregistry,\\n address resolver,\\n uint64 duration,\\n bytes32 referrer\\n )\\n external\\n pure\\n returns (bytes32);\\n}\\n\",\"keccak256\":\"0x7e824c5019f8eb7d7a283451700234716353e01d649c811b5ced5cf58b476289\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for renewing \\\".eth\\\" names.\\n/// @dev Interface selector: `0x06aaeb32`\\ninterface IETHRenewer {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice A name was extended by `duration`.\\n /// @param tokenId The registry token id.\\n /// @param label The name of the renewal.\\n /// @param duration The duration extension, in seconds.\\n /// @param newExpiry The new expiry, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n /// @param amount The amount of `paymentToken`.\\n event NameRenewed(\\n uint256 indexed tokenId,\\n string label,\\n uint64 duration,\\n uint64 newExpiry,\\n IERC20 paymentToken,\\n bytes32 indexed referrer,\\n uint256 amount\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `duration` less than `minDuration`.\\n /// @dev Error selector: `0xa096b844`\\n error DurationTooShort(uint64 duration, uint64 minDuration);\\n\\n /// @notice `label` cannot be renewed.\\n /// @dev Error selector: `0x1caefaa0`\\n error NameNotRenewable(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Renew a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @param referrer The referrer hash.\\n function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer)\\n external;\\n\\n /// @notice Determine renew price for a name.\\n /// @param label The name to renew.\\n /// @param duration The duration extension, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice Check if name is renewable.\\n /// @param label The name to check.\\n /// @return `true` if renewable.\\n function isRenewable(string calldata label) external view returns (bool);\\n\\n /// @notice Determine remaining grace period.\\n /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`.\\n /// @param label The name to check.\\n /// @return The remaining grace period, in seconds.\\n function getRemainingGracePeriod(string calldata label) external view returns (uint64);\\n\\n /// @notice Post-expiry period where still renewable and not available, in seconds.\\n function GRACE_PERIOD() external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\"},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/// @notice Interface for pricing registration and renewals.\\n/// @dev Interface selector: `0xdb06fc00`\\ninterface IRentPriceOracle {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice `label` is not valid.\\n /// @dev Error selector: `0xdbfa2886`\\n error NotValid(string label);\\n\\n /// @notice `paymentToken` is not supported for payment.\\n /// @dev Error selector: `0x02e2ae9e`\\n error PaymentTokenNotSupported(IERC20 paymentToken);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Determine registration price for `label`.\\n /// @param label The name to price.\\n /// @param available The duration the name has been available, in seconds.\\n /// @param duration The duration to register for, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return base The amount of `paymentToken` for the registration.\\n /// @return premium The amount of `paymentToken` due to premium.\\n function getRegisterPrice(\\n string calldata label,\\n uint64 available,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256 base, uint256 premium);\\n\\n /// @notice Determine renewal price for `label`.\\n /// @param label The name to price.\\n /// @param expiry The current expiry, in seconds.\\n /// @param duration The extension to price, in seconds.\\n /// @param paymentToken The payment token.\\n /// @return The amount of `paymentToken`.\\n function getRenewPrice(\\n string calldata label,\\n uint64 expiry,\\n uint64 duration,\\n IERC20 paymentToken\\n )\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 39: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 62: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x01771816c1c5b16c10f29b33083dbd1cc2eb64dbfec60fb45a1a1969cec06624\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/DelegatedContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\n/// @dev Mixin for delegated contract naming. \\nabstract contract DelegatedContractNamer is ERC165, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Delegated contract namer.\\n IContractNamer public immutable CONTRACT_NAMER;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param contractNamer Delegated contract namer.\\n constructor(IContractNamer contractNamer) {\\n CONTRACT_NAMER = contractNamer;\\n }\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) external view returns (bool) {\\n return CONTRACT_NAMER.isContractNamer(namer);\\n }\\n}\\n\",\"keccak256\":\"0xee94197bc054092f1d867d85b738a041b3f2d56ba0d30efe1533220f24309988\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/WrappedErrorLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.24;\\n\\nimport {HexUtils} from \\\"@ens/contracts/utils/HexUtils.sol\\\";\\n\\n/// @dev Library to wrap and unwrap typed error data inside of `Error(string)`.\\n/// Uses hex to embed arbitrary data and avoid invalid unicode.\\nlibrary WrappedErrorLib {\\n /// @dev Error selector for `Error(string)`.\\n bytes4 internal constant ERROR_STRING_SELECTOR = 0x08c379a0;\\n\\n /// @dev The detectable human-readable error prefix.\\n /// Must be exactly 16 bytes.\\n bytes16 internal constant WRAPPED_ERROR_PREFIX = \\\"WrappedError::0x\\\";\\n\\n /// @dev Wrap an error and then revert.\\n function wrapAndRevert(bytes memory err) internal pure {\\n err = wrap(err);\\n assembly {\\n revert(add(err, 32), mload(err))\\n }\\n }\\n\\n /// @dev Embed a typed error into `Error(string)`.\\n /// Does nothing if already `Error(string)`.\\n /// For detection, `WRAPPED_ERROR_PREFIX` is leading bytes the error string.\\n function wrap(bytes memory err) internal pure returns (bytes memory) {\\n if (err.length > 0 && bytes4(err) != ERROR_STRING_SELECTOR) {\\n // assert((err.length & 31) == 4);\\n err = abi.encodeWithSelector(\\n ERROR_STRING_SELECTOR,\\n abi.encodePacked(WRAPPED_ERROR_PREFIX, HexUtils.bytesToHex(err))\\n );\\n }\\n return err;\\n }\\n\\n /// @dev Unwrap a typed error from `Error(string)`.\\n /// Does nothing if detection and extracton fails.\\n /// @param err The error data to unwrap.\\n /// @return The unwrapped error data, or unmodified if not wrapped.\\n function unwrap(bytes memory err) internal pure returns (bytes memory) {\\n if (bytes4(err) == ERROR_STRING_SELECTOR) {\\n bytes memory v;\\n assembly {\\n v := add(err, 4) // skip selector\\n }\\n v = abi.decode(v, (bytes));\\n if (bytes16(v) == WRAPPED_ERROR_PREFIX) {\\n (bytes memory inner, bool ok) = HexUtils.hexToBytes(v, 16, v.length);\\n if (ok) {\\n return inner;\\n }\\n }\\n }\\n return err;\\n }\\n}\\n\",\"keccak256\":\"0xf92862b6509cf553bd542925617318a2509bfdc6457e8b5d102c8e9658c610e4\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "errors": { + "InvalidData()": [ + { + "notice": "The encoded data is invalid." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "NameDataMismatch(uint256)": [ + { + "notice": "NameWrapper or BaseRegistrar token does not match supplied data." + } + ], + "NameIsLocked(uint256)": [ + { + "notice": "NameWrapper token is locked." + } + ], + "UnauthorizedCaller(address)": [ + { + "notice": "Thrown when a caller is not authorized to perform the requested operation" + } + ] + }, + "kind": "user", + "methods": { + "CONTRACT_NAMER()": { + "notice": "Delegated contract namer." + }, + "ETH_REGISTRY()": { + "notice": "The ENSv2 .eth `PermissionedRegistry` where migrated names are registered." + }, + "GRAVEYARD()": { + "notice": "The ENSv1 `BaseRegistrar` token graveyard." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens." + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "notice": "Convert NameWrapper tokens to their equivalent ENSv2 form." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "notice": "Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "notice": "Migrate one NameWrapper token via `safeTransferFrom()`." + }, + "onERC721Received(address,address,uint256,bytes)": { + "notice": "Receives an unwrapped .eth name via ERC721 `safeTransferFrom` from the `BaseRegistrar`. Decodes a single `LibMigration.Data` from `data` and registers the equivalent name in ENSv2." + } + }, + "notice": "Migration controller for handling unwrapped and unlocked .eth names. Assumes premigration has `RESERVED` existing ENSv1 names. Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration. Supports (2) token sources: 1. NameWrapper (ERC-1155) but unlocked only. Reverts with `NameIsWrapped` if `LibMigration.isLocked()` => use LockedMigrationController instead. 2. BaseRegistrar (ERC-721) Unlike locked migration, no subregistry is deployed and no fuse-to-role translation is performed. The name is registered in the .eth registry with the roles and subregistry specified in the caller-provided `LibMigration.Data`.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce80000000000000000000000006f4bf58ac55e0018589b2d9734ed8bb82740124d00000000000000000000000067b728a792e789a8978b30cf1b3b641f19354b4300000000000000000000000068658a771044873906fc9b6e9f278ac5a0501342", + "transaction": { + "hash": "0x93fc2878e1507c09ab995ffb5b636422a098dca1e2b3e31c5368130d8c20bcd6", + "nonce": "0x55", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x5cb2a1f335d1a6d2dcc5497c3a8e3573dee890da3c7fb8d579baaa09451aa02b", + "blockNumber": "0xaa5709", + "transactionIndex": "0x68" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/UpgradableUniversalResolverProxy.json b/contracts/deployments/sepolia/UpgradableUniversalResolverProxy.json new file mode 100644 index 000000000..5db20ed9d --- /dev/null +++ b/contracts/deployments/sepolia/UpgradableUniversalResolverProxy.json @@ -0,0 +1,7245 @@ +{ + "address": "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe", + "argsData": "0x", + "contractName": "UpgradableUniversalResolverProxy", + "sourceName": "src/universalResolver/UpgradableUniversalResolverProxy.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CallerNotAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidImplementation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "string[]", + "name": "urls", + "type": "string[]" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "bytes4", + "name": "callbackFunction", + "type": "bytes4" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "OffchainLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "OffsetOutOfBoundsError", + "type": "error" + }, + { + "inputs": [], + "name": "SameImplementation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "AdminRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f80fd5b50604051610c26380380610c2683398101604081905261002e9161019b565b6100378161006e565b5f80516020610c0683398151915280546001600160a01b0319166001600160a01b038316179055610067826100e6565b50506101cc565b6001600160a01b038116158061008c57506001600160a01b0381163b155b156100aa5760405163340aafcd60e11b815260040160405180910390fd5b6001600160a01b0381166100bc61014d565b6001600160a01b0316036100e357604051634c3b76bf60e01b815260040160405180910390fd5b50565b5f6100ef61016c565b9050815f80516020610be683398151915280546001600160a01b0319166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b5f5f80516020610c068339815191525b546001600160a01b0316919050565b5f5f80516020610be683398151915261015d565b80516001600160a01b0381168114610196575f80fd5b919050565b5f80604083850312156101ac575f80fd5b6101b583610180565b91506101c360208401610180565b90509250929050565b610a0d806101d95f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f806100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610693565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106da565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079a565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107b5565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610889565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109c4565b6105a4565b6104308361041d83856109c4565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b5f815160208301516001600160e01b0319808216935060048310156106775780818460040360031b1b83161693505b505050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106a6576106a661067f565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a015f5b8281101561073f5760bf1988870301845261072d8683516106ac565b95509284019290840190600101610711565b5050505050828103604084015261075681876106ac565b6001600160e01b0319861660608501529050828103608084015261077a81856106ac565b98975050505050505050565b6001600160a01b038116811461051a575f80fd5b5f602082840312156107aa575f80fd5b813561024481610786565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f2576107f26107b5565b604052919050565b5f67ffffffffffffffff831115610813576108136107b5565b610826601f8401601f19166020016107c9565b9050828152838383011115610839575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261085e575f80fd5b610244838351602085016107fa565b80516001600160e01b031981168114610884575f80fd5b919050565b5f805f805f60a0868803121561089d575f80fd5b85516108a881610786565b8095505060208087015167ffffffffffffffff808211156108c7575f80fd5b818901915089601f8301126108da575f80fd5b8151818111156108ec576108ec6107b5565b8060051b6108fb8582016107c9565b918252838101850191858101908d841115610914575f80fd5b86860192505b8383101561096157825185811115610930575f80fd5b8601603f81018f13610940575f80fd5b6109518f89830151604084016107fa565b835250918601919086019061091a565b60408d0151909a5095505050508083111561097a575f80fd5b6109868a848b0161084f565b955061099460608a0161086d565b945060808901519250808311156109a9575f80fd5b50506109b78882890161084f565b9150509295509295909350565b808201808211156106a6576106a661067f56fea2646970667358221220b497e606fddd22fd3bdcf262866dcd9d2d07fa9e7b15191a16b45ee0405c434e64736f6c63430008190033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f806100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610693565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106da565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079a565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107b5565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610889565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109c4565b6105a4565b6104308361041d83856109c4565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b5f815160208301516001600160e01b0319808216935060048310156106775780818460040360031b1b83161693505b505050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106a6576106a661067f565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a015f5b8281101561073f5760bf1988870301845261072d8683516106ac565b95509284019290840190600101610711565b5050505050828103604084015261075681876106ac565b6001600160e01b0319861660608501529050828103608084015261077a81856106ac565b98975050505050505050565b6001600160a01b038116811461051a575f80fd5b5f602082840312156107aa575f80fd5b813561024481610786565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f2576107f26107b5565b604052919050565b5f67ffffffffffffffff831115610813576108136107b5565b610826601f8401601f19166020016107c9565b9050828152838383011115610839575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261085e575f80fd5b610244838351602085016107fa565b80516001600160e01b031981168114610884575f80fd5b919050565b5f805f805f60a0868803121561089d575f80fd5b85516108a881610786565b8095505060208087015167ffffffffffffffff808211156108c7575f80fd5b818901915089601f8301126108da575f80fd5b8151818111156108ec576108ec6107b5565b8060051b6108fb8582016107c9565b918252838101850191858101908d841115610914575f80fd5b86860192505b8383101561096157825185811115610930575f80fd5b8601603f81018f13610940575f80fd5b6109518f89830151604084016107fa565b835250918601919086019061091a565b60408d0151909a5095505050508083111561097a575f80fd5b6109868a848b0161084f565b955061099460608a0161086d565b945060808901519250808311156109a9575f80fd5b50506109b78882890161084f565b9150509295509295909350565b808201808211156106a6576106a661067f56fea2646970667358221220b497e606fddd22fd3bdcf262866dcd9d2d07fa9e7b15191a16b45ee0405c434e64736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": {}, + "inputSourceName": "project/src/universalResolver/UpgradableUniversalResolverProxy.sol", + "devdoc": { + "errors": { + "CallerNotAdmin()": [ + { + "details": "Error selector: `0x06d919f2`" + } + ], + "InvalidImplementation()": [ + { + "details": "Error selector: `0x68155f9a`" + } + ], + "OffchainLookup(address,string[],bytes,bytes4,bytes)": [ + { + "details": "https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`" + } + ], + "OffsetOutOfBoundsError(uint256,uint256)": [ + { + "details": "`offset` was beyond `length`. Error selector: `0x8a3c1cfb`" + } + ], + "SameImplementation()": [ + { + "details": "Error selector: `0x4c3b76bf`" + } + ] + }, + "events": { + "AdminChanged(address,address)": { + "params": { + "newAdmin": "The new admin address", + "previousAdmin": "The previous admin address" + } + }, + "AdminRemoved(address)": { + "params": { + "admin": "The admin address that was removed" + } + }, + "Upgraded(address)": { + "params": { + "implementation": "The new implementation address" + } + } + }, + "kind": "dev", + "methods": { + "constructor": { + "params": { + "admin_": "The address of the admin", + "implementation_": "The address of the implementation" + } + }, + "upgradeTo(address)": { + "params": { + "newImplementation": "Address of the new implementation" + } + } + }, + "stateVariables": { + "_ADMIN_SLOT": { + "details": "Storage slot for admin (EIP-1967 compatible)" + }, + "_IMPLEMENTATION_SLOT": { + "details": "Storage slot for implementation address (EIP-1967 compatible)" + } + }, + "title": "UpgradableUniversalResolverProxy", + "version": 1 + }, + "evm": { + "bytecode": { + "functionDebugData": { + "@_74300": { + "entryPoint": null, + "id": 74300, + "parameterSlots": 2, + "returnSlots": 0 + }, + "@_getAdmin_74497": { + "entryPoint": 364, + "id": 74497, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_getImplementation_74484": { + "entryPoint": 333, + "id": 74484, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_setAdmin_74539": { + "entryPoint": 230, + "id": 74539, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_setImplementation_74513": { + "entryPoint": null, + "id": 74513, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_validateImplementation_74471": { + "entryPoint": 110, + "id": 74471, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@getAddressSlot_44365": { + "entryPoint": null, + "id": 44365, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_address_fromMemory": { + "entryPoint": 384, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_tuple_t_addresst_address_fromMemory": { + "entryPoint": 411, + "id": null, + "parameterSlots": 2, + "returnSlots": 2 + } + }, + "generatedSources": [ + { + "ast": { + "nativeSrc": "0:491:381", + "nodeType": "YulBlock", + "src": "0:491:381", + "statements": [ + { + "nativeSrc": "6:3:381", + "nodeType": "YulBlock", + "src": "6:3:381", + "statements": [] + }, + { + "body": { + "nativeSrc": "74:117:381", + "nodeType": "YulBlock", + "src": "74:117:381", + "statements": [ + { + "nativeSrc": "84:22:381", + "nodeType": "YulAssignment", + "src": "84:22:381", + "value": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "99:6:381", + "nodeType": "YulIdentifier", + "src": "99:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "93:5:381", + "nodeType": "YulIdentifier", + "src": "93:5:381" + }, + "nativeSrc": "93:13:381", + "nodeType": "YulFunctionCall", + "src": "93:13:381" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "84:5:381", + "nodeType": "YulIdentifier", + "src": "84:5:381" + } + ] + }, + { + "body": { + "nativeSrc": "169:16:381", + "nodeType": "YulBlock", + "src": "169:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "178:1:381", + "nodeType": "YulLiteral", + "src": "178:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "181:1:381", + "nodeType": "YulLiteral", + "src": "181:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "171:6:381", + "nodeType": "YulIdentifier", + "src": "171:6:381" + }, + "nativeSrc": "171:12:381", + "nodeType": "YulFunctionCall", + "src": "171:12:381" + }, + "nativeSrc": "171:12:381", + "nodeType": "YulExpressionStatement", + "src": "171:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "128:5:381", + "nodeType": "YulIdentifier", + "src": "128:5:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "139:5:381", + "nodeType": "YulIdentifier", + "src": "139:5:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "154:3:381", + "nodeType": "YulLiteral", + "src": "154:3:381", + "type": "", + "value": "160" + }, + { + "kind": "number", + "nativeSrc": "159:1:381", + "nodeType": "YulLiteral", + "src": "159:1:381", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "150:3:381", + "nodeType": "YulIdentifier", + "src": "150:3:381" + }, + "nativeSrc": "150:11:381", + "nodeType": "YulFunctionCall", + "src": "150:11:381" + }, + { + "kind": "number", + "nativeSrc": "163:1:381", + "nodeType": "YulLiteral", + "src": "163:1:381", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "146:3:381", + "nodeType": "YulIdentifier", + "src": "146:3:381" + }, + "nativeSrc": "146:19:381", + "nodeType": "YulFunctionCall", + "src": "146:19:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "135:3:381", + "nodeType": "YulIdentifier", + "src": "135:3:381" + }, + "nativeSrc": "135:31:381", + "nodeType": "YulFunctionCall", + "src": "135:31:381" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "125:2:381", + "nodeType": "YulIdentifier", + "src": "125:2:381" + }, + "nativeSrc": "125:42:381", + "nodeType": "YulFunctionCall", + "src": "125:42:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "118:6:381", + "nodeType": "YulIdentifier", + "src": "118:6:381" + }, + "nativeSrc": "118:50:381", + "nodeType": "YulFunctionCall", + "src": "118:50:381" + }, + "nativeSrc": "115:70:381", + "nodeType": "YulIf", + "src": "115:70:381" + } + ] + }, + "name": "abi_decode_address_fromMemory", + "nativeSrc": "14:177:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "53:6:381", + "nodeType": "YulTypedName", + "src": "53:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "64:5:381", + "nodeType": "YulTypedName", + "src": "64:5:381", + "type": "" + } + ], + "src": "14:177:381" + }, + { + "body": { + "nativeSrc": "294:195:381", + "nodeType": "YulBlock", + "src": "294:195:381", + "statements": [ + { + "body": { + "nativeSrc": "340:16:381", + "nodeType": "YulBlock", + "src": "340:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "349:1:381", + "nodeType": "YulLiteral", + "src": "349:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "352:1:381", + "nodeType": "YulLiteral", + "src": "352:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "342:6:381", + "nodeType": "YulIdentifier", + "src": "342:6:381" + }, + "nativeSrc": "342:12:381", + "nodeType": "YulFunctionCall", + "src": "342:12:381" + }, + "nativeSrc": "342:12:381", + "nodeType": "YulExpressionStatement", + "src": "342:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "315:7:381", + "nodeType": "YulIdentifier", + "src": "315:7:381" + }, + { + "name": "headStart", + "nativeSrc": "324:9:381", + "nodeType": "YulIdentifier", + "src": "324:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "311:3:381", + "nodeType": "YulIdentifier", + "src": "311:3:381" + }, + "nativeSrc": "311:23:381", + "nodeType": "YulFunctionCall", + "src": "311:23:381" + }, + { + "kind": "number", + "nativeSrc": "336:2:381", + "nodeType": "YulLiteral", + "src": "336:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "307:3:381", + "nodeType": "YulIdentifier", + "src": "307:3:381" + }, + "nativeSrc": "307:32:381", + "nodeType": "YulFunctionCall", + "src": "307:32:381" + }, + "nativeSrc": "304:52:381", + "nodeType": "YulIf", + "src": "304:52:381" + }, + { + "nativeSrc": "365:50:381", + "nodeType": "YulAssignment", + "src": "365:50:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "405:9:381", + "nodeType": "YulIdentifier", + "src": "405:9:381" + } + ], + "functionName": { + "name": "abi_decode_address_fromMemory", + "nativeSrc": "375:29:381", + "nodeType": "YulIdentifier", + "src": "375:29:381" + }, + "nativeSrc": "375:40:381", + "nodeType": "YulFunctionCall", + "src": "375:40:381" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "365:6:381", + "nodeType": "YulIdentifier", + "src": "365:6:381" + } + ] + }, + { + "nativeSrc": "424:59:381", + "nodeType": "YulAssignment", + "src": "424:59:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "468:9:381", + "nodeType": "YulIdentifier", + "src": "468:9:381" + }, + { + "kind": "number", + "nativeSrc": "479:2:381", + "nodeType": "YulLiteral", + "src": "479:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "464:3:381", + "nodeType": "YulIdentifier", + "src": "464:3:381" + }, + "nativeSrc": "464:18:381", + "nodeType": "YulFunctionCall", + "src": "464:18:381" + } + ], + "functionName": { + "name": "abi_decode_address_fromMemory", + "nativeSrc": "434:29:381", + "nodeType": "YulIdentifier", + "src": "434:29:381" + }, + "nativeSrc": "434:49:381", + "nodeType": "YulFunctionCall", + "src": "434:49:381" + }, + "variableNames": [ + { + "name": "value1", + "nativeSrc": "424:6:381", + "nodeType": "YulIdentifier", + "src": "424:6:381" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_addresst_address_fromMemory", + "nativeSrc": "196:293:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "252:9:381", + "nodeType": "YulTypedName", + "src": "252:9:381", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "263:7:381", + "nodeType": "YulTypedName", + "src": "263:7:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "275:6:381", + "nodeType": "YulTypedName", + "src": "275:6:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "283:6:381", + "nodeType": "YulTypedName", + "src": "283:6:381", + "type": "" + } + ], + "src": "196:293:381" + } + ] + }, + "contents": "{\n { }\n function abi_decode_address_fromMemory(offset) -> value\n {\n value := mload(offset)\n if iszero(eq(value, and(value, sub(shl(160, 1), 1)))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_addresst_address_fromMemory(headStart, dataEnd) -> value0, value1\n {\n if slt(sub(dataEnd, headStart), 64) { revert(0, 0) }\n value0 := abi_decode_address_fromMemory(headStart)\n value1 := abi_decode_address_fromMemory(add(headStart, 32))\n }\n}", + "id": 381, + "language": "Yul", + "name": "#utility.yul" + } + ], + "linkReferences": {}, + "object": "608060405234801561000f575f80fd5b50604051610c26380380610c2683398101604081905261002e9161019b565b6100378161006e565b5f80516020610c0683398151915280546001600160a01b0319166001600160a01b038316179055610067826100e6565b50506101cc565b6001600160a01b038116158061008c57506001600160a01b0381163b155b156100aa5760405163340aafcd60e11b815260040160405180910390fd5b6001600160a01b0381166100bc61014d565b6001600160a01b0316036100e357604051634c3b76bf60e01b815260040160405180910390fd5b50565b5f6100ef61016c565b9050815f80516020610be683398151915280546001600160a01b0319166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b5f5f80516020610c068339815191525b546001600160a01b0316919050565b5f5f80516020610be683398151915261015d565b80516001600160a01b0381168114610196575f80fd5b919050565b5f80604083850312156101ac575f80fd5b6101b583610180565b91506101c360208401610180565b90509250929050565b610a0d806101d95f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f806100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610693565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106da565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079a565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107b5565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610889565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109c4565b6105a4565b6104308361041d83856109c4565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b5f815160208301516001600160e01b0319808216935060048310156106775780818460040360031b1b83161693505b505050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106a6576106a661067f565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a015f5b8281101561073f5760bf1988870301845261072d8683516106ac565b95509284019290840190600101610711565b5050505050828103604084015261075681876106ac565b6001600160e01b0319861660608501529050828103608084015261077a81856106ac565b98975050505050505050565b6001600160a01b038116811461051a575f80fd5b5f602082840312156107aa575f80fd5b813561024481610786565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f2576107f26107b5565b604052919050565b5f67ffffffffffffffff831115610813576108136107b5565b610826601f8401601f19166020016107c9565b9050828152838383011115610839575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261085e575f80fd5b610244838351602085016107fa565b80516001600160e01b031981168114610884575f80fd5b919050565b5f805f805f60a0868803121561089d575f80fd5b85516108a881610786565b8095505060208087015167ffffffffffffffff808211156108c7575f80fd5b818901915089601f8301126108da575f80fd5b8151818111156108ec576108ec6107b5565b8060051b6108fb8582016107c9565b918252838101850191858101908d841115610914575f80fd5b86860192505b8383101561096157825185811115610930575f80fd5b8601603f81018f13610940575f80fd5b6109518f89830151604084016107fa565b835250918601919086019061091a565b60408d0151909a5095505050508083111561097a575f80fd5b6109868a848b0161084f565b955061099460608a0161086d565b945060808901519250808311156109a9575f80fd5b50506109b78882890161084f565b9150509295509295909350565b808201808211156106a6576106a661067f56fea2646970667358221220b497e606fddd22fd3bdcf262866dcd9d2d07fa9e7b15191a16b45ee0405c434e64736f6c63430008190033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH2 0xC26 CODESIZE SUB DUP1 PUSH2 0xC26 DUP4 CODECOPY DUP2 ADD PUSH1 0x40 DUP2 SWAP1 MSTORE PUSH2 0x2E SWAP2 PUSH2 0x19B JUMP JUMPDEST PUSH2 0x37 DUP2 PUSH2 0x6E JUMP JUMPDEST PUSH0 DUP1 MLOAD PUSH1 0x20 PUSH2 0xC06 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP1 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH2 0x67 DUP3 PUSH2 0xE6 JUMP JUMPDEST POP POP PUSH2 0x1CC JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x8C JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0xAA JUMPI PUSH1 0x40 MLOAD PUSH4 0x340AAFCD PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND PUSH2 0xBC PUSH2 0x14D JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0xE3 JUMPI PUSH1 0x40 MLOAD PUSH4 0x4C3B76BF PUSH1 0xE0 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0xEF PUSH2 0x16C JUMP JUMPDEST SWAP1 POP DUP2 PUSH0 DUP1 MLOAD PUSH1 0x20 PUSH2 0xBE6 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE DUP1 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST PUSH0 PUSH0 DUP1 MLOAD PUSH1 0x20 PUSH2 0xC06 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH0 DUP1 MLOAD PUSH1 0x20 PUSH2 0xBE6 DUP4 CODECOPY DUP2 MLOAD SWAP2 MSTORE PUSH2 0x15D JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x196 JUMPI PUSH0 DUP1 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP1 PUSH1 0x40 DUP4 DUP6 SUB SLT ISZERO PUSH2 0x1AC JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x1B5 DUP4 PUSH2 0x180 JUMP JUMPDEST SWAP2 POP PUSH2 0x1C3 PUSH1 0x20 DUP5 ADD PUSH2 0x180 JUMP JUMPDEST SWAP1 POP SWAP3 POP SWAP3 SWAP1 POP JUMP JUMPDEST PUSH2 0xA0D DUP1 PUSH2 0x1D9 PUSH0 CODECOPY PUSH0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4A JUMPI PUSH0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x3659CFE6 EQ PUSH2 0x176 JUMPI DUP1 PUSH4 0x5C60DA1B EQ PUSH2 0x189 JUMPI DUP1 PUSH4 0x8BAD0C0A EQ PUSH2 0x1AD JUMPI DUP1 PUSH4 0xF851A440 EQ PUSH2 0x1B5 JUMPI JUMPDEST PUSH0 DUP1 PUSH2 0x54 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH0 CALLDATASIZE PUSH1 0x40 MLOAD PUSH2 0x6D SWAP3 SWAP2 SWAP1 PUSH2 0x639 JUMP JUMPDEST PUSH0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 GAS STATICCALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH0 DUP2 EQ PUSH2 0xA5 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0xAA JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 ISZERO DUP1 ISZERO PUSH2 0xD5 JUMPI POP PUSH4 0x556F183 PUSH1 0xE4 SHL PUSH2 0xC9 DUP3 PUSH2 0x648 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND EQ JUMPDEST ISZERO PUSH2 0x15E JUMPI PUSH0 PUSH2 0xFB PUSH2 0xF6 DUP4 PUSH1 0x4 DUP1 DUP7 MLOAD PUSH2 0xF1 SWAP2 SWAP1 PUSH2 0x693 JUMP JUMPDEST PUSH2 0x1EF JUMP JUMPDEST PUSH2 0x24B JUMP JUMPDEST SWAP1 POP PUSH2 0x105 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 PUSH0 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x15C JUMPI ADDRESS DUP2 PUSH1 0x20 ADD MLOAD DUP3 PUSH1 0x40 ADD MLOAD DUP4 PUSH1 0x60 ADD MLOAD DUP5 PUSH1 0x80 ADD MLOAD PUSH1 0x40 MLOAD PUSH4 0x556F183 PUSH1 0xE4 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x153 SWAP6 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x6DA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMPDEST DUP2 ISZERO PUSH2 0x16C JUMPI DUP1 MLOAD PUSH1 0x20 DUP3 ADD RETURN JUMPDEST DUP1 MLOAD PUSH1 0x20 DUP3 ADD REVERT JUMPDEST STOP JUMPDEST PUSH2 0x174 PUSH2 0x184 CALLDATASIZE PUSH1 0x4 PUSH2 0x79A JUMP JUMPDEST PUSH2 0x2B6 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x375 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x174 PUSH2 0x383 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x406 JUMP JUMPDEST PUSH0 PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 DUP2 PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x20A JUMPI PUSH2 0x20A PUSH2 0x7B5 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x1F ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x234 JUMPI PUSH1 0x20 DUP3 ADD DUP2 DUP1 CALLDATASIZE DUP4 CALLDATACOPY ADD SWAP1 POP JUMPDEST POP SWAP1 POP PUSH2 0x244 DUP5 DUP5 DUP4 PUSH0 DUP7 PUSH2 0x40F JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0xA0 DUP2 ADD DUP3 MSTORE PUSH0 DUP1 DUP3 MSTORE PUSH1 0x60 PUSH1 0x20 DUP4 ADD DUP2 SWAP1 MSTORE SWAP3 DUP3 ADD DUP4 SWAP1 MSTORE DUP3 DUP3 ADD MSTORE PUSH1 0x80 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP2 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD DUP2 ADD SWAP1 PUSH2 0x288 SWAP2 SWAP1 PUSH2 0x889 JUMP JUMPDEST PUSH1 0x80 DUP7 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND PUSH1 0x60 DUP6 ADD MSTORE PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x20 DUP4 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x2BE PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x2EF JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0x2F8 DUP2 PUSH2 0x473 JUMP JUMPDEST PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xBC7CD75A20EE27FD9ADEBAB32041F755214DBC6BFFA90CC0225B39DA2E5C2D3B SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x1BD JUMP JUMPDEST SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x38B PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x3BC JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH0 PUSH2 0x3C5 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP PUSH2 0x3D0 PUSH0 PUSH2 0x51D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xA3B62BC36326052D97EA62D63C3D60308ED4C3EA8AC079DD8499F1E9C4F80C0F SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x44C JUMP JUMPDEST PUSH2 0x422 DUP6 PUSH2 0x41D DUP4 DUP8 PUSH2 0x9C4 JUMP JUMPDEST PUSH2 0x5A4 JUMP JUMPDEST PUSH2 0x430 DUP4 PUSH2 0x41D DUP4 DUP6 PUSH2 0x9C4 JUMP JUMPDEST PUSH2 0x445 DUP3 PUSH1 0x20 DUP6 ADD ADD DUP6 PUSH1 0x20 DUP9 ADD ADD DUP4 PUSH2 0x5F0 JUMP JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH0 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 PUSH2 0x1E0 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x491 JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0x4C8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x68155F9A00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH2 0x4DA PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x51A JUMPI PUSH1 0x40 MLOAD PUSH32 0x4C3B76BF00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0x526 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP DUP2 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST DUP2 MLOAD DUP2 GT ISZERO PUSH2 0x5EC JUMPI DUP2 MLOAD PUSH1 0x40 MLOAD PUSH32 0x8A3C1CFB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x153 SWAP2 DUP4 SWAP2 PUSH1 0x4 ADD SWAP2 DUP3 MSTORE PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST POP POP JUMP JUMPDEST JUMPDEST PUSH1 0x1F DUP2 GT ISZERO PUSH2 0x611 JUMPI DUP2 MLOAD DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1F NOT ADD PUSH2 0x5F1 JUMP JUMPDEST DUP1 ISZERO PUSH2 0x634 JUMPI DUP2 MLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0x20 DUP5 SWAP1 SUB PUSH1 0x3 SHL SHL PUSH0 NOT ADD DUP1 NOT SWAP1 SWAP3 AND SWAP2 AND OR DUP4 MSTORE JUMPDEST POP POP POP JUMP JUMPDEST DUP2 DUP4 DUP3 CALLDATACOPY PUSH0 SWAP2 ADD SWAP1 DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP2 MLOAD PUSH1 0x20 DUP4 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP1 DUP3 AND SWAP4 POP PUSH1 0x4 DUP4 LT ISZERO PUSH2 0x677 JUMPI DUP1 DUP2 DUP5 PUSH1 0x4 SUB PUSH1 0x3 SHL SHL DUP4 AND AND SWAP4 POP JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x11 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST DUP2 DUP2 SUB DUP2 DUP2 GT ISZERO PUSH2 0x6A6 JUMPI PUSH2 0x6A6 PUSH2 0x67F JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 DUP2 MLOAD DUP1 DUP5 MSTORE DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP7 ADD MCOPY PUSH0 PUSH1 0x20 DUP3 DUP7 ADD ADD MSTORE PUSH1 0x20 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 PUSH1 0xA0 DUP3 ADD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP9 AND DUP4 MSTORE PUSH1 0x20 PUSH1 0xA0 PUSH1 0x20 DUP6 ADD MSTORE DUP2 DUP9 MLOAD DUP1 DUP5 MSTORE PUSH1 0xC0 DUP7 ADD SWAP2 POP PUSH1 0xC0 DUP2 PUSH1 0x5 SHL DUP8 ADD ADD SWAP4 POP PUSH1 0x20 DUP11 ADD PUSH0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x73F JUMPI PUSH1 0xBF NOT DUP9 DUP8 SUB ADD DUP5 MSTORE PUSH2 0x72D DUP7 DUP4 MLOAD PUSH2 0x6AC JUMP JUMPDEST SWAP6 POP SWAP3 DUP5 ADD SWAP3 SWAP1 DUP5 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x711 JUMP JUMPDEST POP POP POP POP POP DUP3 DUP2 SUB PUSH1 0x40 DUP5 ADD MSTORE PUSH2 0x756 DUP2 DUP8 PUSH2 0x6AC JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP7 AND PUSH1 0x60 DUP6 ADD MSTORE SWAP1 POP DUP3 DUP2 SUB PUSH1 0x80 DUP5 ADD MSTORE PUSH2 0x77A DUP2 DUP6 PUSH2 0x6AC JUMP JUMPDEST SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x51A JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x7AA JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x244 DUP2 PUSH2 0x786 JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x41 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1F DUP3 ADD PUSH1 0x1F NOT AND DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x7F2 JUMPI PUSH2 0x7F2 PUSH2 0x7B5 JUMP JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH8 0xFFFFFFFFFFFFFFFF DUP4 GT ISZERO PUSH2 0x813 JUMPI PUSH2 0x813 PUSH2 0x7B5 JUMP JUMPDEST PUSH2 0x826 PUSH1 0x1F DUP5 ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD PUSH2 0x7C9 JUMP JUMPDEST SWAP1 POP DUP3 DUP2 MSTORE DUP4 DUP4 DUP4 ADD GT ISZERO PUSH2 0x839 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP3 DUP3 PUSH1 0x20 DUP4 ADD MCOPY PUSH0 PUSH1 0x20 DUP5 DUP4 ADD ADD MSTORE SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x85E JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x244 DUP4 DUP4 MLOAD PUSH1 0x20 DUP6 ADD PUSH2 0x7FA JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP2 AND DUP2 EQ PUSH2 0x884 JUMPI PUSH0 DUP1 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP1 PUSH0 DUP1 PUSH0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0x89D JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP6 MLOAD PUSH2 0x8A8 DUP2 PUSH2 0x786 JUMP JUMPDEST DUP1 SWAP6 POP POP PUSH1 0x20 DUP1 DUP8 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x8C7 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 DUP10 ADD SWAP2 POP DUP10 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x8DA JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 MLOAD DUP2 DUP2 GT ISZERO PUSH2 0x8EC JUMPI PUSH2 0x8EC PUSH2 0x7B5 JUMP JUMPDEST DUP1 PUSH1 0x5 SHL PUSH2 0x8FB DUP6 DUP3 ADD PUSH2 0x7C9 JUMP JUMPDEST SWAP2 DUP3 MSTORE DUP4 DUP2 ADD DUP6 ADD SWAP2 DUP6 DUP2 ADD SWAP1 DUP14 DUP5 GT ISZERO PUSH2 0x914 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP7 DUP7 ADD SWAP3 POP JUMPDEST DUP4 DUP4 LT ISZERO PUSH2 0x961 JUMPI DUP3 MLOAD DUP6 DUP2 GT ISZERO PUSH2 0x930 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP7 ADD PUSH1 0x3F DUP2 ADD DUP16 SGT PUSH2 0x940 JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x951 DUP16 DUP10 DUP4 ADD MLOAD PUSH1 0x40 DUP5 ADD PUSH2 0x7FA JUMP JUMPDEST DUP4 MSTORE POP SWAP2 DUP7 ADD SWAP2 SWAP1 DUP7 ADD SWAP1 PUSH2 0x91A JUMP JUMPDEST PUSH1 0x40 DUP14 ADD MLOAD SWAP1 SWAP11 POP SWAP6 POP POP POP POP DUP1 DUP4 GT ISZERO PUSH2 0x97A JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x986 DUP11 DUP5 DUP12 ADD PUSH2 0x84F JUMP JUMPDEST SWAP6 POP PUSH2 0x994 PUSH1 0x60 DUP11 ADD PUSH2 0x86D JUMP JUMPDEST SWAP5 POP PUSH1 0x80 DUP10 ADD MLOAD SWAP3 POP DUP1 DUP4 GT ISZERO PUSH2 0x9A9 JUMPI PUSH0 DUP1 REVERT JUMPDEST POP POP PUSH2 0x9B7 DUP9 DUP3 DUP10 ADD PUSH2 0x84F JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 POP SWAP3 SWAP6 SWAP1 SWAP4 POP JUMP JUMPDEST DUP1 DUP3 ADD DUP1 DUP3 GT ISZERO PUSH2 0x6A6 JUMPI PUSH2 0x6A6 PUSH2 0x67F JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0xB4 SWAP8 0xE6 MOD REVERT 0xDD 0x22 REVERT EXTCODESIZE 0xDC CALLCODE PUSH3 0x866DCD SWAP14 0x2D SMOD STATICCALL SWAP15 PUSH28 0x15191A16B45EE0405C434E64736F6C63430008190033B53127684A56 DUP12 BALANCE PUSH20 0xAE13B9F8A6016E243E63B6E8EE1178D6A717850B TSTORE PUSH2 0x336 ADDMOD SWAP5 LOG1 EXTCODESIZE LOG1 LOG3 0x21 MOD PUSH8 0xC828492DB98DCA3E KECCAK256 PUSH23 0xCC3735A920A3CA505D382BBC0000000000000000000000 ", + "sourceMap": "490:6212:360:-:0;;;2878:182;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2941:40;2965:15;2941:23;:40::i;:::-;-1:-1:-1;;;;;;;;;;;6350:74:360;;-1:-1:-1;;;;;;6350:74:360;-1:-1:-1;;;;;6350:74:360;;;;;3036:17;3046:6;3036:9;:17::i;:::-;2878:182;;490:6212;;5307:328;-1:-1:-1;;;;;5395:31:360;;;;:69;;-1:-1:-1;;;;;;5430:29:360;;;:34;5395:69;5391:130;;;5487:23;;-1:-1:-1;;;5487:23:360;;;;;;;;;;;5391:130;-1:-1:-1;;;;;5534:41:360;;:20;:18;:20::i;:::-;-1:-1:-1;;;;;5534:41:360;;5530:99;;5598:20;;-1:-1:-1;;;5598:20:360;;;;;;;;;;;5530:99;5307:328;:::o;6485:215::-;6540:21;6564:11;:9;:11::i;:::-;6540:35;-1:-1:-1;6633:8:360;-1:-1:-1;;;;;;;;;;;6585:56:360;;-1:-1:-1;;;;;;6585:56:360;-1:-1:-1;;;;;6585:56:360;;;;;;6656:37;;;;;;;;;;;-1:-1:-1;;6656:37:360;6530:170;6485:215;:::o;5708:140::-;5761:7;-1:-1:-1;;;;;;;;;;;5787:48:360;:54;-1:-1:-1;;;;;5787:54:360;;5708:140;-1:-1:-1;5708:140:360:o;5912:122::-;5956:7;-1:-1:-1;;;;;;;;;;;5982:39:360;1899:163:257;14:177:381;93:13;;-1:-1:-1;;;;;135:31:381;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:293::-;275:6;283;336:2;324:9;315:7;311:23;307:32;304:52;;;352:1;349;342:12;304:52;375:40;405:9;375:40;:::i;:::-;365:50;;434:49;479:2;468:9;464:18;434:49;:::i;:::-;424:59;;196:293;;;;;:::o;:::-;490:6212:360;;;;;;" + }, + "deployedBytecode": { + "functionDebugData": { + "@_74374": { + "entryPoint": null, + "id": 74374, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@_checkBound_20014": { + "entryPoint": 1444, + "id": 20014, + "parameterSlots": 2, + "returnSlots": 0 + }, + "@_getAdmin_74497": { + "entryPoint": 1100, + "id": 74497, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_getImplementation_74484": { + "entryPoint": 445, + "id": 74484, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@_setAdmin_74539": { + "entryPoint": 1309, + "id": 74539, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_setImplementation_74513": { + "entryPoint": null, + "id": 74513, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@_validateImplementation_74471": { + "entryPoint": 1139, + "id": 74471, + "parameterSlots": 1, + "returnSlots": 0 + }, + "@admin_74438": { + "entryPoint": 1030, + "id": 74438, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@copyBytes_20513": { + "entryPoint": 1039, + "id": 20513, + "parameterSlots": 5, + "returnSlots": 0 + }, + "@copy_21720": { + "entryPoint": 1520, + "id": 21720, + "parameterSlots": 3, + "returnSlots": 0 + }, + "@decode_1541": { + "entryPoint": 587, + "id": 1541, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@getAddressSlot_44365": { + "entryPoint": null, + "id": 44365, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@implementation_74428": { + "entryPoint": 885, + "id": 74428, + "parameterSlots": 0, + "returnSlots": 1 + }, + "@ptr_21730": { + "entryPoint": null, + "id": 21730, + "parameterSlots": 1, + "returnSlots": 1 + }, + "@renounceAdmin_74418": { + "entryPoint": 899, + "id": 74418, + "parameterSlots": 0, + "returnSlots": 0 + }, + "@substring_20541": { + "entryPoint": 495, + "id": 20541, + "parameterSlots": 3, + "returnSlots": 1 + }, + "@upgradeTo_74395": { + "entryPoint": 694, + "id": 74395, + "parameterSlots": 1, + "returnSlots": 0 + }, + "abi_decode_available_length_string_fromMemory": { + "entryPoint": 2042, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "abi_decode_bytes4_fromMemory": { + "entryPoint": 2157, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "abi_decode_bytes_fromMemory": { + "entryPoint": 2127, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_decode_tuple_t_address": { + "entryPoint": 1946, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory": { + "entryPoint": 2185, + "id": null, + "parameterSlots": 2, + "returnSlots": 5 + }, + "abi_encode_bytes4": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 0 + }, + "abi_encode_string": { + "entryPoint": 1708, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed": { + "entryPoint": 1593, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "abi_encode_tuple_t_address__to_t_address__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed": { + "entryPoint": 1754, + "id": null, + "parameterSlots": 6, + "returnSlots": 1 + }, + "abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed": { + "entryPoint": null, + "id": null, + "parameterSlots": 3, + "returnSlots": 1 + }, + "allocate_memory": { + "entryPoint": 1993, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "checked_add_t_uint256": { + "entryPoint": 2500, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "checked_sub_t_uint256": { + "entryPoint": 1683, + "id": null, + "parameterSlots": 2, + "returnSlots": 1 + }, + "convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4": { + "entryPoint": 1608, + "id": null, + "parameterSlots": 1, + "returnSlots": 1 + }, + "panic_error_0x11": { + "entryPoint": 1663, + "id": null, + "parameterSlots": 0, + "returnSlots": 0 + }, + "panic_error_0x41": { + "entryPoint": 1973, + "id": null, + "parameterSlots": 0, + "returnSlots": 0 + }, + "validator_revert_address": { + "entryPoint": 1926, + "id": null, + "parameterSlots": 1, + "returnSlots": 0 + } + }, + "generatedSources": [ + { + "ast": { + "nativeSrc": "0:7012:381", + "nodeType": "YulBlock", + "src": "0:7012:381", + "statements": [ + { + "nativeSrc": "6:3:381", + "nodeType": "YulBlock", + "src": "6:3:381", + "statements": [] + }, + { + "body": { + "nativeSrc": "161:124:381", + "nodeType": "YulBlock", + "src": "161:124:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "184:3:381", + "nodeType": "YulIdentifier", + "src": "184:3:381" + }, + { + "name": "value0", + "nativeSrc": "189:6:381", + "nodeType": "YulIdentifier", + "src": "189:6:381" + }, + { + "name": "value1", + "nativeSrc": "197:6:381", + "nodeType": "YulIdentifier", + "src": "197:6:381" + } + ], + "functionName": { + "name": "calldatacopy", + "nativeSrc": "171:12:381", + "nodeType": "YulIdentifier", + "src": "171:12:381" + }, + "nativeSrc": "171:33:381", + "nodeType": "YulFunctionCall", + "src": "171:33:381" + }, + "nativeSrc": "171:33:381", + "nodeType": "YulExpressionStatement", + "src": "171:33:381" + }, + { + "nativeSrc": "213:26:381", + "nodeType": "YulVariableDeclaration", + "src": "213:26:381", + "value": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "227:3:381", + "nodeType": "YulIdentifier", + "src": "227:3:381" + }, + { + "name": "value1", + "nativeSrc": "232:6:381", + "nodeType": "YulIdentifier", + "src": "232:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "223:3:381", + "nodeType": "YulIdentifier", + "src": "223:3:381" + }, + "nativeSrc": "223:16:381", + "nodeType": "YulFunctionCall", + "src": "223:16:381" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "217:2:381", + "nodeType": "YulTypedName", + "src": "217:2:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "255:2:381", + "nodeType": "YulIdentifier", + "src": "255:2:381" + }, + { + "kind": "number", + "nativeSrc": "259:1:381", + "nodeType": "YulLiteral", + "src": "259:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "248:6:381", + "nodeType": "YulIdentifier", + "src": "248:6:381" + }, + "nativeSrc": "248:13:381", + "nodeType": "YulFunctionCall", + "src": "248:13:381" + }, + "nativeSrc": "248:13:381", + "nodeType": "YulExpressionStatement", + "src": "248:13:381" + }, + { + "nativeSrc": "270:9:381", + "nodeType": "YulAssignment", + "src": "270:9:381", + "value": { + "name": "_1", + "nativeSrc": "277:2:381", + "nodeType": "YulIdentifier", + "src": "277:2:381" + }, + "variableNames": [ + { + "name": "end", + "nativeSrc": "270:3:381", + "nodeType": "YulIdentifier", + "src": "270:3:381" + } + ] + } + ] + }, + "name": "abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed", + "nativeSrc": "14:271:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "pos", + "nativeSrc": "129:3:381", + "nodeType": "YulTypedName", + "src": "129:3:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "134:6:381", + "nodeType": "YulTypedName", + "src": "134:6:381", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "142:6:381", + "nodeType": "YulTypedName", + "src": "142:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "end", + "nativeSrc": "153:3:381", + "nodeType": "YulTypedName", + "src": "153:3:381", + "type": "" + } + ], + "src": "14:271:381" + }, + { + "body": { + "nativeSrc": "383:314:381", + "nodeType": "YulBlock", + "src": "383:314:381", + "statements": [ + { + "nativeSrc": "393:26:381", + "nodeType": "YulVariableDeclaration", + "src": "393:26:381", + "value": { + "arguments": [ + { + "name": "array", + "nativeSrc": "413:5:381", + "nodeType": "YulIdentifier", + "src": "413:5:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "407:5:381", + "nodeType": "YulIdentifier", + "src": "407:5:381" + }, + "nativeSrc": "407:12:381", + "nodeType": "YulFunctionCall", + "src": "407:12:381" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "397:6:381", + "nodeType": "YulTypedName", + "src": "397:6:381", + "type": "" + } + ] + }, + { + "nativeSrc": "428:33:381", + "nodeType": "YulVariableDeclaration", + "src": "428:33:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "448:5:381", + "nodeType": "YulIdentifier", + "src": "448:5:381" + }, + { + "kind": "number", + "nativeSrc": "455:4:381", + "nodeType": "YulLiteral", + "src": "455:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "444:3:381", + "nodeType": "YulIdentifier", + "src": "444:3:381" + }, + "nativeSrc": "444:16:381", + "nodeType": "YulFunctionCall", + "src": "444:16:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "438:5:381", + "nodeType": "YulIdentifier", + "src": "438:5:381" + }, + "nativeSrc": "438:23:381", + "nodeType": "YulFunctionCall", + "src": "438:23:381" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "432:2:381", + "nodeType": "YulTypedName", + "src": "432:2:381", + "type": "" + } + ] + }, + { + "nativeSrc": "470:76:381", + "nodeType": "YulVariableDeclaration", + "src": "470:76:381", + "value": { + "kind": "number", + "nativeSrc": "480:66:381", + "nodeType": "YulLiteral", + "src": "480:66:381", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + }, + "variables": [ + { + "name": "_2", + "nativeSrc": "474:2:381", + "nodeType": "YulTypedName", + "src": "474:2:381", + "type": "" + } + ] + }, + { + "nativeSrc": "555:20:381", + "nodeType": "YulAssignment", + "src": "555:20:381", + "value": { + "arguments": [ + { + "name": "_1", + "nativeSrc": "568:2:381", + "nodeType": "YulIdentifier", + "src": "568:2:381" + }, + { + "name": "_2", + "nativeSrc": "572:2:381", + "nodeType": "YulIdentifier", + "src": "572:2:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "564:3:381", + "nodeType": "YulIdentifier", + "src": "564:3:381" + }, + "nativeSrc": "564:11:381", + "nodeType": "YulFunctionCall", + "src": "564:11:381" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "555:5:381", + "nodeType": "YulIdentifier", + "src": "555:5:381" + } + ] + }, + { + "body": { + "nativeSrc": "609:82:381", + "nodeType": "YulBlock", + "src": "609:82:381", + "statements": [ + { + "nativeSrc": "623:58:381", + "nodeType": "YulAssignment", + "src": "623:58:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_1", + "nativeSrc": "640:2:381", + "nodeType": "YulIdentifier", + "src": "640:2:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "652:1:381", + "nodeType": "YulLiteral", + "src": "652:1:381", + "type": "", + "value": "3" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "659:1:381", + "nodeType": "YulLiteral", + "src": "659:1:381", + "type": "", + "value": "4" + }, + { + "name": "length", + "nativeSrc": "662:6:381", + "nodeType": "YulIdentifier", + "src": "662:6:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "655:3:381", + "nodeType": "YulIdentifier", + "src": "655:3:381" + }, + "nativeSrc": "655:14:381", + "nodeType": "YulFunctionCall", + "src": "655:14:381" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "648:3:381", + "nodeType": "YulIdentifier", + "src": "648:3:381" + }, + "nativeSrc": "648:22:381", + "nodeType": "YulFunctionCall", + "src": "648:22:381" + }, + { + "name": "_2", + "nativeSrc": "672:2:381", + "nodeType": "YulIdentifier", + "src": "672:2:381" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "644:3:381", + "nodeType": "YulIdentifier", + "src": "644:3:381" + }, + "nativeSrc": "644:31:381", + "nodeType": "YulFunctionCall", + "src": "644:31:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "636:3:381", + "nodeType": "YulIdentifier", + "src": "636:3:381" + }, + "nativeSrc": "636:40:381", + "nodeType": "YulFunctionCall", + "src": "636:40:381" + }, + { + "name": "_2", + "nativeSrc": "678:2:381", + "nodeType": "YulIdentifier", + "src": "678:2:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "632:3:381", + "nodeType": "YulIdentifier", + "src": "632:3:381" + }, + "nativeSrc": "632:49:381", + "nodeType": "YulFunctionCall", + "src": "632:49:381" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "623:5:381", + "nodeType": "YulIdentifier", + "src": "623:5:381" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "length", + "nativeSrc": "590:6:381", + "nodeType": "YulIdentifier", + "src": "590:6:381" + }, + { + "kind": "number", + "nativeSrc": "598:1:381", + "nodeType": "YulLiteral", + "src": "598:1:381", + "type": "", + "value": "4" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "587:2:381", + "nodeType": "YulIdentifier", + "src": "587:2:381" + }, + "nativeSrc": "587:13:381", + "nodeType": "YulFunctionCall", + "src": "587:13:381" + }, + "nativeSrc": "584:107:381", + "nodeType": "YulIf", + "src": "584:107:381" + } + ] + }, + "name": "convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4", + "nativeSrc": "290:407:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "array", + "nativeSrc": "363:5:381", + "nodeType": "YulTypedName", + "src": "363:5:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "373:5:381", + "nodeType": "YulTypedName", + "src": "373:5:381", + "type": "" + } + ], + "src": "290:407:381" + }, + { + "body": { + "nativeSrc": "734:152:381", + "nodeType": "YulBlock", + "src": "734:152:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "751:1:381", + "nodeType": "YulLiteral", + "src": "751:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "754:77:381", + "nodeType": "YulLiteral", + "src": "754:77:381", + "type": "", + "value": "35408467139433450592217433187231851964531694900788300625387963629091585785856" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "744:6:381", + "nodeType": "YulIdentifier", + "src": "744:6:381" + }, + "nativeSrc": "744:88:381", + "nodeType": "YulFunctionCall", + "src": "744:88:381" + }, + "nativeSrc": "744:88:381", + "nodeType": "YulExpressionStatement", + "src": "744:88:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "848:1:381", + "nodeType": "YulLiteral", + "src": "848:1:381", + "type": "", + "value": "4" + }, + { + "kind": "number", + "nativeSrc": "851:4:381", + "nodeType": "YulLiteral", + "src": "851:4:381", + "type": "", + "value": "0x11" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "841:6:381", + "nodeType": "YulIdentifier", + "src": "841:6:381" + }, + "nativeSrc": "841:15:381", + "nodeType": "YulFunctionCall", + "src": "841:15:381" + }, + "nativeSrc": "841:15:381", + "nodeType": "YulExpressionStatement", + "src": "841:15:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "872:1:381", + "nodeType": "YulLiteral", + "src": "872:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "875:4:381", + "nodeType": "YulLiteral", + "src": "875:4:381", + "type": "", + "value": "0x24" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "865:6:381", + "nodeType": "YulIdentifier", + "src": "865:6:381" + }, + "nativeSrc": "865:15:381", + "nodeType": "YulFunctionCall", + "src": "865:15:381" + }, + "nativeSrc": "865:15:381", + "nodeType": "YulExpressionStatement", + "src": "865:15:381" + } + ] + }, + "name": "panic_error_0x11", + "nativeSrc": "702:184:381", + "nodeType": "YulFunctionDefinition", + "src": "702:184:381" + }, + { + "body": { + "nativeSrc": "940:79:381", + "nodeType": "YulBlock", + "src": "940:79:381", + "statements": [ + { + "nativeSrc": "950:17:381", + "nodeType": "YulAssignment", + "src": "950:17:381", + "value": { + "arguments": [ + { + "name": "x", + "nativeSrc": "962:1:381", + "nodeType": "YulIdentifier", + "src": "962:1:381" + }, + { + "name": "y", + "nativeSrc": "965:1:381", + "nodeType": "YulIdentifier", + "src": "965:1:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "958:3:381", + "nodeType": "YulIdentifier", + "src": "958:3:381" + }, + "nativeSrc": "958:9:381", + "nodeType": "YulFunctionCall", + "src": "958:9:381" + }, + "variableNames": [ + { + "name": "diff", + "nativeSrc": "950:4:381", + "nodeType": "YulIdentifier", + "src": "950:4:381" + } + ] + }, + { + "body": { + "nativeSrc": "991:22:381", + "nodeType": "YulBlock", + "src": "991:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x11", + "nativeSrc": "993:16:381", + "nodeType": "YulIdentifier", + "src": "993:16:381" + }, + "nativeSrc": "993:18:381", + "nodeType": "YulFunctionCall", + "src": "993:18:381" + }, + "nativeSrc": "993:18:381", + "nodeType": "YulExpressionStatement", + "src": "993:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "diff", + "nativeSrc": "982:4:381", + "nodeType": "YulIdentifier", + "src": "982:4:381" + }, + { + "name": "x", + "nativeSrc": "988:1:381", + "nodeType": "YulIdentifier", + "src": "988:1:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "979:2:381", + "nodeType": "YulIdentifier", + "src": "979:2:381" + }, + "nativeSrc": "979:11:381", + "nodeType": "YulFunctionCall", + "src": "979:11:381" + }, + "nativeSrc": "976:37:381", + "nodeType": "YulIf", + "src": "976:37:381" + } + ] + }, + "name": "checked_sub_t_uint256", + "nativeSrc": "891:128:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "x", + "nativeSrc": "922:1:381", + "nodeType": "YulTypedName", + "src": "922:1:381", + "type": "" + }, + { + "name": "y", + "nativeSrc": "925:1:381", + "nodeType": "YulTypedName", + "src": "925:1:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "diff", + "nativeSrc": "931:4:381", + "nodeType": "YulTypedName", + "src": "931:4:381", + "type": "" + } + ], + "src": "891:128:381" + }, + { + "body": { + "nativeSrc": "1074:239:381", + "nodeType": "YulBlock", + "src": "1074:239:381", + "statements": [ + { + "nativeSrc": "1084:26:381", + "nodeType": "YulVariableDeclaration", + "src": "1084:26:381", + "value": { + "arguments": [ + { + "name": "value", + "nativeSrc": "1104:5:381", + "nodeType": "YulIdentifier", + "src": "1104:5:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "1098:5:381", + "nodeType": "YulIdentifier", + "src": "1098:5:381" + }, + "nativeSrc": "1098:12:381", + "nodeType": "YulFunctionCall", + "src": "1098:12:381" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "1088:6:381", + "nodeType": "YulTypedName", + "src": "1088:6:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1126:3:381", + "nodeType": "YulIdentifier", + "src": "1126:3:381" + }, + { + "name": "length", + "nativeSrc": "1131:6:381", + "nodeType": "YulIdentifier", + "src": "1131:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1119:6:381", + "nodeType": "YulIdentifier", + "src": "1119:6:381" + }, + "nativeSrc": "1119:19:381", + "nodeType": "YulFunctionCall", + "src": "1119:19:381" + }, + "nativeSrc": "1119:19:381", + "nodeType": "YulExpressionStatement", + "src": "1119:19:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1157:3:381", + "nodeType": "YulIdentifier", + "src": "1157:3:381" + }, + { + "kind": "number", + "nativeSrc": "1162:4:381", + "nodeType": "YulLiteral", + "src": "1162:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1153:3:381", + "nodeType": "YulIdentifier", + "src": "1153:3:381" + }, + "nativeSrc": "1153:14:381", + "nodeType": "YulFunctionCall", + "src": "1153:14:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "1173:5:381", + "nodeType": "YulIdentifier", + "src": "1173:5:381" + }, + { + "kind": "number", + "nativeSrc": "1180:4:381", + "nodeType": "YulLiteral", + "src": "1180:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1169:3:381", + "nodeType": "YulIdentifier", + "src": "1169:3:381" + }, + "nativeSrc": "1169:16:381", + "nodeType": "YulFunctionCall", + "src": "1169:16:381" + }, + { + "name": "length", + "nativeSrc": "1187:6:381", + "nodeType": "YulIdentifier", + "src": "1187:6:381" + } + ], + "functionName": { + "name": "mcopy", + "nativeSrc": "1147:5:381", + "nodeType": "YulIdentifier", + "src": "1147:5:381" + }, + "nativeSrc": "1147:47:381", + "nodeType": "YulFunctionCall", + "src": "1147:47:381" + }, + "nativeSrc": "1147:47:381", + "nodeType": "YulExpressionStatement", + "src": "1147:47:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1218:3:381", + "nodeType": "YulIdentifier", + "src": "1218:3:381" + }, + { + "name": "length", + "nativeSrc": "1223:6:381", + "nodeType": "YulIdentifier", + "src": "1223:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1214:3:381", + "nodeType": "YulIdentifier", + "src": "1214:3:381" + }, + "nativeSrc": "1214:16:381", + "nodeType": "YulFunctionCall", + "src": "1214:16:381" + }, + { + "kind": "number", + "nativeSrc": "1232:4:381", + "nodeType": "YulLiteral", + "src": "1232:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1210:3:381", + "nodeType": "YulIdentifier", + "src": "1210:3:381" + }, + "nativeSrc": "1210:27:381", + "nodeType": "YulFunctionCall", + "src": "1210:27:381" + }, + { + "kind": "number", + "nativeSrc": "1239:1:381", + "nodeType": "YulLiteral", + "src": "1239:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1203:6:381", + "nodeType": "YulIdentifier", + "src": "1203:6:381" + }, + "nativeSrc": "1203:38:381", + "nodeType": "YulFunctionCall", + "src": "1203:38:381" + }, + "nativeSrc": "1203:38:381", + "nodeType": "YulExpressionStatement", + "src": "1203:38:381" + }, + { + "nativeSrc": "1250:57:381", + "nodeType": "YulAssignment", + "src": "1250:57:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1265:3:381", + "nodeType": "YulIdentifier", + "src": "1265:3:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "length", + "nativeSrc": "1278:6:381", + "nodeType": "YulIdentifier", + "src": "1278:6:381" + }, + { + "kind": "number", + "nativeSrc": "1286:2:381", + "nodeType": "YulLiteral", + "src": "1286:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1274:3:381", + "nodeType": "YulIdentifier", + "src": "1274:3:381" + }, + "nativeSrc": "1274:15:381", + "nodeType": "YulFunctionCall", + "src": "1274:15:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "1295:2:381", + "nodeType": "YulLiteral", + "src": "1295:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "1291:3:381", + "nodeType": "YulIdentifier", + "src": "1291:3:381" + }, + "nativeSrc": "1291:7:381", + "nodeType": "YulFunctionCall", + "src": "1291:7:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1270:3:381", + "nodeType": "YulIdentifier", + "src": "1270:3:381" + }, + "nativeSrc": "1270:29:381", + "nodeType": "YulFunctionCall", + "src": "1270:29:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1261:3:381", + "nodeType": "YulIdentifier", + "src": "1261:3:381" + }, + "nativeSrc": "1261:39:381", + "nodeType": "YulFunctionCall", + "src": "1261:39:381" + }, + { + "kind": "number", + "nativeSrc": "1302:4:381", + "nodeType": "YulLiteral", + "src": "1302:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1257:3:381", + "nodeType": "YulIdentifier", + "src": "1257:3:381" + }, + "nativeSrc": "1257:50:381", + "nodeType": "YulFunctionCall", + "src": "1257:50:381" + }, + "variableNames": [ + { + "name": "end", + "nativeSrc": "1250:3:381", + "nodeType": "YulIdentifier", + "src": "1250:3:381" + } + ] + } + ] + }, + "name": "abi_encode_string", + "nativeSrc": "1024:289:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "1051:5:381", + "nodeType": "YulTypedName", + "src": "1051:5:381", + "type": "" + }, + { + "name": "pos", + "nativeSrc": "1058:3:381", + "nodeType": "YulTypedName", + "src": "1058:3:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "end", + "nativeSrc": "1066:3:381", + "nodeType": "YulTypedName", + "src": "1066:3:381", + "type": "" + } + ], + "src": "1024:289:381" + }, + { + "body": { + "nativeSrc": "1361:107:381", + "nodeType": "YulBlock", + "src": "1361:107:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "1378:3:381", + "nodeType": "YulIdentifier", + "src": "1378:3:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "1387:5:381", + "nodeType": "YulIdentifier", + "src": "1387:5:381" + }, + { + "kind": "number", + "nativeSrc": "1394:66:381", + "nodeType": "YulLiteral", + "src": "1394:66:381", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1383:3:381", + "nodeType": "YulIdentifier", + "src": "1383:3:381" + }, + "nativeSrc": "1383:78:381", + "nodeType": "YulFunctionCall", + "src": "1383:78:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1371:6:381", + "nodeType": "YulIdentifier", + "src": "1371:6:381" + }, + "nativeSrc": "1371:91:381", + "nodeType": "YulFunctionCall", + "src": "1371:91:381" + }, + "nativeSrc": "1371:91:381", + "nodeType": "YulExpressionStatement", + "src": "1371:91:381" + } + ] + }, + "name": "abi_encode_bytes4", + "nativeSrc": "1318:150:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "1345:5:381", + "nodeType": "YulTypedName", + "src": "1345:5:381", + "type": "" + }, + { + "name": "pos", + "nativeSrc": "1352:3:381", + "nodeType": "YulTypedName", + "src": "1352:3:381", + "type": "" + } + ], + "src": "1318:150:381" + }, + { + "body": { + "nativeSrc": "1790:985:381", + "nodeType": "YulBlock", + "src": "1790:985:381", + "statements": [ + { + "nativeSrc": "1800:33:381", + "nodeType": "YulVariableDeclaration", + "src": "1800:33:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "1818:9:381", + "nodeType": "YulIdentifier", + "src": "1818:9:381" + }, + { + "kind": "number", + "nativeSrc": "1829:3:381", + "nodeType": "YulLiteral", + "src": "1829:3:381", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1814:3:381", + "nodeType": "YulIdentifier", + "src": "1814:3:381" + }, + "nativeSrc": "1814:19:381", + "nodeType": "YulFunctionCall", + "src": "1814:19:381" + }, + "variables": [ + { + "name": "tail_1", + "nativeSrc": "1804:6:381", + "nodeType": "YulTypedName", + "src": "1804:6:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "1849:9:381", + "nodeType": "YulIdentifier", + "src": "1849:9:381" + }, + { + "arguments": [ + { + "name": "value0", + "nativeSrc": "1864:6:381", + "nodeType": "YulIdentifier", + "src": "1864:6:381" + }, + { + "kind": "number", + "nativeSrc": "1872:42:381", + "nodeType": "YulLiteral", + "src": "1872:42:381", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "1860:3:381", + "nodeType": "YulIdentifier", + "src": "1860:3:381" + }, + "nativeSrc": "1860:55:381", + "nodeType": "YulFunctionCall", + "src": "1860:55:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1842:6:381", + "nodeType": "YulIdentifier", + "src": "1842:6:381" + }, + "nativeSrc": "1842:74:381", + "nodeType": "YulFunctionCall", + "src": "1842:74:381" + }, + "nativeSrc": "1842:74:381", + "nodeType": "YulExpressionStatement", + "src": "1842:74:381" + }, + { + "nativeSrc": "1925:12:381", + "nodeType": "YulVariableDeclaration", + "src": "1925:12:381", + "value": { + "kind": "number", + "nativeSrc": "1935:2:381", + "nodeType": "YulLiteral", + "src": "1935:2:381", + "type": "", + "value": "32" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "1929:2:381", + "nodeType": "YulTypedName", + "src": "1929:2:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "1957:9:381", + "nodeType": "YulIdentifier", + "src": "1957:9:381" + }, + { + "kind": "number", + "nativeSrc": "1968:2:381", + "nodeType": "YulLiteral", + "src": "1968:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "1953:3:381", + "nodeType": "YulIdentifier", + "src": "1953:3:381" + }, + "nativeSrc": "1953:18:381", + "nodeType": "YulFunctionCall", + "src": "1953:18:381" + }, + { + "kind": "number", + "nativeSrc": "1973:3:381", + "nodeType": "YulLiteral", + "src": "1973:3:381", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "1946:6:381", + "nodeType": "YulIdentifier", + "src": "1946:6:381" + }, + "nativeSrc": "1946:31:381", + "nodeType": "YulFunctionCall", + "src": "1946:31:381" + }, + "nativeSrc": "1946:31:381", + "nodeType": "YulExpressionStatement", + "src": "1946:31:381" + }, + { + "nativeSrc": "1986:17:381", + "nodeType": "YulVariableDeclaration", + "src": "1986:17:381", + "value": { + "name": "tail_1", + "nativeSrc": "1997:6:381", + "nodeType": "YulIdentifier", + "src": "1997:6:381" + }, + "variables": [ + { + "name": "pos", + "nativeSrc": "1990:3:381", + "nodeType": "YulTypedName", + "src": "1990:3:381", + "type": "" + } + ] + }, + { + "nativeSrc": "2012:27:381", + "nodeType": "YulVariableDeclaration", + "src": "2012:27:381", + "value": { + "arguments": [ + { + "name": "value1", + "nativeSrc": "2032:6:381", + "nodeType": "YulIdentifier", + "src": "2032:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "2026:5:381", + "nodeType": "YulIdentifier", + "src": "2026:5:381" + }, + "nativeSrc": "2026:13:381", + "nodeType": "YulFunctionCall", + "src": "2026:13:381" + }, + "variables": [ + { + "name": "length", + "nativeSrc": "2016:6:381", + "nodeType": "YulTypedName", + "src": "2016:6:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "tail_1", + "nativeSrc": "2055:6:381", + "nodeType": "YulIdentifier", + "src": "2055:6:381" + }, + { + "name": "length", + "nativeSrc": "2063:6:381", + "nodeType": "YulIdentifier", + "src": "2063:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2048:6:381", + "nodeType": "YulIdentifier", + "src": "2048:6:381" + }, + "nativeSrc": "2048:22:381", + "nodeType": "YulFunctionCall", + "src": "2048:22:381" + }, + "nativeSrc": "2048:22:381", + "nodeType": "YulExpressionStatement", + "src": "2048:22:381" + }, + { + "nativeSrc": "2079:26:381", + "nodeType": "YulAssignment", + "src": "2079:26:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2090:9:381", + "nodeType": "YulIdentifier", + "src": "2090:9:381" + }, + { + "kind": "number", + "nativeSrc": "2101:3:381", + "nodeType": "YulLiteral", + "src": "2101:3:381", + "type": "", + "value": "192" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2086:3:381", + "nodeType": "YulIdentifier", + "src": "2086:3:381" + }, + "nativeSrc": "2086:19:381", + "nodeType": "YulFunctionCall", + "src": "2086:19:381" + }, + "variableNames": [ + { + "name": "pos", + "nativeSrc": "2079:3:381", + "nodeType": "YulIdentifier", + "src": "2079:3:381" + } + ] + }, + { + "nativeSrc": "2114:54:381", + "nodeType": "YulVariableDeclaration", + "src": "2114:54:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2136:9:381", + "nodeType": "YulIdentifier", + "src": "2136:9:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "2151:1:381", + "nodeType": "YulLiteral", + "src": "2151:1:381", + "type": "", + "value": "5" + }, + { + "name": "length", + "nativeSrc": "2154:6:381", + "nodeType": "YulIdentifier", + "src": "2154:6:381" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "2147:3:381", + "nodeType": "YulIdentifier", + "src": "2147:3:381" + }, + "nativeSrc": "2147:14:381", + "nodeType": "YulFunctionCall", + "src": "2147:14:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2132:3:381", + "nodeType": "YulIdentifier", + "src": "2132:3:381" + }, + "nativeSrc": "2132:30:381", + "nodeType": "YulFunctionCall", + "src": "2132:30:381" + }, + { + "kind": "number", + "nativeSrc": "2164:3:381", + "nodeType": "YulLiteral", + "src": "2164:3:381", + "type": "", + "value": "192" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2128:3:381", + "nodeType": "YulIdentifier", + "src": "2128:3:381" + }, + "nativeSrc": "2128:40:381", + "nodeType": "YulFunctionCall", + "src": "2128:40:381" + }, + "variables": [ + { + "name": "tail_2", + "nativeSrc": "2118:6:381", + "nodeType": "YulTypedName", + "src": "2118:6:381", + "type": "" + } + ] + }, + { + "nativeSrc": "2177:29:381", + "nodeType": "YulVariableDeclaration", + "src": "2177:29:381", + "value": { + "arguments": [ + { + "name": "value1", + "nativeSrc": "2195:6:381", + "nodeType": "YulIdentifier", + "src": "2195:6:381" + }, + { + "kind": "number", + "nativeSrc": "2203:2:381", + "nodeType": "YulLiteral", + "src": "2203:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2191:3:381", + "nodeType": "YulIdentifier", + "src": "2191:3:381" + }, + "nativeSrc": "2191:15:381", + "nodeType": "YulFunctionCall", + "src": "2191:15:381" + }, + "variables": [ + { + "name": "srcPtr", + "nativeSrc": "2181:6:381", + "nodeType": "YulTypedName", + "src": "2181:6:381", + "type": "" + } + ] + }, + { + "nativeSrc": "2215:10:381", + "nodeType": "YulVariableDeclaration", + "src": "2215:10:381", + "value": { + "kind": "number", + "nativeSrc": "2224:1:381", + "nodeType": "YulLiteral", + "src": "2224:1:381", + "type": "", + "value": "0" + }, + "variables": [ + { + "name": "i", + "nativeSrc": "2219:1:381", + "nodeType": "YulTypedName", + "src": "2219:1:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "2283:207:381", + "nodeType": "YulBlock", + "src": "2283:207:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "2304:3:381", + "nodeType": "YulIdentifier", + "src": "2304:3:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "tail_2", + "nativeSrc": "2317:6:381", + "nodeType": "YulIdentifier", + "src": "2317:6:381" + }, + { + "name": "headStart", + "nativeSrc": "2325:9:381", + "nodeType": "YulIdentifier", + "src": "2325:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2313:3:381", + "nodeType": "YulIdentifier", + "src": "2313:3:381" + }, + "nativeSrc": "2313:22:381", + "nodeType": "YulFunctionCall", + "src": "2313:22:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "2341:3:381", + "nodeType": "YulLiteral", + "src": "2341:3:381", + "type": "", + "value": "191" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "2337:3:381", + "nodeType": "YulIdentifier", + "src": "2337:3:381" + }, + "nativeSrc": "2337:8:381", + "nodeType": "YulFunctionCall", + "src": "2337:8:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2309:3:381", + "nodeType": "YulIdentifier", + "src": "2309:3:381" + }, + "nativeSrc": "2309:37:381", + "nodeType": "YulFunctionCall", + "src": "2309:37:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2297:6:381", + "nodeType": "YulIdentifier", + "src": "2297:6:381" + }, + "nativeSrc": "2297:50:381", + "nodeType": "YulFunctionCall", + "src": "2297:50:381" + }, + "nativeSrc": "2297:50:381", + "nodeType": "YulExpressionStatement", + "src": "2297:50:381" + }, + { + "nativeSrc": "2360:50:381", + "nodeType": "YulAssignment", + "src": "2360:50:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "srcPtr", + "nativeSrc": "2394:6:381", + "nodeType": "YulIdentifier", + "src": "2394:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "2388:5:381", + "nodeType": "YulIdentifier", + "src": "2388:5:381" + }, + "nativeSrc": "2388:13:381", + "nodeType": "YulFunctionCall", + "src": "2388:13:381" + }, + { + "name": "tail_2", + "nativeSrc": "2403:6:381", + "nodeType": "YulIdentifier", + "src": "2403:6:381" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2370:17:381", + "nodeType": "YulIdentifier", + "src": "2370:17:381" + }, + "nativeSrc": "2370:40:381", + "nodeType": "YulFunctionCall", + "src": "2370:40:381" + }, + "variableNames": [ + { + "name": "tail_2", + "nativeSrc": "2360:6:381", + "nodeType": "YulIdentifier", + "src": "2360:6:381" + } + ] + }, + { + "nativeSrc": "2423:25:381", + "nodeType": "YulAssignment", + "src": "2423:25:381", + "value": { + "arguments": [ + { + "name": "srcPtr", + "nativeSrc": "2437:6:381", + "nodeType": "YulIdentifier", + "src": "2437:6:381" + }, + { + "name": "_1", + "nativeSrc": "2445:2:381", + "nodeType": "YulIdentifier", + "src": "2445:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2433:3:381", + "nodeType": "YulIdentifier", + "src": "2433:3:381" + }, + "nativeSrc": "2433:15:381", + "nodeType": "YulFunctionCall", + "src": "2433:15:381" + }, + "variableNames": [ + { + "name": "srcPtr", + "nativeSrc": "2423:6:381", + "nodeType": "YulIdentifier", + "src": "2423:6:381" + } + ] + }, + { + "nativeSrc": "2461:19:381", + "nodeType": "YulAssignment", + "src": "2461:19:381", + "value": { + "arguments": [ + { + "name": "pos", + "nativeSrc": "2472:3:381", + "nodeType": "YulIdentifier", + "src": "2472:3:381" + }, + { + "name": "_1", + "nativeSrc": "2477:2:381", + "nodeType": "YulIdentifier", + "src": "2477:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2468:3:381", + "nodeType": "YulIdentifier", + "src": "2468:3:381" + }, + "nativeSrc": "2468:12:381", + "nodeType": "YulFunctionCall", + "src": "2468:12:381" + }, + "variableNames": [ + { + "name": "pos", + "nativeSrc": "2461:3:381", + "nodeType": "YulIdentifier", + "src": "2461:3:381" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "i", + "nativeSrc": "2245:1:381", + "nodeType": "YulIdentifier", + "src": "2245:1:381" + }, + { + "name": "length", + "nativeSrc": "2248:6:381", + "nodeType": "YulIdentifier", + "src": "2248:6:381" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "2242:2:381", + "nodeType": "YulIdentifier", + "src": "2242:2:381" + }, + "nativeSrc": "2242:13:381", + "nodeType": "YulFunctionCall", + "src": "2242:13:381" + }, + "nativeSrc": "2234:256:381", + "nodeType": "YulForLoop", + "post": { + "nativeSrc": "2256:18:381", + "nodeType": "YulBlock", + "src": "2256:18:381", + "statements": [ + { + "nativeSrc": "2258:14:381", + "nodeType": "YulAssignment", + "src": "2258:14:381", + "value": { + "arguments": [ + { + "name": "i", + "nativeSrc": "2267:1:381", + "nodeType": "YulIdentifier", + "src": "2267:1:381" + }, + { + "kind": "number", + "nativeSrc": "2270:1:381", + "nodeType": "YulLiteral", + "src": "2270:1:381", + "type": "", + "value": "1" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2263:3:381", + "nodeType": "YulIdentifier", + "src": "2263:3:381" + }, + "nativeSrc": "2263:9:381", + "nodeType": "YulFunctionCall", + "src": "2263:9:381" + }, + "variableNames": [ + { + "name": "i", + "nativeSrc": "2258:1:381", + "nodeType": "YulIdentifier", + "src": "2258:1:381" + } + ] + } + ] + }, + "pre": { + "nativeSrc": "2238:3:381", + "nodeType": "YulBlock", + "src": "2238:3:381", + "statements": [] + }, + "src": "2234:256:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2510:9:381", + "nodeType": "YulIdentifier", + "src": "2510:9:381" + }, + { + "kind": "number", + "nativeSrc": "2521:2:381", + "nodeType": "YulLiteral", + "src": "2521:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2506:3:381", + "nodeType": "YulIdentifier", + "src": "2506:3:381" + }, + "nativeSrc": "2506:18:381", + "nodeType": "YulFunctionCall", + "src": "2506:18:381" + }, + { + "arguments": [ + { + "name": "tail_2", + "nativeSrc": "2530:6:381", + "nodeType": "YulIdentifier", + "src": "2530:6:381" + }, + { + "name": "headStart", + "nativeSrc": "2538:9:381", + "nodeType": "YulIdentifier", + "src": "2538:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2526:3:381", + "nodeType": "YulIdentifier", + "src": "2526:3:381" + }, + "nativeSrc": "2526:22:381", + "nodeType": "YulFunctionCall", + "src": "2526:22:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2499:6:381", + "nodeType": "YulIdentifier", + "src": "2499:6:381" + }, + "nativeSrc": "2499:50:381", + "nodeType": "YulFunctionCall", + "src": "2499:50:381" + }, + "nativeSrc": "2499:50:381", + "nodeType": "YulExpressionStatement", + "src": "2499:50:381" + }, + { + "nativeSrc": "2558:47:381", + "nodeType": "YulVariableDeclaration", + "src": "2558:47:381", + "value": { + "arguments": [ + { + "name": "value2", + "nativeSrc": "2590:6:381", + "nodeType": "YulIdentifier", + "src": "2590:6:381" + }, + { + "name": "tail_2", + "nativeSrc": "2598:6:381", + "nodeType": "YulIdentifier", + "src": "2598:6:381" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2572:17:381", + "nodeType": "YulIdentifier", + "src": "2572:17:381" + }, + "nativeSrc": "2572:33:381", + "nodeType": "YulFunctionCall", + "src": "2572:33:381" + }, + "variables": [ + { + "name": "tail_3", + "nativeSrc": "2562:6:381", + "nodeType": "YulTypedName", + "src": "2562:6:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value3", + "nativeSrc": "2632:6:381", + "nodeType": "YulIdentifier", + "src": "2632:6:381" + }, + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2644:9:381", + "nodeType": "YulIdentifier", + "src": "2644:9:381" + }, + { + "kind": "number", + "nativeSrc": "2655:2:381", + "nodeType": "YulLiteral", + "src": "2655:2:381", + "type": "", + "value": "96" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2640:3:381", + "nodeType": "YulIdentifier", + "src": "2640:3:381" + }, + "nativeSrc": "2640:18:381", + "nodeType": "YulFunctionCall", + "src": "2640:18:381" + } + ], + "functionName": { + "name": "abi_encode_bytes4", + "nativeSrc": "2614:17:381", + "nodeType": "YulIdentifier", + "src": "2614:17:381" + }, + "nativeSrc": "2614:45:381", + "nodeType": "YulFunctionCall", + "src": "2614:45:381" + }, + "nativeSrc": "2614:45:381", + "nodeType": "YulExpressionStatement", + "src": "2614:45:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "2679:9:381", + "nodeType": "YulIdentifier", + "src": "2679:9:381" + }, + { + "kind": "number", + "nativeSrc": "2690:3:381", + "nodeType": "YulLiteral", + "src": "2690:3:381", + "type": "", + "value": "128" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "2675:3:381", + "nodeType": "YulIdentifier", + "src": "2675:3:381" + }, + "nativeSrc": "2675:19:381", + "nodeType": "YulFunctionCall", + "src": "2675:19:381" + }, + { + "arguments": [ + { + "name": "tail_3", + "nativeSrc": "2700:6:381", + "nodeType": "YulIdentifier", + "src": "2700:6:381" + }, + { + "name": "headStart", + "nativeSrc": "2708:9:381", + "nodeType": "YulIdentifier", + "src": "2708:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "2696:3:381", + "nodeType": "YulIdentifier", + "src": "2696:3:381" + }, + "nativeSrc": "2696:22:381", + "nodeType": "YulFunctionCall", + "src": "2696:22:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "2668:6:381", + "nodeType": "YulIdentifier", + "src": "2668:6:381" + }, + "nativeSrc": "2668:51:381", + "nodeType": "YulFunctionCall", + "src": "2668:51:381" + }, + "nativeSrc": "2668:51:381", + "nodeType": "YulExpressionStatement", + "src": "2668:51:381" + }, + { + "nativeSrc": "2728:41:381", + "nodeType": "YulAssignment", + "src": "2728:41:381", + "value": { + "arguments": [ + { + "name": "value4", + "nativeSrc": "2754:6:381", + "nodeType": "YulIdentifier", + "src": "2754:6:381" + }, + { + "name": "tail_3", + "nativeSrc": "2762:6:381", + "nodeType": "YulIdentifier", + "src": "2762:6:381" + } + ], + "functionName": { + "name": "abi_encode_string", + "nativeSrc": "2736:17:381", + "nodeType": "YulIdentifier", + "src": "2736:17:381" + }, + "nativeSrc": "2736:33:381", + "nodeType": "YulFunctionCall", + "src": "2736:33:381" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "2728:4:381", + "nodeType": "YulIdentifier", + "src": "2728:4:381" + } + ] + } + ] + }, + "name": "abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed", + "nativeSrc": "1473:1302:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "1727:9:381", + "nodeType": "YulTypedName", + "src": "1727:9:381", + "type": "" + }, + { + "name": "value4", + "nativeSrc": "1738:6:381", + "nodeType": "YulTypedName", + "src": "1738:6:381", + "type": "" + }, + { + "name": "value3", + "nativeSrc": "1746:6:381", + "nodeType": "YulTypedName", + "src": "1746:6:381", + "type": "" + }, + { + "name": "value2", + "nativeSrc": "1754:6:381", + "nodeType": "YulTypedName", + "src": "1754:6:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "1762:6:381", + "nodeType": "YulTypedName", + "src": "1762:6:381", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "1770:6:381", + "nodeType": "YulTypedName", + "src": "1770:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "1781:4:381", + "nodeType": "YulTypedName", + "src": "1781:4:381", + "type": "" + } + ], + "src": "1473:1302:381" + }, + { + "body": { + "nativeSrc": "2825:109:381", + "nodeType": "YulBlock", + "src": "2825:109:381", + "statements": [ + { + "body": { + "nativeSrc": "2912:16:381", + "nodeType": "YulBlock", + "src": "2912:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "2921:1:381", + "nodeType": "YulLiteral", + "src": "2921:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "2924:1:381", + "nodeType": "YulLiteral", + "src": "2924:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "2914:6:381", + "nodeType": "YulIdentifier", + "src": "2914:6:381" + }, + "nativeSrc": "2914:12:381", + "nodeType": "YulFunctionCall", + "src": "2914:12:381" + }, + "nativeSrc": "2914:12:381", + "nodeType": "YulExpressionStatement", + "src": "2914:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "2848:5:381", + "nodeType": "YulIdentifier", + "src": "2848:5:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "2859:5:381", + "nodeType": "YulIdentifier", + "src": "2859:5:381" + }, + { + "kind": "number", + "nativeSrc": "2866:42:381", + "nodeType": "YulLiteral", + "src": "2866:42:381", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "2855:3:381", + "nodeType": "YulIdentifier", + "src": "2855:3:381" + }, + "nativeSrc": "2855:54:381", + "nodeType": "YulFunctionCall", + "src": "2855:54:381" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "2845:2:381", + "nodeType": "YulIdentifier", + "src": "2845:2:381" + }, + "nativeSrc": "2845:65:381", + "nodeType": "YulFunctionCall", + "src": "2845:65:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "2838:6:381", + "nodeType": "YulIdentifier", + "src": "2838:6:381" + }, + "nativeSrc": "2838:73:381", + "nodeType": "YulFunctionCall", + "src": "2838:73:381" + }, + "nativeSrc": "2835:93:381", + "nodeType": "YulIf", + "src": "2835:93:381" + } + ] + }, + "name": "validator_revert_address", + "nativeSrc": "2780:154:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "value", + "nativeSrc": "2814:5:381", + "nodeType": "YulTypedName", + "src": "2814:5:381", + "type": "" + } + ], + "src": "2780:154:381" + }, + { + "body": { + "nativeSrc": "3009:177:381", + "nodeType": "YulBlock", + "src": "3009:177:381", + "statements": [ + { + "body": { + "nativeSrc": "3055:16:381", + "nodeType": "YulBlock", + "src": "3055:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3064:1:381", + "nodeType": "YulLiteral", + "src": "3064:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3067:1:381", + "nodeType": "YulLiteral", + "src": "3067:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "3057:6:381", + "nodeType": "YulIdentifier", + "src": "3057:6:381" + }, + "nativeSrc": "3057:12:381", + "nodeType": "YulFunctionCall", + "src": "3057:12:381" + }, + "nativeSrc": "3057:12:381", + "nodeType": "YulExpressionStatement", + "src": "3057:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "3030:7:381", + "nodeType": "YulIdentifier", + "src": "3030:7:381" + }, + { + "name": "headStart", + "nativeSrc": "3039:9:381", + "nodeType": "YulIdentifier", + "src": "3039:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "3026:3:381", + "nodeType": "YulIdentifier", + "src": "3026:3:381" + }, + "nativeSrc": "3026:23:381", + "nodeType": "YulFunctionCall", + "src": "3026:23:381" + }, + { + "kind": "number", + "nativeSrc": "3051:2:381", + "nodeType": "YulLiteral", + "src": "3051:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "3022:3:381", + "nodeType": "YulIdentifier", + "src": "3022:3:381" + }, + "nativeSrc": "3022:32:381", + "nodeType": "YulFunctionCall", + "src": "3022:32:381" + }, + "nativeSrc": "3019:52:381", + "nodeType": "YulIf", + "src": "3019:52:381" + }, + { + "nativeSrc": "3080:36:381", + "nodeType": "YulVariableDeclaration", + "src": "3080:36:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3106:9:381", + "nodeType": "YulIdentifier", + "src": "3106:9:381" + } + ], + "functionName": { + "name": "calldataload", + "nativeSrc": "3093:12:381", + "nodeType": "YulIdentifier", + "src": "3093:12:381" + }, + "nativeSrc": "3093:23:381", + "nodeType": "YulFunctionCall", + "src": "3093:23:381" + }, + "variables": [ + { + "name": "value", + "nativeSrc": "3084:5:381", + "nodeType": "YulTypedName", + "src": "3084:5:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value", + "nativeSrc": "3150:5:381", + "nodeType": "YulIdentifier", + "src": "3150:5:381" + } + ], + "functionName": { + "name": "validator_revert_address", + "nativeSrc": "3125:24:381", + "nodeType": "YulIdentifier", + "src": "3125:24:381" + }, + "nativeSrc": "3125:31:381", + "nodeType": "YulFunctionCall", + "src": "3125:31:381" + }, + "nativeSrc": "3125:31:381", + "nodeType": "YulExpressionStatement", + "src": "3125:31:381" + }, + { + "nativeSrc": "3165:15:381", + "nodeType": "YulAssignment", + "src": "3165:15:381", + "value": { + "name": "value", + "nativeSrc": "3175:5:381", + "nodeType": "YulIdentifier", + "src": "3175:5:381" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "3165:6:381", + "nodeType": "YulIdentifier", + "src": "3165:6:381" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_address", + "nativeSrc": "2939:247:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "2975:9:381", + "nodeType": "YulTypedName", + "src": "2975:9:381", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "2986:7:381", + "nodeType": "YulTypedName", + "src": "2986:7:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "2998:6:381", + "nodeType": "YulTypedName", + "src": "2998:6:381", + "type": "" + } + ], + "src": "2939:247:381" + }, + { + "body": { + "nativeSrc": "3292:125:381", + "nodeType": "YulBlock", + "src": "3292:125:381", + "statements": [ + { + "nativeSrc": "3302:26:381", + "nodeType": "YulAssignment", + "src": "3302:26:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3314:9:381", + "nodeType": "YulIdentifier", + "src": "3314:9:381" + }, + { + "kind": "number", + "nativeSrc": "3325:2:381", + "nodeType": "YulLiteral", + "src": "3325:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3310:3:381", + "nodeType": "YulIdentifier", + "src": "3310:3:381" + }, + "nativeSrc": "3310:18:381", + "nodeType": "YulFunctionCall", + "src": "3310:18:381" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "3302:4:381", + "nodeType": "YulIdentifier", + "src": "3302:4:381" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "3344:9:381", + "nodeType": "YulIdentifier", + "src": "3344:9:381" + }, + { + "arguments": [ + { + "name": "value0", + "nativeSrc": "3359:6:381", + "nodeType": "YulIdentifier", + "src": "3359:6:381" + }, + { + "kind": "number", + "nativeSrc": "3367:42:381", + "nodeType": "YulLiteral", + "src": "3367:42:381", + "type": "", + "value": "0xffffffffffffffffffffffffffffffffffffffff" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "3355:3:381", + "nodeType": "YulIdentifier", + "src": "3355:3:381" + }, + "nativeSrc": "3355:55:381", + "nodeType": "YulFunctionCall", + "src": "3355:55:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3337:6:381", + "nodeType": "YulIdentifier", + "src": "3337:6:381" + }, + "nativeSrc": "3337:74:381", + "nodeType": "YulFunctionCall", + "src": "3337:74:381" + }, + "nativeSrc": "3337:74:381", + "nodeType": "YulExpressionStatement", + "src": "3337:74:381" + } + ] + }, + "name": "abi_encode_tuple_t_address__to_t_address__fromStack_reversed", + "nativeSrc": "3191:226:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "3261:9:381", + "nodeType": "YulTypedName", + "src": "3261:9:381", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "3272:6:381", + "nodeType": "YulTypedName", + "src": "3272:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "3283:4:381", + "nodeType": "YulTypedName", + "src": "3283:4:381", + "type": "" + } + ], + "src": "3191:226:381" + }, + { + "body": { + "nativeSrc": "3454:152:381", + "nodeType": "YulBlock", + "src": "3454:152:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3471:1:381", + "nodeType": "YulLiteral", + "src": "3471:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3474:77:381", + "nodeType": "YulLiteral", + "src": "3474:77:381", + "type": "", + "value": "35408467139433450592217433187231851964531694900788300625387963629091585785856" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3464:6:381", + "nodeType": "YulIdentifier", + "src": "3464:6:381" + }, + "nativeSrc": "3464:88:381", + "nodeType": "YulFunctionCall", + "src": "3464:88:381" + }, + "nativeSrc": "3464:88:381", + "nodeType": "YulExpressionStatement", + "src": "3464:88:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3568:1:381", + "nodeType": "YulLiteral", + "src": "3568:1:381", + "type": "", + "value": "4" + }, + { + "kind": "number", + "nativeSrc": "3571:4:381", + "nodeType": "YulLiteral", + "src": "3571:4:381", + "type": "", + "value": "0x41" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3561:6:381", + "nodeType": "YulIdentifier", + "src": "3561:6:381" + }, + "nativeSrc": "3561:15:381", + "nodeType": "YulFunctionCall", + "src": "3561:15:381" + }, + "nativeSrc": "3561:15:381", + "nodeType": "YulExpressionStatement", + "src": "3561:15:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3592:1:381", + "nodeType": "YulLiteral", + "src": "3592:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "3595:4:381", + "nodeType": "YulLiteral", + "src": "3595:4:381", + "type": "", + "value": "0x24" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "3585:6:381", + "nodeType": "YulIdentifier", + "src": "3585:6:381" + }, + "nativeSrc": "3585:15:381", + "nodeType": "YulFunctionCall", + "src": "3585:15:381" + }, + "nativeSrc": "3585:15:381", + "nodeType": "YulExpressionStatement", + "src": "3585:15:381" + } + ] + }, + "name": "panic_error_0x41", + "nativeSrc": "3422:184:381", + "nodeType": "YulFunctionDefinition", + "src": "3422:184:381" + }, + { + "body": { + "nativeSrc": "3656:230:381", + "nodeType": "YulBlock", + "src": "3656:230:381", + "statements": [ + { + "nativeSrc": "3666:19:381", + "nodeType": "YulAssignment", + "src": "3666:19:381", + "value": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3682:2:381", + "nodeType": "YulLiteral", + "src": "3682:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "3676:5:381", + "nodeType": "YulIdentifier", + "src": "3676:5:381" + }, + "nativeSrc": "3676:9:381", + "nodeType": "YulFunctionCall", + "src": "3676:9:381" + }, + "variableNames": [ + { + "name": "memPtr", + "nativeSrc": "3666:6:381", + "nodeType": "YulIdentifier", + "src": "3666:6:381" + } + ] + }, + { + "nativeSrc": "3694:58:381", + "nodeType": "YulVariableDeclaration", + "src": "3694:58:381", + "value": { + "arguments": [ + { + "name": "memPtr", + "nativeSrc": "3716:6:381", + "nodeType": "YulIdentifier", + "src": "3716:6:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "size", + "nativeSrc": "3732:4:381", + "nodeType": "YulIdentifier", + "src": "3732:4:381" + }, + { + "kind": "number", + "nativeSrc": "3738:2:381", + "nodeType": "YulLiteral", + "src": "3738:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3728:3:381", + "nodeType": "YulIdentifier", + "src": "3728:3:381" + }, + "nativeSrc": "3728:13:381", + "nodeType": "YulFunctionCall", + "src": "3728:13:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3747:2:381", + "nodeType": "YulLiteral", + "src": "3747:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "3743:3:381", + "nodeType": "YulIdentifier", + "src": "3743:3:381" + }, + "nativeSrc": "3743:7:381", + "nodeType": "YulFunctionCall", + "src": "3743:7:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "3724:3:381", + "nodeType": "YulIdentifier", + "src": "3724:3:381" + }, + "nativeSrc": "3724:27:381", + "nodeType": "YulFunctionCall", + "src": "3724:27:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "3712:3:381", + "nodeType": "YulIdentifier", + "src": "3712:3:381" + }, + "nativeSrc": "3712:40:381", + "nodeType": "YulFunctionCall", + "src": "3712:40:381" + }, + "variables": [ + { + "name": "newFreePtr", + "nativeSrc": "3698:10:381", + "nodeType": "YulTypedName", + "src": "3698:10:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "3827:22:381", + "nodeType": "YulBlock", + "src": "3827:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "3829:16:381", + "nodeType": "YulIdentifier", + "src": "3829:16:381" + }, + "nativeSrc": "3829:18:381", + "nodeType": "YulFunctionCall", + "src": "3829:18:381" + }, + "nativeSrc": "3829:18:381", + "nodeType": "YulExpressionStatement", + "src": "3829:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "newFreePtr", + "nativeSrc": "3770:10:381", + "nodeType": "YulIdentifier", + "src": "3770:10:381" + }, + { + "kind": "number", + "nativeSrc": "3782:18:381", + "nodeType": "YulLiteral", + "src": "3782:18:381", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "3767:2:381", + "nodeType": "YulIdentifier", + "src": "3767:2:381" + }, + "nativeSrc": "3767:34:381", + "nodeType": "YulFunctionCall", + "src": "3767:34:381" + }, + { + "arguments": [ + { + "name": "newFreePtr", + "nativeSrc": "3806:10:381", + "nodeType": "YulIdentifier", + "src": "3806:10:381" + }, + { + "name": "memPtr", + "nativeSrc": "3818:6:381", + "nodeType": "YulIdentifier", + "src": "3818:6:381" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "3803:2:381", + "nodeType": "YulIdentifier", + "src": "3803:2:381" + }, + "nativeSrc": "3803:22:381", + "nodeType": "YulFunctionCall", + "src": "3803:22:381" + } + ], + "functionName": { + "name": "or", + "nativeSrc": "3764:2:381", + "nodeType": "YulIdentifier", + "src": "3764:2:381" + }, + "nativeSrc": "3764:62:381", + "nodeType": "YulFunctionCall", + "src": "3764:62:381" + }, + "nativeSrc": "3761:88:381", + "nodeType": "YulIf", + "src": "3761:88:381" + }, + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "3865:2:381", + "nodeType": "YulLiteral", + "src": "3865:2:381", + "type": "", + "value": "64" + }, + { + "name": "newFreePtr", + "nativeSrc": "3869:10:381", + "nodeType": "YulIdentifier", + "src": "3869:10:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "3858:6:381", + "nodeType": "YulIdentifier", + "src": "3858:6:381" + }, + "nativeSrc": "3858:22:381", + "nodeType": "YulFunctionCall", + "src": "3858:22:381" + }, + "nativeSrc": "3858:22:381", + "nodeType": "YulExpressionStatement", + "src": "3858:22:381" + } + ] + }, + "name": "allocate_memory", + "nativeSrc": "3611:275:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "size", + "nativeSrc": "3636:4:381", + "nodeType": "YulTypedName", + "src": "3636:4:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "memPtr", + "nativeSrc": "3645:6:381", + "nodeType": "YulTypedName", + "src": "3645:6:381", + "type": "" + } + ], + "src": "3611:275:381" + }, + { + "body": { + "nativeSrc": "3977:325:381", + "nodeType": "YulBlock", + "src": "3977:325:381", + "statements": [ + { + "body": { + "nativeSrc": "4021:22:381", + "nodeType": "YulBlock", + "src": "4021:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "4023:16:381", + "nodeType": "YulIdentifier", + "src": "4023:16:381" + }, + "nativeSrc": "4023:18:381", + "nodeType": "YulFunctionCall", + "src": "4023:18:381" + }, + "nativeSrc": "4023:18:381", + "nodeType": "YulExpressionStatement", + "src": "4023:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "length", + "nativeSrc": "3993:6:381", + "nodeType": "YulIdentifier", + "src": "3993:6:381" + }, + { + "kind": "number", + "nativeSrc": "4001:18:381", + "nodeType": "YulLiteral", + "src": "4001:18:381", + "type": "", + "value": "0xffffffffffffffff" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "3990:2:381", + "nodeType": "YulIdentifier", + "src": "3990:2:381" + }, + "nativeSrc": "3990:30:381", + "nodeType": "YulFunctionCall", + "src": "3990:30:381" + }, + "nativeSrc": "3987:56:381", + "nodeType": "YulIf", + "src": "3987:56:381" + }, + { + "nativeSrc": "4052:66:381", + "nodeType": "YulAssignment", + "src": "4052:66:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "length", + "nativeSrc": "4089:6:381", + "nodeType": "YulIdentifier", + "src": "4089:6:381" + }, + { + "kind": "number", + "nativeSrc": "4097:2:381", + "nodeType": "YulLiteral", + "src": "4097:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4085:3:381", + "nodeType": "YulIdentifier", + "src": "4085:3:381" + }, + "nativeSrc": "4085:15:381", + "nodeType": "YulFunctionCall", + "src": "4085:15:381" + }, + { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4106:2:381", + "nodeType": "YulLiteral", + "src": "4106:2:381", + "type": "", + "value": "31" + } + ], + "functionName": { + "name": "not", + "nativeSrc": "4102:3:381", + "nodeType": "YulIdentifier", + "src": "4102:3:381" + }, + "nativeSrc": "4102:7:381", + "nodeType": "YulFunctionCall", + "src": "4102:7:381" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "4081:3:381", + "nodeType": "YulIdentifier", + "src": "4081:3:381" + }, + "nativeSrc": "4081:29:381", + "nodeType": "YulFunctionCall", + "src": "4081:29:381" + }, + { + "kind": "number", + "nativeSrc": "4112:4:381", + "nodeType": "YulLiteral", + "src": "4112:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4077:3:381", + "nodeType": "YulIdentifier", + "src": "4077:3:381" + }, + "nativeSrc": "4077:40:381", + "nodeType": "YulFunctionCall", + "src": "4077:40:381" + } + ], + "functionName": { + "name": "allocate_memory", + "nativeSrc": "4061:15:381", + "nodeType": "YulIdentifier", + "src": "4061:15:381" + }, + "nativeSrc": "4061:57:381", + "nodeType": "YulFunctionCall", + "src": "4061:57:381" + }, + "variableNames": [ + { + "name": "array", + "nativeSrc": "4052:5:381", + "nodeType": "YulIdentifier", + "src": "4052:5:381" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "array", + "nativeSrc": "4134:5:381", + "nodeType": "YulIdentifier", + "src": "4134:5:381" + }, + { + "name": "length", + "nativeSrc": "4141:6:381", + "nodeType": "YulIdentifier", + "src": "4141:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "4127:6:381", + "nodeType": "YulIdentifier", + "src": "4127:6:381" + }, + "nativeSrc": "4127:21:381", + "nodeType": "YulFunctionCall", + "src": "4127:21:381" + }, + "nativeSrc": "4127:21:381", + "nodeType": "YulExpressionStatement", + "src": "4127:21:381" + }, + { + "body": { + "nativeSrc": "4186:16:381", + "nodeType": "YulBlock", + "src": "4186:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4195:1:381", + "nodeType": "YulLiteral", + "src": "4195:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4198:1:381", + "nodeType": "YulLiteral", + "src": "4198:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4188:6:381", + "nodeType": "YulIdentifier", + "src": "4188:6:381" + }, + "nativeSrc": "4188:12:381", + "nodeType": "YulFunctionCall", + "src": "4188:12:381" + }, + "nativeSrc": "4188:12:381", + "nodeType": "YulExpressionStatement", + "src": "4188:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "src", + "nativeSrc": "4167:3:381", + "nodeType": "YulIdentifier", + "src": "4167:3:381" + }, + { + "name": "length", + "nativeSrc": "4172:6:381", + "nodeType": "YulIdentifier", + "src": "4172:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4163:3:381", + "nodeType": "YulIdentifier", + "src": "4163:3:381" + }, + "nativeSrc": "4163:16:381", + "nodeType": "YulFunctionCall", + "src": "4163:16:381" + }, + { + "name": "end", + "nativeSrc": "4181:3:381", + "nodeType": "YulIdentifier", + "src": "4181:3:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "4160:2:381", + "nodeType": "YulIdentifier", + "src": "4160:2:381" + }, + "nativeSrc": "4160:25:381", + "nodeType": "YulFunctionCall", + "src": "4160:25:381" + }, + "nativeSrc": "4157:45:381", + "nodeType": "YulIf", + "src": "4157:45:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "4221:5:381", + "nodeType": "YulIdentifier", + "src": "4221:5:381" + }, + { + "kind": "number", + "nativeSrc": "4228:4:381", + "nodeType": "YulLiteral", + "src": "4228:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4217:3:381", + "nodeType": "YulIdentifier", + "src": "4217:3:381" + }, + "nativeSrc": "4217:16:381", + "nodeType": "YulFunctionCall", + "src": "4217:16:381" + }, + { + "name": "src", + "nativeSrc": "4235:3:381", + "nodeType": "YulIdentifier", + "src": "4235:3:381" + }, + { + "name": "length", + "nativeSrc": "4240:6:381", + "nodeType": "YulIdentifier", + "src": "4240:6:381" + } + ], + "functionName": { + "name": "mcopy", + "nativeSrc": "4211:5:381", + "nodeType": "YulIdentifier", + "src": "4211:5:381" + }, + "nativeSrc": "4211:36:381", + "nodeType": "YulFunctionCall", + "src": "4211:36:381" + }, + "nativeSrc": "4211:36:381", + "nodeType": "YulExpressionStatement", + "src": "4211:36:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "array", + "nativeSrc": "4271:5:381", + "nodeType": "YulIdentifier", + "src": "4271:5:381" + }, + { + "name": "length", + "nativeSrc": "4278:6:381", + "nodeType": "YulIdentifier", + "src": "4278:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4267:3:381", + "nodeType": "YulIdentifier", + "src": "4267:3:381" + }, + "nativeSrc": "4267:18:381", + "nodeType": "YulFunctionCall", + "src": "4267:18:381" + }, + { + "kind": "number", + "nativeSrc": "4287:4:381", + "nodeType": "YulLiteral", + "src": "4287:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4263:3:381", + "nodeType": "YulIdentifier", + "src": "4263:3:381" + }, + "nativeSrc": "4263:29:381", + "nodeType": "YulFunctionCall", + "src": "4263:29:381" + }, + { + "kind": "number", + "nativeSrc": "4294:1:381", + "nodeType": "YulLiteral", + "src": "4294:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "4256:6:381", + "nodeType": "YulIdentifier", + "src": "4256:6:381" + }, + "nativeSrc": "4256:40:381", + "nodeType": "YulFunctionCall", + "src": "4256:40:381" + }, + "nativeSrc": "4256:40:381", + "nodeType": "YulExpressionStatement", + "src": "4256:40:381" + } + ] + }, + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "3891:411:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "src", + "nativeSrc": "3946:3:381", + "nodeType": "YulTypedName", + "src": "3946:3:381", + "type": "" + }, + { + "name": "length", + "nativeSrc": "3951:6:381", + "nodeType": "YulTypedName", + "src": "3951:6:381", + "type": "" + }, + { + "name": "end", + "nativeSrc": "3959:3:381", + "nodeType": "YulTypedName", + "src": "3959:3:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "array", + "nativeSrc": "3967:5:381", + "nodeType": "YulTypedName", + "src": "3967:5:381", + "type": "" + } + ], + "src": "3891:411:381" + }, + { + "body": { + "nativeSrc": "4370:173:381", + "nodeType": "YulBlock", + "src": "4370:173:381", + "statements": [ + { + "body": { + "nativeSrc": "4419:16:381", + "nodeType": "YulBlock", + "src": "4419:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4428:1:381", + "nodeType": "YulLiteral", + "src": "4428:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4431:1:381", + "nodeType": "YulLiteral", + "src": "4431:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4421:6:381", + "nodeType": "YulIdentifier", + "src": "4421:6:381" + }, + "nativeSrc": "4421:12:381", + "nodeType": "YulFunctionCall", + "src": "4421:12:381" + }, + "nativeSrc": "4421:12:381", + "nodeType": "YulExpressionStatement", + "src": "4421:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4398:6:381", + "nodeType": "YulIdentifier", + "src": "4398:6:381" + }, + { + "kind": "number", + "nativeSrc": "4406:4:381", + "nodeType": "YulLiteral", + "src": "4406:4:381", + "type": "", + "value": "0x1f" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4394:3:381", + "nodeType": "YulIdentifier", + "src": "4394:3:381" + }, + "nativeSrc": "4394:17:381", + "nodeType": "YulFunctionCall", + "src": "4394:17:381" + }, + { + "name": "end", + "nativeSrc": "4413:3:381", + "nodeType": "YulIdentifier", + "src": "4413:3:381" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "4390:3:381", + "nodeType": "YulIdentifier", + "src": "4390:3:381" + }, + "nativeSrc": "4390:27:381", + "nodeType": "YulFunctionCall", + "src": "4390:27:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "4383:6:381", + "nodeType": "YulIdentifier", + "src": "4383:6:381" + }, + "nativeSrc": "4383:35:381", + "nodeType": "YulFunctionCall", + "src": "4383:35:381" + }, + "nativeSrc": "4380:55:381", + "nodeType": "YulIf", + "src": "4380:55:381" + }, + { + "nativeSrc": "4444:93:381", + "nodeType": "YulAssignment", + "src": "4444:93:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4503:6:381", + "nodeType": "YulIdentifier", + "src": "4503:6:381" + }, + { + "kind": "number", + "nativeSrc": "4511:4:381", + "nodeType": "YulLiteral", + "src": "4511:4:381", + "type": "", + "value": "0x20" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "4499:3:381", + "nodeType": "YulIdentifier", + "src": "4499:3:381" + }, + "nativeSrc": "4499:17:381", + "nodeType": "YulFunctionCall", + "src": "4499:17:381" + }, + { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4524:6:381", + "nodeType": "YulIdentifier", + "src": "4524:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "4518:5:381", + "nodeType": "YulIdentifier", + "src": "4518:5:381" + }, + "nativeSrc": "4518:13:381", + "nodeType": "YulFunctionCall", + "src": "4518:13:381" + }, + { + "name": "end", + "nativeSrc": "4533:3:381", + "nodeType": "YulIdentifier", + "src": "4533:3:381" + } + ], + "functionName": { + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "4453:45:381", + "nodeType": "YulIdentifier", + "src": "4453:45:381" + }, + "nativeSrc": "4453:84:381", + "nodeType": "YulFunctionCall", + "src": "4453:84:381" + }, + "variableNames": [ + { + "name": "array", + "nativeSrc": "4444:5:381", + "nodeType": "YulIdentifier", + "src": "4444:5:381" + } + ] + } + ] + }, + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "4307:236:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "4344:6:381", + "nodeType": "YulTypedName", + "src": "4344:6:381", + "type": "" + }, + { + "name": "end", + "nativeSrc": "4352:3:381", + "nodeType": "YulTypedName", + "src": "4352:3:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "array", + "nativeSrc": "4360:5:381", + "nodeType": "YulTypedName", + "src": "4360:5:381", + "type": "" + } + ], + "src": "4307:236:381" + }, + { + "body": { + "nativeSrc": "4607:164:381", + "nodeType": "YulBlock", + "src": "4607:164:381", + "statements": [ + { + "nativeSrc": "4617:22:381", + "nodeType": "YulAssignment", + "src": "4617:22:381", + "value": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "4632:6:381", + "nodeType": "YulIdentifier", + "src": "4632:6:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "4626:5:381", + "nodeType": "YulIdentifier", + "src": "4626:5:381" + }, + "nativeSrc": "4626:13:381", + "nodeType": "YulFunctionCall", + "src": "4626:13:381" + }, + "variableNames": [ + { + "name": "value", + "nativeSrc": "4617:5:381", + "nodeType": "YulIdentifier", + "src": "4617:5:381" + } + ] + }, + { + "body": { + "nativeSrc": "4749:16:381", + "nodeType": "YulBlock", + "src": "4749:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "4758:1:381", + "nodeType": "YulLiteral", + "src": "4758:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "4761:1:381", + "nodeType": "YulLiteral", + "src": "4761:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "4751:6:381", + "nodeType": "YulIdentifier", + "src": "4751:6:381" + }, + "nativeSrc": "4751:12:381", + "nodeType": "YulFunctionCall", + "src": "4751:12:381" + }, + "nativeSrc": "4751:12:381", + "nodeType": "YulExpressionStatement", + "src": "4751:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "value", + "nativeSrc": "4661:5:381", + "nodeType": "YulIdentifier", + "src": "4661:5:381" + }, + { + "arguments": [ + { + "name": "value", + "nativeSrc": "4672:5:381", + "nodeType": "YulIdentifier", + "src": "4672:5:381" + }, + { + "kind": "number", + "nativeSrc": "4679:66:381", + "nodeType": "YulLiteral", + "src": "4679:66:381", + "type": "", + "value": "0xffffffff00000000000000000000000000000000000000000000000000000000" + } + ], + "functionName": { + "name": "and", + "nativeSrc": "4668:3:381", + "nodeType": "YulIdentifier", + "src": "4668:3:381" + }, + "nativeSrc": "4668:78:381", + "nodeType": "YulFunctionCall", + "src": "4668:78:381" + } + ], + "functionName": { + "name": "eq", + "nativeSrc": "4658:2:381", + "nodeType": "YulIdentifier", + "src": "4658:2:381" + }, + "nativeSrc": "4658:89:381", + "nodeType": "YulFunctionCall", + "src": "4658:89:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "4651:6:381", + "nodeType": "YulIdentifier", + "src": "4651:6:381" + }, + "nativeSrc": "4651:97:381", + "nodeType": "YulFunctionCall", + "src": "4651:97:381" + }, + "nativeSrc": "4648:117:381", + "nodeType": "YulIf", + "src": "4648:117:381" + } + ] + }, + "name": "abi_decode_bytes4_fromMemory", + "nativeSrc": "4548:223:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "offset", + "nativeSrc": "4586:6:381", + "nodeType": "YulTypedName", + "src": "4586:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value", + "nativeSrc": "4597:5:381", + "nodeType": "YulTypedName", + "src": "4597:5:381", + "type": "" + } + ], + "src": "4548:223:381" + }, + { + "body": { + "nativeSrc": "4985:1642:381", + "nodeType": "YulBlock", + "src": "4985:1642:381", + "statements": [ + { + "body": { + "nativeSrc": "5032:16:381", + "nodeType": "YulBlock", + "src": "5032:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5041:1:381", + "nodeType": "YulLiteral", + "src": "5041:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5044:1:381", + "nodeType": "YulLiteral", + "src": "5044:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5034:6:381", + "nodeType": "YulIdentifier", + "src": "5034:6:381" + }, + "nativeSrc": "5034:12:381", + "nodeType": "YulFunctionCall", + "src": "5034:12:381" + }, + "nativeSrc": "5034:12:381", + "nodeType": "YulExpressionStatement", + "src": "5034:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "name": "dataEnd", + "nativeSrc": "5006:7:381", + "nodeType": "YulIdentifier", + "src": "5006:7:381" + }, + { + "name": "headStart", + "nativeSrc": "5015:9:381", + "nodeType": "YulIdentifier", + "src": "5015:9:381" + } + ], + "functionName": { + "name": "sub", + "nativeSrc": "5002:3:381", + "nodeType": "YulIdentifier", + "src": "5002:3:381" + }, + "nativeSrc": "5002:23:381", + "nodeType": "YulFunctionCall", + "src": "5002:23:381" + }, + { + "kind": "number", + "nativeSrc": "5027:3:381", + "nodeType": "YulLiteral", + "src": "5027:3:381", + "type": "", + "value": "160" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "4998:3:381", + "nodeType": "YulIdentifier", + "src": "4998:3:381" + }, + "nativeSrc": "4998:33:381", + "nodeType": "YulFunctionCall", + "src": "4998:33:381" + }, + "nativeSrc": "4995:53:381", + "nodeType": "YulIf", + "src": "4995:53:381" + }, + { + "nativeSrc": "5057:29:381", + "nodeType": "YulVariableDeclaration", + "src": "5057:29:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5076:9:381", + "nodeType": "YulIdentifier", + "src": "5076:9:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5070:5:381", + "nodeType": "YulIdentifier", + "src": "5070:5:381" + }, + "nativeSrc": "5070:16:381", + "nodeType": "YulFunctionCall", + "src": "5070:16:381" + }, + "variables": [ + { + "name": "value", + "nativeSrc": "5061:5:381", + "nodeType": "YulTypedName", + "src": "5061:5:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "value", + "nativeSrc": "5120:5:381", + "nodeType": "YulIdentifier", + "src": "5120:5:381" + } + ], + "functionName": { + "name": "validator_revert_address", + "nativeSrc": "5095:24:381", + "nodeType": "YulIdentifier", + "src": "5095:24:381" + }, + "nativeSrc": "5095:31:381", + "nodeType": "YulFunctionCall", + "src": "5095:31:381" + }, + "nativeSrc": "5095:31:381", + "nodeType": "YulExpressionStatement", + "src": "5095:31:381" + }, + { + "nativeSrc": "5135:15:381", + "nodeType": "YulAssignment", + "src": "5135:15:381", + "value": { + "name": "value", + "nativeSrc": "5145:5:381", + "nodeType": "YulIdentifier", + "src": "5145:5:381" + }, + "variableNames": [ + { + "name": "value0", + "nativeSrc": "5135:6:381", + "nodeType": "YulIdentifier", + "src": "5135:6:381" + } + ] + }, + { + "nativeSrc": "5159:12:381", + "nodeType": "YulVariableDeclaration", + "src": "5159:12:381", + "value": { + "kind": "number", + "nativeSrc": "5169:2:381", + "nodeType": "YulLiteral", + "src": "5169:2:381", + "type": "", + "value": "32" + }, + "variables": [ + { + "name": "_1", + "nativeSrc": "5163:2:381", + "nodeType": "YulTypedName", + "src": "5163:2:381", + "type": "" + } + ] + }, + { + "nativeSrc": "5180:39:381", + "nodeType": "YulVariableDeclaration", + "src": "5180:39:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5204:9:381", + "nodeType": "YulIdentifier", + "src": "5204:9:381" + }, + { + "name": "_1", + "nativeSrc": "5215:2:381", + "nodeType": "YulIdentifier", + "src": "5215:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5200:3:381", + "nodeType": "YulIdentifier", + "src": "5200:3:381" + }, + "nativeSrc": "5200:18:381", + "nodeType": "YulFunctionCall", + "src": "5200:18:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5194:5:381", + "nodeType": "YulIdentifier", + "src": "5194:5:381" + }, + "nativeSrc": "5194:25:381", + "nodeType": "YulFunctionCall", + "src": "5194:25:381" + }, + "variables": [ + { + "name": "offset", + "nativeSrc": "5184:6:381", + "nodeType": "YulTypedName", + "src": "5184:6:381", + "type": "" + } + ] + }, + { + "nativeSrc": "5228:28:381", + "nodeType": "YulVariableDeclaration", + "src": "5228:28:381", + "value": { + "kind": "number", + "nativeSrc": "5238:18:381", + "nodeType": "YulLiteral", + "src": "5238:18:381", + "type": "", + "value": "0xffffffffffffffff" + }, + "variables": [ + { + "name": "_2", + "nativeSrc": "5232:2:381", + "nodeType": "YulTypedName", + "src": "5232:2:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5283:16:381", + "nodeType": "YulBlock", + "src": "5283:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5292:1:381", + "nodeType": "YulLiteral", + "src": "5292:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5295:1:381", + "nodeType": "YulLiteral", + "src": "5295:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5285:6:381", + "nodeType": "YulIdentifier", + "src": "5285:6:381" + }, + "nativeSrc": "5285:12:381", + "nodeType": "YulFunctionCall", + "src": "5285:12:381" + }, + "nativeSrc": "5285:12:381", + "nodeType": "YulExpressionStatement", + "src": "5285:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset", + "nativeSrc": "5271:6:381", + "nodeType": "YulIdentifier", + "src": "5271:6:381" + }, + { + "name": "_2", + "nativeSrc": "5279:2:381", + "nodeType": "YulIdentifier", + "src": "5279:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5268:2:381", + "nodeType": "YulIdentifier", + "src": "5268:2:381" + }, + "nativeSrc": "5268:14:381", + "nodeType": "YulFunctionCall", + "src": "5268:14:381" + }, + "nativeSrc": "5265:34:381", + "nodeType": "YulIf", + "src": "5265:34:381" + }, + { + "nativeSrc": "5308:32:381", + "nodeType": "YulVariableDeclaration", + "src": "5308:32:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "5322:9:381", + "nodeType": "YulIdentifier", + "src": "5322:9:381" + }, + { + "name": "offset", + "nativeSrc": "5333:6:381", + "nodeType": "YulIdentifier", + "src": "5333:6:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5318:3:381", + "nodeType": "YulIdentifier", + "src": "5318:3:381" + }, + "nativeSrc": "5318:22:381", + "nodeType": "YulFunctionCall", + "src": "5318:22:381" + }, + "variables": [ + { + "name": "_3", + "nativeSrc": "5312:2:381", + "nodeType": "YulTypedName", + "src": "5312:2:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5388:16:381", + "nodeType": "YulBlock", + "src": "5388:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5397:1:381", + "nodeType": "YulLiteral", + "src": "5397:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5400:1:381", + "nodeType": "YulLiteral", + "src": "5400:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5390:6:381", + "nodeType": "YulIdentifier", + "src": "5390:6:381" + }, + "nativeSrc": "5390:12:381", + "nodeType": "YulFunctionCall", + "src": "5390:12:381" + }, + "nativeSrc": "5390:12:381", + "nodeType": "YulExpressionStatement", + "src": "5390:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5367:2:381", + "nodeType": "YulIdentifier", + "src": "5367:2:381" + }, + { + "kind": "number", + "nativeSrc": "5371:4:381", + "nodeType": "YulLiteral", + "src": "5371:4:381", + "type": "", + "value": "0x1f" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5363:3:381", + "nodeType": "YulIdentifier", + "src": "5363:3:381" + }, + "nativeSrc": "5363:13:381", + "nodeType": "YulFunctionCall", + "src": "5363:13:381" + }, + { + "name": "dataEnd", + "nativeSrc": "5378:7:381", + "nodeType": "YulIdentifier", + "src": "5378:7:381" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "5359:3:381", + "nodeType": "YulIdentifier", + "src": "5359:3:381" + }, + "nativeSrc": "5359:27:381", + "nodeType": "YulFunctionCall", + "src": "5359:27:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "5352:6:381", + "nodeType": "YulIdentifier", + "src": "5352:6:381" + }, + "nativeSrc": "5352:35:381", + "nodeType": "YulFunctionCall", + "src": "5352:35:381" + }, + "nativeSrc": "5349:55:381", + "nodeType": "YulIf", + "src": "5349:55:381" + }, + { + "nativeSrc": "5413:19:381", + "nodeType": "YulVariableDeclaration", + "src": "5413:19:381", + "value": { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5429:2:381", + "nodeType": "YulIdentifier", + "src": "5429:2:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5423:5:381", + "nodeType": "YulIdentifier", + "src": "5423:5:381" + }, + "nativeSrc": "5423:9:381", + "nodeType": "YulFunctionCall", + "src": "5423:9:381" + }, + "variables": [ + { + "name": "_4", + "nativeSrc": "5417:2:381", + "nodeType": "YulTypedName", + "src": "5417:2:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5455:22:381", + "nodeType": "YulBlock", + "src": "5455:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x41", + "nativeSrc": "5457:16:381", + "nodeType": "YulIdentifier", + "src": "5457:16:381" + }, + "nativeSrc": "5457:18:381", + "nodeType": "YulFunctionCall", + "src": "5457:18:381" + }, + "nativeSrc": "5457:18:381", + "nodeType": "YulExpressionStatement", + "src": "5457:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "_4", + "nativeSrc": "5447:2:381", + "nodeType": "YulIdentifier", + "src": "5447:2:381" + }, + { + "name": "_2", + "nativeSrc": "5451:2:381", + "nodeType": "YulIdentifier", + "src": "5451:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5444:2:381", + "nodeType": "YulIdentifier", + "src": "5444:2:381" + }, + "nativeSrc": "5444:10:381", + "nodeType": "YulFunctionCall", + "src": "5444:10:381" + }, + "nativeSrc": "5441:36:381", + "nodeType": "YulIf", + "src": "5441:36:381" + }, + { + "nativeSrc": "5486:20:381", + "nodeType": "YulVariableDeclaration", + "src": "5486:20:381", + "value": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5500:1:381", + "nodeType": "YulLiteral", + "src": "5500:1:381", + "type": "", + "value": "5" + }, + { + "name": "_4", + "nativeSrc": "5503:2:381", + "nodeType": "YulIdentifier", + "src": "5503:2:381" + } + ], + "functionName": { + "name": "shl", + "nativeSrc": "5496:3:381", + "nodeType": "YulIdentifier", + "src": "5496:3:381" + }, + "nativeSrc": "5496:10:381", + "nodeType": "YulFunctionCall", + "src": "5496:10:381" + }, + "variables": [ + { + "name": "_5", + "nativeSrc": "5490:2:381", + "nodeType": "YulTypedName", + "src": "5490:2:381", + "type": "" + } + ] + }, + { + "nativeSrc": "5515:39:381", + "nodeType": "YulVariableDeclaration", + "src": "5515:39:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_5", + "nativeSrc": "5546:2:381", + "nodeType": "YulIdentifier", + "src": "5546:2:381" + }, + { + "name": "_1", + "nativeSrc": "5550:2:381", + "nodeType": "YulIdentifier", + "src": "5550:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5542:3:381", + "nodeType": "YulIdentifier", + "src": "5542:3:381" + }, + "nativeSrc": "5542:11:381", + "nodeType": "YulFunctionCall", + "src": "5542:11:381" + } + ], + "functionName": { + "name": "allocate_memory", + "nativeSrc": "5526:15:381", + "nodeType": "YulIdentifier", + "src": "5526:15:381" + }, + "nativeSrc": "5526:28:381", + "nodeType": "YulFunctionCall", + "src": "5526:28:381" + }, + "variables": [ + { + "name": "dst", + "nativeSrc": "5519:3:381", + "nodeType": "YulTypedName", + "src": "5519:3:381", + "type": "" + } + ] + }, + { + "nativeSrc": "5563:16:381", + "nodeType": "YulVariableDeclaration", + "src": "5563:16:381", + "value": { + "name": "dst", + "nativeSrc": "5576:3:381", + "nodeType": "YulIdentifier", + "src": "5576:3:381" + }, + "variables": [ + { + "name": "dst_1", + "nativeSrc": "5567:5:381", + "nodeType": "YulTypedName", + "src": "5567:5:381", + "type": "" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "5595:3:381", + "nodeType": "YulIdentifier", + "src": "5595:3:381" + }, + { + "name": "_4", + "nativeSrc": "5600:2:381", + "nodeType": "YulIdentifier", + "src": "5600:2:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "5588:6:381", + "nodeType": "YulIdentifier", + "src": "5588:6:381" + }, + "nativeSrc": "5588:15:381", + "nodeType": "YulFunctionCall", + "src": "5588:15:381" + }, + "nativeSrc": "5588:15:381", + "nodeType": "YulExpressionStatement", + "src": "5588:15:381" + }, + { + "nativeSrc": "5612:19:381", + "nodeType": "YulAssignment", + "src": "5612:19:381", + "value": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "5623:3:381", + "nodeType": "YulIdentifier", + "src": "5623:3:381" + }, + { + "name": "_1", + "nativeSrc": "5628:2:381", + "nodeType": "YulIdentifier", + "src": "5628:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5619:3:381", + "nodeType": "YulIdentifier", + "src": "5619:3:381" + }, + "nativeSrc": "5619:12:381", + "nodeType": "YulFunctionCall", + "src": "5619:12:381" + }, + "variableNames": [ + { + "name": "dst", + "nativeSrc": "5612:3:381", + "nodeType": "YulIdentifier", + "src": "5612:3:381" + } + ] + }, + { + "nativeSrc": "5640:34:381", + "nodeType": "YulVariableDeclaration", + "src": "5640:34:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5662:2:381", + "nodeType": "YulIdentifier", + "src": "5662:2:381" + }, + { + "name": "_5", + "nativeSrc": "5666:2:381", + "nodeType": "YulIdentifier", + "src": "5666:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5658:3:381", + "nodeType": "YulIdentifier", + "src": "5658:3:381" + }, + "nativeSrc": "5658:11:381", + "nodeType": "YulFunctionCall", + "src": "5658:11:381" + }, + { + "name": "_1", + "nativeSrc": "5671:2:381", + "nodeType": "YulIdentifier", + "src": "5671:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5654:3:381", + "nodeType": "YulIdentifier", + "src": "5654:3:381" + }, + "nativeSrc": "5654:20:381", + "nodeType": "YulFunctionCall", + "src": "5654:20:381" + }, + "variables": [ + { + "name": "srcEnd", + "nativeSrc": "5644:6:381", + "nodeType": "YulTypedName", + "src": "5644:6:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5706:16:381", + "nodeType": "YulBlock", + "src": "5706:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5715:1:381", + "nodeType": "YulLiteral", + "src": "5715:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5718:1:381", + "nodeType": "YulLiteral", + "src": "5718:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5708:6:381", + "nodeType": "YulIdentifier", + "src": "5708:6:381" + }, + "nativeSrc": "5708:12:381", + "nodeType": "YulFunctionCall", + "src": "5708:12:381" + }, + "nativeSrc": "5708:12:381", + "nodeType": "YulExpressionStatement", + "src": "5708:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "srcEnd", + "nativeSrc": "5689:6:381", + "nodeType": "YulIdentifier", + "src": "5689:6:381" + }, + { + "name": "dataEnd", + "nativeSrc": "5697:7:381", + "nodeType": "YulIdentifier", + "src": "5697:7:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5686:2:381", + "nodeType": "YulIdentifier", + "src": "5686:2:381" + }, + "nativeSrc": "5686:19:381", + "nodeType": "YulFunctionCall", + "src": "5686:19:381" + }, + "nativeSrc": "5683:39:381", + "nodeType": "YulIf", + "src": "5683:39:381" + }, + { + "nativeSrc": "5731:22:381", + "nodeType": "YulVariableDeclaration", + "src": "5731:22:381", + "value": { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5746:2:381", + "nodeType": "YulIdentifier", + "src": "5746:2:381" + }, + { + "name": "_1", + "nativeSrc": "5750:2:381", + "nodeType": "YulIdentifier", + "src": "5750:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5742:3:381", + "nodeType": "YulIdentifier", + "src": "5742:3:381" + }, + "nativeSrc": "5742:11:381", + "nodeType": "YulFunctionCall", + "src": "5742:11:381" + }, + "variables": [ + { + "name": "src", + "nativeSrc": "5735:3:381", + "nodeType": "YulTypedName", + "src": "5735:3:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5818:359:381", + "nodeType": "YulBlock", + "src": "5818:359:381", + "statements": [ + { + "nativeSrc": "5832:29:381", + "nodeType": "YulVariableDeclaration", + "src": "5832:29:381", + "value": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5857:3:381", + "nodeType": "YulIdentifier", + "src": "5857:3:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "5851:5:381", + "nodeType": "YulIdentifier", + "src": "5851:5:381" + }, + "nativeSrc": "5851:10:381", + "nodeType": "YulFunctionCall", + "src": "5851:10:381" + }, + "variables": [ + { + "name": "innerOffset", + "nativeSrc": "5836:11:381", + "nodeType": "YulTypedName", + "src": "5836:11:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "5897:16:381", + "nodeType": "YulBlock", + "src": "5897:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "5906:1:381", + "nodeType": "YulLiteral", + "src": "5906:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "5909:1:381", + "nodeType": "YulLiteral", + "src": "5909:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "5899:6:381", + "nodeType": "YulIdentifier", + "src": "5899:6:381" + }, + "nativeSrc": "5899:12:381", + "nodeType": "YulFunctionCall", + "src": "5899:12:381" + }, + "nativeSrc": "5899:12:381", + "nodeType": "YulExpressionStatement", + "src": "5899:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "innerOffset", + "nativeSrc": "5880:11:381", + "nodeType": "YulIdentifier", + "src": "5880:11:381" + }, + { + "name": "_2", + "nativeSrc": "5893:2:381", + "nodeType": "YulIdentifier", + "src": "5893:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "5877:2:381", + "nodeType": "YulIdentifier", + "src": "5877:2:381" + }, + "nativeSrc": "5877:19:381", + "nodeType": "YulFunctionCall", + "src": "5877:19:381" + }, + "nativeSrc": "5874:39:381", + "nodeType": "YulIf", + "src": "5874:39:381" + }, + { + "nativeSrc": "5926:30:381", + "nodeType": "YulVariableDeclaration", + "src": "5926:30:381", + "value": { + "arguments": [ + { + "name": "_3", + "nativeSrc": "5940:2:381", + "nodeType": "YulIdentifier", + "src": "5940:2:381" + }, + { + "name": "innerOffset", + "nativeSrc": "5944:11:381", + "nodeType": "YulIdentifier", + "src": "5944:11:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5936:3:381", + "nodeType": "YulIdentifier", + "src": "5936:3:381" + }, + "nativeSrc": "5936:20:381", + "nodeType": "YulFunctionCall", + "src": "5936:20:381" + }, + "variables": [ + { + "name": "_6", + "nativeSrc": "5930:2:381", + "nodeType": "YulTypedName", + "src": "5930:2:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6006:16:381", + "nodeType": "YulBlock", + "src": "6006:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6015:1:381", + "nodeType": "YulLiteral", + "src": "6015:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6018:1:381", + "nodeType": "YulLiteral", + "src": "6018:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6008:6:381", + "nodeType": "YulIdentifier", + "src": "6008:6:381" + }, + "nativeSrc": "6008:12:381", + "nodeType": "YulFunctionCall", + "src": "6008:12:381" + }, + "nativeSrc": "6008:12:381", + "nodeType": "YulExpressionStatement", + "src": "6008:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "arguments": [ + { + "arguments": [ + { + "name": "_6", + "nativeSrc": "5987:2:381", + "nodeType": "YulIdentifier", + "src": "5987:2:381" + }, + { + "kind": "number", + "nativeSrc": "5991:2:381", + "nodeType": "YulLiteral", + "src": "5991:2:381", + "type": "", + "value": "63" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5983:3:381", + "nodeType": "YulIdentifier", + "src": "5983:3:381" + }, + "nativeSrc": "5983:11:381", + "nodeType": "YulFunctionCall", + "src": "5983:11:381" + }, + { + "name": "dataEnd", + "nativeSrc": "5996:7:381", + "nodeType": "YulIdentifier", + "src": "5996:7:381" + } + ], + "functionName": { + "name": "slt", + "nativeSrc": "5979:3:381", + "nodeType": "YulIdentifier", + "src": "5979:3:381" + }, + "nativeSrc": "5979:25:381", + "nodeType": "YulFunctionCall", + "src": "5979:25:381" + } + ], + "functionName": { + "name": "iszero", + "nativeSrc": "5972:6:381", + "nodeType": "YulIdentifier", + "src": "5972:6:381" + }, + "nativeSrc": "5972:33:381", + "nodeType": "YulFunctionCall", + "src": "5972:33:381" + }, + "nativeSrc": "5969:53:381", + "nodeType": "YulIf", + "src": "5969:53:381" + }, + { + "expression": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "6042:3:381", + "nodeType": "YulIdentifier", + "src": "6042:3:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "_6", + "nativeSrc": "6097:2:381", + "nodeType": "YulIdentifier", + "src": "6097:2:381" + }, + { + "kind": "number", + "nativeSrc": "6101:2:381", + "nodeType": "YulLiteral", + "src": "6101:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6093:3:381", + "nodeType": "YulIdentifier", + "src": "6093:3:381" + }, + "nativeSrc": "6093:11:381", + "nodeType": "YulFunctionCall", + "src": "6093:11:381" + }, + { + "arguments": [ + { + "arguments": [ + { + "name": "_6", + "nativeSrc": "6116:2:381", + "nodeType": "YulIdentifier", + "src": "6116:2:381" + }, + { + "name": "_1", + "nativeSrc": "6120:2:381", + "nodeType": "YulIdentifier", + "src": "6120:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6112:3:381", + "nodeType": "YulIdentifier", + "src": "6112:3:381" + }, + "nativeSrc": "6112:11:381", + "nodeType": "YulFunctionCall", + "src": "6112:11:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6106:5:381", + "nodeType": "YulIdentifier", + "src": "6106:5:381" + }, + "nativeSrc": "6106:18:381", + "nodeType": "YulFunctionCall", + "src": "6106:18:381" + }, + { + "name": "dataEnd", + "nativeSrc": "6126:7:381", + "nodeType": "YulIdentifier", + "src": "6126:7:381" + } + ], + "functionName": { + "name": "abi_decode_available_length_string_fromMemory", + "nativeSrc": "6047:45:381", + "nodeType": "YulIdentifier", + "src": "6047:45:381" + }, + "nativeSrc": "6047:87:381", + "nodeType": "YulFunctionCall", + "src": "6047:87:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "6035:6:381", + "nodeType": "YulIdentifier", + "src": "6035:6:381" + }, + "nativeSrc": "6035:100:381", + "nodeType": "YulFunctionCall", + "src": "6035:100:381" + }, + "nativeSrc": "6035:100:381", + "nodeType": "YulExpressionStatement", + "src": "6035:100:381" + }, + { + "nativeSrc": "6148:19:381", + "nodeType": "YulAssignment", + "src": "6148:19:381", + "value": { + "arguments": [ + { + "name": "dst", + "nativeSrc": "6159:3:381", + "nodeType": "YulIdentifier", + "src": "6159:3:381" + }, + { + "name": "_1", + "nativeSrc": "6164:2:381", + "nodeType": "YulIdentifier", + "src": "6164:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6155:3:381", + "nodeType": "YulIdentifier", + "src": "6155:3:381" + }, + "nativeSrc": "6155:12:381", + "nodeType": "YulFunctionCall", + "src": "6155:12:381" + }, + "variableNames": [ + { + "name": "dst", + "nativeSrc": "6148:3:381", + "nodeType": "YulIdentifier", + "src": "6148:3:381" + } + ] + } + ] + }, + "condition": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5773:3:381", + "nodeType": "YulIdentifier", + "src": "5773:3:381" + }, + { + "name": "srcEnd", + "nativeSrc": "5778:6:381", + "nodeType": "YulIdentifier", + "src": "5778:6:381" + } + ], + "functionName": { + "name": "lt", + "nativeSrc": "5770:2:381", + "nodeType": "YulIdentifier", + "src": "5770:2:381" + }, + "nativeSrc": "5770:15:381", + "nodeType": "YulFunctionCall", + "src": "5770:15:381" + }, + "nativeSrc": "5762:415:381", + "nodeType": "YulForLoop", + "post": { + "nativeSrc": "5786:23:381", + "nodeType": "YulBlock", + "src": "5786:23:381", + "statements": [ + { + "nativeSrc": "5788:19:381", + "nodeType": "YulAssignment", + "src": "5788:19:381", + "value": { + "arguments": [ + { + "name": "src", + "nativeSrc": "5799:3:381", + "nodeType": "YulIdentifier", + "src": "5799:3:381" + }, + { + "name": "_1", + "nativeSrc": "5804:2:381", + "nodeType": "YulIdentifier", + "src": "5804:2:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "5795:3:381", + "nodeType": "YulIdentifier", + "src": "5795:3:381" + }, + "nativeSrc": "5795:12:381", + "nodeType": "YulFunctionCall", + "src": "5795:12:381" + }, + "variableNames": [ + { + "name": "src", + "nativeSrc": "5788:3:381", + "nodeType": "YulIdentifier", + "src": "5788:3:381" + } + ] + } + ] + }, + "pre": { + "nativeSrc": "5766:3:381", + "nodeType": "YulBlock", + "src": "5766:3:381", + "statements": [] + }, + "src": "5762:415:381" + }, + { + "nativeSrc": "6186:15:381", + "nodeType": "YulAssignment", + "src": "6186:15:381", + "value": { + "name": "dst_1", + "nativeSrc": "6196:5:381", + "nodeType": "YulIdentifier", + "src": "6196:5:381" + }, + "variableNames": [ + { + "name": "value1", + "nativeSrc": "6186:6:381", + "nodeType": "YulIdentifier", + "src": "6186:6:381" + } + ] + }, + { + "nativeSrc": "6210:41:381", + "nodeType": "YulVariableDeclaration", + "src": "6210:41:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6236:9:381", + "nodeType": "YulIdentifier", + "src": "6236:9:381" + }, + { + "kind": "number", + "nativeSrc": "6247:2:381", + "nodeType": "YulLiteral", + "src": "6247:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6232:3:381", + "nodeType": "YulIdentifier", + "src": "6232:3:381" + }, + "nativeSrc": "6232:18:381", + "nodeType": "YulFunctionCall", + "src": "6232:18:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6226:5:381", + "nodeType": "YulIdentifier", + "src": "6226:5:381" + }, + "nativeSrc": "6226:25:381", + "nodeType": "YulFunctionCall", + "src": "6226:25:381" + }, + "variables": [ + { + "name": "offset_1", + "nativeSrc": "6214:8:381", + "nodeType": "YulTypedName", + "src": "6214:8:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6280:16:381", + "nodeType": "YulBlock", + "src": "6280:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6289:1:381", + "nodeType": "YulLiteral", + "src": "6289:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6292:1:381", + "nodeType": "YulLiteral", + "src": "6292:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6282:6:381", + "nodeType": "YulIdentifier", + "src": "6282:6:381" + }, + "nativeSrc": "6282:12:381", + "nodeType": "YulFunctionCall", + "src": "6282:12:381" + }, + "nativeSrc": "6282:12:381", + "nodeType": "YulExpressionStatement", + "src": "6282:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset_1", + "nativeSrc": "6266:8:381", + "nodeType": "YulIdentifier", + "src": "6266:8:381" + }, + { + "name": "_2", + "nativeSrc": "6276:2:381", + "nodeType": "YulIdentifier", + "src": "6276:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6263:2:381", + "nodeType": "YulIdentifier", + "src": "6263:2:381" + }, + "nativeSrc": "6263:16:381", + "nodeType": "YulFunctionCall", + "src": "6263:16:381" + }, + "nativeSrc": "6260:36:381", + "nodeType": "YulIf", + "src": "6260:36:381" + }, + { + "nativeSrc": "6305:72:381", + "nodeType": "YulAssignment", + "src": "6305:72:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6347:9:381", + "nodeType": "YulIdentifier", + "src": "6347:9:381" + }, + { + "name": "offset_1", + "nativeSrc": "6358:8:381", + "nodeType": "YulIdentifier", + "src": "6358:8:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6343:3:381", + "nodeType": "YulIdentifier", + "src": "6343:3:381" + }, + "nativeSrc": "6343:24:381", + "nodeType": "YulFunctionCall", + "src": "6343:24:381" + }, + { + "name": "dataEnd", + "nativeSrc": "6369:7:381", + "nodeType": "YulIdentifier", + "src": "6369:7:381" + } + ], + "functionName": { + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "6315:27:381", + "nodeType": "YulIdentifier", + "src": "6315:27:381" + }, + "nativeSrc": "6315:62:381", + "nodeType": "YulFunctionCall", + "src": "6315:62:381" + }, + "variableNames": [ + { + "name": "value2", + "nativeSrc": "6305:6:381", + "nodeType": "YulIdentifier", + "src": "6305:6:381" + } + ] + }, + { + "nativeSrc": "6386:58:381", + "nodeType": "YulAssignment", + "src": "6386:58:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6429:9:381", + "nodeType": "YulIdentifier", + "src": "6429:9:381" + }, + { + "kind": "number", + "nativeSrc": "6440:2:381", + "nodeType": "YulLiteral", + "src": "6440:2:381", + "type": "", + "value": "96" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6425:3:381", + "nodeType": "YulIdentifier", + "src": "6425:3:381" + }, + "nativeSrc": "6425:18:381", + "nodeType": "YulFunctionCall", + "src": "6425:18:381" + } + ], + "functionName": { + "name": "abi_decode_bytes4_fromMemory", + "nativeSrc": "6396:28:381", + "nodeType": "YulIdentifier", + "src": "6396:28:381" + }, + "nativeSrc": "6396:48:381", + "nodeType": "YulFunctionCall", + "src": "6396:48:381" + }, + "variableNames": [ + { + "name": "value3", + "nativeSrc": "6386:6:381", + "nodeType": "YulIdentifier", + "src": "6386:6:381" + } + ] + }, + { + "nativeSrc": "6453:42:381", + "nodeType": "YulVariableDeclaration", + "src": "6453:42:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6479:9:381", + "nodeType": "YulIdentifier", + "src": "6479:9:381" + }, + { + "kind": "number", + "nativeSrc": "6490:3:381", + "nodeType": "YulLiteral", + "src": "6490:3:381", + "type": "", + "value": "128" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6475:3:381", + "nodeType": "YulIdentifier", + "src": "6475:3:381" + }, + "nativeSrc": "6475:19:381", + "nodeType": "YulFunctionCall", + "src": "6475:19:381" + } + ], + "functionName": { + "name": "mload", + "nativeSrc": "6469:5:381", + "nodeType": "YulIdentifier", + "src": "6469:5:381" + }, + "nativeSrc": "6469:26:381", + "nodeType": "YulFunctionCall", + "src": "6469:26:381" + }, + "variables": [ + { + "name": "offset_2", + "nativeSrc": "6457:8:381", + "nodeType": "YulTypedName", + "src": "6457:8:381", + "type": "" + } + ] + }, + { + "body": { + "nativeSrc": "6524:16:381", + "nodeType": "YulBlock", + "src": "6524:16:381", + "statements": [ + { + "expression": { + "arguments": [ + { + "kind": "number", + "nativeSrc": "6533:1:381", + "nodeType": "YulLiteral", + "src": "6533:1:381", + "type": "", + "value": "0" + }, + { + "kind": "number", + "nativeSrc": "6536:1:381", + "nodeType": "YulLiteral", + "src": "6536:1:381", + "type": "", + "value": "0" + } + ], + "functionName": { + "name": "revert", + "nativeSrc": "6526:6:381", + "nodeType": "YulIdentifier", + "src": "6526:6:381" + }, + "nativeSrc": "6526:12:381", + "nodeType": "YulFunctionCall", + "src": "6526:12:381" + }, + "nativeSrc": "6526:12:381", + "nodeType": "YulExpressionStatement", + "src": "6526:12:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "offset_2", + "nativeSrc": "6510:8:381", + "nodeType": "YulIdentifier", + "src": "6510:8:381" + }, + { + "name": "_2", + "nativeSrc": "6520:2:381", + "nodeType": "YulIdentifier", + "src": "6520:2:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6507:2:381", + "nodeType": "YulIdentifier", + "src": "6507:2:381" + }, + "nativeSrc": "6507:16:381", + "nodeType": "YulFunctionCall", + "src": "6507:16:381" + }, + "nativeSrc": "6504:36:381", + "nodeType": "YulIf", + "src": "6504:36:381" + }, + { + "nativeSrc": "6549:72:381", + "nodeType": "YulAssignment", + "src": "6549:72:381", + "value": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6591:9:381", + "nodeType": "YulIdentifier", + "src": "6591:9:381" + }, + { + "name": "offset_2", + "nativeSrc": "6602:8:381", + "nodeType": "YulIdentifier", + "src": "6602:8:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6587:3:381", + "nodeType": "YulIdentifier", + "src": "6587:3:381" + }, + "nativeSrc": "6587:24:381", + "nodeType": "YulFunctionCall", + "src": "6587:24:381" + }, + { + "name": "dataEnd", + "nativeSrc": "6613:7:381", + "nodeType": "YulIdentifier", + "src": "6613:7:381" + } + ], + "functionName": { + "name": "abi_decode_bytes_fromMemory", + "nativeSrc": "6559:27:381", + "nodeType": "YulIdentifier", + "src": "6559:27:381" + }, + "nativeSrc": "6559:62:381", + "nodeType": "YulFunctionCall", + "src": "6559:62:381" + }, + "variableNames": [ + { + "name": "value4", + "nativeSrc": "6549:6:381", + "nodeType": "YulIdentifier", + "src": "6549:6:381" + } + ] + } + ] + }, + "name": "abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory", + "nativeSrc": "4776:1851:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "4919:9:381", + "nodeType": "YulTypedName", + "src": "4919:9:381", + "type": "" + }, + { + "name": "dataEnd", + "nativeSrc": "4930:7:381", + "nodeType": "YulTypedName", + "src": "4930:7:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "value0", + "nativeSrc": "4942:6:381", + "nodeType": "YulTypedName", + "src": "4942:6:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "4950:6:381", + "nodeType": "YulTypedName", + "src": "4950:6:381", + "type": "" + }, + { + "name": "value2", + "nativeSrc": "4958:6:381", + "nodeType": "YulTypedName", + "src": "4958:6:381", + "type": "" + }, + { + "name": "value3", + "nativeSrc": "4966:6:381", + "nodeType": "YulTypedName", + "src": "4966:6:381", + "type": "" + }, + { + "name": "value4", + "nativeSrc": "4974:6:381", + "nodeType": "YulTypedName", + "src": "4974:6:381", + "type": "" + } + ], + "src": "4776:1851:381" + }, + { + "body": { + "nativeSrc": "6680:77:381", + "nodeType": "YulBlock", + "src": "6680:77:381", + "statements": [ + { + "nativeSrc": "6690:16:381", + "nodeType": "YulAssignment", + "src": "6690:16:381", + "value": { + "arguments": [ + { + "name": "x", + "nativeSrc": "6701:1:381", + "nodeType": "YulIdentifier", + "src": "6701:1:381" + }, + { + "name": "y", + "nativeSrc": "6704:1:381", + "nodeType": "YulIdentifier", + "src": "6704:1:381" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6697:3:381", + "nodeType": "YulIdentifier", + "src": "6697:3:381" + }, + "nativeSrc": "6697:9:381", + "nodeType": "YulFunctionCall", + "src": "6697:9:381" + }, + "variableNames": [ + { + "name": "sum", + "nativeSrc": "6690:3:381", + "nodeType": "YulIdentifier", + "src": "6690:3:381" + } + ] + }, + { + "body": { + "nativeSrc": "6729:22:381", + "nodeType": "YulBlock", + "src": "6729:22:381", + "statements": [ + { + "expression": { + "arguments": [], + "functionName": { + "name": "panic_error_0x11", + "nativeSrc": "6731:16:381", + "nodeType": "YulIdentifier", + "src": "6731:16:381" + }, + "nativeSrc": "6731:18:381", + "nodeType": "YulFunctionCall", + "src": "6731:18:381" + }, + "nativeSrc": "6731:18:381", + "nodeType": "YulExpressionStatement", + "src": "6731:18:381" + } + ] + }, + "condition": { + "arguments": [ + { + "name": "x", + "nativeSrc": "6721:1:381", + "nodeType": "YulIdentifier", + "src": "6721:1:381" + }, + { + "name": "sum", + "nativeSrc": "6724:3:381", + "nodeType": "YulIdentifier", + "src": "6724:3:381" + } + ], + "functionName": { + "name": "gt", + "nativeSrc": "6718:2:381", + "nodeType": "YulIdentifier", + "src": "6718:2:381" + }, + "nativeSrc": "6718:10:381", + "nodeType": "YulFunctionCall", + "src": "6718:10:381" + }, + "nativeSrc": "6715:36:381", + "nodeType": "YulIf", + "src": "6715:36:381" + } + ] + }, + "name": "checked_add_t_uint256", + "nativeSrc": "6632:125:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "x", + "nativeSrc": "6663:1:381", + "nodeType": "YulTypedName", + "src": "6663:1:381", + "type": "" + }, + { + "name": "y", + "nativeSrc": "6666:1:381", + "nodeType": "YulTypedName", + "src": "6666:1:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "sum", + "nativeSrc": "6672:3:381", + "nodeType": "YulTypedName", + "src": "6672:3:381", + "type": "" + } + ], + "src": "6632:125:381" + }, + { + "body": { + "nativeSrc": "6891:119:381", + "nodeType": "YulBlock", + "src": "6891:119:381", + "statements": [ + { + "nativeSrc": "6901:26:381", + "nodeType": "YulAssignment", + "src": "6901:26:381", + "value": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6913:9:381", + "nodeType": "YulIdentifier", + "src": "6913:9:381" + }, + { + "kind": "number", + "nativeSrc": "6924:2:381", + "nodeType": "YulLiteral", + "src": "6924:2:381", + "type": "", + "value": "64" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6909:3:381", + "nodeType": "YulIdentifier", + "src": "6909:3:381" + }, + "nativeSrc": "6909:18:381", + "nodeType": "YulFunctionCall", + "src": "6909:18:381" + }, + "variableNames": [ + { + "name": "tail", + "nativeSrc": "6901:4:381", + "nodeType": "YulIdentifier", + "src": "6901:4:381" + } + ] + }, + { + "expression": { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6943:9:381", + "nodeType": "YulIdentifier", + "src": "6943:9:381" + }, + { + "name": "value0", + "nativeSrc": "6954:6:381", + "nodeType": "YulIdentifier", + "src": "6954:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "6936:6:381", + "nodeType": "YulIdentifier", + "src": "6936:6:381" + }, + "nativeSrc": "6936:25:381", + "nodeType": "YulFunctionCall", + "src": "6936:25:381" + }, + "nativeSrc": "6936:25:381", + "nodeType": "YulExpressionStatement", + "src": "6936:25:381" + }, + { + "expression": { + "arguments": [ + { + "arguments": [ + { + "name": "headStart", + "nativeSrc": "6981:9:381", + "nodeType": "YulIdentifier", + "src": "6981:9:381" + }, + { + "kind": "number", + "nativeSrc": "6992:2:381", + "nodeType": "YulLiteral", + "src": "6992:2:381", + "type": "", + "value": "32" + } + ], + "functionName": { + "name": "add", + "nativeSrc": "6977:3:381", + "nodeType": "YulIdentifier", + "src": "6977:3:381" + }, + "nativeSrc": "6977:18:381", + "nodeType": "YulFunctionCall", + "src": "6977:18:381" + }, + { + "name": "value1", + "nativeSrc": "6997:6:381", + "nodeType": "YulIdentifier", + "src": "6997:6:381" + } + ], + "functionName": { + "name": "mstore", + "nativeSrc": "6970:6:381", + "nodeType": "YulIdentifier", + "src": "6970:6:381" + }, + "nativeSrc": "6970:34:381", + "nodeType": "YulFunctionCall", + "src": "6970:34:381" + }, + "nativeSrc": "6970:34:381", + "nodeType": "YulExpressionStatement", + "src": "6970:34:381" + } + ] + }, + "name": "abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed", + "nativeSrc": "6762:248:381", + "nodeType": "YulFunctionDefinition", + "parameters": [ + { + "name": "headStart", + "nativeSrc": "6852:9:381", + "nodeType": "YulTypedName", + "src": "6852:9:381", + "type": "" + }, + { + "name": "value1", + "nativeSrc": "6863:6:381", + "nodeType": "YulTypedName", + "src": "6863:6:381", + "type": "" + }, + { + "name": "value0", + "nativeSrc": "6871:6:381", + "nodeType": "YulTypedName", + "src": "6871:6:381", + "type": "" + } + ], + "returnVariables": [ + { + "name": "tail", + "nativeSrc": "6882:4:381", + "nodeType": "YulTypedName", + "src": "6882:4:381", + "type": "" + } + ], + "src": "6762:248:381" + } + ] + }, + "contents": "{\n { }\n function abi_encode_tuple_packed_t_bytes_calldata_ptr__to_t_bytes_memory_ptr__nonPadded_inplace_fromStack_reversed(pos, value1, value0) -> end\n {\n calldatacopy(pos, value0, value1)\n let _1 := add(pos, value1)\n mstore(_1, 0)\n end := _1\n }\n function convert_bytes_to_fixedbytes_from_t_bytes_memory_ptr_to_t_bytes4(array) -> value\n {\n let length := mload(array)\n let _1 := mload(add(array, 0x20))\n let _2 := 0xffffffff00000000000000000000000000000000000000000000000000000000\n value := and(_1, _2)\n if lt(length, 4)\n {\n value := and(and(_1, shl(shl(3, sub(4, length)), _2)), _2)\n }\n }\n function panic_error_0x11()\n {\n mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)\n mstore(4, 0x11)\n revert(0, 0x24)\n }\n function checked_sub_t_uint256(x, y) -> diff\n {\n diff := sub(x, y)\n if gt(diff, x) { panic_error_0x11() }\n }\n function abi_encode_string(value, pos) -> end\n {\n let length := mload(value)\n mstore(pos, length)\n mcopy(add(pos, 0x20), add(value, 0x20), length)\n mstore(add(add(pos, length), 0x20), 0)\n end := add(add(pos, and(add(length, 31), not(31))), 0x20)\n }\n function abi_encode_bytes4(value, pos)\n {\n mstore(pos, and(value, 0xffffffff00000000000000000000000000000000000000000000000000000000))\n }\n function abi_encode_tuple_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__to_t_address_t_array$_t_string_memory_ptr_$dyn_memory_ptr_t_bytes_memory_ptr_t_bytes4_t_bytes_memory_ptr__fromStack_reversed(headStart, value4, value3, value2, value1, value0) -> tail\n {\n let tail_1 := add(headStart, 160)\n mstore(headStart, and(value0, 0xffffffffffffffffffffffffffffffffffffffff))\n let _1 := 32\n mstore(add(headStart, 32), 160)\n let pos := tail_1\n let length := mload(value1)\n mstore(tail_1, length)\n pos := add(headStart, 192)\n let tail_2 := add(add(headStart, shl(5, length)), 192)\n let srcPtr := add(value1, 32)\n let i := 0\n for { } lt(i, length) { i := add(i, 1) }\n {\n mstore(pos, add(sub(tail_2, headStart), not(191)))\n tail_2 := abi_encode_string(mload(srcPtr), tail_2)\n srcPtr := add(srcPtr, _1)\n pos := add(pos, _1)\n }\n mstore(add(headStart, 64), sub(tail_2, headStart))\n let tail_3 := abi_encode_string(value2, tail_2)\n abi_encode_bytes4(value3, add(headStart, 96))\n mstore(add(headStart, 128), sub(tail_3, headStart))\n tail := abi_encode_string(value4, tail_3)\n }\n function validator_revert_address(value)\n {\n if iszero(eq(value, and(value, 0xffffffffffffffffffffffffffffffffffffffff))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_address(headStart, dataEnd) -> value0\n {\n if slt(sub(dataEnd, headStart), 32) { revert(0, 0) }\n let value := calldataload(headStart)\n validator_revert_address(value)\n value0 := value\n }\n function abi_encode_tuple_t_address__to_t_address__fromStack_reversed(headStart, value0) -> tail\n {\n tail := add(headStart, 32)\n mstore(headStart, and(value0, 0xffffffffffffffffffffffffffffffffffffffff))\n }\n function panic_error_0x41()\n {\n mstore(0, 35408467139433450592217433187231851964531694900788300625387963629091585785856)\n mstore(4, 0x41)\n revert(0, 0x24)\n }\n function allocate_memory(size) -> memPtr\n {\n memPtr := mload(64)\n let newFreePtr := add(memPtr, and(add(size, 31), not(31)))\n if or(gt(newFreePtr, 0xffffffffffffffff), lt(newFreePtr, memPtr)) { panic_error_0x41() }\n mstore(64, newFreePtr)\n }\n function abi_decode_available_length_string_fromMemory(src, length, end) -> array\n {\n if gt(length, 0xffffffffffffffff) { panic_error_0x41() }\n array := allocate_memory(add(and(add(length, 31), not(31)), 0x20))\n mstore(array, length)\n if gt(add(src, length), end) { revert(0, 0) }\n mcopy(add(array, 0x20), src, length)\n mstore(add(add(array, length), 0x20), 0)\n }\n function abi_decode_bytes_fromMemory(offset, end) -> array\n {\n if iszero(slt(add(offset, 0x1f), end)) { revert(0, 0) }\n array := abi_decode_available_length_string_fromMemory(add(offset, 0x20), mload(offset), end)\n }\n function abi_decode_bytes4_fromMemory(offset) -> value\n {\n value := mload(offset)\n if iszero(eq(value, and(value, 0xffffffff00000000000000000000000000000000000000000000000000000000))) { revert(0, 0) }\n }\n function abi_decode_tuple_t_address_payablet_array$_t_string_memory_ptr_$dyn_memory_ptrt_bytes_memory_ptrt_bytes4t_bytes_memory_ptr_fromMemory(headStart, dataEnd) -> value0, value1, value2, value3, value4\n {\n if slt(sub(dataEnd, headStart), 160) { revert(0, 0) }\n let value := mload(headStart)\n validator_revert_address(value)\n value0 := value\n let _1 := 32\n let offset := mload(add(headStart, _1))\n let _2 := 0xffffffffffffffff\n if gt(offset, _2) { revert(0, 0) }\n let _3 := add(headStart, offset)\n if iszero(slt(add(_3, 0x1f), dataEnd)) { revert(0, 0) }\n let _4 := mload(_3)\n if gt(_4, _2) { panic_error_0x41() }\n let _5 := shl(5, _4)\n let dst := allocate_memory(add(_5, _1))\n let dst_1 := dst\n mstore(dst, _4)\n dst := add(dst, _1)\n let srcEnd := add(add(_3, _5), _1)\n if gt(srcEnd, dataEnd) { revert(0, 0) }\n let src := add(_3, _1)\n for { } lt(src, srcEnd) { src := add(src, _1) }\n {\n let innerOffset := mload(src)\n if gt(innerOffset, _2) { revert(0, 0) }\n let _6 := add(_3, innerOffset)\n if iszero(slt(add(_6, 63), dataEnd)) { revert(0, 0) }\n mstore(dst, abi_decode_available_length_string_fromMemory(add(_6, 64), mload(add(_6, _1)), dataEnd))\n dst := add(dst, _1)\n }\n value1 := dst_1\n let offset_1 := mload(add(headStart, 64))\n if gt(offset_1, _2) { revert(0, 0) }\n value2 := abi_decode_bytes_fromMemory(add(headStart, offset_1), dataEnd)\n value3 := abi_decode_bytes4_fromMemory(add(headStart, 96))\n let offset_2 := mload(add(headStart, 128))\n if gt(offset_2, _2) { revert(0, 0) }\n value4 := abi_decode_bytes_fromMemory(add(headStart, offset_2), dataEnd)\n }\n function checked_add_t_uint256(x, y) -> sum\n {\n sum := add(x, y)\n if gt(x, sum) { panic_error_0x11() }\n }\n function abi_encode_tuple_t_uint256_t_uint256__to_t_uint256_t_uint256__fromStack_reversed(headStart, value1, value0) -> tail\n {\n tail := add(headStart, 64)\n mstore(headStart, value0)\n mstore(add(headStart, 32), value1)\n }\n}", + "id": 381, + "language": "Yul", + "name": "#utility.yul" + } + ], + "immutableReferences": {}, + "linkReferences": {}, + "object": "608060405234801561000f575f80fd5b506004361061004a575f3560e01c80633659cfe6146101765780635c60da1b146101895780638bad0c0a146101ad578063f851a440146101b5575b5f806100546101bd565b6001600160a01b03165f3660405161006d929190610639565b5f60405180830381855afa9150503d805f81146100a5576040519150601f19603f3d011682016040523d82523d5f602084013e6100aa565b606091505b5091509150811580156100d55750630556f18360e41b6100c982610648565b6001600160e01b031916145b1561015e575f6100fb6100f68360048086516100f19190610693565b6101ef565b61024b565b90506101056101bd565b6001600160a01b0316815f01516001600160a01b03160361015c57308160200151826040015183606001518460800151604051630556f18360e41b81526004016101539594939291906106da565b60405180910390fd5b505b811561016c57805160208201f35b805160208201fd5b005b61017461018436600461079a565b6102b6565b610191610375565b6040516001600160a01b03909116815260200160405180910390f35b610174610383565b610191610406565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b546001600160a01b0316919050565b60608167ffffffffffffffff81111561020a5761020a6107b5565b6040519080825280601f01601f191660200182016040528015610234576020820181803683370190505b5090506102448484835f8661040f565b9392505050565b6040805160a0810182525f808252606060208301819052928201839052828201526080810191909152818060200190518101906102889190610889565b60808601526001600160e01b0319166060850152604084015260208301526001600160a01b03168152919050565b6102be61044c565b6001600160a01b0316336001600160a01b0316146102ef5760405163036c8cf960e11b815260040160405180910390fd5b6102f881610473565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790556040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b5f61037e6101bd565b905090565b61038b61044c565b6001600160a01b0316336001600160a01b0316146103bc5760405163036c8cf960e11b815260040160405180910390fd5b5f6103c561044c565b90506103d05f61051d565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f905f90a250565b5f61037e61044c565b6104228561041d83876109c4565b6105a4565b6104308361041d83856109c4565b610445826020850101856020880101836105f0565b5050505050565b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036101e0565b6001600160a01b038116158061049157506001600160a01b0381163b155b156104c8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001600160a01b03166104da6101bd565b6001600160a01b03160361051a576040517f4c3b76bf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b5f61052661044c565b9050817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03928316179055604051838216918316907f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f905f90a35050565b81518111156105ec5781516040517f8a3c1cfb000000000000000000000000000000000000000000000000000000008152610153918391600401918252602082015260400190565b5050565b5b601f811115610611578151835260209283019290910190601f19016105f1565b801561063457815183516001602084900360031b1b5f1901801990921691161783525b505050565b818382375f9101908152919050565b5f815160208301516001600160e01b0319808216935060048310156106775780818460040360031b1b83161693505b505050919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156106a6576106a661067f565b92915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f60a082016001600160a01b0388168352602060a0602085015281885180845260c08601915060c08160051b870101935060208a015f5b8281101561073f5760bf1988870301845261072d8683516106ac565b95509284019290840190600101610711565b5050505050828103604084015261075681876106ac565b6001600160e01b0319861660608501529050828103608084015261077a81856106ac565b98975050505050505050565b6001600160a01b038116811461051a575f80fd5b5f602082840312156107aa575f80fd5b813561024481610786565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156107f2576107f26107b5565b604052919050565b5f67ffffffffffffffff831115610813576108136107b5565b610826601f8401601f19166020016107c9565b9050828152838383011115610839575f80fd5b8282602083015e5f602084830101529392505050565b5f82601f83011261085e575f80fd5b610244838351602085016107fa565b80516001600160e01b031981168114610884575f80fd5b919050565b5f805f805f60a0868803121561089d575f80fd5b85516108a881610786565b8095505060208087015167ffffffffffffffff808211156108c7575f80fd5b818901915089601f8301126108da575f80fd5b8151818111156108ec576108ec6107b5565b8060051b6108fb8582016107c9565b918252838101850191858101908d841115610914575f80fd5b86860192505b8383101561096157825185811115610930575f80fd5b8601603f81018f13610940575f80fd5b6109518f89830151604084016107fa565b835250918601919086019061091a565b60408d0151909a5095505050508083111561097a575f80fd5b6109868a848b0161084f565b955061099460608a0161086d565b945060808901519250808311156109a9575f80fd5b50506109b78882890161084f565b9150509295509295909350565b808201808211156106a6576106a661067f56fea2646970667358221220b497e606fddd22fd3bdcf262866dcd9d2d07fa9e7b15191a16b45ee0405c434e64736f6c63430008190033", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0xF JUMPI PUSH0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4A JUMPI PUSH0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x3659CFE6 EQ PUSH2 0x176 JUMPI DUP1 PUSH4 0x5C60DA1B EQ PUSH2 0x189 JUMPI DUP1 PUSH4 0x8BAD0C0A EQ PUSH2 0x1AD JUMPI DUP1 PUSH4 0xF851A440 EQ PUSH2 0x1B5 JUMPI JUMPDEST PUSH0 DUP1 PUSH2 0x54 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH0 CALLDATASIZE PUSH1 0x40 MLOAD PUSH2 0x6D SWAP3 SWAP2 SWAP1 PUSH2 0x639 JUMP JUMPDEST PUSH0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 GAS STATICCALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH0 DUP2 EQ PUSH2 0xA5 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0xAA JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 ISZERO DUP1 ISZERO PUSH2 0xD5 JUMPI POP PUSH4 0x556F183 PUSH1 0xE4 SHL PUSH2 0xC9 DUP3 PUSH2 0x648 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND EQ JUMPDEST ISZERO PUSH2 0x15E JUMPI PUSH0 PUSH2 0xFB PUSH2 0xF6 DUP4 PUSH1 0x4 DUP1 DUP7 MLOAD PUSH2 0xF1 SWAP2 SWAP1 PUSH2 0x693 JUMP JUMPDEST PUSH2 0x1EF JUMP JUMPDEST PUSH2 0x24B JUMP JUMPDEST SWAP1 POP PUSH2 0x105 PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 PUSH0 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x15C JUMPI ADDRESS DUP2 PUSH1 0x20 ADD MLOAD DUP3 PUSH1 0x40 ADD MLOAD DUP4 PUSH1 0x60 ADD MLOAD DUP5 PUSH1 0x80 ADD MLOAD PUSH1 0x40 MLOAD PUSH4 0x556F183 PUSH1 0xE4 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x153 SWAP6 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x6DA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMPDEST DUP2 ISZERO PUSH2 0x16C JUMPI DUP1 MLOAD PUSH1 0x20 DUP3 ADD RETURN JUMPDEST DUP1 MLOAD PUSH1 0x20 DUP3 ADD REVERT JUMPDEST STOP JUMPDEST PUSH2 0x174 PUSH2 0x184 CALLDATASIZE PUSH1 0x4 PUSH2 0x79A JUMP JUMPDEST PUSH2 0x2B6 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x375 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x174 PUSH2 0x383 JUMP JUMPDEST PUSH2 0x191 PUSH2 0x406 JUMP JUMPDEST PUSH0 PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC JUMPDEST SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x60 DUP2 PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x20A JUMPI PUSH2 0x20A PUSH2 0x7B5 JUMP JUMPDEST PUSH1 0x40 MLOAD SWAP1 DUP1 DUP3 MSTORE DUP1 PUSH1 0x1F ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD DUP3 ADD PUSH1 0x40 MSTORE DUP1 ISZERO PUSH2 0x234 JUMPI PUSH1 0x20 DUP3 ADD DUP2 DUP1 CALLDATASIZE DUP4 CALLDATACOPY ADD SWAP1 POP JUMPDEST POP SWAP1 POP PUSH2 0x244 DUP5 DUP5 DUP4 PUSH0 DUP7 PUSH2 0x40F JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0xA0 DUP2 ADD DUP3 MSTORE PUSH0 DUP1 DUP3 MSTORE PUSH1 0x60 PUSH1 0x20 DUP4 ADD DUP2 SWAP1 MSTORE SWAP3 DUP3 ADD DUP4 SWAP1 MSTORE DUP3 DUP3 ADD MSTORE PUSH1 0x80 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP2 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD DUP2 ADD SWAP1 PUSH2 0x288 SWAP2 SWAP1 PUSH2 0x889 JUMP JUMPDEST PUSH1 0x80 DUP7 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT AND PUSH1 0x60 DUP6 ADD MSTORE PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x20 DUP4 ADD MSTORE PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH2 0x2BE PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x2EF JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH2 0x2F8 DUP2 PUSH2 0x473 JUMP JUMPDEST PUSH32 0x360894A13BA1A3210667C828492DB98DCA3E2076CC3735A920A3CA505D382BBC DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xBC7CD75A20EE27FD9ADEBAB32041F755214DBC6BFFA90CC0225B39DA2E5C2D3B SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x1BD JUMP JUMPDEST SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x38B PUSH2 0x44C JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND CALLER PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND EQ PUSH2 0x3BC JUMPI PUSH1 0x40 MLOAD PUSH4 0x36C8CF9 PUSH1 0xE1 SHL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH0 PUSH2 0x3C5 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP PUSH2 0x3D0 PUSH0 PUSH2 0x51D JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP3 AND SWAP1 PUSH32 0xA3B62BC36326052D97EA62D63C3D60308ED4C3EA8AC079DD8499F1E9C4F80C0F SWAP1 PUSH0 SWAP1 LOG2 POP JUMP JUMPDEST PUSH0 PUSH2 0x37E PUSH2 0x44C JUMP JUMPDEST PUSH2 0x422 DUP6 PUSH2 0x41D DUP4 DUP8 PUSH2 0x9C4 JUMP JUMPDEST PUSH2 0x5A4 JUMP JUMPDEST PUSH2 0x430 DUP4 PUSH2 0x41D DUP4 DUP6 PUSH2 0x9C4 JUMP JUMPDEST PUSH2 0x445 DUP3 PUSH1 0x20 DUP6 ADD ADD DUP6 PUSH1 0x20 DUP9 ADD ADD DUP4 PUSH2 0x5F0 JUMP JUMPDEST POP POP POP POP POP JUMP JUMPDEST PUSH0 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 PUSH2 0x1E0 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND ISZERO DUP1 PUSH2 0x491 JUMPI POP PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND EXTCODESIZE ISZERO JUMPDEST ISZERO PUSH2 0x4C8 JUMPI PUSH1 0x40 MLOAD PUSH32 0x68155F9A00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST DUP1 PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND PUSH2 0x4DA PUSH2 0x1BD JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB AND SUB PUSH2 0x51A JUMPI PUSH1 0x40 MLOAD PUSH32 0x4C3B76BF00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH0 PUSH2 0x526 PUSH2 0x44C JUMP JUMPDEST SWAP1 POP DUP2 PUSH32 0xB53127684A568B3173AE13B9F8A6016E243E63B6E8EE1178D6A717850B5D6103 DUP1 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF NOT AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP3 DUP4 AND OR SWAP1 SSTORE PUSH1 0x40 MLOAD DUP4 DUP3 AND SWAP2 DUP4 AND SWAP1 PUSH32 0x7E644D79422F17C01E4894B5F4F588D331EBFA28653D42AE832DC59E38C9798F SWAP1 PUSH0 SWAP1 LOG3 POP POP JUMP JUMPDEST DUP2 MLOAD DUP2 GT ISZERO PUSH2 0x5EC JUMPI DUP2 MLOAD PUSH1 0x40 MLOAD PUSH32 0x8A3C1CFB00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x153 SWAP2 DUP4 SWAP2 PUSH1 0x4 ADD SWAP2 DUP3 MSTORE PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x40 ADD SWAP1 JUMP JUMPDEST POP POP JUMP JUMPDEST JUMPDEST PUSH1 0x1F DUP2 GT ISZERO PUSH2 0x611 JUMPI DUP2 MLOAD DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1F NOT ADD PUSH2 0x5F1 JUMP JUMPDEST DUP1 ISZERO PUSH2 0x634 JUMPI DUP2 MLOAD DUP4 MLOAD PUSH1 0x1 PUSH1 0x20 DUP5 SWAP1 SUB PUSH1 0x3 SHL SHL PUSH0 NOT ADD DUP1 NOT SWAP1 SWAP3 AND SWAP2 AND OR DUP4 MSTORE JUMPDEST POP POP POP JUMP JUMPDEST DUP2 DUP4 DUP3 CALLDATACOPY PUSH0 SWAP2 ADD SWAP1 DUP2 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP2 MLOAD PUSH1 0x20 DUP4 ADD MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP1 DUP3 AND SWAP4 POP PUSH1 0x4 DUP4 LT ISZERO PUSH2 0x677 JUMPI DUP1 DUP2 DUP5 PUSH1 0x4 SUB PUSH1 0x3 SHL SHL DUP4 AND AND SWAP4 POP JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x11 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST DUP2 DUP2 SUB DUP2 DUP2 GT ISZERO PUSH2 0x6A6 JUMPI PUSH2 0x6A6 PUSH2 0x67F JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 DUP2 MLOAD DUP1 DUP5 MSTORE DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP7 ADD MCOPY PUSH0 PUSH1 0x20 DUP3 DUP7 ADD ADD MSTORE PUSH1 0x20 PUSH1 0x1F NOT PUSH1 0x1F DUP4 ADD AND DUP6 ADD ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH0 PUSH1 0xA0 DUP3 ADD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP9 AND DUP4 MSTORE PUSH1 0x20 PUSH1 0xA0 PUSH1 0x20 DUP6 ADD MSTORE DUP2 DUP9 MLOAD DUP1 DUP5 MSTORE PUSH1 0xC0 DUP7 ADD SWAP2 POP PUSH1 0xC0 DUP2 PUSH1 0x5 SHL DUP8 ADD ADD SWAP4 POP PUSH1 0x20 DUP11 ADD PUSH0 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x73F JUMPI PUSH1 0xBF NOT DUP9 DUP8 SUB ADD DUP5 MSTORE PUSH2 0x72D DUP7 DUP4 MLOAD PUSH2 0x6AC JUMP JUMPDEST SWAP6 POP SWAP3 DUP5 ADD SWAP3 SWAP1 DUP5 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x711 JUMP JUMPDEST POP POP POP POP POP DUP3 DUP2 SUB PUSH1 0x40 DUP5 ADD MSTORE PUSH2 0x756 DUP2 DUP8 PUSH2 0x6AC JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP7 AND PUSH1 0x60 DUP6 ADD MSTORE SWAP1 POP DUP3 DUP2 SUB PUSH1 0x80 DUP5 ADD MSTORE PUSH2 0x77A DUP2 DUP6 PUSH2 0x6AC JUMP JUMPDEST SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB DUP2 AND DUP2 EQ PUSH2 0x51A JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x7AA JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0x244 DUP2 PUSH2 0x786 JUMP JUMPDEST PUSH4 0x4E487B71 PUSH1 0xE0 SHL PUSH0 MSTORE PUSH1 0x41 PUSH1 0x4 MSTORE PUSH1 0x24 PUSH0 REVERT JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x1F DUP3 ADD PUSH1 0x1F NOT AND DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x7F2 JUMPI PUSH2 0x7F2 PUSH2 0x7B5 JUMP JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 PUSH8 0xFFFFFFFFFFFFFFFF DUP4 GT ISZERO PUSH2 0x813 JUMPI PUSH2 0x813 PUSH2 0x7B5 JUMP JUMPDEST PUSH2 0x826 PUSH1 0x1F DUP5 ADD PUSH1 0x1F NOT AND PUSH1 0x20 ADD PUSH2 0x7C9 JUMP JUMPDEST SWAP1 POP DUP3 DUP2 MSTORE DUP4 DUP4 DUP4 ADD GT ISZERO PUSH2 0x839 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP3 DUP3 PUSH1 0x20 DUP4 ADD MCOPY PUSH0 PUSH1 0x20 DUP5 DUP4 ADD ADD MSTORE SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x85E JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x244 DUP4 DUP4 MLOAD PUSH1 0x20 DUP6 ADD PUSH2 0x7FA JUMP JUMPDEST DUP1 MLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xE0 SHL SUB NOT DUP2 AND DUP2 EQ PUSH2 0x884 JUMPI PUSH0 DUP1 REVERT JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH0 DUP1 PUSH0 DUP1 PUSH0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0x89D JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP6 MLOAD PUSH2 0x8A8 DUP2 PUSH2 0x786 JUMP JUMPDEST DUP1 SWAP6 POP POP PUSH1 0x20 DUP1 DUP8 ADD MLOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x8C7 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 DUP10 ADD SWAP2 POP DUP10 PUSH1 0x1F DUP4 ADD SLT PUSH2 0x8DA JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP2 MLOAD DUP2 DUP2 GT ISZERO PUSH2 0x8EC JUMPI PUSH2 0x8EC PUSH2 0x7B5 JUMP JUMPDEST DUP1 PUSH1 0x5 SHL PUSH2 0x8FB DUP6 DUP3 ADD PUSH2 0x7C9 JUMP JUMPDEST SWAP2 DUP3 MSTORE DUP4 DUP2 ADD DUP6 ADD SWAP2 DUP6 DUP2 ADD SWAP1 DUP14 DUP5 GT ISZERO PUSH2 0x914 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP7 DUP7 ADD SWAP3 POP JUMPDEST DUP4 DUP4 LT ISZERO PUSH2 0x961 JUMPI DUP3 MLOAD DUP6 DUP2 GT ISZERO PUSH2 0x930 JUMPI PUSH0 DUP1 REVERT JUMPDEST DUP7 ADD PUSH1 0x3F DUP2 ADD DUP16 SGT PUSH2 0x940 JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x951 DUP16 DUP10 DUP4 ADD MLOAD PUSH1 0x40 DUP5 ADD PUSH2 0x7FA JUMP JUMPDEST DUP4 MSTORE POP SWAP2 DUP7 ADD SWAP2 SWAP1 DUP7 ADD SWAP1 PUSH2 0x91A JUMP JUMPDEST PUSH1 0x40 DUP14 ADD MLOAD SWAP1 SWAP11 POP SWAP6 POP POP POP POP DUP1 DUP4 GT ISZERO PUSH2 0x97A JUMPI PUSH0 DUP1 REVERT JUMPDEST PUSH2 0x986 DUP11 DUP5 DUP12 ADD PUSH2 0x84F JUMP JUMPDEST SWAP6 POP PUSH2 0x994 PUSH1 0x60 DUP11 ADD PUSH2 0x86D JUMP JUMPDEST SWAP5 POP PUSH1 0x80 DUP10 ADD MLOAD SWAP3 POP DUP1 DUP4 GT ISZERO PUSH2 0x9A9 JUMPI PUSH0 DUP1 REVERT JUMPDEST POP POP PUSH2 0x9B7 DUP9 DUP3 DUP10 ADD PUSH2 0x84F JUMP JUMPDEST SWAP2 POP POP SWAP3 SWAP6 POP SWAP3 SWAP6 SWAP1 SWAP4 POP JUMP JUMPDEST DUP1 DUP3 ADD DUP1 DUP3 GT ISZERO PUSH2 0x6A6 JUMPI PUSH2 0x6A6 PUSH2 0x67F JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0xB4 SWAP8 0xE6 MOD REVERT 0xDD 0x22 REVERT EXTCODESIZE 0xDC CALLCODE PUSH3 0x866DCD SWAP14 0x2D SMOD STATICCALL SWAP15 PUSH28 0x15191A16B45EE0405C434E64736F6C63430008190033000000000000 ", + "sourceMap": "490:6212:360:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3416:7;3425:14;3443:20;:18;:20::i;:::-;-1:-1:-1;;;;;3443:31:360;3475:8;;3443:41;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3415:69;;;;3499:2;3498:3;:43;;;;-1:-1:-1;;;;3505:9:360;3512:1;3505:9;:::i;:::-;-1:-1:-1;;;;;;3505:36:360;;3498:43;3494:447;;;3557:23;3583:56;3598:40;3619:1;3622;3636;3625;:8;:12;;;;:::i;:::-;3598:20;:40::i;:::-;3583:14;:56::i;:::-;3557:82;;3669:20;:18;:20::i;:::-;-1:-1:-1;;;;;3657:32:360;:1;:8;;;-1:-1:-1;;;;;3657:32:360;;3653:278;;3760:4;3787:1;:6;;;3815:1;:10;;;3847:1;:18;;;3887:1;:11;;;3716:200;;-1:-1:-1;;;3716:200:360;;;;;;;;;;;;:::i;:::-;;;;;;;;3653:278;3543:398;3494:447;3955:2;3951:200;;;4025:1;4019:8;4014:2;4011:1;4007:10;4000:28;3951:200;4124:1;4118:8;4113:2;4110:1;4106:10;4099:28;3951:200;3405:752;4280:213;;;;;;:::i;:::-;;:::i;4822:102::-;;;:::i;:::-;;;-1:-1:-1;;;;;3355:55:381;;;3337:74;;3325:2;3310:18;4822:102:360;;;;;;;4589:167;;;:::i;4981:84::-;;;:::i;5708:140::-;5761:7;841:66;5787:48;:54;-1:-1:-1;;;;;5787:54:360;;5708:140;-1:-1:-1;5708:140:360:o;8960:218:130:-;9077:17;9123:3;9113:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9113:14:130;;9106:21;;9137:34;9147:4;9153:3;9158:4;9164:1;9167:3;9137:9;:34::i;:::-;8960:218;;;;;:::o;752:224:3:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;924:1:3;900:69;;;;;;;;;;;;:::i;:::-;885:11;;;834:135;-1:-1:-1;;;;;;834:135:3;865:18;;;834:135;853:10;;;834:135;845:6;;;834:135;-1:-1:-1;;;;;834:135:3;;;835:1;752:224;-1:-1:-1;752:224:3:o;4280:213:360:-;2517:11;:9;:11::i;:::-;-1:-1:-1;;;;;2503:25:360;:10;-1:-1:-1;;;;;2503:25:360;;2499:66;;2549:16;;-1:-1:-1;;;2549:16:360;;;;;;;;;;;2499:66;4355:42:::1;4379:17;4355:23;:42::i;:::-;841:66:::0;6350:74;;-1:-1:-1;;6350:74:360;-1:-1:-1;;;;;6350:74:360;;;;;4459:27:::1;::::0;-1:-1:-1;;;;;4459:27:360;::::1;::::0;::::1;::::0;;;::::1;4280:213:::0;:::o;4822:102::-;4871:7;4897:20;:18;:20::i;:::-;4890:27;;4822:102;:::o;4589:167::-;2517:11;:9;:11::i;:::-;-1:-1:-1;;;;;2503:25:360;:10;-1:-1:-1;;;;;2503:25:360;;2499:66;;2549:16;;-1:-1:-1;;;2549:16:360;;;;;;;;;;;2499:66;4643:20:::1;4666:11;:9;:11::i;:::-;4643:34;;4687:21;4705:1;4687:9;:21::i;:::-;4723:26;::::0;-1:-1:-1;;;;;4723:26:360;::::1;::::0;::::1;::::0;;;::::1;4633:123;4589:167::o:0;4981:84::-;5021:7;5047:11;:9;:11::i;8279:427:130:-;8451:31;8463:4;8469:12;8478:3;8469:6;:12;:::i;:::-;8451:11;:31::i;:::-;8492;8504:4;8510:12;8519:3;8510:6;:12;:::i;8492:31::-;8557:132;8605:6;1271:2:137;1264:10;;8586:25:130;8648:6;1271:2:137;1264:10;;8629:25:130;8672:3;8557:11;:132::i;:::-;8279:427;;;;;:::o;5912:122:360:-;5956:7;1019:66;5982:39;1899:163:257;5307:328:360;-1:-1:-1;;;;;5395:31:360;;;;:69;;-1:-1:-1;;;;;;5430:29:360;;;:34;5395:69;5391:130;;;5487:23;;;;;;;;;;;;;;5391:130;5558:17;-1:-1:-1;;;;;5534:41:360;:20;:18;:20::i;:::-;-1:-1:-1;;;;;5534:41:360;;5530:99;;5598:20;;;;;;;;;;;;;;5530:99;5307:328;:::o;6485:215::-;6540:21;6564:11;:9;:11::i;:::-;6540:35;-1:-1:-1;6633:8:360;1019:66;6585:56;;-1:-1:-1;;6585:56:360;-1:-1:-1;;;;;6585:56:360;;;;;;6656:37;;;;;;;;;;;-1:-1:-1;;6656:37:360;6530:170;6485:215;:::o;338:169:130:-;422:1;:8;416:3;:14;412:89;;;481:8;;453:37;;;;;;;476:3;;453:37;;6936:25:381;;;6992:2;6977:18;;6970:34;6924:2;6909:18;;6762:248;412:89:130;338:169;;:::o;327:671:137:-;512:185;527:2;522:3;519:11;512:185;;;564:10;;552:23;;608:2;599:12;;;;635;;;;-1:-1:-1;;671:12:137;512:185;;;749:3;746:236;;;852:10;;907;;817:1;802:2;798:12;;;795:1;791:20;787:28;-1:-1:-1;;783:36:137;864:9;;848:26;;;903:21;;953:14;941:27;;746:236;327:671;;;:::o;14:271:381:-;197:6;189;184:3;171:33;153:3;223:16;;248:13;;;223:16;14:271;-1:-1:-1;14:271:381:o;290:407::-;373:5;413;407:12;455:4;448:5;444:16;438:23;-1:-1:-1;;;;;;572:2:381;568;564:11;555:20;;598:1;590:6;587:13;584:107;;;678:2;672;662:6;659:1;655:14;652:1;648:22;644:31;640:2;636:40;632:49;623:58;;584:107;;;;290:407;;;:::o;702:184::-;-1:-1:-1;;;751:1:381;744:88;851:4;848:1;841:15;875:4;872:1;865:15;891:128;958:9;;;979:11;;;976:37;;;993:18;;:::i;:::-;891:128;;;;:::o;1024:289::-;1066:3;1104:5;1098:12;1131:6;1126:3;1119:19;1187:6;1180:4;1173:5;1169:16;1162:4;1157:3;1153:14;1147:47;1239:1;1232:4;1223:6;1218:3;1214:16;1210:27;1203:38;1302:4;1295:2;1291:7;1286:2;1278:6;1274:15;1270:29;1265:3;1261:39;1257:50;1250:57;;;1024:289;;;;:::o;1473:1302::-;1781:4;1829:3;1818:9;1814:19;-1:-1:-1;;;;;1864:6:381;1860:55;1849:9;1842:74;1935:2;1973:3;1968:2;1957:9;1953:18;1946:31;1997:6;2032;2026:13;2063:6;2055;2048:22;2101:3;2090:9;2086:19;2079:26;;2164:3;2154:6;2151:1;2147:14;2136:9;2132:30;2128:40;2114:54;;2203:2;2195:6;2191:15;2224:1;2234:256;2248:6;2245:1;2242:13;2234:256;;;2341:3;2337:8;2325:9;2317:6;2313:22;2309:37;2304:3;2297:50;2370:40;2403:6;2394;2388:13;2370:40;:::i;:::-;2360:50;-1:-1:-1;2468:12:381;;;;2433:15;;;;2270:1;2263:9;2234:256;;;2238:3;;;;;2538:9;2530:6;2526:22;2521:2;2510:9;2506:18;2499:50;2572:33;2598:6;2590;2572:33;:::i;:::-;-1:-1:-1;;;;;;1383:78:381;;2655:2;2640:18;;1371:91;2558:47;-1:-1:-1;2708:9:381;2700:6;2696:22;2690:3;2679:9;2675:19;2668:51;2736:33;2762:6;2754;2736:33;:::i;:::-;2728:41;1473:1302;-1:-1:-1;;;;;;;;1473:1302:381:o;2780:154::-;-1:-1:-1;;;;;2859:5:381;2855:54;2848:5;2845:65;2835:93;;2924:1;2921;2914:12;2939:247;2998:6;3051:2;3039:9;3030:7;3026:23;3022:32;3019:52;;;3067:1;3064;3057:12;3019:52;3106:9;3093:23;3125:31;3150:5;3125:31;:::i;3422:184::-;-1:-1:-1;;;3471:1:381;3464:88;3571:4;3568:1;3561:15;3595:4;3592:1;3585:15;3611:275;3682:2;3676:9;3747:2;3728:13;;-1:-1:-1;;3724:27:381;3712:40;;3782:18;3767:34;;3803:22;;;3764:62;3761:88;;;3829:18;;:::i;:::-;3865:2;3858:22;3611:275;;-1:-1:-1;3611:275:381:o;3891:411::-;3967:5;4001:18;3993:6;3990:30;3987:56;;;4023:18;;:::i;:::-;4061:57;4106:2;4085:15;;-1:-1:-1;;4081:29:381;4112:4;4077:40;4061:57;:::i;:::-;4052:66;;4141:6;4134:5;4127:21;4181:3;4172:6;4167:3;4163:16;4160:25;4157:45;;;4198:1;4195;4188:12;4157:45;4240:6;4235:3;4228:4;4221:5;4217:16;4211:36;4294:1;4287:4;4278:6;4271:5;4267:18;4263:29;4256:40;3891:411;;;;;:::o;4307:236::-;4360:5;4413:3;4406:4;4398:6;4394:17;4390:27;4380:55;;4431:1;4428;4421:12;4380:55;4453:84;4533:3;4524:6;4518:13;4511:4;4503:6;4499:17;4453:84;:::i;4548:223::-;4626:13;;-1:-1:-1;;;;;;4668:78:381;;4658:89;;4648:117;;4761:1;4758;4751:12;4648:117;4548:223;;;:::o;4776:1851::-;4942:6;4950;4958;4966;4974;5027:3;5015:9;5006:7;5002:23;4998:33;4995:53;;;5044:1;5041;5034:12;4995:53;5076:9;5070:16;5095:31;5120:5;5095:31;:::i;:::-;5145:5;5135:15;;;5169:2;5215;5204:9;5200:18;5194:25;5238:18;5279:2;5271:6;5268:14;5265:34;;;5295:1;5292;5285:12;5265:34;5333:6;5322:9;5318:22;5308:32;;5378:7;5371:4;5367:2;5363:13;5359:27;5349:55;;5400:1;5397;5390:12;5349:55;5429:2;5423:9;5451:2;5447;5444:10;5441:36;;;5457:18;;:::i;:::-;5503:2;5500:1;5496:10;5526:28;5550:2;5546;5542:11;5526:28;:::i;:::-;5588:15;;;5658:11;;;5654:20;;;5619:12;;;;5686:19;;;5683:39;;;5718:1;5715;5708:12;5683:39;5750:2;5746;5742:11;5731:22;;5762:415;5778:6;5773:3;5770:15;5762:415;;;5857:3;5851:10;5893:2;5880:11;5877:19;5874:39;;;5909:1;5906;5899:12;5874:39;5936:20;;5991:2;5983:11;;5979:25;-1:-1:-1;5969:53:381;;6018:1;6015;6008:12;5969:53;6047:87;6126:7;6120:2;6116;6112:11;6106:18;6101:2;6097;6093:11;6047:87;:::i;:::-;6035:100;;-1:-1:-1;5795:12:381;;;;6155;;;;5762:415;;;6247:2;6232:18;;6226:25;6196:5;;-1:-1:-1;6226:25:381;-1:-1:-1;;;;6263:16:381;;;6260:36;;;6292:1;6289;6282:12;6260:36;6315:62;6369:7;6358:8;6347:9;6343:24;6315:62;:::i;:::-;6305:72;;6396:48;6440:2;6429:9;6425:18;6396:48;:::i;:::-;6386:58;;6490:3;6479:9;6475:19;6469:26;6453:42;;6520:2;6510:8;6507:16;6504:36;;;6536:1;6533;6526:12;6504:36;;;6559:62;6613:7;6602:8;6591:9;6587:24;6559:62;:::i;:::-;6549:72;;;4776:1851;;;;;;;;:::o;6632:125::-;6697:9;;;6718:10;;;6715:36;;;6731:18;;:::i" + }, + "gasEstimates": { + "creation": { + "codeDepositCost": "514600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "": "infinite", + "admin()": "2430", + "implementation()": "2375", + "renounceAdmin()": "infinite", + "upgradeTo(address)": "infinite" + }, + "internal": { + "_getAdmin()": "2152", + "_getImplementation()": "2141", + "_setAdmin(address)": "27982", + "_setImplementation(address)": "infinite", + "_validateImplementation(address)": "infinite" + } + }, + "methodIdentifiers": { + "admin()": "f851a440", + "implementation()": "5c60da1b", + "renounceAdmin()": "8bad0c0a", + "upgradeTo(address)": "3659cfe6" + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CallerNotAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"string[]\",\"name\":\"urls\",\"type\":\"string[]\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes4\",\"name\":\"callbackFunction\",\"type\":\"bytes4\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"OffchainLookup\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"offset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"OffsetOutOfBoundsError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SameImplementation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"AdminRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"CallerNotAdmin()\":[{\"details\":\"Error selector: `0x06d919f2`\"}],\"InvalidImplementation()\":[{\"details\":\"Error selector: `0x68155f9a`\"}],\"OffchainLookup(address,string[],bytes,bytes4,bytes)\":[{\"details\":\"https://eips.ethereum.org/EIPS/eip-3668 Error selector: `0x556f1830`\"}],\"OffsetOutOfBoundsError(uint256,uint256)\":[{\"details\":\"`offset` was beyond `length`. Error selector: `0x8a3c1cfb`\"}],\"SameImplementation()\":[{\"details\":\"Error selector: `0x4c3b76bf`\"}]},\"events\":{\"AdminChanged(address,address)\":{\"params\":{\"newAdmin\":\"The new admin address\",\"previousAdmin\":\"The previous admin address\"}},\"AdminRemoved(address)\":{\"params\":{\"admin\":\"The admin address that was removed\"}},\"Upgraded(address)\":{\"params\":{\"implementation\":\"The new implementation address\"}}},\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"admin_\":\"The address of the admin\",\"implementation_\":\"The address of the implementation\"}},\"upgradeTo(address)\":{\"params\":{\"newImplementation\":\"Address of the new implementation\"}}},\"stateVariables\":{\"_ADMIN_SLOT\":{\"details\":\"Storage slot for admin (EIP-1967 compatible)\"},\"_IMPLEMENTATION_SLOT\":{\"details\":\"Storage slot for implementation address (EIP-1967 compatible)\"}},\"title\":\"UpgradableUniversalResolverProxy\",\"version\":1},\"userdoc\":{\"events\":{\"AdminChanged(address,address)\":{\"notice\":\"Event emitted when the admin is changed.\"},\"AdminRemoved(address)\":{\"notice\":\"Event emitted when the admin is removed.\"},\"Upgraded(address)\":{\"notice\":\"Event emitted when the implementation is upgraded.\"}},\"kind\":\"user\",\"methods\":{\"admin()\":{\"notice\":\"Returns the current admin address.\"},\"implementation()\":{\"notice\":\"Returns the current implementation address.\"},\"renounceAdmin()\":{\"notice\":\"Allows admin to revoke their admin rights by setting admin to address(0).\"},\"upgradeTo(address)\":{\"notice\":\"Upgrades to a new implementation.\"}},\"notice\":\"A specialized proxy for UniversalResolver that forwards method calls and properly handles CCIP-Read reverts. Admin can upgrade the implementation.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/universalResolver/UpgradableUniversalResolverProxy.sol\":\"UpgradableUniversalResolverProxy\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@ensdomains/solsha1/contracts/=project/lib/solsha1/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts-v5/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/ens-contracts/:@unruggable/gateways/=project/lib/unruggable-gateways/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts-upgradeable/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ccipRead/EIP3668.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @dev https://eips.ethereum.org/EIPS/eip-3668\\n/// Error selector: `0x556f1830`\\nerror OffchainLookup(\\n address sender,\\n string[] urls,\\n bytes callData,\\n bytes4 callbackFunction,\\n bytes extraData\\n);\\n\\n/// @dev Simple library for decoding `OffchainLookup` error data.\\n/// Avoids \\\"stack too deep\\\" issues as the natural decoding consumes 5 variables.\\nlibrary EIP3668 {\\n /// @dev Struct with members matching `OffchainLookup`.\\n struct Params {\\n address sender;\\n string[] urls;\\n bytes callData;\\n bytes4 callbackFunction;\\n bytes extraData;\\n }\\n\\n /// @dev Decode an `OffchainLookup` into a struct from the data after the error selector.\\n function decode(bytes memory v) internal pure returns (Params memory p) {\\n (p.sender, p.urls, p.callData, p.callbackFunction, p.extraData) = abi\\n .decode(v, (address, string[], bytes, bytes4, bytes));\\n }\\n}\\n\",\"keccak256\":\"0x14619de0f3d9f085e6209767b35c2888b8d2af6d787af535f30db7b51e843bf8\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport {LibMem} from \\\"./LibMem/LibMem.sol\\\";\\n\\nlibrary BytesUtils {\\n /// @dev `offset` was beyond `length`.\\n /// Error selector: `0x8a3c1cfb`\\n error OffsetOutOfBoundsError(uint256 offset, uint256 length);\\n\\n /// @dev Assert `end` is not beyond the length of `v`.\\n function _checkBound(bytes memory v, uint256 end) internal pure {\\n if (end > v.length) {\\n revert OffsetOutOfBoundsError(end, v.length);\\n }\\n }\\n\\n /// @dev Compute `keccak256(v[off:off+len])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to hash.\\n /// @return ret The corresponding hash.\\n function keccak(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n ret := keccak256(add(add(v, 32), off), len)\\n }\\n }\\n\\n /// @dev Lexicographically compare two byte strings.\\n /// @param vA The first bytes to compare.\\n /// @param vB The second bytes to compare.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (int256) {\\n return compare(vA, 0, vA.length, vB, 0, vB.length);\\n }\\n\\n /// @dev Lexicographically compare two byte ranges: `A = vA[offA:offA+lenA]` and `B = vB[offB:offB+lenB]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset of the first bytes.\\n /// @param lenA The length of the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset of the second bytes.\\n /// @param lenB The length of the second bytes.\\n /// @return Positive number if `A > B`, negative number if `A < B`, or zero if `A == B`.\\n function compare(\\n bytes memory vA,\\n uint256 offA,\\n uint256 lenA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 lenB\\n ) internal pure returns (int256) {\\n _checkBound(vA, offA + lenA);\\n _checkBound(vB, offB + lenB);\\n unchecked {\\n uint256 ptrA = LibMem.ptr(vA) + offA;\\n uint256 ptrB = LibMem.ptr(vB) + offB;\\n uint256 shortest = lenA < lenB ? lenA : lenB;\\n for (uint256 i; i < shortest; i += 32) {\\n uint256 a = LibMem.load(ptrA + i);\\n uint256 b = LibMem.load(ptrB + i);\\n if (a != b) {\\n uint256 rest = shortest - i;\\n if (rest < 32) {\\n rest = (32 - rest) << 3; // bits to drop\\n a >>= rest; // shift out the\\n b >>= rest; // irrelevant bits\\n }\\n if (a < b) {\\n return -1;\\n } else if (a > b) {\\n return 1;\\n }\\n }\\n }\\n }\\n return int256(lenA) - int256(lenB);\\n }\\n\\n /// @dev Determine if `a[offA:offA+len] == b[offB:offB+len]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @param len The number of bytes to compare.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB,\\n uint256 len\\n ) internal pure returns (bool) {\\n return keccak(vA, offA, len) == keccak(vB, offB, len);\\n }\\n\\n /// @dev Determine if `a[offA:] == b[offB:]`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @param offB The offset into the second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB,\\n uint256 offB\\n ) internal pure returns (bool) {\\n _checkBound(vA, offA);\\n _checkBound(vB, offB);\\n unchecked {\\n return\\n keccak(vA, offA, vA.length - offA) ==\\n keccak(vB, offB, vB.length - offB);\\n }\\n }\\n\\n /// @dev Determine if `a[offA:] == b`.\\n /// @param vA The first bytes.\\n /// @param offA The offset into the first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the byte ranges are equal.\\n function equals(\\n bytes memory vA,\\n uint256 offA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return\\n vA.length == offA + vB.length &&\\n keccak(vA, offA, vB.length) == keccak256(vB);\\n }\\n\\n /// @dev Determine if `a == b`.\\n /// @param vA The first bytes.\\n /// @param vB The second bytes.\\n /// @return True if the bytes are equal.\\n function equals(\\n bytes memory vA,\\n bytes memory vB\\n ) internal pure returns (bool) {\\n return vA.length == vB.length && keccak256(vA) == keccak256(vB);\\n }\\n\\n /// @dev Returns `uint8(v[off])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return The corresponding `uint8`.\\n function readUint8(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint8) {\\n _checkBound(v, off + 1);\\n unchecked {\\n return uint8(v[off]);\\n }\\n }\\n\\n /// @dev Returns `uint16(bytes2(v[off:off+2]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint16`.\\n function readUint16(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint16 ret) {\\n _checkBound(v, off + 2);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(240, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `uint32(bytes4(v[off:off+4]))`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `uint32`.\\n function readUint32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (uint32 ret) {\\n _checkBound(v, off + 4);\\n assembly (\\\"memory-safe\\\") {\\n ret := shr(224, mload(add(add(v, 32), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes20(v[off:off+20])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes20`.\\n function readBytes20(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes20 ret) {\\n _checkBound(v, off + 20);\\n assembly (\\\"memory-safe\\\") {\\n ret := shl(96, mload(add(add(v, 20), off)))\\n }\\n }\\n\\n /// @dev Returns `bytes32(v[off:off+32])`.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @return ret The corresponding `bytes32`.\\n function readBytes32(\\n bytes memory v,\\n uint256 off\\n ) internal pure returns (bytes32 ret) {\\n _checkBound(v, off + 32);\\n assembly (\\\"memory-safe\\\") {\\n ret := mload(add(add(v, 32), off))\\n }\\n }\\n\\n /// @dev Returns `bytes32(bytesN(v[off:off+len]))`.\\n /// Accepts 0-32 bytes or reverts.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes.\\n /// @return ret The corresponding N-bytes left-aligned in a `bytes32`.\\n function readBytesN(\\n bytes memory v,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes32 ret) {\\n assert(len <= 32);\\n _checkBound(v, off + len);\\n assembly (\\\"memory-safe\\\") {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1) // <(32-N)x00>\\n ret := and(mload(add(add(v, 32), off)), not(mask))\\n }\\n }\\n\\n /// @dev Copy `vSrc[offSrc:offSrc+len]` to `vDst[offDst:offDst:len]`.\\n /// @param vSrc The source bytes.\\n /// @param offSrc The offset into the source to begin the copy.\\n /// @param vDst The destination bytes.\\n /// @param offDst The offset into the destination to place the copy.\\n /// @param len The number of bytes to copy.\\n function copyBytes(\\n bytes memory vSrc,\\n uint256 offSrc,\\n bytes memory vDst,\\n uint256 offDst,\\n uint256 len\\n ) internal pure {\\n _checkBound(vSrc, offSrc + len);\\n _checkBound(vDst, offDst + len);\\n unchecked {\\n LibMem.copy(\\n LibMem.ptr(vDst) + offDst,\\n LibMem.ptr(vSrc) + offSrc,\\n len\\n );\\n }\\n }\\n\\n /// @dev Copies a substring into a new byte string.\\n /// @param vSrc The byte string to copy from.\\n /// @param off The offset to start copying at.\\n /// @param len The number of bytes to copy.\\n /// @return vDst The copied substring.\\n function substring(\\n bytes memory vSrc,\\n uint256 off,\\n uint256 len\\n ) internal pure returns (bytes memory vDst) {\\n vDst = new bytes(len);\\n copyBytes(vSrc, off, vDst, 0, len);\\n }\\n\\n /// @dev Find the first occurrence of `needle`.\\n /// @param v The bytes to search.\\n /// @param off The offset to start searching.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return The offset of `needle`, or `type(uint256).max` if not found.\\n function find(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (uint256) {\\n for (uint256 end = off + len; off < end; off++) {\\n if (v[off] == needle) {\\n return off;\\n }\\n }\\n return type(uint256).max;\\n }\\n\\n /// @dev Returns `true` if word contains a zero byte.\\n function hasZeroByte(uint256 word) internal pure returns (bool) {\\n unchecked {\\n return\\n ((~word &\\n (word -\\n 0x0101010101010101010101010101010101010101010101010101010101010101)) &\\n 0x8080808080808080808080808080808080808080808080808080808080808080) !=\\n 0;\\n }\\n }\\n\\n /// @dev Efficiently check if `v[off:off+len]` contains `needle` byte.\\n /// @param v The source bytes.\\n /// @param off The offset into the source.\\n /// @param len The number of bytes to search.\\n /// @param needle The byte to search for.\\n /// @return found `true` if `needle` was found.\\n function includes(\\n bytes memory v,\\n uint256 off,\\n uint256 len,\\n bytes1 needle\\n ) internal pure returns (bool found) {\\n _checkBound(v, off + len);\\n unchecked {\\n uint256 wide = uint8(needle);\\n wide |= wide << 8;\\n wide |= wide << 16;\\n wide |= wide << 32;\\n wide |= wide << 64;\\n wide |= wide << 128; // broadcast byte across word\\n off += LibMem.ptr(v);\\n len += off;\\n while (off < len) {\\n uint256 word = LibMem.load(off) ^ wide; // zero needle byte\\n off += 32;\\n if (hasZeroByte(word)) {\\n return\\n off <= len ||\\n hasZeroByte(\\n word | ((1 << ((off - len) << 3)) - 1) // recheck overflow by making it nonzero\\n );\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\"},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"content\":\"//SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\nlibrary LibMem {\\n /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`.\\n /// Equivalent to `mcopy()`.\\n ///\\n /// @param src The source memory offset.\\n /// @param dst The destination memory offset.\\n /// @param len The number of bytes to copy.\\n function copy(uint256 dst, uint256 src, uint256 len) internal pure {\\n assembly {\\n // Copy word-length chunks while possible\\n // prettier-ignore\\n for {} gt(len, 31) {} {\\n mstore(dst, mload(src))\\n dst := add(dst, 32)\\n src := add(src, 32)\\n len := sub(len, 32)\\n }\\n // Copy remaining bytes\\n if len {\\n let mask := sub(shl(shl(3, sub(32, len)), 1), 1)\\n let wSrc := and(mload(src), not(mask))\\n let wDst := and(mload(dst), mask)\\n mstore(dst, or(wSrc, wDst))\\n }\\n }\\n }\\n\\n /// @dev Convert bytes to a memory offset.\\n ///\\n /// @param v The bytes to convert.\\n ///\\n /// @return ret The corresponding memory offset.\\n function ptr(bytes memory v) internal pure returns (uint256 ret) {\\n assembly {\\n ret := add(v, 32)\\n }\\n }\\n\\n /// @dev Read word at memory offset.\\n ///\\n /// @param src The memory offset.\\n ///\\n /// @return ret The read word.\\n function load(uint256 src) internal pure returns (uint256 ret) {\\n assembly {\\n ret := mload(src)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/src/universalResolver/UpgradableUniversalResolverProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport {EIP3668, OffchainLookup} from \\\"@ens/contracts/ccipRead/EIP3668.sol\\\";\\nimport {BytesUtils} from \\\"@ens/contracts/utils/BytesUtils.sol\\\";\\nimport {StorageSlot} from \\\"@openzeppelin/contracts/utils/StorageSlot.sol\\\";\\n\\n/// @title UpgradableUniversalResolverProxy\\n/// @notice A specialized proxy for UniversalResolver that forwards method calls\\n/// and properly handles CCIP-Read reverts. Admin can upgrade the implementation.\\ncontract UpgradableUniversalResolverProxy {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Storage slot for implementation address (EIP-1967 compatible)\\n bytes32 private constant _IMPLEMENTATION_SLOT =\\n 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @dev Storage slot for admin (EIP-1967 compatible)\\n bytes32 private constant _ADMIN_SLOT =\\n 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Event emitted when the implementation is upgraded.\\n /// @param implementation The new implementation address\\n event Upgraded(address indexed implementation);\\n\\n /// @notice Event emitted when the admin is changed.\\n /// @param previousAdmin The previous admin address\\n /// @param newAdmin The new admin address\\n event AdminChanged(address indexed previousAdmin, address indexed newAdmin);\\n\\n /// @notice Event emitted when the admin is removed.\\n /// @param admin The admin address that was removed\\n event AdminRemoved(address indexed admin);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x06d919f2`\\n error CallerNotAdmin();\\n\\n /// @dev Error selector: `0x68155f9a`\\n error InvalidImplementation();\\n\\n /// @dev Error selector: `0x4c3b76bf`\\n error SameImplementation();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier restricting a function to the admin.\\n modifier onlyAdmin() {\\n if (msg.sender != _getAdmin())\\n revert CallerNotAdmin();\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param admin_ The address of the admin\\n /// @param implementation_ The address of the implementation\\n constructor(address admin_, address implementation_) {\\n _validateImplementation(implementation_);\\n _setImplementation(implementation_);\\n _setAdmin(admin_);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Fallback function that handles forwarding calls to the implementation\\n /// and properly manages CCIP-Read reverts.\\n fallback() external {\\n (bool ok, bytes memory v) = _getImplementation().staticcall(msg.data);\\n if (!ok && bytes4(v) == OffchainLookup.selector) {\\n EIP3668.Params memory p = EIP3668.decode(BytesUtils.substring(v, 4, v.length - 4));\\n if (p.sender == _getImplementation()) {\\n revert OffchainLookup(\\n address(this),\\n p.urls,\\n p.callData,\\n p.callbackFunction,\\n p.extraData\\n );\\n }\\n }\\n\\n if (ok) {\\n assembly {\\n return(add(v, 32), mload(v))\\n }\\n } else {\\n assembly {\\n revert(add(v, 32), mload(v))\\n }\\n }\\n }\\n\\n /// @notice Upgrades to a new implementation.\\n /// @param newImplementation Address of the new implementation\\n function upgradeTo(address newImplementation) external onlyAdmin {\\n _validateImplementation(newImplementation);\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /// @notice Allows admin to revoke their admin rights by setting admin to address(0).\\n function renounceAdmin() external onlyAdmin {\\n address currentAdmin = _getAdmin();\\n _setAdmin(address(0));\\n emit AdminRemoved(currentAdmin);\\n }\\n\\n /// @notice Returns the current implementation address.\\n function implementation() external view returns (address) {\\n return _getImplementation();\\n }\\n\\n /// @notice Returns the current admin address.\\n function admin() external view returns (address) {\\n return _getAdmin();\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Validates if the implementation is valid.\\n function _validateImplementation(address newImplementation) internal view {\\n if (newImplementation == address(0) || newImplementation.code.length == 0) {\\n revert InvalidImplementation();\\n }\\n if (_getImplementation() == newImplementation) {\\n revert SameImplementation();\\n }\\n }\\n\\n /// @dev Gets the current implementation address from storage.\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /// @dev Gets the current admin address from storage.\\n function _getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Sets the implementation address in storage.\\n function _setImplementation(address newImplementation) private {\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /// @dev Sets the admin address in storage.\\n function _setAdmin(address newAdmin) private {\\n address previousAdmin = _getAdmin();\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n emit AdminChanged(previousAdmin, newAdmin);\\n }\\n}\\n\",\"keccak256\":\"0x12df288b00cb10a4e94697b04af4203300f5592cf32ab27735d0682078fb6110\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "events": { + "AdminChanged(address,address)": { + "notice": "Event emitted when the admin is changed." + }, + "AdminRemoved(address)": { + "notice": "Event emitted when the admin is removed." + }, + "Upgraded(address)": { + "notice": "Event emitted when the implementation is upgraded." + } + }, + "kind": "user", + "methods": { + "admin()": { + "notice": "Returns the current admin address." + }, + "implementation()": { + "notice": "Returns the current implementation address." + }, + "renounceAdmin()": { + "notice": "Allows admin to revoke their admin rights by setting admin to address(0)." + }, + "upgradeTo(address)": { + "notice": "Upgrades to a new implementation." + } + }, + "notice": "A specialized proxy for UniversalResolver that forwards method calls and properly handles CCIP-Read reverts. Admin can upgrade the implementation.", + "version": 1 + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/UserRegistryImpl.json b/contracts/deployments/sepolia/UserRegistryImpl.json new file mode 100644 index 000000000..0eed6aa51 --- /dev/null +++ b/contracts/deployments/sepolia/UserRegistryImpl.json @@ -0,0 +1,3031 @@ +{ + "address": "0x840fa461059862ea466a711e8c98c8de732061c0", + "abi": [ + { + "inputs": [ + { + "internalType": "contract ILabelStore", + "name": "labelStore", + "type": "address" + }, + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "oldExpiry", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "CannotReduceExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "CannotSetPastExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "LabelExpired", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "TransferDisallowed", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExpiryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ParentUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RegistryCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ResolverUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SubregistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTokenId", + "type": "uint256" + } + ], + "name": "TokenRegenerated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "TokenResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "renderer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "URIUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "LABEL_STORE", + "outputs": [ + { + "internalType": "contract ILabelStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "canUpgradeFrom", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParent", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getResource", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "internalType": "address", + "name": "latestOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "internalType": "struct IPermissionedRegistry.State", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getStatus", + "outputs": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getSubregistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "rootAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "latestOwnerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setParent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "setSubregistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + }, + { + "internalType": "contract IRegistryURIRenderer", + "name": "renderer", + "type": "address" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "UserRegistry", + "sourceName": "src/registry/UserRegistry.sol", + "bytecode": "0x60c06040523060a052348015610013575f80fd5b5060405161538e38038061538e83398101604081905261003291610e02565b604051829082907f0100000000000000000000000000000001000000000000000000000000000000907fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16001600160a01b0383166080526100995f8284826100b2565b505050506100ab6101c460201b60201c565b5050611024565b5f835f036100c157505f6101bc565b6100ca84610261565b6001600160a01b0383166100f15760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b03871684529091529020548481178082146101b6575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616610151888260016102aa565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a384156101aa576101aa888785858b6103da565b600193505050506101bc565b5f925050505b949350505050565b5f6101cd6103ea565b805490915068010000000000000000900460ff16156101ff5760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161461025e5780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561025e57604051630153d96960e51b8152600481018290526024015b60405180910390fd5b5f6102b483610414565b9050811561034a575f848152600360205260409020546102fa9082161980195f8051602061536e83398151915291909101165f8051602061534e83398151915216151590565b1561032257604051631f22ca6960e31b815260048101859052602481018490526044016102a1565b5f848152600360205260408120805485929061033f908490610e4e565b909155506103d49050565b5f84815260036020526040902054610389901982161980195f8051602061536e83398151915291909101165f8051602061534e83398151915216151590565b156103b157604051631f80c19b60e01b815260048101859052602481018490526044016102a1565b5f84815260036020526040812080548592906103ce908490610e61565b90915550505b50505050565b6103e38561042e565b5050505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b5f61041e82610261565b50600181901b17600281901b1790565b801561025e5763ffffffff811681185f9081526101086020526040812090610456838361051a565b5f818152602081905260409020549091506001600160a01b031661047c8183600161053b565b8254839060049061049a90640100000000900463ffffffff16610e74565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f6104c9838561051a60201b60201c565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a36103e38282600160405180602001604052805f8152506105a260201b60201c565b80545f9063ffffffff808516851864010000000090920416185b9392505050565b6001600160a01b03831661056357604051626a0d4560e21b81525f60048201526024016102a1565b604080516001808252602082018590528183019081526060820184905260a082019092525f608082018181529192916103e39187918590859083610617565b6001600160a01b0384166105cb57604051632bfa23e760e11b81525f60048201526024016102a1565b604080516001808252602082018690528183019081526060820185905260808201909252906105fe5f8784848784610617565b505050505050565b63ffffffff82811690921891161890565b6106238686868661066d565b6001600160a01b038516156105fe57801561064b57610646338787878787610748565b6105fe565b60208481015190840151610663338989858589610872565b5050505050505050565b61067984848484610959565b6001600160a01b0383161580159061069957506001600160a01b03841615155b156103d4575f5b82518110156103e3575f8382815181106106bc576106bc610e96565b602002602001015190506106db816001609c1b88610b3f60201b60201c565b61070a576040516372c7b6ad60e11b8152600481018290526001600160a01b03871660248201526044016102a1565b5f83838151811061071d5761071d610e96565b6020026020010151111561073f5761073f61073782610b53565b87875f610b7a565b506001016106a0565b6001600160a01b0384163b156105fe5760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061078c9089908990889088908890600401610f12565b6020604051808303815f875af19250505080156107c6575060408051601f3d908101601f191682019092526107c391810190610f6f565b60015b61082d573d8080156107f3576040519150601f19603f3d011682016040523d82523d5f602084013e6107f8565b606091505b5080515f0361082557604051632bfa23e760e11b81526001600160a01b03861660048201526024016102a1565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461086957604051632bfa23e760e11b81526001600160a01b03861660048201526024016102a1565b50505050505050565b6001600160a01b0384163b156105fe5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906108b69089908990889088908890600401610f96565b6020604051808303815f875af19250505080156108f0575060408051601f3d908101601f191682019092526108ed91810190610f6f565b60015b61091d573d8080156107f3576040519150601f19603f3d011682016040523d82523d5f602084013e6107f8565b6001600160e01b0319811663f23a6e6160e01b1461086957604051632bfa23e760e11b81526001600160a01b03861660048201526024016102a1565b80518251146109885781518151604051635b05999160e01b8152600481019290925260248201526044016102a1565b5f5b8251811015610a79576020818102848101820151908401909101518015610a6f575f828152602081905260409020546001600160a01b039081169088168114610a05576040516303dee4c560e01b81526001600160a01b03891660048201525f602482015260448101839052606481018490526084016102a1565b6001821115610a47576040516303dee4c560e01b81526001600160a01b03891660048201526001602482015260448101839052606481018490526084016102a1565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0388161790555b505060010161098a565b508151600103610ae2576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a450506103d4565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051610b31929190610fda565b60405180910390a450505050565b5f6101bc610b4c85610b53565b8484610bbb565b5f61040e82610b758163ffffffff8116185f9081526101086020526040902090565b610bd2565b5f8481526002602090815260408083206001600160a01b038716845290915290205480156103e357610bae85828685610c20565b506105fe858285856100b2565b5f8280610bc88685610c8c565b1614949350505050565b5f82610bdf57508161040e565b60018201546105349084906001600160401b0316421015610c0d57835463ffffffff82811690921891161890565b83546106069063ffffffff166001611007565b5f610c2a84610261565b5f8581526002602090815260408083206001600160a01b0387168452909152902054841981168082146101b6575f8781526002602090815260408083206001600160a01b038916845290915281208290558683169061015190899083906102aa565b5f610c978383610ca9565b610ca15f84610ca9565b179392505050565b5f8281526002602090815260408083206001600160a01b0385168452909152902054821561040e575f610cdb84610d6a565b90506001600160a01b03811615801590610d075750826001600160a01b0316816001600160a01b031614155b8015610d3757506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b15610d63575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b63ffffffff811681185f90815261010860205260408120600101546001600160401b0316421015610dc057610dbb610da183610dc7565b5f908152602081905260409020546001600160a01b031690565b61040e565b5f92915050565b5f61040e82610de98163ffffffff8116185f9081526101086020526040902090565b61051a565b6001600160a01b038116811461025e575f80fd5b5f8060408385031215610e13575f80fd5b8251610e1e81610dee565b6020840151909250610e2f81610dee565b809150509250929050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561040e5761040e610e3a565b8181038181111561040e5761040e610e3a565b5f63ffffffff808316818103610e8c57610e8c610e3a565b6001019392505050565b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b83811015610ed957815187529582019590820190600101610ebd565b509495945050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0386811682528516602082015260a0604082018190525f90610f3d90830186610eaa565b8281036060840152610f4f8186610eaa565b90508281036080840152610f638185610ee4565b98975050505050505050565b5f60208284031215610f7f575f80fd5b81516001600160e01b031981168114610534575f80fd5b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f90610fcf90830184610ee4565b979650505050505050565b604081525f610fec6040830185610eaa565b8281036020840152610ffe8185610eaa565b95945050505050565b63ffffffff818116838216019080821115610d6357610d63610e3a565b60805160a0516142f461105a5f395f8181611e9101528181611eba015261204e01525f818161078d01526121d701526142f45ff3fe6080604052600436106102f7575f3560e01c80636352211e11610191578063ad3cb1cc116100dc578063d3bf89b111610087578063e985e9c511610062578063e985e9c51461092d578063f242432a14610974578063f41a143d14610993575f80fd5b8063d3bf89b1146108d0578063dfa70d8b146108ef578063e4ae7d771461090e575f80fd5b8063c41a360a116100b7578063c41a360a14610873578063cd6dc68714610892578063ce156e82146108b1575f80fd5b8063ad3cb1cc146107ed578063bc7b6d6214610835578063bd242bcb14610854575f80fd5b806380f760211161013c5780639dbba19d116101175780639dbba19d1461077c578063a02b161e146107af578063a22cb465146107ce575f80fd5b806380f760211461071c57806385f3e6431461073e57806391b3c0371461075d575f80fd5b80636f537c721161016c5780636f537c72146106bf578063781ef8db146106de5780637c300586146106fd575f80fd5b80636352211e1461066257806363560a8e146106815780636f3ff726146106a0575f80fd5b8063341ec559116102515780634f1ef286116101fc5780635569f33d116101d75780635569f33d146105f85780635adf4724146106175780635c622a0e14610636575f80fd5b80634f1ef286146105b257806352d1902d146105c55780635357263f146105d9575f80fd5b806344c9af281161022c57806344c9af281461053b57806348688f95146105675780634e1273f414610586575f80fd5b8063341ec559146104b157806335af6216146104d05780633634f91114610507575f80fd5b806313c72608116102b15780631e8fca2d1161028c5780631e8fca2d146104525780632eb2c2d6146104715780632f27fa2414610492575f80fd5b806313c72608146103c657806314ff5ea3146104205780631c3fc3eb1461043f575f80fd5b8063072d5d77116102e1578063072d5d771461035c5780630e89341c1461037b57806311b8e00a146103a7575f80fd5b8062fdd58e146102fb57806301ffc9a71461032d575b5f80fd5b348015610306575f80fd5b5061031a61031536600461367c565b6109b3565b6040519081526020015b60405180910390f35b348015610338575f80fd5b5061034c6103473660046136bb565b6109fe565b6040519015158152602001610324565b348015610367575f80fd5b5061034c6103763660046136d6565b610a6f565b348015610386575f80fd5b5061039a610395366004613704565b610a93565b6040516103249190613749565b3480156103b2575f80fd5b5061034c6103c136600461375b565b610bc3565b3480156103d1575f80fd5b506104076103e0366004613704565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610324565b34801561042b575f80fd5b5061031a61043a366004613704565b610bdd565b34801561044a575f80fd5b5061031a5f81565b34801561045d575f80fd5b5061031a61046c366004613704565b610c04565b34801561047c575f80fd5b5061049061048b3660046138c3565b610c2b565b005b34801561049d575f80fd5b5061031a6104ac366004613704565b610c49565b3480156104bc575f80fd5b506104906104cb3660046136d6565b610c67565b3480156104db575f80fd5b506104ef6104ea3660046139a8565b610cea565b6040516001600160a01b039091168152602001610324565b348015610512575f80fd5b5061052661052136600461375b565b610d80565b60408051928352602083019190915201610324565b348015610546575f80fd5b5061055a610555366004613704565b610da0565b6040516103249190613a1b565b348015610572575f80fd5b50610490610581366004613a6e565b610e72565b348015610591575f80fd5b506105a56105a0366004613ac1565b610eff565b6040516103249190613bb7565b6104906105c0366004613bc9565b610fcf565b3480156105d0575f80fd5b5061031a610fee565b3480156105e4575f80fd5b506104906105f3366004613bc9565b61101c565b348015610603575f80fd5b50610490610612366004613c28565b6110b1565b348015610622575f80fd5b5061031a6106313660046136d6565b6111ff565b348015610641575f80fd5b50610655610650366004613704565b611212565b6040516103249190613c52565b34801561066d575f80fd5b506104ef61067c366004613704565b611268565b34801561068c575f80fd5b506104ef61069b3660046139a8565b6112d2565b3480156106ab575f80fd5b5061034c6106ba366004613c60565b611314565b3480156106ca575f80fd5b506104076106d93660046139a8565b61132f565b3480156106e9575f80fd5b5061034c6106f83660046136d6565b611371565b348015610708575f80fd5b5061034c610717366004613c7b565b611387565b348015610727575f80fd5b5061073061139b565b604051610324929190613ca6565b348015610749575f80fd5b5061031a610758366004613cc7565b611446565b348015610768575f80fd5b5061031a6107773660046139a8565b611462565b348015610787575f80fd5b506104ef7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107ba575f80fd5b506104906107c9366004613704565b6114a4565b3480156107d9575f80fd5b506104906107e8366004613d50565b6115a0565b3480156107f8575f80fd5b5061039a6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b348015610840575f80fd5b5061049061084f3660046136d6565b6115ab565b34801561085f575f80fd5b506104ef61086e366004613704565b611634565b34801561087e575f80fd5b506104ef61088d366004613704565b611650565b34801561089d575f80fd5b506104906108ac36600461367c565b611694565b3480156108bc575f80fd5b5061034c6108cb3660046136d6565b61181d565b3480156108db575f80fd5b5061034c6108ea366004613c7b565b611838565b3480156108fa575f80fd5b5061034c610909366004613c7b565b61184c565b348015610919575f80fd5b506104ef6109283660046139a8565b611860565b348015610938575f80fd5b5061034c610947366004613d80565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b34801561097f575f80fd5b5061049061098e366004613dac565b6118d6565b34801561099e575f80fd5b5061034c6109ad366004613c60565b50600190565b5f6001600160a01b038316158015906109e55750826001600160a01b03166109da83611268565b6001600160a01b0316145b6109ef575f6109f2565b60015b60ff1690505b92915050565b5f6001600160e01b031982167fb0f3d367000000000000000000000000000000000000000000000000000000001480610a6057506001600160e01b031982167ff41a143d00000000000000000000000000000000000000000000000000000000145b806109f857506109f8826118ed565b5f8083610a7d828233611a62565b610a8a5f86866001611ab0565b95945050505050565b610107546060906001600160a01b0316610b36576101068054610ab590613e10565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae190613e10565b8015610b2c5780601f10610b0357610100808354040283529160200191610b2c565b820191905f5260205f20905b815481529060010190602001808311610b0f57829003601f168201915b50505050506109f8565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610b9c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109f89190810190613e48565b5f610bd6610bd084610c04565b83611bd9565b9392505050565b5f6109f882610bff8463ffffffff8116185f9081526101086020526040902090565b611bf0565b5f6109f882610c268463ffffffff8116185f9081526101086020526040902090565b611c0e565b610c358533611c68565b610c428585858585611cf9565b5050505050565b5f6109f8610c5683610c04565b5f9081526003602052604090205490565b5f80610c768462100000611d59565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b038716908102919091178255604051929450909250339184907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a450505050565b5f80610d46610d2d85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610d76578054600160401b90046001600160a01b0316610d78565b5f5b949350505050565b5f80610d94610d8e85610c04565b84611dcd565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610dfe8584611bf0565b606085018190529050610e118584611c0e565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610e3f8382611df0565b85906002811115610e5257610e526139e7565b90816002811115610e6557610e656139e7565b8152505050505050919050565b641000000000610e835f8233611e27565b610106610e91848683613f01565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905560405133907fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd590610ef190879087908790613fbb565b60405180910390a250505050565b60608151835114610f355781518351604051635b05999160e01b8152600481019290925260248201526044015b60405180910390fd5b5f835167ffffffffffffffff811115610f5057610f5061377b565b604051908082528060200260200182016040528015610f79578160200160208202803683370190505b5090505f5b8451811015610fc757602080820286010151610fa2906020808402870101516109b3565b828281518110610fb457610fb4613ffb565b6020908102919091010152600101610f7e565b509392505050565b610fd7611e86565b610fe082611f3f565b610fea8282611f5b565b5050565b5f610ff7612043565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b61010061102a5f8233611e27565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105611060838261400f565b50336001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff4846040516110a49190613749565b60405180910390a3505050565b63ffffffff821682185f90815261010860205260408120906110d38483611bf0565b600183015490915067ffffffffffffffff164281116111305767ffffffffffffffff8116158061110a5750611108823361208c565b155b1561112b5760405163311388dd60e21b815260048101839052602401610f2c565b611147565b61114761113d8685611c0e565b6201000033611e27565b8067ffffffffffffffff168467ffffffffffffffff1610156111a9576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015285166024820152604401610f2c565b60018301805467ffffffffffffffff191667ffffffffffffffff861690811790915560405133919084907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a45050505050565b5f610bd661120c84610c04565b8361209a565b63ffffffff811681185f908152610108602052604081206001810154610bd69067ffffffffffffffff166112636112498685611bf0565b5f908152602081905260409020546001600160a01b031690565b611df0565b63ffffffff811681185f908152610108602052604081206112898382611bf0565b831415806112a55750600181015467ffffffffffffffff164210155b6112ca575f838152602081905260409020546001600160a01b0316610bd6565b610bd6565b5f9392505050565b5f610bd661088d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b5f6109f86f0100000000000000000000000000000083611371565b5f610bd66103e084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b5f828361137e5f856120a1565b16149392505050565b5f610d7861139485610c04565b8484612162565b6101045461010580545f926060926001600160a01b039091169181906113c090613e10565b80601f01602080910402602001604051908101604052809291908181526020018280546113ec90613e10565b80156114375780601f1061140e57610100808354040283529160200191611437565b820191905f5260205f20905b81548152906001019060200180831161141a57829003601f168201915b50505050509050915091509091565b5f61145787878787878760016121a5565b979650505050505050565b5f610bd661043a84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b5f806114b283611000611d59565b6040519193509150339083907f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea8905f90a35f828152602081905260409020546001600160a01b0316801561157d5761150c818460016126d6565b815482905f906115219063ffffffff166140df565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff1661155e906140df565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b610fea33838361273d565b5f806115bb846301000000611d59565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b03881690810291909117909155604051929450909250339184907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a450505050565b5f818152602081905260408120546001600160a01b03166109f8565b63ffffffff811681185f908152610108602052604081206001015467ffffffffffffffff1642101561168d5761168861124983610bdd565b6109f8565b5f92915050565b5f61169d6127e3565b805490915060ff600160401b820416159067ffffffffffffffff165f811580156116c45750825b90505f8267ffffffffffffffff1660011480156116e05750303b155b9050811580156116ee575080155b15611725576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561175457845468ff00000000000000001916600160401b1785555b6001600160a01b038716611794576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16117c85f87895f611ab0565b50831561181457845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f808361182b82823361280b565b610a8a5f8686600161286c565b5f610d7861184585610c04565b84846128d8565b5f610d7861185985610c04565b84846128ef565b5f806118a3610d2d85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b600181015490915067ffffffffffffffff16421015610d76576001810154600160401b90046001600160a01b0316610d78565b6118e08533611c68565b610c428585858585612928565b5f6001600160e01b031982167f6be50c6900000000000000000000000000000000000000000000000000000000148061194f57506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b8061198357506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b806119b757506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b806119eb57506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b80611a1f57506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b80611a5357506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b806109f857506109f8826129ac565b5f611a6d84836129e9565b90508019831615611aaa5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610f2c565b50505050565b5f835f03611abf57505f610d78565b611ac884612a32565b6001600160a01b038316611b08576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611bcd575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616611b6888826001612a92565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a38415611bc157611bc1888785858b612c27565b60019350505050610d78565b505f9695505050505050565b5f80611be58484610d80565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610bd6565b5f82611c1b5750816109f8565b6001820154610bd690849067ffffffffffffffff16421015611c4457835463ffffffff16611c57565b8354611c579063ffffffff166001614101565b63ffffffff82811690921891161890565b806001600160a01b0316826001600160a01b031614158015611caf57506001600160a01b038083165f9081526001602090815260408083209385168352929052205460ff16155b15610fea576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b03808316600483015283166024820152604401610f2c565b6001600160a01b038416611d2257604051632bfa23e760e11b81525f6004820152602401610f2c565b6001600160a01b038516611d4a57604051626a0d4560e21b81525f6004820152602401610f2c565b610c4285858585856001612c30565b63ffffffff821682185f90815261010860205260408120611d7a8482611bf0565b600182015490925067ffffffffffffffff164210611dae5760405163311388dd60e21b815260048101839052602401610f2c565b610d99611dbb8583611c0e565b8433611e27565b805160209091012090565b5f80611dd883612c87565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff83164210611e0957505f6109f8565b6001600160a01b038216611e1f575060016109f8565b5060026109f8565b611e32838383611838565b611e81576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610f2c565b505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480611f1f57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611f137f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b15611f3d5760405163703e46dd60e11b815260040160405180910390fd5b565b6f10000000000000000000000000000000610fea5f8233611e27565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611fb5575060408051601f3d908101601f19168201909252611fb29181019061411e565b60015b611fdd57604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610f2c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612039576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401610f2c565b611e818383612ca1565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611f3d5760405163703e46dd60e11b815260040160405180910390fd5b5f610bd66201000083611371565b5f610bd683835b5f8281526002602090815260408083206001600160a01b038516845290915290205482156109f8575f6120d384611650565b90506001600160a01b038116158015906120ff5750826001600160a01b0316816001600160a01b031614155b801561212f57506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b1561215b575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b5f8383612170828233611a62565b8561218e57604051631850848b60e31b815260040160405180910390fd5b61219b8686866001611ab0565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf5309699061220c908b90600401613749565b5f604051808303815f87803b158015612223575f80fd5b505af1158015612235573d5f803e3d5ffd5b5050895160208b012091505f90506122608263ffffffff8116185f9081526101086020526040902090565b905061226c8282611bf0565b5f8181526020819052604090205460018301549194506001600160a01b03169067ffffffffffffffff1642106122f65784156122ae576122ae5f600133611e27565b6001600160a01b038a161580156122c457508615155b156122f15760405163d1a3b35560e01b81525f600482015260248101889052336044820152606401610f2c565b6123bb565b6001600160a01b03811615612339578a6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610f2c9190613749565b6001600160a01b038a1661237b578a6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610f2c9190613749565b841561238d5761238d5f601033611e27565b8567ffffffffffffffff165f036123b057600182015467ffffffffffffffff1695505b640100000000871796505b6001600160a01b038a16156123dd5767ffffffffffffffff86164210156123ea565b67ffffffffffffffff8616155b1561242d576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602401610f2c565b6001600160a01b038116156124c557612448818560016126d6565b815482905f9061245d9063ffffffff166140df565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff1661249a906140df565b91906101000a81548163ffffffff021916908363ffffffff1602179055506124c28483611bf0565b93505b60018201805483546001600160a01b03808d16600160401b9081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921786558b81169091026001600160e01b031990921667ffffffffffffffff8a1617919091179091558a1661258157336001600160a01b0316835f1b857f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88e8a604051612574929190614135565b60405180910390a461263a565b336001600160a01b0316835f1b857f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8e8e8b6040516125c293929190614160565b60405180910390a46125e58a85600160405180602001604052805f815250612cf6565b5f6125f08584611c0e565b9050806125ff576125ff61419b565b604051819086907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a361263781898d5f611ab0565b50505b6001600160a01b038916156126815760405133906001600160a01b038b169086907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a45b6001600160a01b038816156126c85760405133906001600160a01b038a169086907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a45b505050979650505050505050565b6001600160a01b0383166126fe57604051626a0d4560e21b81525f6004820152602401610f2c565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291610c429187918590859083612c30565b6001600160a01b03821661277f576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610f2c565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3191016110a4565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006109f8565b5f6128168483612d52565b90508019831615611aaa576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610f2c565b5f61287684612a32565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611bcd575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690611b689089908390612a92565b5f82836128e58685612d8d565b1614949350505050565b5f83836128fd82823361280b565b8561291b57604051631850848b60e31b815260040160405180910390fd5b61219b868686600161286c565b6001600160a01b03841661295157604051632bfa23e760e11b81525f6004820152602401610f2c565b6001600160a01b03851661297957604051626a0d4560e21b81525f6004820152602401610f2c565b6040805160018082526020820186905281830190815260608201859052608082019092529061181487878484875f612c30565b5f6001600160e01b031982167f8f452d620000000000000000000000000000000000000000000000000000000014806109f857506109f882612daa565b5f8215801590612a0957505f6129fe84611650565b6001600160a01b0316145b15612a1557505f6109f8565b5f612a208484612d52565b90508315610bd657608081901c610d78565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612a8f576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610f2c565b50565b5f612a9c83612c87565b90508115612b65575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612b3d576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610f2c565b5f8481526003602052604081208054859290612b5a9084906141af565b90915550611aaa9050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612bff576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610f2c565b5f8481526003602052604081208054859290612c1c9084906141c2565b909155505050505050565b610c4285612e78565b612c3c86868686612f58565b6001600160a01b03851615612c7f578015612c6457612c5f338787878787613056565b612c7f565b60208481015190840151612c7c338989858589613177565b50505b505050505050565b5f612c9182612a32565b50600181901b17600281901b1790565b612caa8261325e565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115612cee57611e8182826132e1565b610fea61334a565b6001600160a01b038416612d1f57604051632bfa23e760e11b81525f6004820152602401610f2c565b60408051600180825260208201869052818301908152606082018590526080820190925290612c7f5f8784848784612c30565b5f610bd6612d608484612d8d565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000811660809190911c1790565b5f612d9883836120a1565b612da25f846120a1565b179392505050565b5f6001600160e01b031982167fd9b67a26000000000000000000000000000000000000000000000000000000001480612e0c57506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b80612e4057506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b806109f857507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316146109f8565b8015612a8f5763ffffffff811681185f9081526101086020526040812090612ea08383611bf0565b5f818152602081905260409020549091506001600160a01b0316612ec6818360016126d6565b82548390600490612ee490640100000000900463ffffffff166140df565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f612f0d8385611bf0565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3610c428282600160405180602001604052805f815250612cf6565b612f6484848484613382565b6001600160a01b03831615801590612f8457506001600160a01b03841615155b15611aaa575f5b8251811015610c42575f838281518110612fa757612fa7613ffb565b60200260200101519050612fd08173100000000000000000000000000000000000000088611838565b613018576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610f2c565b5f83838151811061302b5761302b613ffb565b6020026020010151111561304d5761304d61304582610c04565b87875f613575565b50600101612f8b565b6001600160a01b0384163b15612c7f5760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061309a90899089908890889088906004016141d5565b6020604051808303815f875af19250505080156130d4575060408051601f3d908101601f191682019092526130d191810190614232565b60015b61313b573d808015613101576040519150601f19603f3d011682016040523d82523d5f602084013e613106565b606091505b5080515f0361313357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610f2c565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461181457604051632bfa23e760e11b81526001600160a01b0386166004820152602401610f2c565b6001600160a01b0384163b15612c7f5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906131bb908990899088908890889060040161424d565b6020604051808303815f875af19250505080156131f5575060408051601f3d908101601f191682019092526131f291810190614232565b60015b613222573d808015613101576040519150601f19603f3d011682016040523d82523d5f602084013e613106565b6001600160e01b0319811663f23a6e6160e01b1461181457604051632bfa23e760e11b81526001600160a01b0386166004820152602401610f2c565b806001600160a01b03163b5f0361329357604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610f2c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516132fd9190614284565b5f60405180830381855af49150503d805f8114613335576040519150601f19603f3d011682016040523d82523d5f602084013e61333a565b606091505b5091509150610a8a8583836135b6565b3415611f3d576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80518251146133b15781518151604051635b05999160e01b815260048101929092526024820152604401610f2c565b5f5b82518110156134af5760208181028481018201519084019091015180156134a5575f828152602081905260409020546001600160a01b03908116908816811461342e576040516303dee4c560e01b81526001600160a01b03891660048201525f60248201526044810183905260648101849052608401610f2c565b6001821115613470576040516303dee4c560e01b81526001600160a01b0389166004820152600160248201526044810183905260648101849052608401610f2c565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388161790555b50506001016133b3565b508151600103613518576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050611aaa565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb858560405161356792919061429a565b60405180910390a450505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015610c42576135a98582868561286c565b50612c7f85828585611ab0565b6060826135c6576112c582613626565b81511580156135dd57506001600160a01b0384163b155b1561361f576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610f2c565b5080610bd6565b8051156136365780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0381168114612a8f575f80fd5b5f806040838503121561368d575f80fd5b823561369881613668565b946020939093013593505050565b6001600160e01b031981168114612a8f575f80fd5b5f602082840312156136cb575f80fd5b8135610bd6816136a6565b5f80604083850312156136e7575f80fd5b8235915060208301356136f981613668565b809150509250929050565b5f60208284031215613714575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610bd6602083018461371b565b5f806040838503121561376c575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156137b8576137b861377b565b604052919050565b5f67ffffffffffffffff8211156137d9576137d961377b565b5060051b60200190565b5f82601f8301126137f2575f80fd5b81356020613807613802836137c0565b61378f565b8083825260208201915060208460051b870101935086841115613828575f80fd5b602086015b84811015613844578035835291830191830161382d565b509695505050505050565b5f67ffffffffffffffff8211156138685761386861377b565b50601f01601f191660200190565b5f82601f830112613885575f80fd5b81356138936138028261384f565b8181528460208386010111156138a7575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a086880312156138d7575f80fd5b85356138e281613668565b945060208601356138f281613668565b9350604086013567ffffffffffffffff8082111561390e575f80fd5b61391a89838a016137e3565b9450606088013591508082111561392f575f80fd5b61393b89838a016137e3565b93506080880135915080821115613950575f80fd5b5061395d88828901613876565b9150509295509295909350565b5f8083601f84011261397a575f80fd5b50813567ffffffffffffffff811115613991575f80fd5b602083019150836020828501011115610d99575f80fd5b5f80602083850312156139b9575f80fd5b823567ffffffffffffffff8111156139cf575f80fd5b6139db8582860161396a565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b60038110613a1757634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a082019050613a2d8284516139fb565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f60408486031215613a80575f80fd5b833567ffffffffffffffff811115613a96575f80fd5b613aa28682870161396a565b9094509250506020840135613ab681613668565b809150509250925092565b5f8060408385031215613ad2575f80fd5b823567ffffffffffffffff80821115613ae9575f80fd5b818501915085601f830112613afc575f80fd5b81356020613b0c613802836137c0565b82815260059290921b84018101918181019089841115613b2a575f80fd5b948201945b83861015613b51578535613b4281613668565b82529482019490820190613b2f565b96505086013592505080821115613b66575f80fd5b50613b73858286016137e3565b9150509250929050565b5f815180845260208085019450602084015f5b83811015613bac57815187529582019590820190600101613b90565b509495945050505050565b602081525f610bd66020830184613b7d565b5f8060408385031215613bda575f80fd5b8235613be581613668565b9150602083013567ffffffffffffffff811115613c00575f80fd5b613b7385828601613876565b803567ffffffffffffffff81168114613c23575f80fd5b919050565b5f8060408385031215613c39575f80fd5b82359150613c4960208401613c0c565b90509250929050565b602081016109f882846139fb565b5f60208284031215613c70575f80fd5b8135610bd681613668565b5f805f60608486031215613c8d575f80fd5b83359250602084013591506040840135613ab681613668565b6001600160a01b0383168152604060208201525f610d78604083018461371b565b5f805f805f8060c08789031215613cdc575f80fd5b863567ffffffffffffffff811115613cf2575f80fd5b613cfe89828a01613876565b9650506020870135613d0f81613668565b94506040870135613d1f81613668565b93506060870135613d2f81613668565b925060808701359150613d4460a08801613c0c565b90509295509295509295565b5f8060408385031215613d61575f80fd5b8235613d6c81613668565b9150602083013580151581146136f9575f80fd5b5f8060408385031215613d91575f80fd5b8235613d9c81613668565b915060208301356136f981613668565b5f805f805f60a08688031215613dc0575f80fd5b8535613dcb81613668565b94506020860135613ddb81613668565b93506040860135925060608601359150608086013567ffffffffffffffff811115613e04575f80fd5b61395d88828901613876565b600181811c90821680613e2457607f821691505b602082108103613e4257634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613e58575f80fd5b815167ffffffffffffffff811115613e6e575f80fd5b8201601f81018413613e7e575f80fd5b8051613e8c6138028261384f565b818152856020838501011115613ea0575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b601f821115611e8157805f5260205f20601f840160051c81016020851015613ee25750805b601f840160051c820191505b81811015610c42575f8155600101613eee565b67ffffffffffffffff831115613f1957613f1961377b565b613f2d83613f278354613e10565b83613ebd565b5f601f841160018114613f5e575f8515613f475750838201355b5f19600387901b1c1916600186901b178355610c42565b5f83815260208120601f198716915b82811015613f8d5786850135825560209485019460019092019101613f6d565b5086821015613fa9575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff8111156140295761402961377b565b61403d816140378454613e10565b84613ebd565b602080601f831160018114614070575f84156140595750858301515b5f19600386901b1c1916600185901b178555612c7f565b5f85815260208120601f198616915b8281101561409e5788860151825594840194600190910190840161407f565b50858210156140bb57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036140f7576140f76140cb565b6001019392505050565b63ffffffff81811683821601908082111561215b5761215b6140cb565b5f6020828403121561412e575f80fd5b5051919050565b604081525f614147604083018561371b565b905067ffffffffffffffff831660208301529392505050565b606081525f614172606083018661371b565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b808201808211156109f8576109f86140cb565b818103818111156109f8576109f86140cb565b5f6001600160a01b03808816835280871660208401525060a0604083015261420060a0830186613b7d565b82810360608401526142128186613b7d565b90508281036080840152614226818561371b565b98975050505050505050565b5f60208284031215614242575f80fd5b8151610bd6816136a6565b5f6001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261145760a083018461371b565b5f82518060208501845e5f920191825250919050565b604081525f6142ac6040830185613b7d565b8281036020840152610a8a8185613b7d56fea26469706673582212208e412974a6acab301cca4b8cd6175ca050f45502e53694b21451bd8a9fd20cb164736f6c634300081900338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x6080604052600436106102f7575f3560e01c80636352211e11610191578063ad3cb1cc116100dc578063d3bf89b111610087578063e985e9c511610062578063e985e9c51461092d578063f242432a14610974578063f41a143d14610993575f80fd5b8063d3bf89b1146108d0578063dfa70d8b146108ef578063e4ae7d771461090e575f80fd5b8063c41a360a116100b7578063c41a360a14610873578063cd6dc68714610892578063ce156e82146108b1575f80fd5b8063ad3cb1cc146107ed578063bc7b6d6214610835578063bd242bcb14610854575f80fd5b806380f760211161013c5780639dbba19d116101175780639dbba19d1461077c578063a02b161e146107af578063a22cb465146107ce575f80fd5b806380f760211461071c57806385f3e6431461073e57806391b3c0371461075d575f80fd5b80636f537c721161016c5780636f537c72146106bf578063781ef8db146106de5780637c300586146106fd575f80fd5b80636352211e1461066257806363560a8e146106815780636f3ff726146106a0575f80fd5b8063341ec559116102515780634f1ef286116101fc5780635569f33d116101d75780635569f33d146105f85780635adf4724146106175780635c622a0e14610636575f80fd5b80634f1ef286146105b257806352d1902d146105c55780635357263f146105d9575f80fd5b806344c9af281161022c57806344c9af281461053b57806348688f95146105675780634e1273f414610586575f80fd5b8063341ec559146104b157806335af6216146104d05780633634f91114610507575f80fd5b806313c72608116102b15780631e8fca2d1161028c5780631e8fca2d146104525780632eb2c2d6146104715780632f27fa2414610492575f80fd5b806313c72608146103c657806314ff5ea3146104205780631c3fc3eb1461043f575f80fd5b8063072d5d77116102e1578063072d5d771461035c5780630e89341c1461037b57806311b8e00a146103a7575f80fd5b8062fdd58e146102fb57806301ffc9a71461032d575b5f80fd5b348015610306575f80fd5b5061031a61031536600461367c565b6109b3565b6040519081526020015b60405180910390f35b348015610338575f80fd5b5061034c6103473660046136bb565b6109fe565b6040519015158152602001610324565b348015610367575f80fd5b5061034c6103763660046136d6565b610a6f565b348015610386575f80fd5b5061039a610395366004613704565b610a93565b6040516103249190613749565b3480156103b2575f80fd5b5061034c6103c136600461375b565b610bc3565b3480156103d1575f80fd5b506104076103e0366004613704565b63ffffffff8116185f908152610108602052604090206001015467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610324565b34801561042b575f80fd5b5061031a61043a366004613704565b610bdd565b34801561044a575f80fd5b5061031a5f81565b34801561045d575f80fd5b5061031a61046c366004613704565b610c04565b34801561047c575f80fd5b5061049061048b3660046138c3565b610c2b565b005b34801561049d575f80fd5b5061031a6104ac366004613704565b610c49565b3480156104bc575f80fd5b506104906104cb3660046136d6565b610c67565b3480156104db575f80fd5b506104ef6104ea3660046139a8565b610cea565b6040516001600160a01b039091168152602001610324565b348015610512575f80fd5b5061052661052136600461375b565b610d80565b60408051928352602083019190915201610324565b348015610546575f80fd5b5061055a610555366004613704565b610da0565b6040516103249190613a1b565b348015610572575f80fd5b50610490610581366004613a6e565b610e72565b348015610591575f80fd5b506105a56105a0366004613ac1565b610eff565b6040516103249190613bb7565b6104906105c0366004613bc9565b610fcf565b3480156105d0575f80fd5b5061031a610fee565b3480156105e4575f80fd5b506104906105f3366004613bc9565b61101c565b348015610603575f80fd5b50610490610612366004613c28565b6110b1565b348015610622575f80fd5b5061031a6106313660046136d6565b6111ff565b348015610641575f80fd5b50610655610650366004613704565b611212565b6040516103249190613c52565b34801561066d575f80fd5b506104ef61067c366004613704565b611268565b34801561068c575f80fd5b506104ef61069b3660046139a8565b6112d2565b3480156106ab575f80fd5b5061034c6106ba366004613c60565b611314565b3480156106ca575f80fd5b506104076106d93660046139a8565b61132f565b3480156106e9575f80fd5b5061034c6106f83660046136d6565b611371565b348015610708575f80fd5b5061034c610717366004613c7b565b611387565b348015610727575f80fd5b5061073061139b565b604051610324929190613ca6565b348015610749575f80fd5b5061031a610758366004613cc7565b611446565b348015610768575f80fd5b5061031a6107773660046139a8565b611462565b348015610787575f80fd5b506104ef7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107ba575f80fd5b506104906107c9366004613704565b6114a4565b3480156107d9575f80fd5b506104906107e8366004613d50565b6115a0565b3480156107f8575f80fd5b5061039a6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b348015610840575f80fd5b5061049061084f3660046136d6565b6115ab565b34801561085f575f80fd5b506104ef61086e366004613704565b611634565b34801561087e575f80fd5b506104ef61088d366004613704565b611650565b34801561089d575f80fd5b506104906108ac36600461367c565b611694565b3480156108bc575f80fd5b5061034c6108cb3660046136d6565b61181d565b3480156108db575f80fd5b5061034c6108ea366004613c7b565b611838565b3480156108fa575f80fd5b5061034c610909366004613c7b565b61184c565b348015610919575f80fd5b506104ef6109283660046139a8565b611860565b348015610938575f80fd5b5061034c610947366004613d80565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b34801561097f575f80fd5b5061049061098e366004613dac565b6118d6565b34801561099e575f80fd5b5061034c6109ad366004613c60565b50600190565b5f6001600160a01b038316158015906109e55750826001600160a01b03166109da83611268565b6001600160a01b0316145b6109ef575f6109f2565b60015b60ff1690505b92915050565b5f6001600160e01b031982167fb0f3d367000000000000000000000000000000000000000000000000000000001480610a6057506001600160e01b031982167ff41a143d00000000000000000000000000000000000000000000000000000000145b806109f857506109f8826118ed565b5f8083610a7d828233611a62565b610a8a5f86866001611ab0565b95945050505050565b610107546060906001600160a01b0316610b36576101068054610ab590613e10565b80601f0160208091040260200160405190810160405280929190818152602001828054610ae190613e10565b8015610b2c5780601f10610b0357610100808354040283529160200191610b2c565b820191905f5260205f20905b815481529060010190602001808311610b0f57829003601f168201915b50505050506109f8565b610107546040517f6c55e19b000000000000000000000000000000000000000000000000000000008152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610b9c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109f89190810190613e48565b5f610bd6610bd084610c04565b83611bd9565b9392505050565b5f6109f882610bff8463ffffffff8116185f9081526101086020526040902090565b611bf0565b5f6109f882610c268463ffffffff8116185f9081526101086020526040902090565b611c0e565b610c358533611c68565b610c428585858585611cf9565b5050505050565b5f6109f8610c5683610c04565b5f9081526003602052604090205490565b5f80610c768462100000611d59565b80547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b038716908102919091178255604051929450909250339184907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a450505050565b5f80610d46610d2d85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b63ffffffff8116185f9081526101086020526040902090565b600181015490915067ffffffffffffffff16421015610d76578054600160401b90046001600160a01b0316610d78565b5f5b949350505050565b5f80610d94610d8e85610c04565b84611dcd565b915091505b9250929050565b6040805160a0810182525f8082526020808301828152838501839052606084018390526080840183905263ffffffff861686188352610108909152928120600181015467ffffffffffffffff1693849052919290610dfe8584611bf0565b606085018190529050610e118584611c0e565b60808501525f8181526020819052604090819020546001600160a01b0316908501819052610e3f8382611df0565b85906002811115610e5257610e526139e7565b90816002811115610e6557610e656139e7565b8152505050505050919050565b641000000000610e835f8233611e27565b610106610e91848683613f01565b50610107805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03841617905560405133907fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd590610ef190879087908790613fbb565b60405180910390a250505050565b60608151835114610f355781518351604051635b05999160e01b8152600481019290925260248201526044015b60405180910390fd5b5f835167ffffffffffffffff811115610f5057610f5061377b565b604051908082528060200260200182016040528015610f79578160200160208202803683370190505b5090505f5b8451811015610fc757602080820286010151610fa2906020808402870101516109b3565b828281518110610fb457610fb4613ffb565b6020908102919091010152600101610f7e565b509392505050565b610fd7611e86565b610fe082611f3f565b610fea8282611f5b565b5050565b5f610ff7612043565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b61010061102a5f8233611e27565b610104805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038516179055610105611060838261400f565b50336001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff4846040516110a49190613749565b60405180910390a3505050565b63ffffffff821682185f90815261010860205260408120906110d38483611bf0565b600183015490915067ffffffffffffffff164281116111305767ffffffffffffffff8116158061110a5750611108823361208c565b155b1561112b5760405163311388dd60e21b815260048101839052602401610f2c565b611147565b61114761113d8685611c0e565b6201000033611e27565b8067ffffffffffffffff168467ffffffffffffffff1610156111a9576040517f68c1425a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808316600483015285166024820152604401610f2c565b60018301805467ffffffffffffffff191667ffffffffffffffff861690811790915560405133919084907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a45050505050565b5f610bd661120c84610c04565b8361209a565b63ffffffff811681185f908152610108602052604081206001810154610bd69067ffffffffffffffff166112636112498685611bf0565b5f908152602081905260409020546001600160a01b031690565b611df0565b63ffffffff811681185f908152610108602052604081206112898382611bf0565b831415806112a55750600181015467ffffffffffffffff164210155b6112ca575f838152602081905260409020546001600160a01b0316610bd6565b610bd6565b5f9392505050565b5f610bd661088d84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b5f6109f86f0100000000000000000000000000000083611371565b5f610bd66103e084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b5f828361137e5f856120a1565b16149392505050565b5f610d7861139485610c04565b8484612162565b6101045461010580545f926060926001600160a01b039091169181906113c090613e10565b80601f01602080910402602001604051908101604052809291908181526020018280546113ec90613e10565b80156114375780601f1061140e57610100808354040283529160200191611437565b820191905f5260205f20905b81548152906001019060200180831161141a57829003601f168201915b50505050509050915091509091565b5f61145787878787878760016121a5565b979650505050505050565b5f610bd661043a84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b5f806114b283611000611d59565b6040519193509150339083907f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea8905f90a35f828152602081905260409020546001600160a01b0316801561157d5761150c818460016126d6565b815482905f906115219063ffffffff166140df565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff1661155e906140df565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff19164267ffffffffffffffff161790555050565b610fea33838361273d565b5f806115bb846301000000611d59565b6001810180547fffffffff0000000000000000000000000000000000000000ffffffffffffffff16600160401b6001600160a01b03881690810291909117909155604051929450909250339184907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a450505050565b5f818152602081905260408120546001600160a01b03166109f8565b63ffffffff811681185f908152610108602052604081206001015467ffffffffffffffff1642101561168d5761168861124983610bdd565b6109f8565b5f92915050565b5f61169d6127e3565b805490915060ff600160401b820416159067ffffffffffffffff165f811580156116c45750825b90505f8267ffffffffffffffff1660011480156116e05750303b155b9050811580156116ee575080155b15611725576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561175457845468ff00000000000000001916600160401b1785555b6001600160a01b038716611794576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a16117c85f87895f611ab0565b50831561181457845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b5f808361182b82823361280b565b610a8a5f8686600161286c565b5f610d7861184585610c04565b84846128d8565b5f610d7861185985610c04565b84846128ef565b5f806118a3610d2d85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611dc292505050565b600181015490915067ffffffffffffffff16421015610d76576001810154600160401b90046001600160a01b0316610d78565b6118e08533611c68565b610c428585858585612928565b5f6001600160e01b031982167f6be50c6900000000000000000000000000000000000000000000000000000000148061194f57506001600160e01b031982167fb844ab6c00000000000000000000000000000000000000000000000000000000145b8061198357506001600160e01b031982167f91b3c03700000000000000000000000000000000000000000000000000000000145b806119b757506001600160e01b031982167f6f537c7200000000000000000000000000000000000000000000000000000000145b806119eb57506001600160e01b031982167f63560a8e00000000000000000000000000000000000000000000000000000000145b80611a1f57506001600160e01b031982167f51f67f4000000000000000000000000000000000000000000000000000000000145b80611a5357506001600160e01b031982167f6f3ff72600000000000000000000000000000000000000000000000000000000145b806109f857506109f8826129ac565b5f611a6d84836129e9565b90508019831615611aaa5760405163d1a3b35560e01b815260048101859052602481018490526001600160a01b0383166044820152606401610f2c565b50505050565b5f835f03611abf57505f610d78565b611ac884612a32565b6001600160a01b038316611b08576040517fec3fc59200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611bcd575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616611b6888826001612a92565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a38415611bc157611bc1888785858b612c27565b60019350505050610d78565b505f9695505050505050565b5f80611be58484610d80565b501515949350505050565b80545f9063ffffffff80851685186401000000009092041618610bd6565b5f82611c1b5750816109f8565b6001820154610bd690849067ffffffffffffffff16421015611c4457835463ffffffff16611c57565b8354611c579063ffffffff166001614101565b63ffffffff82811690921891161890565b806001600160a01b0316826001600160a01b031614158015611caf57506001600160a01b038083165f9081526001602090815260408083209385168352929052205460ff16155b15610fea576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b03808316600483015283166024820152604401610f2c565b6001600160a01b038416611d2257604051632bfa23e760e11b81525f6004820152602401610f2c565b6001600160a01b038516611d4a57604051626a0d4560e21b81525f6004820152602401610f2c565b610c4285858585856001612c30565b63ffffffff821682185f90815261010860205260408120611d7a8482611bf0565b600182015490925067ffffffffffffffff164210611dae5760405163311388dd60e21b815260048101839052602401610f2c565b610d99611dbb8583611c0e565b8433611e27565b805160209091012090565b5f80611dd883612c87565b5f948552600360205260409094205484169492505050565b5f67ffffffffffffffff83164210611e0957505f6109f8565b6001600160a01b038216611e1f575060016109f8565b5060026109f8565b611e32838383611838565b611e81576040517f4b27a13300000000000000000000000000000000000000000000000000000000815260048101849052602481018390526001600160a01b0382166044820152606401610f2c565b505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480611f1f57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611f137f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b15611f3d5760405163703e46dd60e11b815260040160405180910390fd5b565b6f10000000000000000000000000000000610fea5f8233611e27565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611fb5575060408051601f3d908101601f19168201909252611fb29181019061411e565b60015b611fdd57604051634c9c8ce360e01b81526001600160a01b0383166004820152602401610f2c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612039576040517faa1d49a400000000000000000000000000000000000000000000000000000000815260048101829052602401610f2c565b611e818383612ca1565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611f3d5760405163703e46dd60e11b815260040160405180910390fd5b5f610bd66201000083611371565b5f610bd683835b5f8281526002602090815260408083206001600160a01b038516845290915290205482156109f8575f6120d384611650565b90506001600160a01b038116158015906120ff5750826001600160a01b0316816001600160a01b031614155b801561212f57506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b1561215b575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b5f8383612170828233611a62565b8561218e57604051631850848b60e31b815260040160405180910390fd5b61219b8686866001611ab0565b9695505050505050565b6040517fbf5309690000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf5309699061220c908b90600401613749565b5f604051808303815f87803b158015612223575f80fd5b505af1158015612235573d5f803e3d5ffd5b5050895160208b012091505f90506122608263ffffffff8116185f9081526101086020526040902090565b905061226c8282611bf0565b5f8181526020819052604090205460018301549194506001600160a01b03169067ffffffffffffffff1642106122f65784156122ae576122ae5f600133611e27565b6001600160a01b038a161580156122c457508615155b156122f15760405163d1a3b35560e01b81525f600482015260248101889052336044820152606401610f2c565b6123bb565b6001600160a01b03811615612339578a6040517fdef545a4000000000000000000000000000000000000000000000000000000008152600401610f2c9190613749565b6001600160a01b038a1661237b578a6040517ff60759e0000000000000000000000000000000000000000000000000000000008152600401610f2c9190613749565b841561238d5761238d5f601033611e27565b8567ffffffffffffffff165f036123b057600182015467ffffffffffffffff1695505b640100000000871796505b6001600160a01b038a16156123dd5767ffffffffffffffff86164210156123ea565b67ffffffffffffffff8616155b1561242d576040517ff1d446c300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602401610f2c565b6001600160a01b038116156124c557612448818560016126d6565b815482905f9061245d9063ffffffff166140df565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff1661249a906140df565b91906101000a81548163ffffffff021916908363ffffffff1602179055506124c28483611bf0565b93505b60018201805483546001600160a01b03808d16600160401b9081027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9093169290921786558b81169091026001600160e01b031990921667ffffffffffffffff8a1617919091179091558a1661258157336001600160a01b0316835f1b857f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88e8a604051612574929190614135565b60405180910390a461263a565b336001600160a01b0316835f1b857f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8e8e8b6040516125c293929190614160565b60405180910390a46125e58a85600160405180602001604052805f815250612cf6565b5f6125f08584611c0e565b9050806125ff576125ff61419b565b604051819086907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a361263781898d5f611ab0565b50505b6001600160a01b038916156126815760405133906001600160a01b038b169086907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a45b6001600160a01b038816156126c85760405133906001600160a01b038a169086907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a45b505050979650505050505050565b6001600160a01b0383166126fe57604051626a0d4560e21b81525f6004820152602401610f2c565b604080516001808252602082018590528183019081526060820184905260a082019092525f60808201818152919291610c429187918590859083612c30565b6001600160a01b03821661277f576040517fced3e1000000000000000000000000000000000000000000000000000000000081525f6004820152602401610f2c565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3191016110a4565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a006109f8565b5f6128168483612d52565b90508019831615611aaa576040517fa604e31800000000000000000000000000000000000000000000000000000000815260048101859052602481018490526001600160a01b0383166044820152606401610f2c565b5f61287684612a32565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611bcd575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690611b689089908390612a92565b5f82836128e58685612d8d565b1614949350505050565b5f83836128fd82823361280b565b8561291b57604051631850848b60e31b815260040160405180910390fd5b61219b868686600161286c565b6001600160a01b03841661295157604051632bfa23e760e11b81525f6004820152602401610f2c565b6001600160a01b03851661297957604051626a0d4560e21b81525f6004820152602401610f2c565b6040805160018082526020820186905281830190815260608201859052608082019092529061181487878484875f612c30565b5f6001600160e01b031982167f8f452d620000000000000000000000000000000000000000000000000000000014806109f857506109f882612daa565b5f8215801590612a0957505f6129fe84611650565b6001600160a01b0316145b15612a1557505f6109f8565b5f612a208484612d52565b90508315610bd657608081901c610d78565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811615612a8f576040517f2a7b2d2000000000000000000000000000000000000000000000000000000000815260048101829052602401610f2c565b50565b5f612a9c83612c87565b90508115612b65575f848152600360205260409020547f888888888888888888888888888888888888888888888888888888888888888890821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612b3d576040517ff91653480000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610f2c565b5f8481526003602052604081208054859290612b5a9084906141af565b90915550611aaa9050565b5f848152600360205260409020547f88888888888888888888888888888888888888888888888888888888888888889019821680197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef01161615612bff576040517f1f80c19b0000000000000000000000000000000000000000000000000000000081526004810185905260248101849052604401610f2c565b5f8481526003602052604081208054859290612c1c9084906141c2565b909155505050505050565b610c4285612e78565b612c3c86868686612f58565b6001600160a01b03851615612c7f578015612c6457612c5f338787878787613056565b612c7f565b60208481015190840151612c7c338989858589613177565b50505b505050505050565b5f612c9182612a32565b50600181901b17600281901b1790565b612caa8261325e565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115612cee57611e8182826132e1565b610fea61334a565b6001600160a01b038416612d1f57604051632bfa23e760e11b81525f6004820152602401610f2c565b60408051600180825260208201869052818301908152606082018590526080820190925290612c7f5f8784848784612c30565b5f610bd6612d608484612d8d565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000811660809190911c1790565b5f612d9883836120a1565b612da25f846120a1565b179392505050565b5f6001600160e01b031982167fd9b67a26000000000000000000000000000000000000000000000000000000001480612e0c57506001600160e01b031982167f6352211e00000000000000000000000000000000000000000000000000000000145b80612e4057506001600160e01b031982167f0e89341c00000000000000000000000000000000000000000000000000000000145b806109f857507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316146109f8565b8015612a8f5763ffffffff811681185f9081526101086020526040812090612ea08383611bf0565b5f818152602081905260409020549091506001600160a01b0316612ec6818360016126d6565b82548390600490612ee490640100000000900463ffffffff166140df565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f612f0d8385611bf0565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3610c428282600160405180602001604052805f815250612cf6565b612f6484848484613382565b6001600160a01b03831615801590612f8457506001600160a01b03841615155b15611aaa575f5b8251811015610c42575f838281518110612fa757612fa7613ffb565b60200260200101519050612fd08173100000000000000000000000000000000000000088611838565b613018576040517fe58f6d5a000000000000000000000000000000000000000000000000000000008152600481018290526001600160a01b0387166024820152604401610f2c565b5f83838151811061302b5761302b613ffb565b6020026020010151111561304d5761304d61304582610c04565b87875f613575565b50600101612f8b565b6001600160a01b0384163b15612c7f5760405163bc197c8160e01b81526001600160a01b0385169063bc197c819061309a90899089908890889088906004016141d5565b6020604051808303815f875af19250505080156130d4575060408051601f3d908101601f191682019092526130d191810190614232565b60015b61313b573d808015613101576040519150601f19603f3d011682016040523d82523d5f602084013e613106565b606091505b5080515f0361313357604051632bfa23e760e11b81526001600160a01b0386166004820152602401610f2c565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461181457604051632bfa23e760e11b81526001600160a01b0386166004820152602401610f2c565b6001600160a01b0384163b15612c7f5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e61906131bb908990899088908890889060040161424d565b6020604051808303815f875af19250505080156131f5575060408051601f3d908101601f191682019092526131f291810190614232565b60015b613222573d808015613101576040519150601f19603f3d011682016040523d82523d5f602084013e613106565b6001600160e01b0319811663f23a6e6160e01b1461181457604051632bfa23e760e11b81526001600160a01b0386166004820152602401610f2c565b806001600160a01b03163b5f0361329357604051634c9c8ce360e01b81526001600160a01b0382166004820152602401610f2c565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516132fd9190614284565b5f60405180830381855af49150503d805f8114613335576040519150601f19603f3d011682016040523d82523d5f602084013e61333a565b606091505b5091509150610a8a8583836135b6565b3415611f3d576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80518251146133b15781518151604051635b05999160e01b815260048101929092526024820152604401610f2c565b5f5b82518110156134af5760208181028481018201519084019091015180156134a5575f828152602081905260409020546001600160a01b03908116908816811461342e576040516303dee4c560e01b81526001600160a01b03891660048201525f60248201526044810183905260648101849052608401610f2c565b6001821115613470576040516303dee4c560e01b81526001600160a01b0389166004820152600160248201526044810183905260648101849052608401610f2c565b505f828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0388161790555b50506001016133b3565b508151600103613518576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050611aaa565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb858560405161356792919061429a565b60405180910390a450505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015610c42576135a98582868561286c565b50612c7f85828585611ab0565b6060826135c6576112c582613626565b81511580156135dd57506001600160a01b0384163b155b1561361f576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610f2c565b5080610bd6565b8051156136365780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0381168114612a8f575f80fd5b5f806040838503121561368d575f80fd5b823561369881613668565b946020939093013593505050565b6001600160e01b031981168114612a8f575f80fd5b5f602082840312156136cb575f80fd5b8135610bd6816136a6565b5f80604083850312156136e7575f80fd5b8235915060208301356136f981613668565b809150509250929050565b5f60208284031215613714575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610bd6602083018461371b565b5f806040838503121561376c575f80fd5b50508035926020909101359150565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156137b8576137b861377b565b604052919050565b5f67ffffffffffffffff8211156137d9576137d961377b565b5060051b60200190565b5f82601f8301126137f2575f80fd5b81356020613807613802836137c0565b61378f565b8083825260208201915060208460051b870101935086841115613828575f80fd5b602086015b84811015613844578035835291830191830161382d565b509695505050505050565b5f67ffffffffffffffff8211156138685761386861377b565b50601f01601f191660200190565b5f82601f830112613885575f80fd5b81356138936138028261384f565b8181528460208386010111156138a7575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a086880312156138d7575f80fd5b85356138e281613668565b945060208601356138f281613668565b9350604086013567ffffffffffffffff8082111561390e575f80fd5b61391a89838a016137e3565b9450606088013591508082111561392f575f80fd5b61393b89838a016137e3565b93506080880135915080821115613950575f80fd5b5061395d88828901613876565b9150509295509295909350565b5f8083601f84011261397a575f80fd5b50813567ffffffffffffffff811115613991575f80fd5b602083019150836020828501011115610d99575f80fd5b5f80602083850312156139b9575f80fd5b823567ffffffffffffffff8111156139cf575f80fd5b6139db8582860161396a565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b60038110613a1757634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a082019050613a2d8284516139fb565b67ffffffffffffffff60208401511660208301526001600160a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f60408486031215613a80575f80fd5b833567ffffffffffffffff811115613a96575f80fd5b613aa28682870161396a565b9094509250506020840135613ab681613668565b809150509250925092565b5f8060408385031215613ad2575f80fd5b823567ffffffffffffffff80821115613ae9575f80fd5b818501915085601f830112613afc575f80fd5b81356020613b0c613802836137c0565b82815260059290921b84018101918181019089841115613b2a575f80fd5b948201945b83861015613b51578535613b4281613668565b82529482019490820190613b2f565b96505086013592505080821115613b66575f80fd5b50613b73858286016137e3565b9150509250929050565b5f815180845260208085019450602084015f5b83811015613bac57815187529582019590820190600101613b90565b509495945050505050565b602081525f610bd66020830184613b7d565b5f8060408385031215613bda575f80fd5b8235613be581613668565b9150602083013567ffffffffffffffff811115613c00575f80fd5b613b7385828601613876565b803567ffffffffffffffff81168114613c23575f80fd5b919050565b5f8060408385031215613c39575f80fd5b82359150613c4960208401613c0c565b90509250929050565b602081016109f882846139fb565b5f60208284031215613c70575f80fd5b8135610bd681613668565b5f805f60608486031215613c8d575f80fd5b83359250602084013591506040840135613ab681613668565b6001600160a01b0383168152604060208201525f610d78604083018461371b565b5f805f805f8060c08789031215613cdc575f80fd5b863567ffffffffffffffff811115613cf2575f80fd5b613cfe89828a01613876565b9650506020870135613d0f81613668565b94506040870135613d1f81613668565b93506060870135613d2f81613668565b925060808701359150613d4460a08801613c0c565b90509295509295509295565b5f8060408385031215613d61575f80fd5b8235613d6c81613668565b9150602083013580151581146136f9575f80fd5b5f8060408385031215613d91575f80fd5b8235613d9c81613668565b915060208301356136f981613668565b5f805f805f60a08688031215613dc0575f80fd5b8535613dcb81613668565b94506020860135613ddb81613668565b93506040860135925060608601359150608086013567ffffffffffffffff811115613e04575f80fd5b61395d88828901613876565b600181811c90821680613e2457607f821691505b602082108103613e4257634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613e58575f80fd5b815167ffffffffffffffff811115613e6e575f80fd5b8201601f81018413613e7e575f80fd5b8051613e8c6138028261384f565b818152856020838501011115613ea0575f80fd5b8160208401602083015e5f91810160200191909152949350505050565b601f821115611e8157805f5260205f20601f840160051c81016020851015613ee25750805b601f840160051c820191505b81811015610c42575f8155600101613eee565b67ffffffffffffffff831115613f1957613f1961377b565b613f2d83613f278354613e10565b83613ebd565b5f601f841160018114613f5e575f8515613f475750838201355b5f19600387901b1c1916600186901b178355610c42565b5f83815260208120601f198716915b82811015613f8d5786850135825560209485019460019092019101613f6d565b5086821015613fa9575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152826040820152828460608301375f606084830101525f6060601f19601f86011683010190506001600160a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b815167ffffffffffffffff8111156140295761402961377b565b61403d816140378454613e10565b84613ebd565b602080601f831160018114614070575f84156140595750858301515b5f19600386901b1c1916600185901b178555612c7f565b5f85815260208120601f198616915b8281101561409e5788860151825594840194600190910190840161407f565b50858210156140bb57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036140f7576140f76140cb565b6001019392505050565b63ffffffff81811683821601908082111561215b5761215b6140cb565b5f6020828403121561412e575f80fd5b5051919050565b604081525f614147604083018561371b565b905067ffffffffffffffff831660208301529392505050565b606081525f614172606083018661371b565b90506001600160a01b038416602083015267ffffffffffffffff83166040830152949350505050565b634e487b7160e01b5f52600160045260245ffd5b808201808211156109f8576109f86140cb565b818103818111156109f8576109f86140cb565b5f6001600160a01b03808816835280871660208401525060a0604083015261420060a0830186613b7d565b82810360608401526142128186613b7d565b90508281036080840152614226818561371b565b98975050505050505050565b5f60208284031215614242575f80fd5b8151610bd6816136a6565b5f6001600160a01b03808816835280871660208401525084604083015283606083015260a0608083015261145760a083018461371b565b5f82518060208501845e5f920191825250919050565b604081525f6142ac6040830185613b7d565b8281036020840152610a8a8185613b7d56fea26469706673582212208e412974a6acab301cca4b8cd6175ca050f45502e53694b21451bd8a9fd20cb164736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "10903": [ + { + "length": 32, + "start": 7825 + }, + { + "length": 32, + "start": 7866 + }, + { + "length": 32, + "start": 8270 + } + ], + "28814": [ + { + "length": 32, + "start": 1933 + }, + { + "length": 32, + "start": 8663 + } + ] + }, + "inputSourceName": "project/src/registry/UserRegistry.sol", + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "CannotReduceExpiry(uint64,uint64)": [ + { + "details": "Error selector: `0x68c1425a`" + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "details": "Error selector: `0xf1d446c3`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1155InsufficientBalance(address,uint256,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred.", + "tokenId": "Identifier number of a token." + } + } + ], + "ERC1155InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "ERC1155InvalidOperator(address)": [ + { + "details": "Indicates a failure with the `operator` to be approved. Used in approvals.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC1155InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC1155InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC1155MissingApprovalForAll(address,address)": [ + { + "details": "Indicates a failure with the `operator`’s approval. Used in transfers.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner.", + "owner": "Address of the current owner of a token." + } + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "LabelAlreadyRegistered(string)": [ + { + "details": "Error selector: `0xdef545a4`" + } + ], + "LabelAlreadyReserved(string)": [ + { + "details": "Error selector: `0xf60759e0`" + } + ], + "LabelExpired(uint256)": [ + { + "details": "Error selector: `0xc44e2374`" + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "details": "Error selector: `0xe58f6d5a`" + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "ExpiryUpdated(uint256,uint64,address)": { + "params": { + "newExpiry": "The new expiry of the label.", + "sender": "The sender of the call to update the expiry.", + "tokenId": "The token ID of the label." + } + }, + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label registered.", + "labelHash": "The label hash registered.", + "owner": "The owner of the label.", + "sender": "The sender of the call to register.", + "tokenId": "The token ID registered." + } + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label reserved.", + "labelHash": "The label hash reserved.", + "sender": "The sender of the call to reserve.", + "tokenId": "The token ID reserved." + } + }, + "LabelUnregistered(uint256,address)": { + "params": { + "sender": "The sender of the call to unregister.", + "tokenId": "The token ID unregistered." + } + }, + "ParentUpdated(address,string,address)": { + "params": { + "label": "The new label.", + "parent": "The new parent.", + "sender": "The sender of the call to update the parent." + } + }, + "ResolverUpdated(uint256,address,address)": { + "params": { + "resolver": "The new resolver.", + "sender": "The sender of the call to update the resolver.", + "tokenId": "The token ID of the label." + } + }, + "SubregistryUpdated(uint256,address,address)": { + "params": { + "sender": "The sender of the call to update the subregistry.", + "subregistry": "The new subregistry.", + "tokenId": "The token ID of the label." + } + }, + "TokenRegenerated(uint256,uint256)": { + "params": { + "newTokenId": "The new token ID.", + "oldTokenId": "The old token ID." + } + }, + "TokenResource(uint256,uint256)": { + "params": { + "resource": "The EAC resource.", + "tokenId": "The token ID." + } + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + }, + "URIUpdated(string,address,address)": { + "params": { + "renderer": "The new render address.", + "sender": "The sender of the call to update the URI.", + "uri": "The new URI." + } + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "balanceOf(address,uint256)": { + "params": { + "account": "The account to get the balance for.", + "id": "The token ID." + }, + "returns": { + "_0": "balance The balance of the token for the account. This will only ever be 1 or 0." + } + }, + "balanceOfBatch(address[],uint256[])": { + "details": "`accounts` and `ids` must have the same length.", + "params": { + "accounts": "The accounts to get the balances for.", + "ids": "The token IDs." + }, + "returns": { + "_0": "batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0." + } + }, + "canUpgradeFrom(address)": { + "details": "Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call.", + "params": { + "": "{previousImplementation} Ignored." + }, + "returns": { + "allowed": "Always `true` for implementations in this registry family." + } + }, + "constructor": { + "params": { + "labelStore": "The shared label database.", + "namer": "The implementation namer." + } + }, + "findExpiry(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The expiry of the label." + } + }, + "findOwner(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The owner of the label." + } + }, + "findTokenId(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The token ID of the label." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getExpiry(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The expiry of the label, in seconds." + } + }, + "getOwner(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token owner." + } + }, + "getParent()": { + "returns": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "getResolver(string)": { + "params": { + "label": "The label to fetch a resolver for." + }, + "returns": { + "_0": "resolver The address of a resolver responsible for this label, or `address(0)` if none exists." + } + }, + "getResource(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The resource." + } + }, + "getState(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "state": "The state of the label." + } + }, + "getStatus(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The status of the label." + } + }, + "getSubregistry(string)": { + "params": { + "label": "The label to resolve." + }, + "returns": { + "_0": "The address of the registry for this label, or `address(0)` if none exists." + } + }, + "getTokenId(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token ID." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "initialize(address,uint256)": { + "details": "Grants the supplied role bitmap to `rootAccount` on the root resource. Reverts if the zero address.", + "params": { + "roleBitmap": "The role bitmap granted to `rootAccount`.", + "rootAccount": "Account granted root roles." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "account": "The account to get the approval for.", + "operator": "The operator to get the approval for." + }, + "returns": { + "_0": "approved The approval status." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "latestOwnerOf(uint256)": { + "params": { + "tokenId": "The token ID to query." + }, + "returns": { + "_0": "The latest owner address." + } + }, + "ownerOf(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The owner of the token." + } + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "register(string,address,address,address,uint256,uint64)": { + "params": { + "expiry": "The expiry of the label, in seconds.", + "label": "The label to register.", + "owner": "The address of the owner of the label.", + "registry": "The registry to set as the label.", + "resolver": "The resolver to set for the label.", + "roleBitmap": "The role bitmap to set for the label." + }, + "returns": { + "_0": "The token ID." + } + }, + "renew(uint256,uint64)": { + "details": "If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.", + "params": { + "anyId": "The labelhash, token ID, or resource.", + "newExpiry": "The new expiry, in seconds." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the tokens from.", + "ids": "The token IDs.", + "to": "The address to transfer the tokens to.", + "values": "The amounts of tokens to transfer." + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the token from.", + "id": "The token ID.", + "to": "The address to transfer the token to.", + "value": "The amount of tokens to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "The approval status.", + "operator": "The operator to set the approval for." + } + }, + "setParent(address,string)": { + "details": "Should emit `ParentUpdated`.", + "params": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "setResolver(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "resolver": "The new resolver." + } + }, + "setSubregistry(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "registry": "The new registry." + } + }, + "setURI(string,address)": { + "params": { + "renderer": "The new renderer address.", + "uri_": "The new URI." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "unregister(uint256)": { + "details": "Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.", + "params": { + "anyId": "The labelhash, token ID, or resource." + } + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "uri(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The URI for the token." + } + } + }, + "title": "UserRegistry", + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "3428000", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "LABEL_STORE()": "infinite", + "ROOT_RESOURCE()": "295", + "UPGRADE_INTERFACE_VERSION()": "infinite", + "balanceOf(address,uint256)": "infinite", + "balanceOfBatch(address[],uint256[])": "infinite", + "canUpgradeFrom(address)": "463", + "findExpiry(string)": "infinite", + "findOwner(string)": "infinite", + "findTokenId(string)": "infinite", + "getAssigneeCount(uint256,uint256)": "7395", + "getExpiry(uint256)": "2537", + "getOwner(uint256)": "infinite", + "getParent()": "infinite", + "getResolver(string)": "infinite", + "getResource(uint256)": "4896", + "getState(uint256)": "infinite", + "getStatus(uint256)": "infinite", + "getSubregistry(string)": "infinite", + "getTokenId(uint256)": "2663", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "infinite", + "hasRoles(uint256,uint256,address)": "infinite", + "hasRootRoles(uint256,address)": "2821", + "initialize(address,uint256)": "infinite", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "infinite", + "latestOwnerOf(uint256)": "2620", + "ownerOf(uint256)": "infinite", + "proxiableUUID()": "infinite", + "register(string,address,address,address,uint256,uint64)": "infinite", + "renew(uint256,uint64)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "infinite", + "roles(uint256,address)": "infinite", + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": "infinite", + "safeTransferFrom(address,address,uint256,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "26773", + "setParent(address,string)": "infinite", + "setResolver(uint256,address)": "infinite", + "setSubregistry(uint256,address)": "infinite", + "setURI(string,address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "unregister(uint256)": "infinite", + "upgradeToAndCall(address,bytes)": "infinite", + "uri(uint256)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"labelStore\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"oldExpiry\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"CannotReduceExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"CannotSetPastExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyReserved\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"LabelExpired\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"TransferDisallowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ExpiryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelReserved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelUnregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ParentUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RegistryCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ResolverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SubregistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldTokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newTokenId\",\"type\":\"uint256\"}],\"name\":\"TokenRegenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"TokenResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"renderer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"URIUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"LABEL_STORE\",\"outputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"canUpgradeFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getParent\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getResource\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"latestOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"internalType\":\"struct IPermissionedRegistry.State\",\"name\":\"state\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getSubregistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rootAccount\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"latestOwnerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setParent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"setSubregistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"},{\"internalType\":\"contract IRegistryURIRenderer\",\"name\":\"renderer\",\"type\":\"address\"}],\"name\":\"setURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"CannotReduceExpiry(uint64,uint64)\":[{\"details\":\"Error selector: `0x68c1425a`\"}],\"CannotSetPastExpiry(uint64)\":[{\"details\":\"Error selector: `0xf1d446c3`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1155InsufficientBalance(address,uint256,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\",\"tokenId\":\"Identifier number of a token.\"}}],\"ERC1155InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"ERC1155InvalidOperator(address)\":[{\"details\":\"Indicates a failure with the `operator` to be approved. Used in approvals.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC1155InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC1155InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC1155MissingApprovalForAll(address,address)\":[{\"details\":\"Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\",\"owner\":\"Address of the current owner of a token.\"}}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"LabelAlreadyRegistered(string)\":[{\"details\":\"Error selector: `0xdef545a4`\"}],\"LabelAlreadyReserved(string)\":[{\"details\":\"Error selector: `0xf60759e0`\"}],\"LabelExpired(uint256)\":[{\"details\":\"Error selector: `0xc44e2374`\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"TransferDisallowed(uint256,address)\":[{\"details\":\"Error selector: `0xe58f6d5a`\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"ExpiryUpdated(uint256,uint64,address)\":{\"params\":{\"newExpiry\":\"The new expiry of the label.\",\"sender\":\"The sender of the call to update the expiry.\",\"tokenId\":\"The token ID of the label.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label registered.\",\"labelHash\":\"The label hash registered.\",\"owner\":\"The owner of the label.\",\"sender\":\"The sender of the call to register.\",\"tokenId\":\"The token ID registered.\"}},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label reserved.\",\"labelHash\":\"The label hash reserved.\",\"sender\":\"The sender of the call to reserve.\",\"tokenId\":\"The token ID reserved.\"}},\"LabelUnregistered(uint256,address)\":{\"params\":{\"sender\":\"The sender of the call to unregister.\",\"tokenId\":\"The token ID unregistered.\"}},\"ParentUpdated(address,string,address)\":{\"params\":{\"label\":\"The new label.\",\"parent\":\"The new parent.\",\"sender\":\"The sender of the call to update the parent.\"}},\"ResolverUpdated(uint256,address,address)\":{\"params\":{\"resolver\":\"The new resolver.\",\"sender\":\"The sender of the call to update the resolver.\",\"tokenId\":\"The token ID of the label.\"}},\"SubregistryUpdated(uint256,address,address)\":{\"params\":{\"sender\":\"The sender of the call to update the subregistry.\",\"subregistry\":\"The new subregistry.\",\"tokenId\":\"The token ID of the label.\"}},\"TokenRegenerated(uint256,uint256)\":{\"params\":{\"newTokenId\":\"The new token ID.\",\"oldTokenId\":\"The old token ID.\"}},\"TokenResource(uint256,uint256)\":{\"params\":{\"resource\":\"The EAC resource.\",\"tokenId\":\"The token ID.\"}},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"},\"URIUpdated(string,address,address)\":{\"params\":{\"renderer\":\"The new render address.\",\"sender\":\"The sender of the call to update the URI.\",\"uri\":\"The new URI.\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"params\":{\"account\":\"The account to get the balance for.\",\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"balance The balance of the token for the account. This will only ever be 1 or 0.\"}},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"`accounts` and `ids` must have the same length.\",\"params\":{\"accounts\":\"The accounts to get the balances for.\",\"ids\":\"The token IDs.\"},\"returns\":{\"_0\":\"batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\"}},\"canUpgradeFrom(address)\":{\"details\":\"Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call.\",\"params\":{\"\":\"{previousImplementation} Ignored.\"},\"returns\":{\"allowed\":\"Always `true` for implementations in this registry family.\"}},\"constructor\":{\"params\":{\"labelStore\":\"The shared label database.\",\"namer\":\"The implementation namer.\"}},\"findExpiry(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The expiry of the label.\"}},\"findOwner(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The owner of the label.\"}},\"findTokenId(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The token ID of the label.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getExpiry(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The expiry of the label, in seconds.\"}},\"getOwner(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token owner.\"}},\"getParent()\":{\"returns\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"getResolver(string)\":{\"params\":{\"label\":\"The label to fetch a resolver for.\"},\"returns\":{\"_0\":\"resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\"}},\"getResource(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The resource.\"}},\"getState(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"state\":\"The state of the label.\"}},\"getStatus(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The status of the label.\"}},\"getSubregistry(string)\":{\"params\":{\"label\":\"The label to resolve.\"},\"returns\":{\"_0\":\"The address of the registry for this label, or `address(0)` if none exists.\"}},\"getTokenId(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"initialize(address,uint256)\":{\"details\":\"Grants the supplied role bitmap to `rootAccount` on the root resource. Reverts if the zero address.\",\"params\":{\"roleBitmap\":\"The role bitmap granted to `rootAccount`.\",\"rootAccount\":\"Account granted root roles.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"account\":\"The account to get the approval for.\",\"operator\":\"The operator to get the approval for.\"},\"returns\":{\"_0\":\"approved The approval status.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"latestOwnerOf(uint256)\":{\"params\":{\"tokenId\":\"The token ID to query.\"},\"returns\":{\"_0\":\"The latest owner address.\"}},\"ownerOf(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The owner of the token.\"}},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"register(string,address,address,address,uint256,uint64)\":{\"params\":{\"expiry\":\"The expiry of the label, in seconds.\",\"label\":\"The label to register.\",\"owner\":\"The address of the owner of the label.\",\"registry\":\"The registry to set as the label.\",\"resolver\":\"The resolver to set for the label.\",\"roleBitmap\":\"The role bitmap to set for the label.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"renew(uint256,uint64)\":{\"details\":\"If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"newExpiry\":\"The new expiry, in seconds.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the tokens from.\",\"ids\":\"The token IDs.\",\"to\":\"The address to transfer the tokens to.\",\"values\":\"The amounts of tokens to transfer.\"}},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the token from.\",\"id\":\"The token ID.\",\"to\":\"The address to transfer the token to.\",\"value\":\"The amount of tokens to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"The approval status.\",\"operator\":\"The operator to set the approval for.\"}},\"setParent(address,string)\":{\"details\":\"Should emit `ParentUpdated`.\",\"params\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"setResolver(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"resolver\":\"The new resolver.\"}},\"setSubregistry(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"registry\":\"The new registry.\"}},\"setURI(string,address)\":{\"params\":{\"renderer\":\"The new renderer address.\",\"uri_\":\"The new URI.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"unregister(uint256)\":{\"details\":\"Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"}},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"uri(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The URI for the token.\"}}},\"title\":\"UserRegistry\",\"version\":1},\"userdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"notice\":\"Label expiry cannot be reduced.\"}],\"CannotSetPastExpiry(uint64)\":[{\"notice\":\"Label expiry cannot be before now.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"LabelAlreadyRegistered(string)\":[{\"notice\":\"Label is already registered.\"}],\"LabelAlreadyReserved(string)\":[{\"notice\":\"Label cannot be reserved again.\"}],\"LabelExpired(uint256)\":[{\"notice\":\"Label is expired/unregistered.\"}],\"TransferDisallowed(uint256,address)\":[{\"notice\":\"Transfer is not allowed due to missing transfer admin role.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"ExpiryUpdated(uint256,uint64,address)\":{\"notice\":\"Expiry of label was changed.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"notice\":\"A label was registered.\"},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"notice\":\"A label was reserved.\"},\"LabelUnregistered(uint256,address)\":{\"notice\":\"A label was unregistered.\"},\"ParentUpdated(address,string,address)\":{\"notice\":\"Parent was changed.\"},\"RegistryCreated()\":{\"notice\":\"A registry was created/initialized.\"},\"ResolverUpdated(uint256,address,address)\":{\"notice\":\"Resolver of label was changed.\"},\"SubregistryUpdated(uint256,address,address)\":{\"notice\":\"Subregistry of label was changed.\"},\"TokenRegenerated(uint256,uint256)\":{\"notice\":\"Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance.\"},\"TokenResource(uint256,uint256)\":{\"notice\":\"Associate a token with an EAC resource.\"},\"URIUpdated(string,address,address)\":{\"notice\":\"URI was changed.\"}},\"kind\":\"user\",\"methods\":{\"LABEL_STORE()\":{\"notice\":\"The shared label database.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"balanceOf(address,uint256)\":{\"notice\":\"Returns the balance of a token for an account.\"},\"balanceOfBatch(address[],uint256[])\":{\"notice\":\"Returns the balances of a batch of tokens for an account.\"},\"canUpgradeFrom(address)\":{\"notice\":\"Declares this implementation as an eligible verifiable proxy upgrade target.\"},\"findExpiry(string)\":{\"notice\":\"Fetches the label expiry.\"},\"findOwner(string)\":{\"notice\":\"Fetches the label owner.\"},\"findTokenId(string)\":{\"notice\":\"Fetches the token ID for a label.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getExpiry(uint256)\":{\"notice\":\"Get expiry of label.\"},\"getOwner(uint256)\":{\"notice\":\"Get token owner from `anyId`.\"},\"getParent()\":{\"notice\":\"Get canonical \\\"location\\\" of this registry.\"},\"getResolver(string)\":{\"notice\":\"Fetches the resolver responsible for the specified label.\"},\"getResource(uint256)\":{\"notice\":\"Get `resource` from `anyId`.\"},\"getState(uint256)\":{\"notice\":\"Get the state of a label.\"},\"getStatus(uint256)\":{\"notice\":\"Get `Status` from `anyId`.\"},\"getSubregistry(string)\":{\"notice\":\"Fetches the registry for a label.\"},\"getTokenId(uint256)\":{\"notice\":\"Get `tokenId` from `anyId`.\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"initialize(address,uint256)\":{\"notice\":\"Initializes a proxy instance of `UserRegistry`.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Returns the approval for all operator.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"latestOwnerOf(uint256)\":{\"notice\":\"Get the latest owner of a token. If the token was burned, returns null.\"},\"ownerOf(uint256)\":{\"notice\":\"Returns the owner of a token.\"},\"register(string,address,address,address,uint256,uint64)\":{\"notice\":\"Registers a new label.\"},\"renew(uint256,uint64)\":{\"notice\":\"Renew a label.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Transfers multiple tokens from one address to another.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"notice\":\"Transfers a single token from one address to another.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Sets the approval for all operator.\"},\"setParent(address,string)\":{\"notice\":\"Change canonical \\\"location\\\".\"},\"setResolver(uint256,address)\":{\"notice\":\"Change resolver of label.\"},\"setSubregistry(uint256,address)\":{\"notice\":\"Change registry of label.\"},\"setURI(string,address)\":{\"notice\":\"Set the URI for the registry.\"},\"unregister(uint256)\":{\"notice\":\"Delete a label.\"},\"uri(uint256)\":{\"notice\":\"Returns the URI for a token.\"}},\"notice\":\"UUPS-upgradeable `PermissionedRegistry` designed to be deployed as a proxy via `VerifiableFactory` for user-owned subdomain registries. The constructor disables initializers on the implementation contract; proxies call `initialize()` to set up the admin and initial roles. Upgrade authorization requires the upgrade role in the root resource.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/UserRegistry.sol\":\"UserRegistry\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\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 * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\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 Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reinitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\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 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\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 _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\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 // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.\\n *\\n * NOTE: Consider following the ERC-7201 formula to derive storage locations.\\n */\\n function _initializableStorageSlot() internal pure virtual returns (bytes32) {\\n return INITIALIZABLE_STORAGE;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n bytes32 slot = _initializableStorageSlot();\\n assembly {\\n $.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IERC1822Proxiable} from \\\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\\\";\\nimport {ERC1967Utils} from \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol\\\";\\nimport {Initializable} from \\\"./Initializable.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 */\\nabstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`\\n * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\\n * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.\\n * If the getter returns `\\\"5.0.0\\\"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must\\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\\n * during an upgrade.\\n */\\n string public constant UPGRADE_INTERFACE_VERSION = \\\"5.0.0\\\";\\n\\n /**\\n * @dev The call is from an unauthorized context.\\n */\\n error UUPSUnauthorizedCallContext();\\n\\n /**\\n * @dev The storage `slot` is unsupported as a UUID.\\n */\\n error UUPSUnsupportedProxiableUUID(bytes32 slot);\\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 ERC-1967) 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 ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n _checkProxy();\\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 _checkNotDelegated();\\n _;\\n }\\n\\n function __UUPSUpgradeable_init() internal onlyInitializing {\\n }\\n\\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\\n }\\n /**\\n * @dev Implementation of the ERC-1822 {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 notDelegated returns (bytes32) {\\n return ERC1967Utils.IMPLEMENTATION_SLOT;\\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 * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data);\\n }\\n\\n /**\\n * @dev Reverts if the execution is not performed via delegatecall or the execution\\n * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.\\n */\\n function _checkProxy() internal view virtual {\\n if (\\n address(this) == __self || // Must be called through delegatecall\\n ERC1967Utils.getImplementation() != __self // Must be called through an active proxy\\n ) {\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Reverts if the execution is performed via delegatecall.\\n * See {notDelegated}.\\n */\\n function _checkNotDelegated() internal view virtual {\\n if (address(this) != __self) {\\n // Must not be called through delegatecall\\n revert UUPSUnauthorizedCallContext();\\n }\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {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 onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n\\n /**\\n * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.\\n *\\n * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value\\n * is expected to be the implementation slot in ERC-1967.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {\\n revert UUPSUnsupportedProxiableUUID(slot);\\n }\\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\\n } catch {\\n // The implementation is not UUPS\\n revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\\n */\\ninterface IERC1967 {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Emitted when the beacon is changed.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n}\\n\",\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev ERC-1822: 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\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)\\n\\npragma solidity ^0.8.22;\\n\\nimport {IBeacon} from \\\"../beacon/IBeacon.sol\\\";\\nimport {IERC1967} from \\\"../../interfaces/IERC1967.sol\\\";\\nimport {Address} from \\\"../../utils/Address.sol\\\";\\nimport {StorageSlot} from \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This library provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\\n */\\nlibrary ERC1967Utils {\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev The `implementation` of the proxy is invalid.\\n */\\n error ERC1967InvalidImplementation(address implementation);\\n\\n /**\\n * @dev The `admin` of the proxy is invalid.\\n */\\n error ERC1967InvalidAdmin(address admin);\\n\\n /**\\n * @dev The `beacon` of the proxy is invalid.\\n */\\n error ERC1967InvalidBeacon(address beacon);\\n\\n /**\\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\\n */\\n error ERC1967NonPayable();\\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 ERC-1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n if (newImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(newImplementation);\\n }\\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\\n _setImplementation(newImplementation);\\n emit IERC1967.Upgraded(newImplementation);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(newImplementation, data);\\n } else {\\n _checkNonPayable();\\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.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\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 ERC-1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n if (newAdmin == address(0)) {\\n revert ERC1967InvalidAdmin(address(0));\\n }\\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {IERC1967-AdminChanged} event.\\n */\\n function changeAdmin(address newAdmin) internal {\\n emit IERC1967.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 the keccak-256 hash of \\\"eip1967.proxy.beacon\\\" subtracted by 1.\\n */\\n // solhint-disable-next-line private-vars-leading-underscore\\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\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 ERC-1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n if (newBeacon.code.length == 0) {\\n revert ERC1967InvalidBeacon(newBeacon);\\n }\\n\\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\\n\\n address beaconImplementation = IBeacon(newBeacon).implementation();\\n if (beaconImplementation.code.length == 0) {\\n revert ERC1967InvalidImplementation(beaconImplementation);\\n }\\n }\\n\\n /**\\n * @dev Change the beacon and trigger a setup call if data is nonempty.\\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\\n * to avoid stuck value in the contract.\\n *\\n * Emits an {IERC1967-BeaconUpgraded} event.\\n *\\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\\n * efficiency.\\n */\\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\\n _setBeacon(newBeacon);\\n emit IERC1967.BeaconUpgraded(newBeacon);\\n\\n if (data.length > 0) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n } else {\\n _checkNonPayable();\\n }\\n }\\n\\n /**\\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\\n * if an upgrade doesn't perform an initialization call.\\n */\\n function _checkNonPayable() private {\\n if (msg.value > 0) {\\n revert ERC1967NonPayable();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.20;\\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 * {UpgradeableBeacon} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev There's no code at `target` (it is not a contract).\\n */\\n error AddressEmptyCode(address target);\\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n\\n (bool success, bytes memory returndata) = recipient.call{value: amount}(\\\"\\\");\\n if (!success) {\\n _revert(returndata);\\n }\\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 or custom error, it is bubbled\\n * up by this function (like regular Solidity function calls). However, if\\n * the call reverted with no returned reason, this function reverts with a\\n * {Errors.FailedCall} error.\\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0);\\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n if (address(this).balance < value) {\\n revert Errors.InsufficientBalance(address(this).balance, value);\\n }\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\\n * of an unsuccessful call.\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata\\n ) internal view returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n // only check if target is a contract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n if (returndata.length == 0 && target.code.length == 0) {\\n revert AddressEmptyCode(target);\\n }\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\\n * revert reason or with a default {Errors.FailedCall} error.\\n */\\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\\n if (!success) {\\n _revert(returndata);\\n } else {\\n return returndata;\\n }\\n }\\n\\n /**\\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\\n */\\n function _revert(bytes memory returndata) 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 assembly (\\\"memory-safe\\\") {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert Errors.FailedCall();\\n }\\n }\\n}\\n\",\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Standard ERC-20 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\\n */\\ninterface IERC20Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC20InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC20InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `spender`\\u2019s `allowance`. Used in transfers.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n * @param allowance Amount of tokens a `spender` is allowed to operate with.\\n * @param needed Minimum amount required to perform a transfer.\\n */\\n error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC20InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\\n * @param spender Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC20InvalidSpender(address spender);\\n}\\n\\n/**\\n * @dev Standard ERC-721 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\\n */\\ninterface IERC721Errors {\\n /**\\n * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\\n * Used in balance queries.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721InvalidOwner(address owner);\\n\\n /**\\n * @dev Indicates a `tokenId` whose `owner` is the zero address.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721NonexistentToken(uint256 tokenId);\\n\\n /**\\n * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param tokenId Identifier number of a token.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC721InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC721InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC721InsufficientApproval(address operator, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC721InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC721InvalidOperator(address operator);\\n}\\n\\n/**\\n * @dev Standard ERC-1155 Errors\\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\\n */\\ninterface IERC1155Errors {\\n /**\\n * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n * @param balance Current balance for the interacting account.\\n * @param needed Minimum amount required to perform a transfer.\\n * @param tokenId Identifier number of a token.\\n */\\n error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\\n\\n /**\\n * @dev Indicates a failure with the token `sender`. Used in transfers.\\n * @param sender Address whose tokens are being transferred.\\n */\\n error ERC1155InvalidSender(address sender);\\n\\n /**\\n * @dev Indicates a failure with the token `receiver`. Used in transfers.\\n * @param receiver Address to which tokens are being transferred.\\n */\\n error ERC1155InvalidReceiver(address receiver);\\n\\n /**\\n * @dev Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n * @param owner Address of the current owner of a token.\\n */\\n error ERC1155MissingApprovalForAll(address operator, address owner);\\n\\n /**\\n * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\\n * @param approver Address initiating an approval operation.\\n */\\n error ERC1155InvalidApprover(address approver);\\n\\n /**\\n * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\\n * @param operator Address that may be allowed to operate on tokens without being their owner.\\n */\\n error ERC1155InvalidOperator(address operator);\\n\\n /**\\n * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\\n * Used in batch transfers.\\n * @param idsLength Length of the array of token identifiers\\n * @param valuesLength Length of the array of token amounts\\n */\\n error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\\n}\\n\",\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC-1155 compliant contract, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-1155[ERC].\\n */\\ninterface IERC1155 is IERC165 {\\n /**\\n * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\\n */\\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\\n\\n /**\\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\\n * transfers.\\n */\\n event TransferBatch(\\n address indexed operator,\\n address indexed from,\\n address indexed to,\\n uint256[] ids,\\n uint256[] values\\n );\\n\\n /**\\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\\n * `approved`.\\n */\\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\\n\\n /**\\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\\n *\\n * If an {URI} event was emitted for `id`, the standard\\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\\n * returned by {IERC1155MetadataURI-uri}.\\n */\\n event URI(string value, uint256 indexed id);\\n\\n /**\\n * @dev Returns the value of tokens of token type `id` owned by `account`.\\n */\\n function balanceOf(address account, uint256 id) external view returns (uint256);\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\\n *\\n * Requirements:\\n *\\n * - `accounts` and `ids` must have the same length.\\n */\\n function balanceOfBatch(\\n address[] calldata accounts,\\n uint256[] calldata ids\\n ) external view returns (uint256[] memory);\\n\\n /**\\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\\n *\\n * Emits an {ApprovalForAll} event.\\n *\\n * Requirements:\\n *\\n * - `operator` cannot be the zero address.\\n */\\n function setApprovalForAll(address operator, bool approved) external;\\n\\n /**\\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\\n *\\n * See {setApprovalForAll}.\\n */\\n function isApprovedForAll(address account, address operator) external view returns (bool);\\n\\n /**\\n * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits a {TransferSingle} event.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\\n * - `from` must have a balance of tokens of type `id` of at least `value` amount.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\\n * acceptance magic value.\\n */\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;\\n\\n /**\\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\\n *\\n * WARNING: This function can potentially allow a reentrancy attack when transferring tokens\\n * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.\\n * Ensure to follow the checks-effects-interactions pattern and consider employing\\n * reentrancy guards when interacting with untrusted contracts.\\n *\\n * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.\\n *\\n * Requirements:\\n *\\n * - `ids` and `values` must have the same length.\\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\\n * acceptance magic value.\\n */\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Interface that must be implemented by smart contracts in order to receive\\n * ERC-1155 token transfers.\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC-1155 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 ERC-1155 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\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/extensions/IERC1155MetadataURI.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155} from \\\"../IERC1155.sol\\\";\\n\\n/**\\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[ERC].\\n */\\ninterface IERC1155MetadataURI is IERC1155 {\\n /**\\n * @dev Returns the URI for token type `id`.\\n *\\n * If the `\\\\{id\\\\}` substring is present in the URI, it must be replaced by\\n * clients with the actual token type ID.\\n */\\n function uri(uint256 id) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x35d120c427299af1525aaf07955314d9e36a62f14408eb93dec71a2e001f74d3\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/utils/ERC1155Utils.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC1155Receiver} from \\\"../IERC1155Receiver.sol\\\";\\nimport {IERC1155Errors} from \\\"../../../interfaces/draft-IERC6093.sol\\\";\\n\\n/**\\n * @dev Library that provide common ERC-1155 utility functions.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-1155[ERC-1155].\\n *\\n * _Available since v5.1._\\n */\\nlibrary ERC1155Utils {\\n /**\\n * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155Received(\\n address operator,\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, value, data) returns (bytes4 response) {\\n if (response != IERC1155Receiver.onERC1155Received.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived}\\n * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\\n *\\n * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\\n * Otherwise, the recipient must implement {IERC1155Receiver-onERC1155Received} and return the acceptance magic value to accept\\n * the transfer.\\n */\\n function checkOnERC1155BatchReceived(\\n address operator,\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n ) internal {\\n if (to.code.length > 0) {\\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, values, data) returns (\\n bytes4 response\\n ) {\\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\\n // Tokens rejected\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n }\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n // non-IERC1155Receiver implementer\\n revert IERC1155Errors.ERC1155InvalidReceiver(to);\\n } else {\\n assembly (\\\"memory-safe\\\") {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x22f099c02c252dd1f6ddc464916ce683294a63b23b3c6ee3d290b77398e2474b\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)\\n// This file was procedurally generated from scripts/generate/templates/Arrays.js.\\n\\npragma solidity ^0.8.20;\\n\\nimport {Comparators} from \\\"./Comparators.sol\\\";\\nimport {SlotDerivation} from \\\"./SlotDerivation.sol\\\";\\nimport {StorageSlot} from \\\"./StorageSlot.sol\\\";\\nimport {Math} from \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev Collection of functions related to array types.\\n */\\nlibrary Arrays {\\n using SlotDerivation for bytes32;\\n using StorageSlot for bytes32;\\n\\n /**\\n * @dev Sort an array of uint256 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n uint256[] memory array,\\n function(uint256, uint256) pure returns (bool) comp\\n ) internal pure returns (uint256[] memory) {\\n _quickSort(_begin(array), _end(array), comp);\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of uint256 in increasing order.\\n */\\n function sort(uint256[] memory array) internal pure returns (uint256[] memory) {\\n sort(array, Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of address (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n address[] memory array,\\n function(address, address) pure returns (bool) comp\\n ) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of address in increasing order.\\n */\\n function sort(address[] memory array) internal pure returns (address[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Sort an array of bytes32 (in memory) following the provided comparator function.\\n *\\n * This function does the sorting \\\"in place\\\", meaning that it overrides the input. The object is returned for\\n * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.\\n *\\n * NOTE: this function's cost is `O(n \\u00b7 log(n))` in average and `O(n\\u00b2)` in the worst case, with n the length of the\\n * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful\\n * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may\\n * consume more gas than is available in a block, leading to potential DoS.\\n *\\n * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.\\n */\\n function sort(\\n bytes32[] memory array,\\n function(bytes32, bytes32) pure returns (bool) comp\\n ) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), _castToUint256Comp(comp));\\n return array;\\n }\\n\\n /**\\n * @dev Variant of {sort} that sorts an array of bytes32 in increasing order.\\n */\\n function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {\\n sort(_castToUint256Array(array), Comparators.lt);\\n return array;\\n }\\n\\n /**\\n * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops\\n * at end (exclusive). Sorting follows the `comp` comparator.\\n *\\n * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.\\n *\\n * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should\\n * be used only if the limits are within a memory array.\\n */\\n function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {\\n unchecked {\\n if (end - begin < 0x40) return;\\n\\n // Use first element as pivot\\n uint256 pivot = _mload(begin);\\n // Position where the pivot should be at the end of the loop\\n uint256 pos = begin;\\n\\n for (uint256 it = begin + 0x20; it < end; it += 0x20) {\\n if (comp(_mload(it), pivot)) {\\n // If the value stored at the iterator's position comes before the pivot, we increment the\\n // position of the pivot and move the value there.\\n pos += 0x20;\\n _swap(pos, it);\\n }\\n }\\n\\n _swap(begin, pos); // Swap pivot into place\\n _quickSort(begin, pos, comp); // Sort the left side of the pivot\\n _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first element of `array`.\\n */\\n function _begin(uint256[] memory array) private pure returns (uint256 ptr) {\\n assembly (\\\"memory-safe\\\") {\\n ptr := add(array, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word\\n * that comes just after the last element of the array.\\n */\\n function _end(uint256[] memory array) private pure returns (uint256 ptr) {\\n unchecked {\\n return _begin(array) + array.length * 0x20;\\n }\\n }\\n\\n /**\\n * @dev Load memory word (as a uint256) at location `ptr`.\\n */\\n function _mload(uint256 ptr) private pure returns (uint256 value) {\\n assembly {\\n value := mload(ptr)\\n }\\n }\\n\\n /**\\n * @dev Swaps the elements memory location `ptr1` and `ptr2`.\\n */\\n function _swap(uint256 ptr1, uint256 ptr2) private pure {\\n assembly {\\n let value1 := mload(ptr1)\\n let value2 := mload(ptr2)\\n mstore(ptr1, value2)\\n mstore(ptr2, value1)\\n }\\n }\\n\\n /// @dev Helper: low level cast address memory array to uint256 memory array\\n function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 memory array to uint256 memory array\\n function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast address comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(address, address) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /// @dev Helper: low level cast bytes32 comp function to uint256 comp function\\n function _castToUint256Comp(\\n function(bytes32, bytes32) pure returns (bool) input\\n ) private pure returns (function(uint256, uint256) pure returns (bool) output) {\\n assembly {\\n output := input\\n }\\n }\\n\\n /**\\n * @dev Searches a sorted `array` and returns the first index that contains\\n * a value greater or equal to `element`. If no such index exists (i.e. all\\n * values in the array are strictly less than `element`), the array length is\\n * returned. Time complexity O(log n).\\n *\\n * NOTE: The `array` is expected to be sorted in ascending order, and to\\n * contain no repeated elements.\\n *\\n * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks\\n * support for repeated elements in the array. The {lowerBound} function should\\n * be used instead.\\n */\\n function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n low = mid + 1;\\n }\\n }\\n\\n // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.\\n if (low > 0 && unsafeAccess(array, low - 1).value == element) {\\n return low - 1;\\n } else {\\n return low;\\n }\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value greater or equal than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].\\n */\\n function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Searches an `array` sorted in ascending order and returns the first\\n * index that contains a value strictly greater than `element`. If no such index\\n * exists (i.e. all values in the array are strictly less than `element`), the array\\n * length is returned. Time complexity O(log n).\\n *\\n * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].\\n */\\n function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeAccess(array, mid).value > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {lowerBound}, but with an array in memory.\\n */\\n function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) < element) {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n } else {\\n high = mid;\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Same as {upperBound}, but with an array in memory.\\n */\\n function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {\\n uint256 low = 0;\\n uint256 high = array.length;\\n\\n if (high == 0) {\\n return 0;\\n }\\n\\n while (low < high) {\\n uint256 mid = Math.average(low, high);\\n\\n // Note that mid will always be strictly less than high (i.e. it will be a valid array index)\\n // because Math.average rounds towards zero (it does integer division with truncation).\\n if (unsafeMemoryAccess(array, mid) > element) {\\n high = mid;\\n } else {\\n // this cannot overflow because mid < high\\n unchecked {\\n low = mid + 1;\\n }\\n }\\n }\\n\\n return low;\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getAddressSlot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getBytes32Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {\\n bytes32 slot;\\n assembly (\\\"memory-safe\\\") {\\n slot := arr.slot\\n }\\n return slot.deriveArray().offset(pos).getUint256Slot();\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Access an array in an \\\"unsafe\\\" way. Skips solidity \\\"index-out-of-range\\\" check.\\n *\\n * WARNING: Only use if you are certain `pos` is lower than the array length.\\n */\\n function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {\\n assembly {\\n res := mload(add(add(arr, 0x20), mul(pos, 0x20)))\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(address[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(bytes32[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n\\n /**\\n * @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.\\n *\\n * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.\\n */\\n function unsafeSetLength(uint256[] storage array, uint256 len) internal {\\n assembly (\\\"memory-safe\\\") {\\n sstore(array.slot, len)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x55a4fdb408e3db950b48f4a6131e538980be8c5f48ee59829d92d66477140cd6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Provides a set of functions to compare values.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Comparators {\\n function lt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a < b;\\n }\\n\\n function gt(uint256 a, uint256 b) internal pure returns (bool) {\\n return a > b;\\n }\\n}\\n\",\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Helper library for emitting standardized panic codes.\\n *\\n * ```solidity\\n * contract Example {\\n * using Panic for uint256;\\n *\\n * // Use any of the declared internal constants\\n * function foo() { Panic.GENERIC.panic(); }\\n *\\n * // Alternatively\\n * function foo() { Panic.panic(Panic.GENERIC); }\\n * }\\n * ```\\n *\\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\\n *\\n * _Available since v5.1._\\n */\\n// slither-disable-next-line unused-state\\nlibrary Panic {\\n /// @dev generic / unspecified error\\n uint256 internal constant GENERIC = 0x00;\\n /// @dev used by the assert() builtin\\n uint256 internal constant ASSERT = 0x01;\\n /// @dev arithmetic underflow or overflow\\n uint256 internal constant UNDER_OVERFLOW = 0x11;\\n /// @dev division or modulo by zero\\n uint256 internal constant DIVISION_BY_ZERO = 0x12;\\n /// @dev enum conversion error\\n uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\\n /// @dev invalid encoding in storage\\n uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\\n /// @dev empty array pop\\n uint256 internal constant EMPTY_ARRAY_POP = 0x31;\\n /// @dev array out of bounds access\\n uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\\n /// @dev resource error (too large allocation or too large array)\\n uint256 internal constant RESOURCE_ERROR = 0x41;\\n /// @dev calling invalid internal function\\n uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\\n\\n /// @dev Reverts with a panic code. Recommended to use with\\n /// the internal constants with predefined codes.\\n function panic(uint256 code) internal pure {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, 0x4e487b71)\\n mstore(0x20, code)\\n revert(0x1c, 0x24)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)\\n// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots\\n * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by\\n * the solidity language / compiler.\\n *\\n * 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.].\\n *\\n * Example usage:\\n * ```solidity\\n * contract Example {\\n * // Add the library methods\\n * using StorageSlot for bytes32;\\n * using SlotDerivation for bytes32;\\n *\\n * // Declare a namespace\\n * string private constant _NAMESPACE = \\\"\\\"; // eg. OpenZeppelin.Slot\\n *\\n * function setValueInNamespace(uint256 key, address newValue) internal {\\n * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;\\n * }\\n *\\n * function getValueInNamespace(uint256 key) internal view returns (address) {\\n * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {StorageSlot}.\\n *\\n * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking\\n * upgrade safety will ignore the slots accessed through this library.\\n *\\n * _Available since v5.1._\\n */\\nlibrary SlotDerivation {\\n /**\\n * @dev Derive an ERC-7201 slot from a string (namespace).\\n */\\n function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))\\n slot := and(keccak256(0x00, 0x20), not(0xff))\\n }\\n }\\n\\n /**\\n * @dev Add an offset to a slot to get the n-th element of a structure or an array.\\n */\\n function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {\\n unchecked {\\n return bytes32(uint256(slot) + pos);\\n }\\n }\\n\\n /**\\n * @dev Derive the location of the first element in an array from the slot where the length is stored.\\n */\\n function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, slot)\\n result := keccak256(0x00, 0x20)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, and(key, shr(96, not(0))))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, iszero(iszero(key)))\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n mstore(0x00, key)\\n mstore(0x20, slot)\\n result := keccak256(0x00, 0x40)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n\\n /**\\n * @dev Derive the location of a mapping element from the key.\\n */\\n function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {\\n assembly (\\\"memory-safe\\\") {\\n let length := mload(key)\\n let begin := add(key, 0x20)\\n let end := add(begin, length)\\n let cache := mload(end)\\n mstore(end, slot)\\n result := keccak256(begin, add(length, 0x20))\\n mstore(end, cache)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x67672e4ca1dafdcc661d4eba8475cfac631fa0933309258e3af7644b92e1fb26\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\\n\\npragma solidity ^0.8.20;\\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 ERC-1967 implementation slot:\\n * ```solidity\\n * contract ERC1967 {\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\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(newImplementation.code.length > 0);\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\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 struct Int256Slot {\\n int256 value;\\n }\\n\\n struct StringSlot {\\n string value;\\n }\\n\\n struct BytesSlot {\\n bytes 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 assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `Int256Slot` with member `value` located at `slot`.\\n */\\n function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `StringSlot` with member `value` located at `slot`.\\n */\\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\\n */\\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n\\n /**\\n * @dev Returns a `BytesSlot` with member `value` located at `slot`.\\n */\\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\\n */\\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\\n assembly (\\\"memory-safe\\\") {\\n r.slot := store.slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {IERC165} from \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Interface of the ERC-165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\\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[ERC 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\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Panic} from \\\"../Panic.sol\\\";\\nimport {SafeCast} from \\\"./SafeCast.sol\\\";\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Floor, // Toward negative infinity\\n Ceil, // Toward positive infinity\\n Trunc, // Toward zero\\n Expand // Away from zero\\n }\\n\\n /**\\n * @dev Return the 512-bit addition of two uint256.\\n *\\n * The result is stored in two 256 variables such that sum = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n assembly (\\\"memory-safe\\\") {\\n low := add(a, b)\\n high := lt(low, a)\\n }\\n }\\n\\n /**\\n * @dev Return the 512-bit multiplication of two uint256.\\n *\\n * The result is stored in two 256 variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n */\\n function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\\n // 512-bit multiply [high low] = x * y. Compute the product mod 2\\u00b2\\u2075\\u2076 and mod 2\\u00b2\\u2075\\u2076 - 1, then use\\n // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = high * 2\\u00b2\\u2075\\u2076 + low.\\n assembly (\\\"memory-safe\\\") {\\n let mm := mulmod(a, b, not(0))\\n low := mul(a, b)\\n high := sub(sub(mm, low), lt(mm, low))\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a + b;\\n success = c >= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a - b;\\n success = c <= a;\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n uint256 c = a * b;\\n assembly (\\\"memory-safe\\\") {\\n // Only true when the multiplication doesn't overflow\\n // (c / a == b) || (a == 0)\\n success := or(eq(div(c, a), b), iszero(a))\\n }\\n // equivalent to: success ? c : 0\\n result = c * SafeCast.toUint(success);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `DIV` opcode returns zero when the denominator is 0.\\n result := div(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\\n unchecked {\\n success = b > 0;\\n assembly (\\\"memory-safe\\\") {\\n // The `MOD` opcode returns zero when the denominator is 0.\\n result := mod(a, b)\\n }\\n }\\n }\\n\\n /**\\n * @dev Unsigned saturating addition, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryAdd(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\\n */\\n function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\\n (, uint256 result) = trySub(a, b);\\n return result;\\n }\\n\\n /**\\n * @dev Unsigned saturating multiplication, bounds to `2\\u00b2\\u2075\\u2076 - 1` instead of overflowing.\\n */\\n function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n (bool success, uint256 result) = tryMul(a, b);\\n return ternary(success, result, type(uint256).max);\\n }\\n\\n /**\\n * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\\n *\\n * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\\n * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\\n * one branch when needed, making this function more expensive.\\n */\\n function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\\n unchecked {\\n // branchless ternary works because:\\n // b ^ (a ^ b) == a\\n // b ^ 0 == b\\n return b ^ ((a ^ b) * SafeCast.toUint(condition));\\n }\\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 ternary(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 ternary(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 towards infinity instead\\n * of rounding towards zero.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (b == 0) {\\n // Guarantee the same behavior as in a regular Solidity division.\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n\\n // The following calculation ensures accurate ceiling division without overflow.\\n // Since a is non-zero, (a - 1) / b will not overflow.\\n // The largest possible result occurs when (a - 1) / b is type(uint256).max,\\n // but the largest value we can obtain is type(uint256).max - 1, which happens\\n // when a = type(uint256).max and b = 1.\\n unchecked {\\n return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\\n }\\n }\\n\\n /**\\n * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\\n * denominator == 0.\\n *\\n * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\\n * Uniswap Labs also under MIT license.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (high == 0) {\\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\\n // The surrounding unchecked block does not change this fact.\\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\\n return low / denominator;\\n }\\n\\n // Make sure the result is less than 2\\u00b2\\u2075\\u2076. Also prevents denominator == 0.\\n if (denominator <= high) {\\n Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [high low].\\n uint256 remainder;\\n assembly (\\\"memory-safe\\\") {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n high := sub(high, gt(remainder, low))\\n low := sub(low, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\\n // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\\n\\n uint256 twos = denominator & (0 - denominator);\\n assembly (\\\"memory-safe\\\") {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [high low] by twos.\\n low := div(low, twos)\\n\\n // Flip twos such that it is 2\\u00b2\\u2075\\u2076 / 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 high into low.\\n low |= high * twos;\\n\\n // Invert denominator mod 2\\u00b2\\u2075\\u2076. Now that denominator is an odd number, it has an inverse modulo 2\\u00b2\\u2075\\u2076 such\\n // that denominator * inv \\u2261 1 mod 2\\u00b2\\u2075\\u2076. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv \\u2261 1 mod 2\\u2074.\\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\\n // works in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u2076\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b3\\u00b2\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u2076\\u2074\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b9\\u00b2\\u2078\\n inverse *= 2 - denominator * inverse; // inverse mod 2\\u00b2\\u2075\\u2076\\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\\u00b2\\u2075\\u2076. Since the preconditions guarantee that the outcome is\\n // less than 2\\u00b2\\u2075\\u2076, this is the final result. We don't need to compute the high bits of the result and high\\n // is no longer required.\\n result = low * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\\n return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\\n }\\n\\n /**\\n * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\\n unchecked {\\n (uint256 high, uint256 low) = mul512(x, y);\\n if (high >= 1 << n) {\\n Panic.panic(Panic.UNDER_OVERFLOW);\\n }\\n return (high << (256 - n)) | (low >> n);\\n }\\n }\\n\\n /**\\n * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\\n */\\n function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\\n return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\\n }\\n\\n /**\\n * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\\n *\\n * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\\n * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\\n *\\n * If the input value is not inversible, 0 is returned.\\n *\\n * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\\n * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\\n */\\n function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\\n unchecked {\\n if (n == 0) return 0;\\n\\n // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\\n // Used to compute integers x and y such that: ax + ny = gcd(a, n).\\n // When the gcd is 1, then the inverse of a modulo n exists and it's x.\\n // ax + ny = 1\\n // ax = 1 + (-y)n\\n // ax \\u2261 1 (mod n) # x is the inverse of a modulo n\\n\\n // If the remainder is 0 the gcd is n right away.\\n uint256 remainder = a % n;\\n uint256 gcd = n;\\n\\n // Therefore the initial coefficients are:\\n // ax + ny = gcd(a, n) = n\\n // 0a + 1n = n\\n int256 x = 0;\\n int256 y = 1;\\n\\n while (remainder != 0) {\\n uint256 quotient = gcd / remainder;\\n\\n (gcd, remainder) = (\\n // The old remainder is the next gcd to try.\\n remainder,\\n // Compute the next remainder.\\n // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\\n // where gcd is at most n (capped to type(uint256).max)\\n gcd - remainder * quotient\\n );\\n\\n (x, y) = (\\n // Increment the coefficient of a.\\n y,\\n // Decrement the coefficient of n.\\n // Can overflow, but the result is casted to uint256 so that the\\n // next value of y is \\\"wrapped around\\\" to a value between 0 and n - 1.\\n x - y * int256(quotient)\\n );\\n }\\n\\n if (gcd != 1) return 0; // No inverse exists.\\n return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\\n }\\n }\\n\\n /**\\n * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\\n *\\n * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\\n * prime, then `a**(p-1) \\u2261 1 mod p`. As a consequence, we have `a * a**(p-2) \\u2261 1 mod p`, which means that\\n * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\\n *\\n * NOTE: this function does NOT check that `p` is a prime greater than `2`.\\n */\\n function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\\n unchecked {\\n return Math.modExp(a, p - 2, p);\\n }\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\\n *\\n * Requirements:\\n * - modulus can't be zero\\n * - underlying staticcall to precompile must succeed\\n *\\n * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\\n * sure the chain you're using it on supports the precompiled contract for modular exponentiation\\n * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\\n * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\\n * interpreted as 0.\\n */\\n function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\\n (bool success, uint256 result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\\n * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\\n * to operate modulo 0 or if the underlying precompile reverted.\\n *\\n * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\\n * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\\n * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\\n * of a revert, but the result may be incorrectly interpreted as 0.\\n */\\n function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\\n if (m == 0) return (false, 0);\\n assembly (\\\"memory-safe\\\") {\\n let ptr := mload(0x40)\\n // | Offset | Content | Content (Hex) |\\n // |-----------|------------|--------------------------------------------------------------------|\\n // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |\\n // | 0x60:0x7f | value of b | 0x<.............................................................b> |\\n // | 0x80:0x9f | value of e | 0x<.............................................................e> |\\n // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\\n mstore(ptr, 0x20)\\n mstore(add(ptr, 0x20), 0x20)\\n mstore(add(ptr, 0x40), 0x20)\\n mstore(add(ptr, 0x60), b)\\n mstore(add(ptr, 0x80), e)\\n mstore(add(ptr, 0xa0), m)\\n\\n // Given the result < m, it's guaranteed to fit in 32 bytes,\\n // so we can use the memory scratch space located at offset 0.\\n success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\\n result := mload(0x00)\\n }\\n }\\n\\n /**\\n * @dev Variant of {modExp} that supports inputs of arbitrary length.\\n */\\n function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\\n (bool success, bytes memory result) = tryModExp(b, e, m);\\n if (!success) {\\n Panic.panic(Panic.DIVISION_BY_ZERO);\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\\n */\\n function tryModExp(\\n bytes memory b,\\n bytes memory e,\\n bytes memory m\\n ) internal view returns (bool success, bytes memory result) {\\n if (_zeroBytes(m)) return (false, new bytes(0));\\n\\n uint256 mLen = m.length;\\n\\n // Encode call args in result and move the free memory pointer\\n result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\\n\\n assembly (\\\"memory-safe\\\") {\\n let dataPtr := add(result, 0x20)\\n // Write result on top of args to avoid allocating extra memory.\\n success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\\n // Overwrite the length.\\n // result.length > returndatasize() is guaranteed because returndatasize() == m.length\\n mstore(result, mLen)\\n // Set the memory pointer after the returned data.\\n mstore(0x40, add(dataPtr, mLen))\\n }\\n }\\n\\n /**\\n * @dev Returns whether the provided byte array is zero.\\n */\\n function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\\n for (uint256 i = 0; i < byteArray.length; ++i) {\\n if (byteArray[i] != 0) {\\n return false;\\n }\\n }\\n return true;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\\n * towards zero.\\n *\\n * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\\n * using integer operations.\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n unchecked {\\n // Take care of easy edge cases when a == 0 or a == 1\\n if (a <= 1) {\\n return a;\\n }\\n\\n // In this function, we use Newton's method to get a root of `f(x) := x\\u00b2 - a`. It involves building a\\n // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\\n // the current value as `\\u03b5_n = | x_n - sqrt(a) |`.\\n //\\n // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\\n // of the target. (i.e. `2**(e-1) \\u2264 sqrt(a) < 2**e`). We know that `e \\u2264 128` because `(2\\u00b9\\u00b2\\u2078)\\u00b2 = 2\\u00b2\\u2075\\u2076` is\\n // bigger than any uint256.\\n //\\n // By noticing that\\n // `2**(e-1) \\u2264 sqrt(a) < 2**e \\u2192 (2**(e-1))\\u00b2 \\u2264 a < (2**e)\\u00b2 \\u2192 2**(2*e-2) \\u2264 a < 2**(2*e)`\\n // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\\n // to the msb function.\\n uint256 aa = a;\\n uint256 xn = 1;\\n\\n if (aa >= (1 << 128)) {\\n aa >>= 128;\\n xn <<= 64;\\n }\\n if (aa >= (1 << 64)) {\\n aa >>= 64;\\n xn <<= 32;\\n }\\n if (aa >= (1 << 32)) {\\n aa >>= 32;\\n xn <<= 16;\\n }\\n if (aa >= (1 << 16)) {\\n aa >>= 16;\\n xn <<= 8;\\n }\\n if (aa >= (1 << 8)) {\\n aa >>= 8;\\n xn <<= 4;\\n }\\n if (aa >= (1 << 4)) {\\n aa >>= 4;\\n xn <<= 2;\\n }\\n if (aa >= (1 << 2)) {\\n xn <<= 1;\\n }\\n\\n // We now have x_n such that `x_n = 2**(e-1) \\u2264 sqrt(a) < 2**e = 2 * x_n`. This implies \\u03b5_n \\u2264 2**(e-1).\\n //\\n // We can refine our estimation by noticing that the middle of that interval minimizes the error.\\n // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to \\u03b5_n \\u2264 2**(e-2).\\n // This is going to be our x_0 (and \\u03b5_0)\\n xn = (3 * xn) >> 1; // \\u03b5_0 := | x_0 - sqrt(a) | \\u2264 2**(e-2)\\n\\n // From here, Newton's method give us:\\n // x_{n+1} = (x_n + a / x_n) / 2\\n //\\n // One should note that:\\n // x_{n+1}\\u00b2 - a = ((x_n + a / x_n) / 2)\\u00b2 - a\\n // = ((x_n\\u00b2 + a) / (2 * x_n))\\u00b2 - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2) - a\\n // = (x_n\\u2074 + 2 * a * x_n\\u00b2 + a\\u00b2 - 4 * a * x_n\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u2074 - 2 * a * x_n\\u00b2 + a\\u00b2) / (4 * x_n\\u00b2)\\n // = (x_n\\u00b2 - a)\\u00b2 / (2 * x_n)\\u00b2\\n // = ((x_n\\u00b2 - a) / (2 * x_n))\\u00b2\\n // \\u2265 0\\n // Which proves that for all n \\u2265 1, sqrt(a) \\u2264 x_n\\n //\\n // This gives us the proof of quadratic convergence of the sequence:\\n // \\u03b5_{n+1} = | x_{n+1} - sqrt(a) |\\n // = | (x_n + a / x_n) / 2 - sqrt(a) |\\n // = | (x_n\\u00b2 + a - 2*x_n*sqrt(a)) / (2 * x_n) |\\n // = | (x_n - sqrt(a))\\u00b2 / (2 * x_n) |\\n // = | \\u03b5_n\\u00b2 / (2 * x_n) |\\n // = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n //\\n // For the first iteration, we have a special case where x_0 is known:\\n // \\u03b5_1 = \\u03b5_0\\u00b2 / | (2 * x_0) |\\n // \\u2264 (2**(e-2))\\u00b2 / (2 * (2**(e-1) + 2**(e-2)))\\n // \\u2264 2**(2*e-4) / (3 * 2**(e-1))\\n // \\u2264 2**(e-3) / 3\\n // \\u2264 2**(e-3-log2(3))\\n // \\u2264 2**(e-4.5)\\n //\\n // For the following iterations, we use the fact that, 2**(e-1) \\u2264 sqrt(a) \\u2264 x_n:\\n // \\u03b5_{n+1} = \\u03b5_n\\u00b2 / | (2 * x_n) |\\n // \\u2264 (2**(e-k))\\u00b2 / (2 * 2**(e-1))\\n // \\u2264 2**(2*e-2*k) / 2**e\\n // \\u2264 2**(e-2*k)\\n xn = (xn + a / xn) >> 1; // \\u03b5_1 := | x_1 - sqrt(a) | \\u2264 2**(e-4.5) -- special case, see above\\n xn = (xn + a / xn) >> 1; // \\u03b5_2 := | x_2 - sqrt(a) | \\u2264 2**(e-9) -- general case with k = 4.5\\n xn = (xn + a / xn) >> 1; // \\u03b5_3 := | x_3 - sqrt(a) | \\u2264 2**(e-18) -- general case with k = 9\\n xn = (xn + a / xn) >> 1; // \\u03b5_4 := | x_4 - sqrt(a) | \\u2264 2**(e-36) -- general case with k = 18\\n xn = (xn + a / xn) >> 1; // \\u03b5_5 := | x_5 - sqrt(a) | \\u2264 2**(e-72) -- general case with k = 36\\n xn = (xn + a / xn) >> 1; // \\u03b5_6 := | x_6 - sqrt(a) | \\u2264 2**(e-144) -- general case with k = 72\\n\\n // Because e \\u2264 128 (as discussed during the first estimation phase), we know have reached a precision\\n // \\u03b5_6 \\u2264 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\\n // sqrt(a) or sqrt(a) + 1.\\n return xn - SafeCast.toUint(xn > a / xn);\\n }\\n }\\n\\n /**\\n * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2 of a positive value rounded towards zero.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // If upper 8 bits of 16-bit half set, add 8 to result\\n r |= SafeCast.toUint((x >> r) > 0xff) << 3;\\n // If upper 4 bits of 8-bit half set, add 4 to result\\n r |= SafeCast.toUint((x >> r) > 0xf) << 2;\\n\\n // Shifts value right by the current result and use it as an index into this lookup table:\\n //\\n // | x (4 bits) | index | table[index] = MSB position |\\n // |------------|---------|-----------------------------|\\n // | 0000 | 0 | table[0] = 0 |\\n // | 0001 | 1 | table[1] = 0 |\\n // | 0010 | 2 | table[2] = 1 |\\n // | 0011 | 3 | table[3] = 1 |\\n // | 0100 | 4 | table[4] = 2 |\\n // | 0101 | 5 | table[5] = 2 |\\n // | 0110 | 6 | table[6] = 2 |\\n // | 0111 | 7 | table[7] = 2 |\\n // | 1000 | 8 | table[8] = 3 |\\n // | 1001 | 9 | table[9] = 3 |\\n // | 1010 | 10 | table[10] = 3 |\\n // | 1011 | 11 | table[11] = 3 |\\n // | 1100 | 12 | table[12] = 3 |\\n // | 1101 | 13 | table[13] = 3 |\\n // | 1110 | 14 | table[14] = 3 |\\n // | 1111 | 15 | table[15] = 3 |\\n //\\n // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\\n assembly (\\\"memory-safe\\\") {\\n r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\\n }\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10 of a positive value rounded towards zero.\\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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256 of a positive value rounded towards zero.\\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 x) internal pure returns (uint256 r) {\\n // If value has upper 128 bits set, log2 result is at least 128\\n r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\\n // If upper 64 bits of 128-bit half set, add 64 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\\n // If upper 32 bits of 64-bit half set, add 32 to result\\n r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\\n // If upper 16 bits of 32-bit half set, add 16 to result\\n r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\\n // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\\n return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\\n }\\n\\n /**\\n * @dev Return the log in base 256, 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\\n }\\n }\\n\\n /**\\n * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\\n */\\n function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\\n return uint8(rounding) % 2 == 1;\\n }\\n}\\n\",\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\"},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\\n\\n /**\\n * @dev An int value doesn't fit in an uint of `bits` size.\\n */\\n error SafeCastOverflowedIntToUint(int256 value);\\n\\n /**\\n * @dev Value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\\n\\n /**\\n * @dev An uint value doesn't fit in an int of `bits` size.\\n */\\n error SafeCastOverflowedUintToInt(uint256 value);\\n\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n if (value > type(uint248).max) {\\n revert SafeCastOverflowedUintDowncast(248, value);\\n }\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n if (value > type(uint240).max) {\\n revert SafeCastOverflowedUintDowncast(240, value);\\n }\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n if (value > type(uint232).max) {\\n revert SafeCastOverflowedUintDowncast(232, value);\\n }\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n if (value > type(uint224).max) {\\n revert SafeCastOverflowedUintDowncast(224, value);\\n }\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n if (value > type(uint216).max) {\\n revert SafeCastOverflowedUintDowncast(216, value);\\n }\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n if (value > type(uint208).max) {\\n revert SafeCastOverflowedUintDowncast(208, value);\\n }\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n if (value > type(uint200).max) {\\n revert SafeCastOverflowedUintDowncast(200, value);\\n }\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n if (value > type(uint192).max) {\\n revert SafeCastOverflowedUintDowncast(192, value);\\n }\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n if (value > type(uint184).max) {\\n revert SafeCastOverflowedUintDowncast(184, value);\\n }\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n if (value > type(uint176).max) {\\n revert SafeCastOverflowedUintDowncast(176, value);\\n }\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n if (value > type(uint168).max) {\\n revert SafeCastOverflowedUintDowncast(168, value);\\n }\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n if (value > type(uint160).max) {\\n revert SafeCastOverflowedUintDowncast(160, value);\\n }\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n if (value > type(uint152).max) {\\n revert SafeCastOverflowedUintDowncast(152, value);\\n }\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n if (value > type(uint144).max) {\\n revert SafeCastOverflowedUintDowncast(144, value);\\n }\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n if (value > type(uint136).max) {\\n revert SafeCastOverflowedUintDowncast(136, value);\\n }\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n if (value > type(uint128).max) {\\n revert SafeCastOverflowedUintDowncast(128, value);\\n }\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n if (value > type(uint120).max) {\\n revert SafeCastOverflowedUintDowncast(120, value);\\n }\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n if (value > type(uint112).max) {\\n revert SafeCastOverflowedUintDowncast(112, value);\\n }\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n if (value > type(uint104).max) {\\n revert SafeCastOverflowedUintDowncast(104, value);\\n }\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n if (value > type(uint96).max) {\\n revert SafeCastOverflowedUintDowncast(96, value);\\n }\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n if (value > type(uint88).max) {\\n revert SafeCastOverflowedUintDowncast(88, value);\\n }\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n if (value > type(uint80).max) {\\n revert SafeCastOverflowedUintDowncast(80, value);\\n }\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n if (value > type(uint72).max) {\\n revert SafeCastOverflowedUintDowncast(72, value);\\n }\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n if (value > type(uint64).max) {\\n revert SafeCastOverflowedUintDowncast(64, value);\\n }\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n if (value > type(uint56).max) {\\n revert SafeCastOverflowedUintDowncast(56, value);\\n }\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n if (value > type(uint48).max) {\\n revert SafeCastOverflowedUintDowncast(48, value);\\n }\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n if (value > type(uint40).max) {\\n revert SafeCastOverflowedUintDowncast(40, value);\\n }\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n if (value > type(uint32).max) {\\n revert SafeCastOverflowedUintDowncast(32, value);\\n }\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n if (value > type(uint24).max) {\\n revert SafeCastOverflowedUintDowncast(24, value);\\n }\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n if (value > type(uint16).max) {\\n revert SafeCastOverflowedUintDowncast(16, value);\\n }\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n if (value > type(uint8).max) {\\n revert SafeCastOverflowedUintDowncast(8, value);\\n }\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n if (value < 0) {\\n revert SafeCastOverflowedIntToUint(value);\\n }\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(248, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(240, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(232, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(224, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(216, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(208, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(200, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(192, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(184, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(176, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(168, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(160, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(152, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(144, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(136, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(128, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(120, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(112, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(104, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(96, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(88, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(80, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(72, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(64, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(56, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(48, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(40, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(32, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(24, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(16, value);\\n }\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n if (downcasted != value) {\\n revert SafeCastOverflowedIntDowncast(8, value);\\n }\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n if (value > uint256(type(int256).max)) {\\n revert SafeCastOverflowedUintToInt(value);\\n }\\n return int256(value);\\n }\\n\\n /**\\n * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\\n */\\n function toUint(bool b) internal pure returns (uint256 u) {\\n assembly (\\\"memory-safe\\\") {\\n u := iszero(iszero(b))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IProxyAuthorization {\\n function canUpgradeFrom(address previousImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\"},\"project/src/CommonErrors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @title Errors\\n/// @dev Common error definitions used across multiple contracts\\n\\n/// @notice Expected valid owner.\\n/// @dev Error selector: `0x49e27cff`\\nerror InvalidOwner();\\n\\n/// @notice Thrown when a caller is not authorized to perform the requested operation\\n/// @dev Error selector: `0xd86ad9cf`\\n/// @param caller The address that attempted the unauthorized operation\\nerror UnauthorizedCaller(address caller);\\n\",\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\"},\"project/src/access-control/EnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (access/AccessControl.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\n\\nimport {IEnhancedAccessControl} from \\\"./interfaces/IEnhancedAccessControl.sol\\\";\\nimport {EACBaseRolesLib} from \\\"./libraries/EACBaseRolesLib.sol\\\";\\n\\n/// @dev Resource-scoped access control system with bitmap-packed roles.\\n///\\n/// Subclasses define custom roles as constants and assign them to accounts within specific\\n/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by\\n/// the subclass (e.g. a token ID, a name hash, etc.).\\n///\\n/// Features:\\n/// - Resource-based roles: each resource has independent role assignments.\\n/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply\\n/// to all resources. Role checks OR the account's root roles with their resource-specific\\n/// roles, so holding a role in either scope satisfies the check.\\n/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role\\n/// grants authority to grant and revoke both the regular role and the admin role itself.\\n/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role.\\n/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react\\n/// to role changes (e.g. regenerating tokens, updating metadata).\\n/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly;\\n/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments.\\n///\\n/// Bitmap layout (uint256, 64 nybbles):\\n///\\n/// 255 128 127 0\\n/// \\u250c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u252c\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2510\\n/// \\u2502 Admin Roles \\u2502 Regular Roles \\u2502\\n/// \\u2514\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2534\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2500\\u2518\\n/// 63 32 31 0\\n///\\n/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits\\n/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper\\n/// half at bits N*4+128 to N*4+131.\\n///\\n/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index\\n/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`.\\n///\\n/// The same nybble-per-role layout is used for assignee counting: each nybble in the count\\n/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15).\\n///\\nabstract contract EnhancedAccessControl is ERC165, IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The `ROOT_RESOURCE`.\\n uint256 public constant ROOT_RESOURCE = 0;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev user roles within a resource stored as a bitmap.\\n /// Resource -> User -> RoleBitmap\\n mapping(uint256 resource => mapping(address account => uint256 roleBitmap)) private _roles;\\n\\n /// @dev The number of assignees for a given role in a given resource.\\n ///\\n /// Each role's count is represented by 4 bits, in little-endian order.\\n /// This results in max. 64 roles, and 15 assignees per role.\\n ///\\n mapping(uint256 resource => uint256 roleCount) private _roleCount;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Modifiers\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles.\\n modifier canGrantRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanGrantRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them.\\n modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) {\\n _checkCanRevokeRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE.\\n modifier onlyRoles(uint256 resource, uint256 roleBitmap) {\\n _checkRoles(resource, roleBitmap, msg.sender);\\n _;\\n }\\n\\n /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`.\\n modifier onlyRootRoles(uint256 roleBitmap) {\\n _checkRoles(ROOT_RESOURCE, roleBitmap, msg.sender);\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc ERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(IEnhancedAccessControl).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _grantRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being granted.\\n function grantRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canGrantRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(resource, roleBitmap)\\n returns (bool)\\n {\\n if (resource == ROOT_RESOURCE) {\\n revert EACRootResourceNotAllowed();\\n }\\n return _revokeRoles(resource, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n /// @dev The caller must have all the necessary admin roles for the roles being revoked.\\n function revokeRootRoles(uint256 roleBitmap, address account)\\n public\\n virtual\\n canRevokeRoles(ROOT_RESOURCE, roleBitmap)\\n returns (bool)\\n {\\n return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 resource, address account) public view virtual returns (uint256) {\\n return _getRoles(resource, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 resource) public view virtual returns (uint256) {\\n return _roleCount[resource];\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) {\\n return _getRoles(ROOT_RESOURCE, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n public\\n view\\n virtual\\n returns (bool)\\n {\\n return _effectiveRoles(resource, account) & roleBitmap == roleBitmap;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) {\\n (uint256 counts, ) = getAssigneeCount(resource, roleBitmap);\\n return counts != 0;\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n public\\n view\\n virtual\\n returns (uint256 counts, uint256 mask)\\n {\\n mask = _roleBitmapToMask(roleBitmap);\\n counts = _roleCount[resource] & mask;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Transfers all roles from `srcAccount` to `dstAccount` within the same resource.\\n ///\\n /// This function first revokes all roles from the source account, then grants them to the\\n /// destination account. This prevents exceeding max assignees limits during transfer.\\n ///\\n /// Does nothing if there are no roles to transfer.\\n ///\\n /// @param resource The resource to transfer roles within.\\n /// @param srcAccount The account to transfer roles from.\\n /// @param dstAccount The account to transfer roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n function _transferRoles(\\n uint256 resource,\\n address srcAccount,\\n address dstAccount,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n {\\n uint256 srcRoles = _roles[resource][srcAccount];\\n if (srcRoles != 0) {\\n // First revoke roles from source account to free up assignee slots\\n _revokeRoles(resource, srcRoles, srcAccount, executeCallbacks);\\n // Then grant roles to destination account\\n _grantRoles(resource, srcRoles, dstAccount, executeCallbacks);\\n }\\n }\\n\\n /// @dev Grants multiple roles to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function _grantRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n if (roleBitmap == 0) {\\n return false;\\n }\\n _checkRoleBitmap(roleBitmap);\\n if (account == address(0)) {\\n revert EACInvalidAccount();\\n }\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles | roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyAddedRoles = roleBitmap & ~currentRoles;\\n _updateRoleCounts(resource, newlyAddedRoles, true);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @param executeCallbacks Whether to execute the callbacks.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function _revokeRoles(\\n uint256 resource,\\n uint256 roleBitmap,\\n address account,\\n bool executeCallbacks\\n )\\n internal\\n virtual\\n returns (bool)\\n {\\n _checkRoleBitmap(roleBitmap);\\n uint256 currentRoles = _roles[resource][account];\\n uint256 updatedRoles = currentRoles & ~roleBitmap;\\n\\n if (currentRoles != updatedRoles) {\\n _roles[resource][account] = updatedRoles;\\n uint256 newlyRemovedRoles = roleBitmap & currentRoles;\\n _updateRoleCounts(resource, newlyRemovedRoles, false);\\n emit EACRolesChanged(resource, account, currentRoles, updatedRoles);\\n if (executeCallbacks) {\\n _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap);\\n }\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /// @dev Updates role counts when roles are granted/revoked\\n /// @param resource The resource to update counts for\\n /// @param roleBitmap The roles being modified\\n /// @param isGrant true for grant, false for revoke\\n function _updateRoleCounts(uint256 resource, uint256 roleBitmap, bool isGrant) internal {\\n uint256 roleMask = _roleBitmapToMask(roleBitmap);\\n\\n if (isGrant) {\\n // Check for overflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & _roleCount[resource]))) {\\n revert EACMaxAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] += roleBitmap;\\n } else {\\n // Check for underflow\\n if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) {\\n revert EACMinAssignees(resource, roleBitmap);\\n }\\n _roleCount[resource] -= roleBitmap;\\n }\\n }\\n\\n /// @dev Callback for when roles are granted.\\n /// @param resource The resource that the roles were granted within.\\n /// @param account The account that the roles were granted to.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Callback for when roles are revoked.\\n /// @param resource The resource that the roles were revoked within.\\n /// @param account The account that the roles were revoked from.\\n /// @param oldRoles The old roles for the account.\\n /// @param newRoles The new roles for the account.\\n /// @param roleBitmap The roles that were revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address account,\\n uint256 oldRoles,\\n uint256 newRoles,\\n uint256 roleBitmap\\n )\\n internal\\n virtual\\n {}\\n\\n /// @dev Reverts if `account` does not have all the given roles.\\n function _checkRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n if (!hasRoles(resource, roleBitmap, account)) {\\n revert EACUnauthorizedAccountRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles.\\n function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 settableRoles = _getSettableRoles(resource, account);\\n if ((roleBitmap & ~settableRoles) != 0) {\\n revert EACCannotGrantRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked.\\n function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n internal\\n view\\n virtual\\n {\\n uint256 revokableRoles = _getRevokableRoles(resource, account);\\n if ((roleBitmap & ~revokableRoles) != 0) {\\n revert EACCannotRevokeRoles(resource, roleBitmap, account);\\n }\\n }\\n\\n /// @dev Returns the settable roles for `account` within `resource`.\\n ///\\n /// The settable roles are the roles (both regular and admin) that the account can grant.\\n /// An account can grant a regular role if they have the corresponding admin role.\\n /// An account can grant an admin role if they have that same admin role.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles for `account` within `resource`.\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the revokable roles for `account` within `resource`.\\n ///\\n /// The revokable roles are the roles (including admin roles) that the account can revoke.\\n ///\\n /// @param resource The resource to get revokable roles for.\\n /// @param account The account to get revokable roles for.\\n /// @return The revokable roles for `account` within `resource`.\\n function _getRevokableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n returns (uint256)\\n {\\n return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account));\\n }\\n\\n /// @dev Returns the roles bitmap for an account for permission checks.\\n function _getRoles(uint256 resource, address account) internal view virtual returns (uint256) {\\n return _roles[resource][account];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Returns the effective roles bitmap for an account for permission checks.\\n function _effectiveRoles(uint256 resource, address account) private view returns (uint256) {\\n return _getRoles(ROOT_RESOURCE, account) | _getRoles(resource, account);\\n }\\n\\n /// @dev Checks if a role bitmap contains only valid role bits.\\n /// @param roleBitmap The role bitmap to check.\\n function _checkRoleBitmap(uint256 roleBitmap) private pure {\\n if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) {\\n revert EACInvalidRoleBitmap(roleBitmap);\\n }\\n }\\n\\n /// @dev Converts a role bitmap to a mask.\\n ///\\n /// The mask is a bitmap where each nybble is set if the corresponding role is in the role bitmap.\\n ///\\n /// @param roleBitmap The role bitmap to convert.\\n /// @return roleMask The mask for the role bitmap.\\n function _roleBitmapToMask(uint256 roleBitmap) private pure returns (uint256 roleMask) {\\n _checkRoleBitmap(roleBitmap);\\n roleMask = roleBitmap | (roleBitmap << 1);\\n roleMask |= roleMask << 2;\\n }\\n}\\n\",\"keccak256\":\"0x934655016f502e7a2f8e5cbd294ef48e85f238821f5608de5675c023f48037af\",\"license\":\"MIT\"},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @notice Interface for Enhanced Access Control system that allows for:\\n/// * Resource-based roles\\n/// * Obtaining assignee count for each role in each resource\\n/// * Root resource override\\n/// * Up to 32 roles and 32 corresponding admin roles\\n/// * Up to 15 assignees per role\\n///\\n/// @dev Interface selector: `0x8f452d62`\\ninterface IEnhancedAccessControl {\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Emitted when roles are changed.\\n /// @param resource The resource that the roles were changed within.\\n /// @param account The account that the roles were changed for.\\n /// @param oldRoleBitmap The old roles for the account.\\n /// @param newRoleBitmap The new roles for the account.\\n event EACRolesChanged(\\n uint256 indexed resource,\\n address indexed account,\\n uint256 oldRoleBitmap,\\n uint256 newRoleBitmap\\n );\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Error selector: `0x4b27a133`\\n error EACUnauthorizedAccountRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xd1a3b355`\\n error EACCannotGrantRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xa604e318`\\n error EACCannotRevokeRoles(uint256 resource, uint256 roleBitmap, address account);\\n\\n /// @dev Error selector: `0xc2842458`\\n error EACRootResourceNotAllowed();\\n\\n /// @dev Error selector: `0xf9165348`\\n error EACMaxAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x1f80c19b`\\n error EACMinAssignees(uint256 resource, uint256 role);\\n\\n /// @dev Error selector: `0x2a7b2d20`\\n error EACInvalidRoleBitmap(uint256 roleBitmap);\\n\\n /// @dev Error selector: `0xec3fc592`\\n error EACInvalidAccount();\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Grants all roles in the given role bitmap to `account`.\\n /// @param resource The resource to grant roles within.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to grant.\\n /// @param account The account to grant roles to.\\n /// @return `true` if the roles were granted, `false` otherwise.\\n function grantRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account`.\\n /// @param resource The resource to revoke roles within.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n returns (bool);\\n\\n /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\\n /// @param roleBitmap The roles bitmap to revoke.\\n /// @param account The account to revoke roles from.\\n /// @return `true` if the roles were revoked, `false` otherwise.\\n function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool);\\n\\n /// @notice Returns the `ROOT_RESOURCE` constant.\\n function ROOT_RESOURCE() external view returns (uint256);\\n\\n /// @notice Returns the roles bitmap for an account in a resource.\\n /// @param resource The resource to get the roles for.\\n /// @param account The account to get the roles for.\\n /// @return The roles bitmap for the account in the resource.\\n function roles(uint256 resource, address account) external view returns (uint256);\\n\\n /// @notice Returns the role count bitmap for a resource.\\n /// @param resource The resource to get the role count for.\\n /// @return count The role count bitmap for the resource.\\n function roleCount(uint256 resource) external view returns (uint256);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool);\\n\\n /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @param account The account to check.\\n /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\\n function hasRoles(uint256 resource, uint256 roleBitmap, address account)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Checks if any of the roles in the given role bitmap has assignees.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\\n function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool);\\n\\n /// @notice Returns the number of assignees for the roles in the given role bitmap.\\n /// @param resource The resource to check.\\n /// @param roleBitmap The roles bitmap to check.\\n /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\\n /// @return mask The mask for the given role bitmap.\\n function getAssigneeCount(uint256 resource, uint256 roleBitmap)\\n external\\n view\\n returns (uint256 counts, uint256 mask);\\n}\\n\",\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\"},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\n/// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system.\\n///\\n/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in\\n/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits\\n/// outside valid positions are set) and for revoking all roles.\\n///\\n/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking\\n/// just the 32 admin role slots. Used to extract which admin roles an account holds.\\n///\\nlibrary EACBaseRolesLib {\\n ////////////////////////////////////////////////////////////////////////\\n // Constants\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Mask with bit 0 set in every nybble \\u2014 represents one unit per role slot across all 64 slots.\\n uint256 internal constant ALL_ROLES =\\n 0x1111111111111111111111111111111111111111111111111111111111111111;\\n\\n /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits).\\n uint256 internal constant ADMIN_ROLES =\\n 0x1111111111111111111111111111111100000000000000000000000000000000;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Admin roles imply their corresponding regular roles.\\n function withAdminRolesApplied(uint256 roleBitmap) internal pure returns (uint256) {\\n roleBitmap >>= 128;\\n return (roleBitmap << 128) | roleBitmap;\\n }\\n\\n /// @dev Derive roles bitmap from assignee counts.\\n /// @param counts Packed role counts (0-15) as `uint4x64`.\\n function fromCounts(uint256 counts) internal pure returns (uint256) {\\n return (counts | (counts >> 1) | (counts >> 2) | (counts >> 3)) & ALL_ROLES;\\n }\\n\\n /// @dev Checks if the given value has any zero nybbles.\\n /// @param value The value to check.\\n /// @return `true` if the value has any zero nybbles, `false` otherwise.\\n function hasZeroNybbles(uint256 value) internal pure returns (bool) {\\n // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord\\n uint256 zeroNybbles;\\n unchecked {\\n zeroNybbles =\\n (value - 0x1111111111111111111111111111111111111111111111111111111111111111) &\\n ~value &\\n 0x8888888888888888888888888888888888888888888888888888888888888888;\\n }\\n return zeroNybbles != 0;\\n }\\n}\\n\",\"keccak256\":\"0xc14f05abd508e75c9f16a35e31d0fb9f1f1dd904b65d058201c788a9ddd562eb\",\"license\":\"MIT\"},\"project/src/erc1155/ERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Errors} from \\\"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\\\";\\nimport {\\n IERC1155MetadataURI\\n} from \\\"@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\\\";\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\nimport {ERC1155Utils} from \\\"@openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol\\\";\\nimport {Arrays} from \\\"@openzeppelin/contracts/utils/Arrays.sol\\\";\\nimport {ERC165} from \\\"@openzeppelin/contracts/utils/introspection/ERC165.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {IERC1155Singleton} from \\\"./interfaces/IERC1155Singleton.sol\\\";\\n\\n/// @notice ERC1155 variant enforcing exactly one owner per token ID.\\n///\\n/// Instead of the standard nested balance mapping (`id \\u2192 address \\u2192 balance`), uses a flat\\n/// `id \\u2192 address` ownership mapping. `balanceOf` returns 1 if the account is the owner,\\n/// 0 otherwise. Transferring value > 1 reverts.\\n///\\n/// Used by `PermissionedRegistry` to represent domain name ownership as non-divisible tokens.\\n/// The registry overrides `ownerOf` to add expiry and version validation on top of raw ownership.\\n///\\n/// @author OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC1155/ERC1155.sol)\\n/// @dev This contract has been modified from the implementation at the above link.\\nabstract contract ERC1155Singleton is\\n ERC165,\\n IERC1155Singleton,\\n IERC1155Errors,\\n IERC1155MetadataURI\\n{\\n using Arrays for uint256[];\\n\\n using Arrays for address[];\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Maps each token ID to its single owner address.\\n mapping(uint256 id => address account) private _owners;\\n\\n /// @dev Standard ERC1155 operator approval mapping.\\n mapping(address account => mapping(address operator => bool)) private _operatorApprovals;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IERC1155).interfaceId ||\\n interfaceId == type(IERC1155Singleton).interfaceId ||\\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Sets the approval for all operator.\\n /// @param operator The operator to set the approval for.\\n /// @param approved The approval status.\\n function setApprovalForAll(address operator, bool approved) public virtual {\\n _setApprovalForAll(msg.sender, operator, approved);\\n }\\n\\n /// @notice Transfers a single token from one address to another.\\n /// @param from The address to transfer the token from.\\n /// @param to The address to transfer the token to.\\n /// @param id The token ID.\\n /// @param value The amount of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `to` cannot be the zero address.\\n /// @dev If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.\\n /// @dev `from` must have a balance of tokens of type `id` of at least `value` amount.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the\\n /// acceptance magic value.\\n function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data)\\n public\\n virtual\\n {\\n _checkApproval(from, msg.sender);\\n _safeTransferFrom(from, to, id, value, data);\\n }\\n\\n /// @notice Transfers multiple tokens from one address to another.\\n /// @param from The address to transfer the tokens from.\\n /// @param to The address to transfer the tokens to.\\n /// @param ids The token IDs.\\n /// @param values The amounts of tokens to transfer.\\n /// @param data Additional data to pass to the receiver.\\n /// @dev `ids` and `values` must have the same length.\\n /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the\\n /// acceptance magic value.\\n function safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n public\\n virtual\\n {\\n _checkApproval(from, msg.sender);\\n _safeBatchTransferFrom(from, to, ids, values, data);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 id) public view virtual returns (address owner) {\\n return _owners[id];\\n }\\n\\n /// @notice Returns the URI for a token.\\n /// @param id The token ID.\\n /// @return uri The URI for the token.\\n function uri(uint256 id) public view virtual returns (string memory uri);\\n\\n /// @notice Returns the balance of a token for an account.\\n /// @param account The account to get the balance for.\\n /// @param id The token ID.\\n /// @return balance The balance of the token for the account. This will only ever be 1 or 0.\\n function balanceOf(address account, uint256 id) public view virtual returns (uint256) {\\n return account != address(0) && ownerOf(id) == account ? 1 : 0;\\n }\\n\\n /// @notice Returns the balances of a batch of tokens for an account.\\n /// @param accounts The accounts to get the balances for.\\n /// @param ids The token IDs.\\n /// @return batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\\n /// @dev `accounts` and `ids` must have the same length.\\n function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\\n public\\n view\\n virtual\\n returns (uint256[] memory)\\n {\\n if (accounts.length != ids.length) {\\n revert ERC1155InvalidArrayLength(ids.length, accounts.length);\\n }\\n\\n uint256[] memory batchBalances = new uint256[](accounts.length);\\n\\n for (uint256 i = 0; i < accounts.length; ++i) {\\n batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));\\n }\\n\\n return batchBalances;\\n }\\n\\n /// @notice Returns the approval for all operator.\\n /// @param account The account to get the approval for.\\n /// @param operator The operator to get the approval for.\\n /// @return approved The approval status.\\n function isApprovedForAll(address account, address operator) public view virtual returns (bool) {\\n return _operatorApprovals[account][operator];\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Apply token updates for each pair in `ids` and `values`.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not the current owner or `value > 1`.\\n /// @dev This function does not perform ERC-1155 receiver acceptance checks.\\n /// @dev Emits `TransferSingle` when one token ID is updated, otherwise emits `TransferBatch`.\\n function _update(address from, address to, uint256[] memory ids, uint256[] memory values)\\n internal\\n virtual\\n {\\n if (ids.length != values.length) {\\n revert ERC1155InvalidArrayLength(ids.length, values.length);\\n }\\n\\n for (uint256 i = 0; i < ids.length; ++i) {\\n uint256 id = ids.unsafeMemoryAccess(i);\\n uint256 value = values.unsafeMemoryAccess(i);\\n\\n if (value > 0) {\\n address owner = _owners[id];\\n if (owner != from) {\\n revert ERC1155InsufficientBalance(from, 0, value, id);\\n } else if (value > 1) {\\n revert ERC1155InsufficientBalance(from, 1, value, id);\\n }\\n _owners[id] = to;\\n }\\n }\\n\\n if (ids.length == 1) {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n emit TransferSingle(msg.sender, from, to, id, value);\\n } else {\\n emit TransferBatch(msg.sender, from, to, ids, values);\\n }\\n }\\n\\n /// @notice Apply token updates and run ERC-1155 receiver acceptance checks.\\n /// @param from Address tokens are moved from. Use `address(0)` for mints.\\n /// @param to Address tokens are moved to. Use `address(0)` for burns.\\n /// @param ids Token IDs to update.\\n /// @param values Amounts for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @param batch `true` if a batch operation.\\n /// @dev Calls `_update` before external receiver callbacks.\\n /// @dev If `to` is a contract, this calls `onERC1155Received` or `onERC1155BatchReceived`.\\n /// @dev Overriding is discouraged because post-callback state writes can introduce reentrancy bugs.\\n function _updateWithAcceptanceCheck(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data,\\n bool batch\\n )\\n internal\\n virtual\\n {\\n _update(from, to, ids, values);\\n if (to != address(0)) {\\n if (batch) {\\n ERC1155Utils.checkOnERC1155BatchReceived(msg.sender, from, to, ids, values, data);\\n } else {\\n uint256 id = ids.unsafeMemoryAccess(0);\\n uint256 value = values.unsafeMemoryAccess(0);\\n ERC1155Utils.checkOnERC1155Received(msg.sender, from, to, id, value, data);\\n }\\n }\\n }\\n\\n /// @notice Safely transfer `value` tokens of token ID `id` from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param id Token ID to transfer.\\n /// @param value Amount to transfer.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _safeTransferFrom(\\n address from,\\n address to,\\n uint256 id,\\n uint256 value,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, to, ids, values, data, false);\\n }\\n\\n /// @notice Safely transfer multiple token IDs from `from` to `to`.\\n /// @param from Address to transfer from.\\n /// @param to Address to transfer to.\\n /// @param ids Token IDs to transfer.\\n /// @param values Amounts to transfer for each token ID.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferBatch`.\\n function _safeBatchTransferFrom(\\n address from,\\n address to,\\n uint256[] memory ids,\\n uint256[] memory values,\\n bytes memory data\\n )\\n internal\\n {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n _updateWithAcceptanceCheck(from, to, ids, values, data, true);\\n }\\n\\n /// @notice Mint `value` tokens of token ID `id` to `to`.\\n /// @param to Address receiving the minted token.\\n /// @param id Token ID to mint.\\n /// @param value Amount to mint.\\n /// @param data Additional calldata passed to receiver hooks.\\n /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address.\\n /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value.\\n /// @dev Emits `TransferSingle`.\\n function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {\\n if (to == address(0)) {\\n revert ERC1155InvalidReceiver(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(address(0), to, ids, values, data, false);\\n }\\n\\n /// @notice Burn `value` tokens of token ID `id` from `from`.\\n /// @param from Address to burn from.\\n /// @param id Token ID to burn.\\n /// @param value Amount to burn.\\n /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address.\\n /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not current owner or `value > 1`.\\n /// @dev Emits `TransferSingle`.\\n function _burn(address from, uint256 id, uint256 value) internal {\\n if (from == address(0)) {\\n revert ERC1155InvalidSender(address(0));\\n }\\n (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\\n _updateWithAcceptanceCheck(from, address(0), ids, values, \\\"\\\", false);\\n }\\n\\n /// @notice Set or clear approval for `operator` to manage all tokens owned by `owner`.\\n /// @param owner Token owner granting or revoking approval.\\n /// @param operator Operator receiving approval.\\n /// @param approved Approval status to set.\\n /// @dev Reverts with `ERC1155InvalidOperator` if `operator` is the zero address.\\n /// @dev Emits `ApprovalForAll`.\\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\\n if (operator == address(0)) {\\n revert ERC1155InvalidOperator(address(0));\\n }\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Private Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev Ensure operator is approved.\\n function _checkApproval(address from, address operator) private view {\\n if (from != operator && !isApprovedForAll(from, operator)) {\\n revert ERC1155MissingApprovalForAll(operator, from);\\n }\\n }\\n\\n /// @dev Gas-optimized assembly helper that creates two length-1 memory arrays without Solidity's\\n /// default zero-initialization overhead. Used to adapt single-token operations (`_mint`,\\n /// `_burn`, `_safeTransferFrom`) to the array-based `_update` function.\\n function _asSingletonArrays(uint256 element1, uint256 element2)\\n private\\n pure\\n returns (uint256[] memory array1, uint256[] memory array2)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Load the free memory pointer\\n array1 := mload(0x40)\\n // Set array length to 1\\n mstore(array1, 1)\\n // Store the single element at the next word after the length (where content starts)\\n mstore(add(array1, 0x20), element1)\\n\\n // Repeat for next array locating it right after the first array\\n array2 := add(array1, 0x40)\\n mstore(array2, 1)\\n mstore(add(array2, 0x20), element2)\\n\\n // Update the free memory pointer by pointing after the second array\\n mstore(0x40, add(array2, 0x40))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7e1c260a1b1791a63a658f049251b2b5390d9e11cdb20d99a2d115083251d37e\",\"license\":\"MIT\"},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155} from \\\"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\\\";\\n\\n/// @notice Extends IERC1155 with an `ownerOf` function that returns the single owner of a token ID\\n/// (analogous to ERC721's `ownerOf`).\\n/// @dev Interface selector: `0x6352211e`\\ninterface IERC1155Singleton is IERC1155 {\\n /// @notice Returns the owner of a token.\\n /// @param id The token ID.\\n /// @return owner The owner of the token.\\n function ownerOf(uint256 id) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\"},\"project/src/registry/PermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {EnhancedAccessControl} from \\\"../access-control/EnhancedAccessControl.sol\\\";\\nimport {IEnhancedAccessControl} from \\\"../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {ERC1155Singleton} from \\\"../erc1155/ERC1155Singleton.sol\\\";\\nimport {IERC1155Singleton} from \\\"../erc1155/interfaces/IERC1155Singleton.sol\\\";\\nimport {IContractNamer} from \\\"../reverse-registrar/interfaces/IContractNamer.sol\\\";\\nimport {ILabelStore} from \\\"../utils/interfaces/ILabelStore.sol\\\";\\nimport {LibLabel} from \\\"../utils/LibLabel.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./interfaces/IOwnedRegistry.sol\\\";\\nimport {IPermissionedRegistry} from \\\"./interfaces/IPermissionedRegistry.sol\\\";\\nimport {IRegistry} from \\\"./interfaces/IRegistry.sol\\\";\\nimport {IRegistryURIRenderer} from \\\"./interfaces/IRegistryURIRenderer.sol\\\";\\nimport {IStandardRegistry} from \\\"./interfaces/IStandardRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./interfaces/ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./interfaces/ITokenizedRegistry.sol\\\";\\nimport {RegistryRolesLib} from \\\"./libraries/RegistryRolesLib.sol\\\";\\n\\n/// @notice A tokenized (ERC1155) registry with resource-scoped access control for subdomain management.\\n///\\n/// Many functions accept an `anyId` parameter that can be a labelhash, tokenId, or resource\\n/// interchangeably. Internally, `_entry()` zeroes version bits (via `LibLabel.withVersion(anyId, 0)`)\\n/// to resolve any of these to the canonical storage slot for the name.\\n///\\n/// The registry maintains two independent version counters per name:\\n/// - `eacVersionId`: incremented on unregister/re-register. Combined with the labelhash to form\\n/// the EAC resource ID. This means a re-registered name gets a fresh permission scope.\\n/// - `tokenVersionId`: incremented on unregister and whenever the token is regenerated (burn + mint)\\n/// due to role changes. Combined with the labelhash to form the ERC1155 token ID, ensuring\\n/// changes to roles create new tokens and prevent frontrunning a transfer with a role revocation.\\n///\\n/// Names are treated as `AVAILABLE` once `block.timestamp >= expiry`.\\n///\\n/// State diagram:\\n///\\n/// register()\\n/// +ROLE_REGISTRAR\\n/// +------------------->----------------------+\\n/// | |\\n/// | renew() | renew()\\n/// | +ROLE_RENEW | +ROLE_RENEW\\n/// | +------+ | +------+\\n/// | | | | | |\\n/// \\u028c \\u028c v v v |\\n/// AVAILABLE --------> RESERVED -------------> REGISTERED >--+\\n/// \\u028c register() v register() v\\n/// | w/owner=0 | +ROLE_REGISTER_RESERVED |\\n/// | +ROLE_REGISTRAR | |\\n/// | | |\\n/// +--------<---------+------------<------------+\\n/// unregister()\\n/// +ROLE_UNREGISTER\\n///\\ncontract PermissionedRegistry is ERC1155Singleton, EnhancedAccessControl, IPermissionedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n struct Entry {\\n /// @dev Incremented on unregister; combined with labelhash to form the EAC resource ID.\\n uint32 eacVersionId;\\n /// @dev Incremented on unregister and on token regeneration; combined with labelhash to form the ERC1155 token ID.\\n uint32 tokenVersionId;\\n /// @dev Child registry for this name.\\n IRegistry subregistry;\\n /// @dev Timestamp at or after which the name is considered expired/available.\\n uint64 expiry;\\n /// @dev Resolver address for this name.\\n address resolver;\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Immutables\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The shared label database.\\n ILabelStore public immutable LABEL_STORE;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Storage\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev The parent registry of this registry.\\n IRegistry internal _parentRegistry;\\n\\n /// @dev The child label of this registry.\\n string internal _childLabel;\\n\\n /// @dev The metadata URI.\\n string internal _uri;\\n\\n /// @dev The metadata renderer.\\n IRegistryURIRenderer internal _uriRenderer;\\n\\n /// @dev The entries of this registry.\\n mapping(uint256 storageId => Entry entry) internal _entries;\\n\\n /// @dev Storage gap for future changes.\\n uint256[256] private __gap;\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param labelStore The shared label database.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n constructor(ILabelStore labelStore, address rootAccount, uint256 roleBitmap) {\\n emit RegistryCreated();\\n LABEL_STORE = labelStore;\\n _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false);\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId)\\n public\\n view\\n virtual\\n override(IERC165, ERC1155Singleton, EnhancedAccessControl)\\n returns (bool)\\n {\\n return\\n interfaceId == type(IPermissionedRegistry).interfaceId ||\\n interfaceId == type(IStandardRegistry).interfaceId ||\\n interfaceId == type(ITokenizedRegistry).interfaceId ||\\n interfaceId == type(ITemporalRegistry).interfaceId ||\\n interfaceId == type(IOwnedRegistry).interfaceId ||\\n interfaceId == type(IRegistry).interfaceId ||\\n interfaceId == type(IContractNamer).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @inheritdoc IStandardRegistry\\n function setSubregistry(uint256 anyId, IRegistry registry) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_SUBREGISTRY);\\n entry.subregistry = registry;\\n emit SubregistryUpdated(tokenId, registry, msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setResolver(uint256 anyId, address resolver) public virtual {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_RESOLVER);\\n entry.resolver = resolver;\\n emit ResolverUpdated(tokenId, resolver, msg.sender);\\n }\\n\\n /// @notice Set the URI for the registry.\\n /// @param uri_ The new URI.\\n /// @param renderer The new renderer address.\\n function setURI(string calldata uri_, IRegistryURIRenderer renderer)\\n public\\n virtual\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_URI)\\n {\\n _uri = uri_;\\n _uriRenderer = renderer;\\n emit URIUpdated(uri_, address(renderer), msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function setParent(IRegistry parent, string memory label)\\n public\\n onlyRootRoles(RegistryRolesLib.ROLE_SET_PARENT)\\n {\\n _parentRegistry = parent;\\n _childLabel = label;\\n emit ParentUpdated(parent, label, msg.sender);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n public\\n virtual\\n returns (uint256)\\n {\\n return _register(label, owner, registry, resolver, roleBitmap, expiry, true);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\\n function unregister(uint256 anyId) public {\\n (uint256 tokenId, Entry storage entry) =\\n _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_UNREGISTER);\\n emit LabelUnregistered(tokenId, msg.sender);\\n address owner = super.ownerOf(tokenId);\\n if (owner != address(0)) {\\n _burn(owner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n }\\n entry.expiry = uint64(block.timestamp);\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n /// @dev If `REGISTERED | RESERVED`, requires `ROLE_RENEW`.\\n /// If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\\n function renew(uint256 anyId, uint64 newExpiry) public override {\\n Entry storage entry = _entry(anyId);\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n uint64 expiry = entry.expiry;\\n if (_isExpired(expiry)) {\\n if (expiry == 0 || !_canRevive(tokenId, msg.sender)) {\\n revert LabelExpired(tokenId); // never registered OR cannot revive\\n }\\n } else {\\n _checkRoles(_constructResource(anyId, entry), RegistryRolesLib.ROLE_RENEW, msg.sender);\\n }\\n if (newExpiry < expiry) {\\n revert CannotReduceExpiry(expiry, newExpiry);\\n }\\n entry.expiry = newExpiry;\\n emit ExpiryUpdated(tokenId, newExpiry, msg.sender);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function grantRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.grantRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function revokeRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.revokeRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IRegistry\\n function getSubregistry(string calldata label) public view virtual returns (IRegistry) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? IRegistry(address(0)) : entry.subregistry;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getResolver(string calldata label) public view virtual returns (address) {\\n Entry storage entry = _entry(LibLabel.id(label));\\n return _isExpired(entry.expiry) ? address(0) : entry.resolver;\\n }\\n\\n /// @inheritdoc IRegistry\\n function getParent() public view returns (IRegistry parent, string memory label) {\\n return (_parentRegistry, _childLabel);\\n }\\n\\n /// @inheritdoc IContractNamer\\n function isContractNamer(address namer) public view virtual returns (bool) {\\n return hasRootRoles(RegistryRolesLib.ROLE_CAN_NAME, namer);\\n }\\n\\n /// @inheritdoc ITemporalRegistry\\n function findExpiry(string calldata label) public view returns (uint64) {\\n return getExpiry(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc IOwnedRegistry\\n function findOwner(string calldata label) public view returns (address) {\\n return getOwner(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ITokenizedRegistry\\n function findTokenId(string calldata label) public view returns (uint256) {\\n return getTokenId(LibLabel.id(label));\\n }\\n\\n /// @inheritdoc ERC1155Singleton\\n function uri(uint256 tokenId) public view override returns (string memory) {\\n return\\n address(_uriRenderer) != address(0)\\n ? _uriRenderer.renderURI(this, tokenId)\\n : _uri;\\n }\\n\\n /// @inheritdoc IStandardRegistry\\n function getExpiry(uint256 anyId) public view returns (uint64) {\\n return _entry(anyId).expiry;\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getResource(uint256 anyId) public view returns (uint256) {\\n return _constructResource(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getTokenId(uint256 anyId) public view returns (uint256) {\\n return _constructTokenId(anyId, _entry(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getOwner(uint256 anyId) public view returns (address) {\\n return _isExpired(getExpiry(anyId)) ? address(0) : super.ownerOf(getTokenId(anyId));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getStatus(uint256 anyId) public view returns (Status) {\\n Entry storage entry = _entry(anyId);\\n return _constructStatus(entry.expiry, super.ownerOf(_constructTokenId(anyId, entry)));\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function getState(uint256 anyId) public view returns (State memory state) {\\n Entry storage entry = _entry(anyId);\\n uint64 expiry = entry.expiry;\\n state.expiry = expiry;\\n uint256 tokenId = _constructTokenId(anyId, entry);\\n state.tokenId = tokenId;\\n state.resource = _constructResource(anyId, entry);\\n address owner = super.ownerOf(tokenId);\\n state.latestOwner = owner;\\n state.status = _constructStatus(expiry, owner);\\n }\\n\\n /// @inheritdoc IPermissionedRegistry\\n function latestOwnerOf(uint256 tokenId) public view returns (address) {\\n return super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IERC1155Singleton\\n function ownerOf(uint256 tokenId)\\n public\\n view\\n override(ERC1155Singleton, IERC1155Singleton)\\n returns (address)\\n {\\n Entry storage entry = _entry(tokenId);\\n return\\n tokenId != _constructTokenId(tokenId, entry) || _isExpired(entry.expiry)\\n ? address(0)\\n : super.ownerOf(tokenId);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roles(uint256 anyId, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roles(getResource(anyId), account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function roleCount(uint256 anyId)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256)\\n {\\n return super.roleCount(getResource(anyId));\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasRoles(uint256 anyId, uint256 roleBitmap, address account)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasRoles(getResource(anyId), roleBitmap, account);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function hasAssignees(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (bool)\\n {\\n return super.hasAssignees(getResource(anyId), roleBitmap);\\n }\\n\\n /// @inheritdoc IEnhancedAccessControl\\n function getAssigneeCount(uint256 anyId, uint256 roleBitmap)\\n public\\n view\\n override(EnhancedAccessControl, IEnhancedAccessControl)\\n returns (uint256 counts, uint256 mask)\\n {\\n return super.getAssigneeCount(getResource(anyId), roleBitmap);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Internal Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @dev If `AVAILABLE`, requires `ROLE_REGISTRAR` on root and status becomes `REGISTERED`.\\n /// * If `owner` is null (`roleBitmap` must be 0), status becomes `RESERVED`.\\n /// If `RESERVED`, requires `ROLE_REGISTER_RESERVED` on root and status becomes `REGISTERED`.\\n /// * If `expiry` is 0, uses current expiry.\\n function _register(\\n string memory label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry,\\n bool checkRoles\\n )\\n internal\\n returns (uint256 tokenId)\\n {\\n LABEL_STORE.setLabel(label);\\n uint256 labelId = LibLabel.id(label);\\n Entry storage entry = _entry(labelId);\\n tokenId = _constructTokenId(labelId, entry);\\n address prevOwner = super.ownerOf(tokenId);\\n if (_isExpired(entry.expiry)) {\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTRAR, msg.sender);\\n }\\n if (owner == address(0) && roleBitmap != 0) {\\n revert EACCannotGrantRoles(ROOT_RESOURCE, roleBitmap, msg.sender); // strict\\n }\\n } else {\\n if (prevOwner != address(0)) {\\n revert LabelAlreadyRegistered(label); // cannot overwrite REGISTERED\\n } else if (owner == address(0)) {\\n revert LabelAlreadyReserved(label); // cannot overwrite RESERVED\\n }\\n if (checkRoles) {\\n _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTER_RESERVED, msg.sender);\\n }\\n if (expiry == 0) {\\n expiry = entry.expiry; // use RESERVED expiry\\n }\\n roleBitmap |= RegistryRolesLib.ROLE_WAS_RESERVED; // remember\\n }\\n if (owner == address(0) ? expiry == 0 : _isExpired(expiry)) {\\n revert CannotSetPastExpiry(expiry);\\n }\\n if (prevOwner != address(0)) {\\n _burn(prevOwner, tokenId, 1);\\n ++entry.eacVersionId;\\n ++entry.tokenVersionId;\\n tokenId = _constructTokenId(tokenId, entry);\\n }\\n entry.expiry = expiry;\\n entry.subregistry = registry;\\n entry.resolver = resolver;\\n if (owner == address(0)) {\\n emit LabelReserved(tokenId, bytes32(labelId), label, expiry, msg.sender);\\n } else {\\n emit LabelRegistered(tokenId, bytes32(labelId), label, owner, expiry, msg.sender);\\n _mint(owner, tokenId, 1, \\\"\\\");\\n uint256 resource = _constructResource(tokenId, entry);\\n assert(resource != ROOT_RESOURCE);\\n emit TokenResource(tokenId, resource);\\n _grantRoles(resource, roleBitmap, owner, false);\\n }\\n if (address(registry) != address(0)) {\\n emit SubregistryUpdated(tokenId, registry, msg.sender);\\n }\\n if (address(resolver) != address(0)) {\\n emit ResolverUpdated(tokenId, resolver, msg.sender);\\n }\\n }\\n\\n /// @dev Override `ERC1155Singleton._update()` to transfer the roles to the new owner if the token is transferred.\\n function _update(address from, address to, uint256[] memory tokenIds, uint256[] memory amounts)\\n internal\\n override\\n {\\n super._update(from, to, tokenIds, amounts); // ensures amounts[i] is 0 or 1\\n if (to != address(0) && from != address(0)) {\\n // only transfers (skip mint and burn)\\n for (uint256 i; i < tokenIds.length; ++i) {\\n uint256 tokenId = tokenIds[i];\\n // only check ROLE_CAN_TRANSFER_ADMIN on original owner (from)\\n // ROLE_CAN_TRANSFER_ADMIN is technically a property of the token\\n if (!hasRoles(tokenId, RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, from)) {\\n revert TransferDisallowed(tokenId, from);\\n } else if (amounts[i] > 0) {\\n _transferRoles(getResource(tokenId), from, to, false);\\n }\\n }\\n }\\n }\\n\\n /// @dev Override the base registry _onRolesGranted function to regenerate the token when the roles are granted.\\n function _onRolesGranted(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Override the base registry _onRolesRevoked function to regenerate the token when the roles are revoked.\\n function _onRolesRevoked(\\n uint256 resource,\\n address /*account*/,\\n uint256 /*oldRoles*/,\\n uint256 /*newRoles*/,\\n uint256 /*roleBitmap*/\\n )\\n internal\\n override\\n {\\n _regenerate(resource);\\n }\\n\\n /// @dev Bump `tokenVersionId` via burn+mint if token is not expired.\\n function _regenerate(uint256 resource) internal {\\n if (resource != ROOT_RESOURCE) {\\n Entry storage entry = _entry(resource);\\n uint256 tokenId = _constructTokenId(resource, entry);\\n address owner = super.ownerOf(tokenId); // grant/revoke only on registered\\n _burn(owner, tokenId, 1);\\n ++entry.tokenVersionId;\\n uint256 newTokenId = _constructTokenId(tokenId, entry);\\n emit TokenRegenerated(tokenId, newTokenId); // resource is unchanged\\n _mint(owner, newTokenId, 1, \\\"\\\");\\n }\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// Token non-admin roles can only be granted to registered tokens.\\n ///\\n /// Token admin roles are only assigned during name registration to maintain\\n /// controlled permission management. This ensures that role delegation\\n /// follows the intended security model where admin privileges are granted at\\n /// registration time and cannot be arbitrarily granted afterward.\\n ///\\n /// Root admin roles are unaffected.\\n ///\\n /// @param resource The resource to get settable roles for.\\n /// @param account The account to get settable roles for.\\n /// @return The settable roles (regular roles only, not admin roles).\\n function _getSettableRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n if (resource != ROOT_RESOURCE && getOwner(resource) == address(0)) {\\n return 0;\\n }\\n uint256 roleBitmap = super._getSettableRoles(resource, account);\\n return resource == ROOT_RESOURCE ? roleBitmap : roleBitmap >> 128;\\n }\\n\\n /// @inheritdoc EnhancedAccessControl\\n /// @dev Override for token-dependent logic:\\n ///\\n /// * if caller is approved by token owner, combine the caller's roles with the owner's roles\\n ///\\n function _getRoles(uint256 resource, address account)\\n internal\\n view\\n virtual\\n override\\n returns (uint256 roleBitmap)\\n {\\n roleBitmap = super._getRoles(resource, account);\\n if (resource != ROOT_RESOURCE) {\\n address owner = getOwner(resource);\\n if (owner != address(0) && owner != account && isApprovedForAll(owner, account)) {\\n roleBitmap |= super._getRoles(resource, owner);\\n }\\n }\\n }\\n\\n /// @dev Zeroes version bits in `anyId` to return the canonical storage entry for the name.\\n function _entry(uint256 anyId) internal view returns (Entry storage) {\\n return _entries[LibLabel.withVersion(anyId, 0)];\\n }\\n\\n /// @dev Determine if token can be revived.\\n function _canRevive(\\n uint256 /*tokenId*/,\\n address sender\\n )\\n internal\\n view\\n virtual\\n returns (bool)\\n {\\n return hasRootRoles(RegistryRolesLib.ROLE_RENEW, sender);\\n }\\n\\n /// @dev Assert token is not expired and caller has necessary roles.\\n function _checkExpiryAndTokenRoles(uint256 anyId, uint256 roleBitmap)\\n internal\\n view\\n returns (uint256 tokenId, Entry storage entry)\\n {\\n entry = _entry(anyId);\\n tokenId = _constructTokenId(anyId, entry);\\n if (_isExpired(entry.expiry)) {\\n revert LabelExpired(tokenId);\\n }\\n _checkRoles(_constructResource(anyId, entry), roleBitmap, msg.sender);\\n }\\n\\n /// @dev Internal logic for expired status.\\n function _isExpired(uint64 expiry) internal view returns (bool) {\\n return block.timestamp >= expiry;\\n }\\n\\n /// @dev Create `resource` from parts.\\n /// Does nothing if `ROOT_RESOURCE`.\\n /// Returns next resource if expired.\\n function _constructResource(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n if (anyId == ROOT_RESOURCE) {\\n return anyId;\\n }\\n return\\n LibLabel.withVersion(\\n anyId,\\n _isExpired(entry.expiry)\\n ? entry.eacVersionId + 1\\n : entry.eacVersionId\\n );\\n }\\n\\n /// @dev Create `tokenId` from parts.\\n function _constructTokenId(uint256 anyId, Entry storage entry) internal view returns (uint256) {\\n return LibLabel.withVersion(anyId, entry.tokenVersionId);\\n }\\n\\n /// @dev Create `Status` from parts.\\n function _constructStatus(uint64 expiry, address owner) internal view returns (Status) {\\n if (_isExpired(expiry)) {\\n return Status.AVAILABLE;\\n } else if (owner == address(0)) {\\n return Status.RESERVED;\\n } else {\\n return Status.REGISTERED;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7df0d16fb74e67612b88f2143f142410c70a4079a21c0980b2063824e291942b\",\"license\":\"MIT\"},\"project/src/registry/UserRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IProxyAuthorization} from \\\"@ensdomains/verifiable-factory/IProxyAuthorization.sol\\\";\\nimport {Initializable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\\\";\\nimport {UUPSUpgradeable} from \\\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\nimport {InvalidOwner} from \\\"../CommonErrors.sol\\\";\\nimport {ILabelStore} from \\\"../utils/interfaces/ILabelStore.sol\\\";\\n\\nimport {RegistryRolesLib} from \\\"./libraries/RegistryRolesLib.sol\\\";\\nimport {PermissionedRegistry} from \\\"./PermissionedRegistry.sol\\\";\\n\\n/// @title UserRegistry\\n/// @notice UUPS-upgradeable `PermissionedRegistry` designed to be deployed as a proxy via\\n/// `VerifiableFactory` for user-owned subdomain registries. The constructor disables\\n/// initializers on the implementation contract; proxies call `initialize()` to set up the\\n/// admin and initial roles. Upgrade authorization requires the upgrade role in the root resource.\\ncontract UserRegistry is Initializable, PermissionedRegistry, UUPSUpgradeable, IProxyAuthorization {\\n ////////////////////////////////////////////////////////////////////////\\n // Initialization\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @param labelStore The shared label database.\\n /// @param namer The implementation namer.\\n constructor(ILabelStore labelStore, address namer)\\n PermissionedRegistry(\\n labelStore,\\n namer,\\n RegistryRolesLib.ROLE_CAN_NAME | RegistryRolesLib.ROLE_CAN_NAME_ADMIN\\n )\\n {\\n // This disables initialization for the implementation contract\\n _disableInitializers();\\n }\\n\\n /// @notice Initializes a proxy instance of `UserRegistry`.\\n /// @dev Grants the supplied role bitmap to `rootAccount` on the root resource.\\n /// Reverts if the zero address.\\n /// @param rootAccount Account granted root roles.\\n /// @param roleBitmap The role bitmap granted to `rootAccount`.\\n function initialize(address rootAccount, uint256 roleBitmap) public initializer {\\n if (rootAccount == address(0)) {\\n revert InvalidOwner();\\n }\\n emit RegistryCreated();\\n _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false);\\n }\\n\\n /// @inheritdoc IERC165\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return\\n interfaceId == type(UUPSUpgradeable).interfaceId ||\\n interfaceId == type(IProxyAuthorization).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Implementation\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Declares this implementation as an eligible verifiable proxy upgrade target.\\n /// @dev Upgrade authorization is still enforced by the current implementation during the UUPS\\n /// upgrade call.\\n /// @param {previousImplementation} Ignored.\\n /// @return allowed Always `true` for implementations in this registry family.\\n function canUpgradeFrom(\\n address /* previousImplementation */\\n )\\n external\\n pure\\n virtual\\n override\\n returns (bool allowed)\\n {\\n return true;\\n }\\n\\n /// @dev Restricts UUPS upgrades to accounts holding the upgrade role on the root resource.\\n /// @param newImplementation The address of the new implementation contract.\\n function _authorizeUpgrade(address newImplementation)\\n internal\\n override\\n onlyRootRoles(RegistryRolesLib.ROLE_UPGRADE)\\n {}\\n}\\n\",\"keccak256\":\"0x2a9a59caa22252b66d809289006b92e9bd50f7ddce6e0332762df47bfdd44de4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with owners.\\n/// @dev Interface selector: `0x63560a8e`\\ninterface IOwnedRegistry is IRegistry {\\n /// @notice Fetches the label owner.\\n /// @param label The label to query.\\n /// @return The owner of the label.\\n function findOwner(string calldata label) external view returns (address);\\n}\\n\",\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IEnhancedAccessControl} from \\\"../../access-control/interfaces/IEnhancedAccessControl.sol\\\";\\nimport {IContractNamer} from \\\"../../reverse-registrar/interfaces/IContractNamer.sol\\\";\\n\\nimport {IStandardRegistry} from \\\"./IStandardRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6be50c69`\\ninterface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer {\\n ////////////////////////////////////////////////////////////////////////\\n // Types\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice The registration status of a label.\\n enum Status {\\n AVAILABLE,\\n RESERVED,\\n REGISTERED\\n }\\n\\n /// @notice The registration state of a label.\\n struct State {\\n Status status; // getStatus()\\n uint64 expiry; // getExpiry()\\n address latestOwner; // latestOwnerOf()\\n uint256 tokenId; // getTokenId()\\n uint256 resource; // getResource()\\n }\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Events\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Associate a token with an EAC resource.\\n /// @param tokenId The token ID.\\n /// @param resource The EAC resource.\\n event TokenResource(uint256 indexed tokenId, uint256 indexed resource);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label cannot be reserved again.\\n /// @dev Error selector: `0xf60759e0`\\n error LabelAlreadyReserved(string label);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Get the latest owner of a token.\\n /// If the token was burned, returns null.\\n /// @param tokenId The token ID to query.\\n /// @return owner The latest owner address.\\n function latestOwnerOf(uint256 tokenId) external view returns (address owner);\\n\\n /// @notice Get the state of a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return state The state of the label.\\n function getState(uint256 anyId) external view returns (State memory state);\\n\\n /// @notice Get `Status` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return status The status of the label.\\n function getStatus(uint256 anyId) external view returns (Status status);\\n\\n /// @notice Get `resource` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return resource The resource.\\n function getResource(uint256 anyId) external view returns (uint256 resource);\\n\\n /// @notice Get `tokenId` from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return tokenId The token ID.\\n function getTokenId(uint256 anyId) external view returns (uint256 tokenId);\\n\\n /// @notice Get token owner from `anyId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return owner The token owner.\\n function getOwner(uint256 anyId) external view returns (address owner);\\n}\\n\",\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistryEvents} from \\\"./IRegistryEvents.sol\\\";\\n\\n/// @dev Interface selector: `0x51f67f40`\\ninterface IRegistry is IRegistryEvents {\\n /// @notice Fetches the registry for a label.\\n /// @param label The label to resolve.\\n /// @return The address of the registry for this label, or `address(0)` if none exists.\\n function getSubregistry(string calldata label) external view returns (IRegistry);\\n\\n /// @notice Fetches the resolver responsible for the specified label.\\n /// @param label The label to fetch a resolver for.\\n /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\\n function getResolver(string calldata label) external view returns (address);\\n\\n /// @notice Get canonical \\\"location\\\" of this registry.\\n /// @return parent The canonical parent of this registry.\\n /// @return label The canonical subdomain of this registry.\\n function getParent() external view returns (IRegistry parent, string memory label);\\n}\\n\",\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice Events interface for the registry, following ENSIP16.\\ninterface IRegistryEvents {\\n /// @notice A registry was created/initialized.\\n event RegistryCreated();\\n\\n /// @notice A label was registered.\\n /// @param tokenId The token ID registered.\\n /// @param labelHash The label hash registered.\\n /// @param label The label registered.\\n /// @param owner The owner of the label.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to register.\\n event LabelRegistered(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n address owner,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was reserved.\\n /// @param tokenId The token ID reserved.\\n /// @param labelHash The label hash reserved.\\n /// @param label The label reserved.\\n /// @param expiry The expiry of the label.\\n /// @param sender The sender of the call to reserve.\\n event LabelReserved(\\n uint256 indexed tokenId,\\n bytes32 indexed labelHash,\\n string label,\\n uint64 expiry,\\n address indexed sender\\n );\\n\\n /// @notice A label was unregistered.\\n /// @param tokenId The token ID unregistered.\\n /// @param sender The sender of the call to unregister.\\n event LabelUnregistered(uint256 indexed tokenId, address indexed sender);\\n\\n /// @notice Expiry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param newExpiry The new expiry of the label.\\n /// @param sender The sender of the call to update the expiry.\\n event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender);\\n\\n /// @notice Subregistry of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param subregistry The new subregistry.\\n /// @param sender The sender of the call to update the subregistry.\\n event SubregistryUpdated(\\n uint256 indexed tokenId,\\n IRegistry indexed subregistry,\\n address indexed sender\\n );\\n\\n /// @notice Resolver of label was changed.\\n /// @param tokenId The token ID of the label.\\n /// @param resolver The new resolver.\\n /// @param sender The sender of the call to update the resolver.\\n event ResolverUpdated(\\n uint256 indexed tokenId,\\n address indexed resolver,\\n address indexed sender\\n );\\n\\n /// @notice URI was changed.\\n /// @param uri The new URI.\\n /// @param renderer The new render address.\\n /// @param sender The sender of the call to update the URI.\\n event URIUpdated(string uri, address renderer, address indexed sender);\\n\\n /// @notice Token was regenerated with a new token ID.\\n /// This occurs when roles are granted or revoked to maintain ERC1155 compliance.\\n /// @param oldTokenId The old token ID.\\n /// @param newTokenId The new token ID.\\n event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId);\\n\\n /// @notice Parent was changed.\\n /// @param parent The new parent.\\n /// @param label The new label.\\n /// @param sender The sender of the call to update the parent.\\n event ParentUpdated(IRegistry indexed parent, string label, address indexed sender);\\n}\\n\",\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IRegistryURIRenderer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @dev Interface selector: `0x6c55e19b`\\ninterface IRegistryURIRenderer {\\n /// @notice Generate URI for `tokenId` from `registry`.\\n /// @param registry The registry.\\n /// @param tokenId The token ID in the registry.\\n /// @return The generated URI.\\n function renderURI(IRegistry registry, uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0xa6ea64ff73d10fa58118ae9c0d0c2caa72f2f3488776227a22bd0cd9cd6586f6\",\"license\":\"MIT\"},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\nimport {ITemporalRegistry} from \\\"./ITemporalRegistry.sol\\\";\\nimport {ITokenizedRegistry} from \\\"./ITokenizedRegistry.sol\\\";\\n\\n/// @title IStandardRegistry\\n/// @notice A tokenized registry with registrations that expire.\\n/// @dev Interface selector: `0xb844ab6c`\\ninterface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry {\\n ////////////////////////////////////////////////////////////////////////\\n // Errors\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Label is already registered.\\n /// @dev Error selector: `0xdef545a4`\\n error LabelAlreadyRegistered(string label);\\n\\n /// @notice Label is expired/unregistered.\\n /// @dev Error selector: `0xc44e2374`\\n error LabelExpired(uint256 tokenId);\\n\\n /// @notice Label expiry cannot be reduced.\\n /// @dev Error selector: `0x68c1425a`\\n error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry);\\n\\n /// @notice Label expiry cannot be before now.\\n /// @dev Error selector: `0xf1d446c3`\\n error CannotSetPastExpiry(uint64 expiry);\\n\\n /// @notice Transfer is not allowed due to missing transfer admin role.\\n /// @dev Error selector: `0xe58f6d5a`\\n error TransferDisallowed(uint256 tokenId, address from);\\n\\n ////////////////////////////////////////////////////////////////////////\\n // Functions\\n ////////////////////////////////////////////////////////////////////////\\n\\n /// @notice Registers a new label.\\n /// @param label The label to register.\\n /// @param owner The address of the owner of the label.\\n /// @param registry The registry to set as the label.\\n /// @param resolver The resolver to set for the label.\\n /// @param roleBitmap The role bitmap to set for the label.\\n /// @param expiry The expiry of the label, in seconds.\\n /// @return tokenId The token ID.\\n function register(\\n string calldata label,\\n address owner,\\n IRegistry registry,\\n address resolver,\\n uint256 roleBitmap,\\n uint64 expiry\\n )\\n external\\n returns (uint256 tokenId);\\n\\n /// @notice Renew a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param newExpiry The new expiry, in seconds.\\n function renew(uint256 anyId, uint64 newExpiry) external;\\n\\n /// @notice Delete a label.\\n /// @param anyId The labelhash, token ID, or resource.\\n function unregister(uint256 anyId) external;\\n\\n /// @notice Change registry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param registry The new registry.\\n function setSubregistry(uint256 anyId, IRegistry registry) external;\\n\\n /// @notice Change resolver of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param resolver The new resolver.\\n function setResolver(uint256 anyId, address resolver) external;\\n\\n /// @notice Change canonical \\\"location\\\".\\n /// @dev Should emit `ParentUpdated`.\\n /// @param parent The canonical parent of this registry.\\n /// @param label The canonical subdomain of this registry.\\n function setParent(IRegistry parent, string calldata label) external;\\n\\n /// @notice Get expiry of label.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @return expiry The expiry of the label, in seconds.\\n function getExpiry(uint256 anyId) external view returns (uint64 expiry);\\n}\\n\",\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IRegistry} from \\\"./IRegistry.sol\\\";\\n\\n/// @notice A registry with expirations.\\n/// @dev Interface selector: `0x6f537c72`\\ninterface ITemporalRegistry is IRegistry {\\n /// @notice Fetches the label expiry.\\n /// @param label The label to query.\\n /// @return The expiry of the label.\\n function findExpiry(string calldata label) external view returns (uint64);\\n}\\n\",\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\"},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\nimport {IERC1155Singleton} from \\\"../../erc1155/interfaces/IERC1155Singleton.sol\\\";\\n\\nimport {IOwnedRegistry} from \\\"./IOwnedRegistry.sol\\\";\\n\\n/// @notice A tokenized registry.\\n/// @dev Interface selector: `0x91b3c037`\\ninterface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton {\\n /// @notice Fetches the token ID for a label.\\n /// @param label The label to query.\\n /// @return The token ID of the label.\\n function findTokenId(string calldata label) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\"},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Defines the registry-specific roles used by `PermissionedRegistry` within the\\n/// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits)\\n/// at a specific index, with its admin counterpart shifted 128 bits higher.\\nlibrary RegistryRolesLib {\\n /// @dev Nybble 0: authorizes registering and reserving new names. Root only.\\n uint256 internal constant ROLE_REGISTRAR = 1 << 0;\\n /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`.\\n uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128;\\n\\n /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only.\\n uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4;\\n /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`.\\n uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128;\\n\\n /// @dev Nybble 2: authorizes setting the parent registry. Root-only.\\n uint256 internal constant ROLE_SET_PARENT = 1 << 8;\\n /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`.\\n uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128;\\n\\n /// @dev Nybble 3: authorizes unregistering names. Root or token.\\n uint256 internal constant ROLE_UNREGISTER = 1 << 12;\\n /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`.\\n uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128;\\n\\n /// @dev Nybble 4: authorizes extending name expiry. Root or token.\\n uint256 internal constant ROLE_RENEW = 1 << 16;\\n /// @dev Nybble 36: authorizes setting `ROLE_RENEW`.\\n uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128;\\n\\n /// @dev Nybble 5: authorizes changing a name's child registry. Root or token.\\n uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20;\\n /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`.\\n uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128;\\n\\n /// @dev Nybble 6: authorizes changing a name's resolver. Root or token.\\n uint256 internal constant ROLE_SET_RESOLVER = 1 << 24;\\n /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`.\\n uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128;\\n\\n /// @dev Nybble 39: authorizes ERC1155 token transfers. Root or token.\\n /// This role is only checked on the token owner, not the operator.\\n uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128;\\n\\n /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable.\\n uint256 internal constant ROLE_WAS_RESERVED = (1 << 32);\\n\\n /// @dev Nybble 9: authorizes setting the URI. Root-only.\\n uint256 internal constant ROLE_SET_URI = 1 << 36;\\n /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`.\\n uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128;\\n\\n /// @dev Nybble 30: authorizes contract naming. Root-only.\\n uint256 internal constant ROLE_CAN_NAME = 1 << 120;\\n /// @dev Nybble 62: authorizes setting ROLE_CAN_NAME.\\n uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128;\\n\\n /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only.\\n uint256 internal constant ROLE_UPGRADE = 1 << 124;\\n /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`.\\n uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128;\\n}\\n\",\"keccak256\":\"0x01771816c1c5b16c10f29b33083dbd1cc2eb64dbfec60fb45a1a1969cec06624\",\"license\":\"MIT\"},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @dev Interface selector: `0x6f3ff726`\\ninterface IContractNamer {\\n /// @notice Determine if an account is authorized to name this contract.\\n /// Called by reverse registrars.\\n /// @param namer The address to check.\\n /// @return `true` if authorized.\\n function isContractNamer(address namer) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\"},\"project/src/utils/LibLabel.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.13;\\n\\n/// @dev Utilities for computing labelhash-based token IDs and applying version suffixes.\\nlibrary LibLabel {\\n /// @dev Compute `labelhash(label)`.\\n function id(string memory label) internal pure returns (uint256) {\\n return uint256(keccak256(bytes(label)));\\n }\\n\\n /// @dev Replace the lower 32-bits of `anyId` with `versionId`.\\n /// @param anyId The labelhash, token ID, or resource.\\n /// @param versionId The version ID.\\n /// @return The versioned ID.\\n function withVersion(uint256 anyId, uint32 versionId) internal pure returns (uint256) {\\n return anyId ^ uint32(anyId) ^ versionId;\\n }\\n}\\n\",\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\"},\"project/src/utils/interfaces/ILabelStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.13;\\n\\n/// @notice Interface for a shared label database.\\n/// @dev Interface selector: `0x0d48fe93`\\ninterface ILabelStore {\\n /// @notice A label was recorded.\\n /// @param labelHash The hash of `label`.\\n /// @param label The recorded label.\\n event Label(bytes32 indexed labelHash, string label);\\n\\n /// @notice Ensure `label` can be inverted from `anyId`.\\n /// @param label The label.\\n function setLabel(string calldata label) external;\\n\\n /// @notice Invert `anyId` to the corresponding label.\\n /// @param anyId The truncated labelhash.\\n /// @return The label or null if unknown.\\n function getLabel(uint256 anyId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 24185, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_owners", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 24192, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 21770, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_roles", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 21775, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_roleCount", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 21780, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "__gap", + "offset": 0, + "slot": "4", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 28818, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_parentRegistry", + "offset": 0, + "slot": "260", + "type": "t_contract(IRegistry)30865" + }, + { + "astId": 28821, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_childLabel", + "offset": 0, + "slot": "261", + "type": "t_string_storage" + }, + { + "astId": 28824, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_uri", + "offset": 0, + "slot": "262", + "type": "t_string_storage" + }, + { + "astId": 28828, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_uriRenderer", + "offset": 0, + "slot": "263", + "type": "t_contract(IRegistryURIRenderer)30980" + }, + { + "astId": 28834, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "_entries", + "offset": 0, + "slot": "264", + "type": "t_mapping(t_uint256,t_struct(Entry)28810_storage)" + }, + { + "astId": 28839, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "__gap", + "offset": 0, + "slot": "265", + "type": "t_array(t_uint256)256_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IRegistry)30865": { + "encoding": "inplace", + "label": "contract IRegistry", + "numberOfBytes": "20" + }, + "t_contract(IRegistryURIRenderer)30980": { + "encoding": "inplace", + "label": "contract IRegistryURIRenderer", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "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_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_struct(Entry)28810_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct PermissionedRegistry.Entry)", + "numberOfBytes": "32", + "value": "t_struct(Entry)28810_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Entry)28810_storage": { + "encoding": "inplace", + "label": "struct PermissionedRegistry.Entry", + "members": [ + { + "astId": 28796, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "eacVersionId", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 28799, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "tokenVersionId", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 28803, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "subregistry", + "offset": 8, + "slot": "0", + "type": "t_contract(IRegistry)30865" + }, + { + "astId": 28806, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "expiry", + "offset": 0, + "slot": "1", + "type": "t_uint64" + }, + { + "astId": 28809, + "contract": "project/src/registry/UserRegistry.sol:UserRegistry", + "label": "resolver", + "offset": 8, + "slot": "1", + "type": "t_address" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "notice": "Label expiry cannot be reduced." + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "notice": "Label expiry cannot be before now." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "LabelAlreadyRegistered(string)": [ + { + "notice": "Label is already registered." + } + ], + "LabelAlreadyReserved(string)": [ + { + "notice": "Label cannot be reserved again." + } + ], + "LabelExpired(uint256)": [ + { + "notice": "Label is expired/unregistered." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "notice": "Transfer is not allowed due to missing transfer admin role." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "ExpiryUpdated(uint256,uint64,address)": { + "notice": "Expiry of label was changed." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "notice": "A label was registered." + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "notice": "A label was reserved." + }, + "LabelUnregistered(uint256,address)": { + "notice": "A label was unregistered." + }, + "ParentUpdated(address,string,address)": { + "notice": "Parent was changed." + }, + "RegistryCreated()": { + "notice": "A registry was created/initialized." + }, + "ResolverUpdated(uint256,address,address)": { + "notice": "Resolver of label was changed." + }, + "SubregistryUpdated(uint256,address,address)": { + "notice": "Subregistry of label was changed." + }, + "TokenRegenerated(uint256,uint256)": { + "notice": "Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance." + }, + "TokenResource(uint256,uint256)": { + "notice": "Associate a token with an EAC resource." + }, + "URIUpdated(string,address,address)": { + "notice": "URI was changed." + } + }, + "kind": "user", + "methods": { + "LABEL_STORE()": { + "notice": "The shared label database." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "balanceOf(address,uint256)": { + "notice": "Returns the balance of a token for an account." + }, + "balanceOfBatch(address[],uint256[])": { + "notice": "Returns the balances of a batch of tokens for an account." + }, + "canUpgradeFrom(address)": { + "notice": "Declares this implementation as an eligible verifiable proxy upgrade target." + }, + "findExpiry(string)": { + "notice": "Fetches the label expiry." + }, + "findOwner(string)": { + "notice": "Fetches the label owner." + }, + "findTokenId(string)": { + "notice": "Fetches the token ID for a label." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getExpiry(uint256)": { + "notice": "Get expiry of label." + }, + "getOwner(uint256)": { + "notice": "Get token owner from `anyId`." + }, + "getParent()": { + "notice": "Get canonical \"location\" of this registry." + }, + "getResolver(string)": { + "notice": "Fetches the resolver responsible for the specified label." + }, + "getResource(uint256)": { + "notice": "Get `resource` from `anyId`." + }, + "getState(uint256)": { + "notice": "Get the state of a label." + }, + "getStatus(uint256)": { + "notice": "Get `Status` from `anyId`." + }, + "getSubregistry(string)": { + "notice": "Fetches the registry for a label." + }, + "getTokenId(uint256)": { + "notice": "Get `tokenId` from `anyId`." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "initialize(address,uint256)": { + "notice": "Initializes a proxy instance of `UserRegistry`." + }, + "isApprovedForAll(address,address)": { + "notice": "Returns the approval for all operator." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "latestOwnerOf(uint256)": { + "notice": "Get the latest owner of a token. If the token was burned, returns null." + }, + "ownerOf(uint256)": { + "notice": "Returns the owner of a token." + }, + "register(string,address,address,address,uint256,uint64)": { + "notice": "Registers a new label." + }, + "renew(uint256,uint64)": { + "notice": "Renew a label." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "notice": "Transfers multiple tokens from one address to another." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "notice": "Transfers a single token from one address to another." + }, + "setApprovalForAll(address,bool)": { + "notice": "Sets the approval for all operator." + }, + "setParent(address,string)": { + "notice": "Change canonical \"location\"." + }, + "setResolver(uint256,address)": { + "notice": "Change resolver of label." + }, + "setSubregistry(uint256,address)": { + "notice": "Change registry of label." + }, + "setURI(string,address)": { + "notice": "Set the URI for the registry." + }, + "unregister(uint256)": { + "notice": "Delete a label." + }, + "uri(uint256)": { + "notice": "Returns the URI for a token." + } + }, + "notice": "UUPS-upgradeable `PermissionedRegistry` designed to be deployed as a proxy via `VerifiableFactory` for user-owned subdomain registries. The constructor disables initializers on the implementation contract; proxies call `initialize()` to set up the admin and initial roles. Upgrade authorization requires the upgrade role in the root resource.", + "version": 1 + }, + "argsData": "0x000000000000000000000000b03524289c16424f71802a1794c29c7bd1b9f57700000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d3", + "transaction": { + "hash": "0x620e91205b122927cf04b8e874ae4c490c5312025163f613def6ee9226ce8c27", + "nonce": "0x51", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0x924f5af4cb870606a8e2dc5edb6fbf87ea8ec0f45a1dd88b392b929f46ab7886", + "blockNumber": "0xaa5705", + "transactionIndex": "0xed" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/VerifiableFactory.json b/contracts/deployments/sepolia/VerifiableFactory.json new file mode 100644 index 000000000..213ab7399 --- /dev/null +++ b/contracts/deployments/sepolia/VerifiableFactory.json @@ -0,0 +1,197 @@ +{ + "address": "0x118bc31a50d559f7015a8da26d54b3b030cdb70f", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "VerificationFailed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "proxyAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "salt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ProxyDeployed", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "uint256", + "name": "salt", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "deployProxy", + "outputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "proxyLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "verifyContract", + "outputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "VerifiableFactory", + "sourceName": "lib/verifiable-factory/src/VerifiableFactory.sol", + "bytecode": "0x60a0604052348015600e575f80fd5b506040516019906042565b604051809103905ff0801580156031573d5f803e3d5ffd5b506001600160a01b0316608052604f565b610577806105e883390190565b60805161057b61006d5f395f8181608a01526102ca015261057b5ff3fe608060405234801561000f575f80fd5b506004361061003f575f3560e01c80633d200b45146100435780635d84121a14610072578063813845bc14610085575b5f80fd5b6100566100513660046103bd565b6100ac565b6040516001600160a01b03909116815260200160405180910390f35b61005661008036600461040c565b610177565b6100567f000000000000000000000000000000000000000000000000000000000000000081565b5f813b6100dc57604051632643f15b60e11b81526001600160a01b03831660048201526024015b60405180910390fd5b816001600160a01b03166395c5c9736040518163ffffffff1660e01b81526004016040805180830381865afa925050508015610135575060408051601f3d908101601f19168201909252610132918101906104d2565b60015b1561015357610144848361028a565b15610150579392505050565b50505b604051632643f15b60e11b81526001600160a01b03831660048201526024016100d3565b604080513360208201529081018390525f9081906060016040516020818303038152906040528051906020012090505f6101b0826102c3565b9050818151602083015ff59250826101c6575f80fd5b6040517fd1f578940000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063d1f578949061020d9089908890600401610500565b5f604051808303815f87803b158015610224575f80fd5b505af1158015610236573d5f803e3d5ffd5b5050604080518881526001600160a01b038a81166020830152871693503392507f0a2c575ff341b41da136c9ccae74ec230a927a024d18f0dccf46d123f28f5f54910160405180910390a350509392505050565b5f80610295836102c3565b90505f6102aa848380519060200120306102f5565b6001600160a01b03908116908616149250505092915050565b60606102ef7f000000000000000000000000000000000000000000000000000000000000000083610327565b92915050565b5f604051836040820152846020820152828152600b8101905060ff8153605590206001600160a01b0316949350505050565b6040805160578082526080820190925260609160208201818036833750507f3d604d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000060208301525060609390931b6034840152507f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006048830152605782015290565b6001600160a01b03811681146103ba575f80fd5b50565b5f602082840312156103cd575f80fd5b81356103d8816103a6565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f805f6060848603121561041e575f80fd5b8335610429816103a6565b925060208401359150604084013567ffffffffffffffff8082111561044c575f80fd5b818601915086601f83011261045f575f80fd5b813581811115610471576104716103df565b604051601f8201601f19908116603f01168101908382118183101715610499576104996103df565b816040528281528960208487010111156104b1575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f80604083850312156104e3575f80fd5b8251915060208301516104f5816103a6565b809150509250929050565b6001600160a01b0383168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f830116840101915050939250505056fea2646970667358221220a2f050e74cc5b3f844e447aa64e648d924f349056e519158d08cb5186c794c9164736f6c6343000819003360a0604052348015600e575f80fd5b503360805260805161054d61002a5f395f6096015261054d5ff3fe60806040526004361061003e575f3560e01c80634f1ef2861461007257806385369dd71461008557806395c5c973146100d5578063d1f5789414610106575b6100706100697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001610119565b005b610070610080366004610468565b610172565b348015610090575f80fd5b506100b87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100e0575f80fd5b506100e96102ff565b604080519283526001600160a01b039091166020830152016100cc565b610070610114366004610468565b610334565b365f80375f80365f855af4811561015f577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54831461015f5763784cf7005f526004601cfd5b3d5f803e80801561016e573d5ff35b3d5ffd5b6001600160a01b0383166101b2576040517f0760838f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6101db7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b90506001600160a01b03811661021d576040517f40dde93500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff41a143d0000000000000000000000000000000000000000000000000000000081526001600160a01b03828116600483015285919082169063f41a143d90602401602060405180830381865afa15801561027d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a191906104f1565b6102ee576040517fca3316870000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301528616602482015260440160405180910390fd5b6102f88286610412565b5050505050565b5f80602080303b035f303c50505f517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc549091565b8261034657630760838f5f526004601cfd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc541561037a57630dc149f05f526004601cfd5b823b61039157634c9c8ce35f52826020526024601cfd5b827f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55827fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2808080156103ff5781845f375f80835f885af4806103f9573d5f803e3d5ffd5b506102f8565b34156102f85763b398979f5f526004601cfd5b365f80375f80365f855af48061042a573d5f803e3d5ffd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54811461046057632be618835f526004601cfd5b3d5f803e3d5ff35b5f805f6040848603121561047a575f80fd5b83356001600160a01b0381168114610490575f80fd5b9250602084013567ffffffffffffffff808211156104ac575f80fd5b818601915086601f8301126104bf575f80fd5b8135818111156104cd575f80fd5b8760208285010111156104de575f80fd5b6020830194508093505050509250925092565b5f60208284031215610501575f80fd5b81518015158114610510575f80fd5b939250505056fea264697066735822122060c270743b281c1904fc204ee55af68b77d01bd9bf139bd3b5efea97d33c52ce64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061003f575f3560e01c80633d200b45146100435780635d84121a14610072578063813845bc14610085575b5f80fd5b6100566100513660046103bd565b6100ac565b6040516001600160a01b03909116815260200160405180910390f35b61005661008036600461040c565b610177565b6100567f000000000000000000000000000000000000000000000000000000000000000081565b5f813b6100dc57604051632643f15b60e11b81526001600160a01b03831660048201526024015b60405180910390fd5b816001600160a01b03166395c5c9736040518163ffffffff1660e01b81526004016040805180830381865afa925050508015610135575060408051601f3d908101601f19168201909252610132918101906104d2565b60015b1561015357610144848361028a565b15610150579392505050565b50505b604051632643f15b60e11b81526001600160a01b03831660048201526024016100d3565b604080513360208201529081018390525f9081906060016040516020818303038152906040528051906020012090505f6101b0826102c3565b9050818151602083015ff59250826101c6575f80fd5b6040517fd1f578940000000000000000000000000000000000000000000000000000000081526001600160a01b0384169063d1f578949061020d9089908890600401610500565b5f604051808303815f87803b158015610224575f80fd5b505af1158015610236573d5f803e3d5ffd5b5050604080518881526001600160a01b038a81166020830152871693503392507f0a2c575ff341b41da136c9ccae74ec230a927a024d18f0dccf46d123f28f5f54910160405180910390a350509392505050565b5f80610295836102c3565b90505f6102aa848380519060200120306102f5565b6001600160a01b03908116908616149250505092915050565b60606102ef7f000000000000000000000000000000000000000000000000000000000000000083610327565b92915050565b5f604051836040820152846020820152828152600b8101905060ff8153605590206001600160a01b0316949350505050565b6040805160578082526080820190925260609160208201818036833750507f3d604d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000060208301525060609390931b6034840152507f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006048830152605782015290565b6001600160a01b03811681146103ba575f80fd5b50565b5f602082840312156103cd575f80fd5b81356103d8816103a6565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f805f6060848603121561041e575f80fd5b8335610429816103a6565b925060208401359150604084013567ffffffffffffffff8082111561044c575f80fd5b818601915086601f83011261045f575f80fd5b813581811115610471576104716103df565b604051601f8201601f19908116603f01168101908382118183101715610499576104996103df565b816040528281528960208487010111156104b1575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f80604083850312156104e3575f80fd5b8251915060208301516104f5816103a6565b809150509250929050565b6001600160a01b0383168152604060208201525f82518060408401528060208501606085015e5f606082850101526060601f19601f830116840101915050939250505056fea2646970667358221220a2f050e74cc5b3f844e447aa64e648d924f349056e519158d08cb5186c794c9164736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "21564": [ + { + "length": 32, + "start": 138 + }, + { + "length": 32, + "start": 714 + } + ] + }, + "inputSourceName": "project/lib/verifiable-factory/src/VerifiableFactory.sol", + "devdoc": { + "kind": "dev", + "methods": { + "deployProxy(address,uint256,bytes)": { + "details": "Deploys a new verifiable proxy clone at a deterministic address. The deployed proxy is an EIP-1167-style clone that delegates proxy mechanics to the factory's `proxyLogic` contract. The clone runtime also appends the derived salt so the factory can later verify the proxy's CREATE2 address. The CREATE2 salt is `keccak256(abi.encode(msg.sender, salt))`, so two callers can reuse the same user salt without colliding.", + "params": { + "implementation": "The address of the contract implementation the proxy will delegate calls to.", + "salt": "A value provided by the caller to ensure uniqueness of the proxy address." + }, + "returns": { + "proxy": "The address of the deployed proxy clone." + } + }, + "verifyContract(address)": { + "details": "Verifies a proxy contract and returns its current implementation. This function attempts to validate a proxy contract by retrieving its salt and reconstructing the address to ensure it was correctly deployed by the current factory.", + "params": { + "proxy": "The address of the proxy contract being verified." + }, + "returns": { + "implementation": "The proxy's current implementation." + } + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "280600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "deployProxy(address,uint256,bytes)": "infinite", + "proxyLogic()": "infinite", + "verifyContract(address)": "infinite" + }, + "internal": { + "_proxyCreationCode(bytes32)": "infinite", + "_verifyContract(address,bytes32)": "infinite", + "isContract(address)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"VerificationFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxyAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"salt\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ProxyDeployed\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"salt\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"deployProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxyLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"verifyContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"deployProxy(address,uint256,bytes)\":{\"details\":\"Deploys a new verifiable proxy clone at a deterministic address. The deployed proxy is an EIP-1167-style clone that delegates proxy mechanics to the factory's `proxyLogic` contract. The clone runtime also appends the derived salt so the factory can later verify the proxy's CREATE2 address. The CREATE2 salt is `keccak256(abi.encode(msg.sender, salt))`, so two callers can reuse the same user salt without colliding.\",\"params\":{\"implementation\":\"The address of the contract implementation the proxy will delegate calls to.\",\"salt\":\"A value provided by the caller to ensure uniqueness of the proxy address.\"},\"returns\":{\"proxy\":\"The address of the deployed proxy clone.\"}},\"verifyContract(address)\":{\"details\":\"Verifies a proxy contract and returns its current implementation. This function attempts to validate a proxy contract by retrieving its salt and reconstructing the address to ensure it was correctly deployed by the current factory.\",\"params\":{\"proxy\":\"The address of the proxy contract being verified.\"},\"returns\":{\"implementation\":\"The proxy's current implementation.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/lib/verifiable-factory/src/VerifiableFactory.sol\":\"VerifiableFactory\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/buffer/=project/lib/buffer/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/:~src/=project/src/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\",\"project/lib/verifiable-factory/:@openzeppelin/contracts/=project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {Errors} from \\\"./Errors.sol\\\";\\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 There's no code to deploy.\\n */\\n error Create2EmptyBytecode();\\n\\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(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {\\n if (address(this).balance < amount) {\\n revert Errors.InsufficientBalance(address(this).balance, amount);\\n }\\n if (bytecode.length == 0) {\\n revert Create2EmptyBytecode();\\n }\\n assembly (\\\"memory-safe\\\") {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n // if no address was created, and returndata is not empty, bubble revert\\n if and(iszero(addr), not(iszero(returndatasize()))) {\\n let p := mload(0x40)\\n returndatacopy(p, 0, returndatasize())\\n revert(p, returndatasize())\\n }\\n }\\n if (addr == address(0)) {\\n revert Errors.FailedDeployment();\\n }\\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(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {\\n assembly (\\\"memory-safe\\\") {\\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 := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xbb7e8401583d26268ea9103013bcdcd90866a7718bd91105ebd21c9bf11f4f06\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev Collection of common custom errors used in multiple contracts\\n *\\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\\n * It is recommended to avoid relying on the error API for critical functionality.\\n *\\n * _Available since v5.1._\\n */\\nlibrary Errors {\\n /**\\n * @dev The ETH balance of the account is not enough to perform the operation.\\n */\\n error InsufficientBalance(uint256 balance, uint256 needed);\\n\\n /**\\n * @dev A call to an address target failed. The target may have reverted.\\n */\\n error FailedCall();\\n\\n /**\\n * @dev The deployment failed.\\n */\\n error FailedDeployment();\\n\\n /**\\n * @dev A necessary precompile is missing.\\n */\\n error MissingPrecompile(address);\\n}\\n\",\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/CloneProxyBytecode.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nlibrary CloneProxyBytecode {\\n // EIP-1167 minimal proxy creation/runtime code:\\n // https://eips.ethereum.org/EIPS/eip-1167\\n //\\n // Standard runtime is 45 bytes:\\n // 363d3d373d3d3d363d73<20-byte implementation>5af43d82803e903d91602b57fd5bf3\\n //\\n // We append a 32-byte salt to the runtime and make the creation stub return 77 bytes\\n // instead of the standard 45. The proxy still executes the same minimal-proxy logic;\\n // UUPSProxyLogic reads the appended salt with extcodecopy().\\n uint256 internal constant CREATION_CODE_LENGTH = 0x57;\\n\\n function creationCode(address logic, bytes32 salt) internal pure returns (bytes memory code) {\\n code = new bytes(CREATION_CODE_LENGTH);\\n\\n assembly (\\\"memory-safe\\\") {\\n let ptr := add(code, 0x20)\\n\\n // Creation stub plus runtime prefix. The creation stub returns 77 bytes:\\n // 45 bytes of EIP-1167 runtime plus our appended 32-byte salt.\\n mstore(ptr, 0x3d604d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n // Fill the EIP-1167 PUSH20 slot with the shared proxy logic address.\\n mstore(add(ptr, 0x14), shl(0x60, logic))\\n // Runtime suffix: delegatecall to `logic`, copy returndata, then return or revert.\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n // Append salt after the executable minimal-proxy runtime for extcodecopy().\\n mstore(add(ptr, 0x37), salt)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2973c5070195e3c2806b59f1dc7a9da5aa1efa4a30867d9715def848bd51780f\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IProxyAuthorization {\\n function canUpgradeFrom(address previousImplementation) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IUUPSProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IUUPSProxy {\\n /// @dev Error selector: `0x0760838f`\\n error ImplementationCannotBeZeroAddress();\\n\\n /// @dev Error selector: `0x0dc149f0`\\n error AlreadyInitialized();\\n\\n /// @dev Error selector: `0x40dde935`\\n error ImplementationNotSet();\\n\\n /// @dev Error selector: `0xca331687`\\n error InvalidUpgradeTarget(address currentImplementation, address newImplementation);\\n\\n /// @dev Error selector: `0x784cf700`\\n error UpgradeNotAllowedInContext();\\n\\n /// @dev Error selector: `0x2be61883`\\n error UnexpectedUpgrade();\\n\\n function initialize(address implementation, bytes calldata data) external payable;\\n\\n function getVerifiableProxyData() external view returns (bytes32 salt, address implementation);\\n\\n function verifiableProxyFactory() external view returns (address);\\n}\\n\",\"keccak256\":\"0x5de1b176834f853b0aba3d6e6b188a158f4b0f75744c7ffebb01bf6f51518233\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/IVerifiableFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\ninterface IVerifiableFactory {\\n error VerificationFailed(address proxy);\\n\\n event ProxyDeployed(address indexed sender, address indexed proxyAddress, uint256 salt, address implementation);\\n\\n function deployProxy(address implementation, uint256 salt, bytes memory data) external returns (address);\\n\\n function verifyContract(address proxy) external view returns (address implementation);\\n}\\n\",\"keccak256\":\"0xe6c1b487e41bb6e89383f8f63942d6db67bd140539df2755b82d999624c6050a\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/UUPSProxyLogic.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport {IProxyAuthorization} from \\\"./IProxyAuthorization.sol\\\";\\nimport {IUUPSProxy} from \\\"./IUUPSProxy.sol\\\";\\n\\ncontract UUPSProxyLogic is IUUPSProxy {\\n /// @dev `keccak256(bytes(\\\"eip1967.proxy.implementation\\\")) - 1`.\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ImplementationCannotBeZeroAddress()\\\")))`.\\n uint256 internal constant _IMPLEMENTATION_CANNOT_BE_ZERO_ADDRESS_ERROR_SELECTOR = 0x0760838f;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"AlreadyInitialized()\\\")))`.\\n uint256 internal constant _ALREADY_INITIALIZED_ERROR_SELECTOR = 0x0dc149f0;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"UpgradeNotAllowedInContext()\\\")))`.\\n uint256 internal constant _UPGRADE_NOT_ALLOWED_IN_CONTEXT_ERROR_SELECTOR = 0x784cf700;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"UnexpectedUpgrade()\\\")))`.\\n uint256 internal constant _UNEXPECTED_UPGRADE_ERROR_SELECTOR = 0x2be61883;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ERC1967InvalidImplementation(address)\\\")))`.\\n uint256 internal constant _ERC1967_INVALID_IMPLEMENTATION_ERROR_SELECTOR = 0x4c9c8ce3;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"ERC1967NonPayable()\\\")))`.\\n uint256 internal constant _ERC1967_NON_PAYABLE_ERROR_SELECTOR = 0xb398979f;\\n\\n /// @dev `bytes4(keccak256(bytes(\\\"Upgraded(address)\\\")))`.\\n uint256 internal constant _UPGRADED_EVENT_SELECTOR =\\n 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b;\\n\\n address public immutable verifiableProxyFactory;\\n\\n constructor() {\\n verifiableProxyFactory = msg.sender;\\n }\\n\\n function initialize(address implementation, bytes calldata data) external payable {\\n assembly {\\n if eq(implementation, 0) {\\n mstore(0, _IMPLEMENTATION_CANNOT_BE_ZERO_ADDRESS_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n if iszero(eq(sload(_IMPLEMENTATION_SLOT), 0)) {\\n mstore(0, _ALREADY_INITIALIZED_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n if iszero(extcodesize(implementation)) {\\n mstore(0, _ERC1967_INVALID_IMPLEMENTATION_ERROR_SELECTOR)\\n mstore(0x20, implementation)\\n revert(0x1c, 0x24)\\n }\\n sstore(_IMPLEMENTATION_SLOT, implementation)\\n log2(0, 0, _UPGRADED_EVENT_SELECTOR, implementation)\\n\\n let dlength := data.length\\n switch dlength\\n case 0 {\\n if callvalue() {\\n mstore(0, _ERC1967_NON_PAYABLE_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n }\\n default {\\n calldatacopy(0, data.offset, dlength)\\n let result := delegatecall(gas(), implementation, 0, dlength, 0, 0)\\n if iszero(result) {\\n returndatacopy(0, 0, returndatasize())\\n revert(0, returndatasize())\\n }\\n }\\n }\\n }\\n\\n function getVerifiableProxyData() public view returns (bytes32 salt, address implementation) {\\n assembly {\\n extcodecopy(address(), 0, sub(extcodesize(address()), 0x20), 0x20)\\n salt := mload(0)\\n implementation := sload(_IMPLEMENTATION_SLOT)\\n }\\n }\\n\\n function upgradeToAndCall(address newImplementation, bytes calldata) external payable {\\n if (newImplementation == address(0)) revert ImplementationCannotBeZeroAddress();\\n\\n address implementation = _implementation();\\n if (implementation == address(0)) revert ImplementationNotSet();\\n\\n IProxyAuthorization newImpl = IProxyAuthorization(newImplementation);\\n if (!newImpl.canUpgradeFrom(implementation)) {\\n revert InvalidUpgradeTarget(implementation, newImplementation);\\n }\\n\\n _delegateUpgrade(implementation, newImplementation);\\n }\\n\\n function _implementation() internal view returns (address impl) {\\n assembly {\\n impl := sload(_IMPLEMENTATION_SLOT)\\n }\\n }\\n\\n function _delegate(address implementation, bool checkImplementation) internal {\\n assembly {\\n calldatacopy(0, 0, calldatasize())\\n\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n if checkImplementation {\\n if iszero(eq(implementation, sload(_IMPLEMENTATION_SLOT))) {\\n mstore(0, _UPGRADE_NOT_ALLOWED_IN_CONTEXT_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n }\\n\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n function _delegateUpgrade(address implementation, address expectedImplementation) internal {\\n assembly {\\n calldatacopy(0, 0, calldatasize())\\n\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n if iszero(result) {\\n returndatacopy(0, 0, returndatasize())\\n revert(0, returndatasize())\\n }\\n\\n if iszero(eq(expectedImplementation, sload(_IMPLEMENTATION_SLOT))) {\\n mstore(0, _UNEXPECTED_UPGRADE_ERROR_SELECTOR)\\n revert(0x1c, 0x04)\\n }\\n\\n returndatacopy(0, 0, returndatasize())\\n return(0, returndatasize())\\n }\\n }\\n\\n fallback() external payable {\\n _delegate(_implementation(), true);\\n }\\n}\\n\",\"keccak256\":\"0x980e42f28d79bc1d473593042c1fd2d17038f81344f13ac08a29c03f2cf20c54\",\"license\":\"MIT\"},\"project/lib/verifiable-factory/src/VerifiableFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.20;\\n\\nimport {Create2} from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\nimport {CloneProxyBytecode} from \\\"./CloneProxyBytecode.sol\\\";\\nimport {UUPSProxyLogic} from \\\"./UUPSProxyLogic.sol\\\";\\nimport {IUUPSProxy} from \\\"./IUUPSProxy.sol\\\";\\nimport {IVerifiableFactory} from \\\"./IVerifiableFactory.sol\\\";\\n\\ncontract VerifiableFactory is IVerifiableFactory {\\n address public immutable proxyLogic;\\n\\n constructor() {\\n proxyLogic = address(new UUPSProxyLogic());\\n }\\n\\n /**\\n * @dev Deploys a new verifiable proxy clone at a deterministic address.\\n *\\n * The deployed proxy is an EIP-1167-style clone that delegates proxy mechanics to the\\n * factory's `proxyLogic` contract. The clone runtime also appends the derived salt so the\\n * factory can later verify the proxy's CREATE2 address.\\n *\\n * The CREATE2 salt is `keccak256(abi.encode(msg.sender, salt))`, so two callers can reuse\\n * the same user salt without colliding.\\n *\\n * @param implementation The address of the contract implementation the proxy will delegate calls to.\\n * @param salt A value provided by the caller to ensure uniqueness of the proxy address.\\n * @return proxy The address of the deployed proxy clone.\\n */\\n function deployProxy(address implementation, uint256 salt, bytes memory data) external returns (address proxy) {\\n bytes32 outerSalt = keccak256(abi.encode(msg.sender, salt));\\n bytes memory executableBytecode = _proxyCreationCode(outerSalt);\\n\\n assembly {\\n proxy := create2(0, add(executableBytecode, 0x20), mload(executableBytecode), outerSalt)\\n if iszero(proxy) {\\n revert(0, 0)\\n }\\n }\\n\\n IUUPSProxy(proxy).initialize(implementation, data);\\n\\n emit ProxyDeployed(msg.sender, proxy, salt, implementation);\\n }\\n\\n /**\\n * @dev Verifies a proxy contract and returns its current implementation.\\n *\\n * This function attempts to validate a proxy contract by retrieving its salt\\n * and reconstructing the address to ensure it was correctly deployed by the\\n * current factory.\\n *\\n * @param proxy The address of the proxy contract being verified.\\n * @return implementation The proxy's current implementation.\\n */\\n function verifyContract(address proxy) public view returns (address implementation) {\\n if (!isContract(proxy)) revert VerificationFailed(proxy);\\n\\n try IUUPSProxy(proxy).getVerifiableProxyData() returns (bytes32 salt, address actualImplementation) {\\n if (_verifyContract(proxy, salt)) return actualImplementation;\\n } catch {}\\n revert VerificationFailed(proxy);\\n }\\n\\n function _verifyContract(address proxy, bytes32 salt) private view returns (bool) {\\n bytes memory proxyBytecode = _proxyCreationCode(salt);\\n\\n address expectedProxyAddress = Create2.computeAddress(salt, keccak256(proxyBytecode), address(this));\\n\\n return expectedProxyAddress == proxy;\\n }\\n\\n function _proxyCreationCode(bytes32 salt) private view returns (bytes memory creationCode) {\\n creationCode = CloneProxyBytecode.creationCode(proxyLogic, salt);\\n }\\n\\n function isContract(address account) internal view returns (bool) {\\n uint256 size;\\n assembly {\\n size := extcodesize(account)\\n }\\n return size > 0;\\n }\\n}\\n\",\"keccak256\":\"0xb5d61f83d18f2a1e615ddc606f7277e1f8bc2eb13d8d452dc8c1f4a4603e72d2\",\"license\":\"MIT\"}},\"version\":1}", + "storageLayout": { + "storage": [], + "types": null + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "argsData": "0x", + "transaction": { + "hash": "0xd6977854a0fe4945daa4fb14c6392bde78f60f1c36566f5ca83ef636a5689b22", + "nonce": "0x13", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xc718ba2c79451415e6ed45b74c620ca15f285c864e563fe8c529bdfce4e16227", + "blockNumber": "0xaa56bc", + "transactionIndex": "0x96" + } +} \ No newline at end of file diff --git a/contracts/deployments/sepolia/WrapperRegistryImpl.json b/contracts/deployments/sepolia/WrapperRegistryImpl.json new file mode 100644 index 000000000..4981bee62 --- /dev/null +++ b/contracts/deployments/sepolia/WrapperRegistryImpl.json @@ -0,0 +1,3703 @@ +{ + "address": "0xcf9f4863a1b44216cfc0be65f4e47b2b9a043924", + "abi": [ + { + "inputs": [ + { + "internalType": "contract INameWrapper", + "name": "nameWrapper", + "type": "address" + }, + { + "internalType": "address", + "name": "graveyard", + "type": "address" + }, + { + "internalType": "contract IVerifiableFactory", + "name": "verifiableFactory", + "type": "address" + }, + { + "internalType": "address", + "name": "ensV1Resolver", + "type": "address" + }, + { + "internalType": "contract ApprovedUpgradeGate", + "name": "upgradeGate", + "type": "address" + }, + { + "internalType": "contract ILabelStore", + "name": "labelStore", + "type": "address" + }, + { + "internalType": "contract IAddressSet", + "name": "publicResolverSet", + "type": "address" + }, + { + "internalType": "address", + "name": "publicResolver", + "type": "address" + }, + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "oldExpiry", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "CannotReduceExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "CannotSetPastExpiry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotGrantRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACCannotRevokeRoles", + "type": "error" + }, + { + "inputs": [], + "name": "EACInvalidAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "EACInvalidRoleBitmap", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMaxAssignees", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "role", + "type": "uint256" + } + ], + "name": "EACMinAssignees", + "type": "error" + }, + { + "inputs": [], + "name": "EACRootResourceNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "EACUnauthorizedAccountRoles", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "ERC1967InvalidImplementation", + "type": "error" + }, + { + "inputs": [], + "name": "ERC1967NonPayable", + "type": "error" + }, + { + "inputs": [], + "name": "FailedCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "FrozenTokenApproval", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "LabelAlreadyReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "LabelExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameDataMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NameNotLocked", + "type": "error" + }, + { + "inputs": [], + "name": "NameRequiresMigration", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "TransferDisallowed", + "type": "error" + }, + { + "inputs": [], + "name": "UUPSUnauthorizedCallContext", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "slot", + "type": "bytes32" + } + ], + "name": "UUPSUnsupportedProxiableUUID", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "UpgradeTargetNotApproved", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldRoleBitmap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newRoleBitmap", + "type": "uint256" + } + ], + "name": "EACRolesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ExpiryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "labelHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelReserved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "LabelUnregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ParentUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RegistryCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ResolverUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SubregistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "oldTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTokenId", + "type": "uint256" + } + ], + "name": "TokenRegenerated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "name": "TokenResource", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "uri", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "renderer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "URIUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "GRAVEYARD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LABEL_STORE", + "outputs": [ + { + "internalType": "contract ILabelStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NAME_WRAPPER", + "outputs": [ + { + "internalType": "contract INameWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PUBLIC_RESOLVER_SET", + "outputs": [ + { + "internalType": "contract IAddressSet", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROOT_RESOURCE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_GATE", + "outputs": [ + { + "internalType": "contract ApprovedUpgradeGate", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPGRADE_INTERFACE_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "V1_RESOLVER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VERIFIABLE_FACTORY", + "outputs": [ + { + "internalType": "contract IVerifiableFactory", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WRAPPER_REGISTRY_IMPL", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "canUpgradeFrom", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "findTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "subregistry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "internalType": "struct LibMigration.Data[]", + "name": "mds", + "type": "tuple[]" + } + ], + "name": "finishERC1155Migration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "getAssigneeCount", + "outputs": [ + { + "internalType": "uint256", + "name": "counts", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mask", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getExpiry", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParent", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getResolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getResource", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "status", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + }, + { + "internalType": "address", + "name": "latestOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resource", + "type": "uint256" + } + ], + "internalType": "struct IPermissionedRegistry.State", + "name": "state", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getStatus", + "outputs": [ + { + "internalType": "enum IPermissionedRegistry.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "getSubregistry", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "getTokenId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedName", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNode", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "hasAssignees", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "contract IRegistry", + "name": "parentRegistry", + "type": "address" + }, + { + "internalType": "string", + "name": "childLabel", + "type": "string" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "namer", + "type": "address" + } + ], + "name": "isContractNamer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "latestOwnerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155BatchReceived", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onERC1155Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expiry", + "type": "uint64" + } + ], + "name": "register", + "outputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "newExpiry", + "type": "uint64" + } + ], + "name": "renew", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roleBitmap", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRootRoles", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "roleCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "roles", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRegistry", + "name": "parent", + "type": "address" + }, + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "setParent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + }, + { + "internalType": "contract IRegistry", + "name": "registry", + "type": "address" + } + ], + "name": "setSubregistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + }, + { + "internalType": "contract IRegistryURIRenderer", + "name": "renderer", + "type": "address" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "anyId", + "type": "uint256" + } + ], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "contractName": "WrapperRegistry", + "sourceName": "src/registry/WrapperRegistry.sol", + "bytecode": "0x6101e06040523061018052348015610015575f80fd5b50604051616cbb380380616cbb83398101604081905261003491610f67565b88888830868685858b896080600160781b901b600160781b177fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f05268760405160405180910390a16001600160a01b0383166080526100925f828482610159565b505050506001600160a01b0382811660a081905290821660c05260408051633f15457f60e01b81529051633f15457f916004808201926020929091908290030181865afa1580156100e5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101099190611025565b6001600160a01b0390811660e052958616610100525050918316610120528216610140528116610160528881166101a05287166101c0525061014b905061026b565b5050505050505050506112d7565b5f835f0361016857505f610263565b61017184610308565b6001600160a01b0383166101985760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b038716845290915290205484811780821461025d575f8781526002602090815260408083206001600160a01b03891684529091529020819055811986166101f888826001610351565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a3841561025157610251888785858b610481565b60019350505050610263565b5f925050505b949350505050565b5f610274610491565b805490915068010000000000000000900460ff16156102a65760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146103055780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561030557604051630153d96960e51b8152600481018290526024015b60405180910390fd5b5f61035b836104bb565b905081156103f1575f848152600360205260409020546103a19082161980195f80516020616c9b83398151915291909101165f80516020616c7b83398151915216151590565b156103c957604051631f22ca6960e31b81526004810185905260248101849052604401610348565b5f84815260036020526040812080548592906103e6908490611054565b9091555061047b9050565b5f84815260036020526040902054610430901982161980195f80516020616c9b83398151915291909101165f80516020616c7b83398151915216151590565b1561045857604051631f80c19b60e01b81526004810185905260248101849052604401610348565b5f8481526003602052604081208054859290610475908490611067565b90915550505b50505050565b61048a856104d5565b5050505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005b92915050565b5f6104c582610308565b50600181901b17600281901b1790565b80156103055763ffffffff811681185f90815261010860205260408120906104fd83836105c1565b5f818152602081905260409020549091506001600160a01b0316610523818360016105e2565b8254839060049061054190640100000000900463ffffffff1661107a565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f61057083856105c160201b60201c565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a361048a8282600160405180602001604052805f81525061064960201b60201c565b80545f9063ffffffff808516851864010000000090920416185b9392505050565b6001600160a01b03831661060a57604051626a0d4560e21b81525f6004820152602401610348565b604080516001808252602082018590528183019081526060820184905260a082019092525f6080820181815291929161048a91879185908590836106be565b6001600160a01b03841661067257604051632bfa23e760e11b81525f6004820152602401610348565b604080516001808252602082018690528183019081526060820185905260808201909252906106a55f87848487846106be565b505050505050565b63ffffffff82811690921891161890565b6106ca86868686610714565b6001600160a01b038516156106a55780156106f2576106ed3387878787876107ef565b6106a5565b6020848101519084015161070a338989858589610919565b5050505050505050565b61072084848484610a00565b6001600160a01b0383161580159061074057506001600160a01b03841615155b1561047b575f5b825181101561048a575f8382815181106107635761076361109c565b60200260200101519050610782816001609c1b88610be660201b60201c565b6107b1576040516372c7b6ad60e11b8152600481018290526001600160a01b0387166024820152604401610348565b5f8383815181106107c4576107c461109c565b602002602001015111156107e6576107e66107de82610bfa565b87875f610c21565b50600101610747565b6001600160a01b0384163b156106a55760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906108339089908990889088908890600401611118565b6020604051808303815f875af192505050801561086d575060408051601f3d908101601f1916820190925261086a91810190611175565b60015b6108d4573d80801561089a576040519150601f19603f3d011682016040523d82523d5f602084013e61089f565b606091505b5080515f036108cc57604051632bfa23e760e11b81526001600160a01b0386166004820152602401610348565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b1461091057604051632bfa23e760e11b81526001600160a01b0386166004820152602401610348565b50505050505050565b6001600160a01b0384163b156106a55760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e619061095d908990899088908890889060040161119c565b6020604051808303815f875af1925050508015610997575060408051601f3d908101601f1916820190925261099491810190611175565b60015b6109c4573d80801561089a576040519150601f19603f3d011682016040523d82523d5f602084013e61089f565b6001600160e01b0319811663f23a6e6160e01b1461091057604051632bfa23e760e11b81526001600160a01b0386166004820152602401610348565b8051825114610a2f5781518151604051635b05999160e01b815260048101929092526024820152604401610348565b5f5b8251811015610b20576020818102848101820151908401909101518015610b16575f828152602081905260409020546001600160a01b039081169088168114610aac576040516303dee4c560e01b81526001600160a01b03891660048201525f60248201526044810183905260648101849052608401610348565b6001821115610aee576040516303dee4c560e01b81526001600160a01b0389166004820152600160248201526044810183905260648101849052608401610348565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0388161790555b5050600101610a31565b508151600103610b89576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4505061047b565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051610bd89291906111e0565b60405180910390a450505050565b5f610263610bf385610bfa565b8484610c62565b5f6104b582610c1c8163ffffffff8116185f9081526101086020526040902090565b610c79565b5f8481526002602090815260408083206001600160a01b0387168452909152902054801561048a57610c5585828685610cc7565b506106a585828585610159565b5f8280610c6f8685610d33565b1614949350505050565b5f82610c865750816104b5565b60018201546105db9084906001600160401b0316421015610cb457835463ffffffff82811690921891161890565b83546106ad9063ffffffff16600161120d565b5f610cd184610308565b5f8581526002602090815260408083206001600160a01b03871684529091529020548419811680821461025d575f8781526002602090815260408083206001600160a01b03891684529091528120829055868316906101f89089908390610351565b5f610d3e8383610d50565b610d485f84610d50565b179392505050565b5f82610e0857610104546001600160a01b03168015801590610def57506040516331ab054760e11b81526001600160a01b038216906363560a8e90610d9b906101059060040161122a565b602060405180830381865afa158015610db6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dda9190611025565b6001600160a01b0316836001600160a01b0316145b15610e0657610dfe8482610e0e565b9150506104b5565b505b6105db83835b5f8281526002602090815260408083206001600160a01b038516845290915290205482156104b5575f610e4084610ecf565b90506001600160a01b03811615801590610e6c5750826001600160a01b0316816001600160a01b031614155b8015610e9c57506001600160a01b038082165f9081526001602090815260408083209387168352929052205460ff165b15610ec8575f8481526002602090815260408083206001600160a01b0385168452909152902054821791505b5092915050565b63ffffffff811681185f90815261010860205260408120600101546001600160401b0316421015610f2557610f20610f0683610f2c565b5f908152602081905260409020546001600160a01b031690565b6104b5565b5f92915050565b5f6104b582610f4e8163ffffffff8116185f9081526101086020526040902090565b6105c1565b6001600160a01b0381168114610305575f80fd5b5f805f805f805f805f6101208a8c031215610f80575f80fd5b8951610f8b81610f53565b60208b0151909950610f9c81610f53565b60408b0151909850610fad81610f53565b60608b0151909750610fbe81610f53565b60808b0151909650610fcf81610f53565b60a08b0151909550610fe081610f53565b60c08b0151909450610ff181610f53565b60e08b015190935061100281610f53565b6101008b015190925061101481610f53565b809150509295985092959850929598565b5f60208284031215611035575f80fd5b81516105db81610f53565b634e487b7160e01b5f52601160045260245ffd5b808201808211156104b5576104b5611040565b818103818111156104b5576104b5611040565b5f63ffffffff80831681810361109257611092611040565b6001019392505050565b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b838110156110df578151875295820195908201906001016110c3565b509495945050505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0386811682528516602082015260a0604082018190525f90611143908301866110b0565b828103606084015261115581866110b0565b9050828103608084015261116981856110ea565b98975050505050505050565b5f60208284031215611185575f80fd5b81516001600160e01b0319811681146105db575f80fd5b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f906111d5908301846110ea565b979650505050505050565b604081525f6111f260408301856110b0565b828103602084015261120481856110b0565b95945050505050565b63ffffffff818116838216019080821115610ec857610ec8611040565b5f60208083525f84545f60018260011c9150600183168061124c57607f831692505b60208310810361126a57634e487b7160e01b5f52602260045260245ffd5b6020880183905260408801818015611289576001811461129f576112c8565b60ff198616825284151560051b820196506112c8565b5f8b8152602090205f5b868110156112c2578154848201529085019089016112a9565b83019750505b50949998505050505050505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516158916113ea5f395f818161060501526122bf01525f81816106380152611b9801525f81816121fd01528181612226015261241001525f8181610b71015261285f01525f8181610b3e01526127e401525f81816106dd015261296a01525f8181610465015261293b01525f81816127470152612dfb01525f818161074e0152818161289e0152612b3101525f81816104a5015281816118c301528181611bf60152818161255d01528181612611015281816126c8015281816128e101528181612a8501528181612afe01528181612d540152612e8d01525f818161090f01526135f301526158915ff3fe60806040526004361061030e575f3560e01c80635d05f04911610197578063ad3cb1cc116100df578063dfa70d8b1161008e578063dfa70d8b14610a72578063e4ae7d7714610a91578063e985e9c514610ab0578063f23a6e6114610acf578063f242432a14610aee578063f41a143d14610b0d578063f923b68514610b2d578063ffeb4a3014610b60575f80fd5b8063ad3cb1cc1461096f578063bc197c811461099f578063bc7b6d62146109d7578063bd242bcb146109f6578063c41a360a14610a15578063ce156e8214610a34578063d3bf89b114610a53575f80fd5b80637c300586116101465780637c3005861461086b57806380f760211461088a57806385f3e643146108ac57806391b3c037146108cb5780639b224b1d146108ea5780639dbba19d146108fe578063a02b161e14610931578063a22cb46514610950575f80fd5b80635d05f0491461079c5780636352211e146107bb57806363560a8e146107da5780636e7a2116146107f95780636f3ff7261461080e5780636f537c721461082d578063781ef8db1461084c575f80fd5b806335af62161161025a5780634f1ef286116102095780634f1ef2861461068657806352d1902d146106995780635357263f146106ad578063547c9d2d146106cc5780635569f33d146106ff5780635adf47241461071e5780635c1a6b681461073d5780635c622a0e14610770575f80fd5b806335af6216146105565780633634f9111461057557806344c9af28146105a957806348688f95146105d55780634b2dc431146105f45780634b30228c146106275780634e1273f41461065a575f80fd5b80631542c01a116102c15780631542c01a1461043357806318ad9b7114610454578063192cf07d146104945780631c3fc3eb146104c75780631e8fca2d146104da5780632eb2c2d6146104f95780632f27fa2414610518578063341ec55914610537575f80fd5b8062fdd58e1461031257806301ffc9a714610344578063072d5d77146103735780630e89341c1461039257806311b8e00a146103be57806313c72608146103dd57806314ff5ea314610414575b5f80fd5b34801561031d575f80fd5b5061033161032c3660046144c6565b610b93565b6040519081526020015b60405180910390f35b34801561034f575f80fd5b5061036361035e366004614505565b610bde565b604051901515815260200161033b565b34801561037e575f80fd5b5061036361038d366004614520565b610c38565b34801561039d575f80fd5b506103b16103ac36600461454e565b610c5c565b60405161033b9190614593565b3480156103c9575f80fd5b506103636103d83660046145a5565b610d73565b3480156103e8575f80fd5b506103fc6103f736600461454e565b610d8d565b6040516001600160401b03909116815260200161033b565b34801561041f575f80fd5b5061033161042e36600461454e565b610daa565b34801561043e575f80fd5b5061045261044d366004614602565b610dbd565b005b34801561045f575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b60405161033b9190614660565b34801561049f575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d2575f80fd5b506103315f81565b3480156104e5575f80fd5b506103316104f436600461454e565b610f6c565b348015610504575f80fd5b506104526105133660046147b9565b610f7f565b348015610523575f80fd5b5061033161053236600461454e565b610f9d565b348015610542575f80fd5b50610452610551366004614520565b610fbb565b348015610561575f80fd5b5061048761057036600461485f565b611029565b348015610580575f80fd5b5061059461058f3660046145a5565b6110aa565b6040805192835260208301919091520161033b565b3480156105b4575f80fd5b506105c86105c336600461454e565b6110ca565b60405161033b91906148d1565b3480156105e0575f80fd5b506104526105ef366004614922565b611190565b3480156105ff575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b348015610632575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b348015610665575f80fd5b50610679610674366004614974565b611210565b60405161033b9190614a69565b610452610694366004614a7b565b6112df565b3480156106a4575f80fd5b506103316112fe565b3480156106b8575f80fd5b506104526106c7366004614a7b565b611319565b3480156106d7575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b34801561070a575f80fd5b50610452610719366004614ad1565b6113a1565b348015610729575f80fd5b50610331610738366004614520565b6114c5565b348015610748575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b34801561077b575f80fd5b5061078f61078a36600461454e565b6114d8565b60405161033b9190614af4565b3480156107a7575f80fd5b506104526107b6366004614b42565b61150f565b3480156107c6575f80fd5b506104876107d536600461454e565b61156d565b3480156107e5575f80fd5b506104876107f436600461485f565b6115b9565b348015610804575f80fd5b5061020954610331565b348015610819575f80fd5b50610363610828366004614ba8565b6115fb565b348015610838575f80fd5b506103fc61084736600461485f565b61160a565b348015610857575f80fd5b50610363610866366004614520565b61164c565b348015610876575f80fd5b50610363610885366004614bc3565b611662565b348015610895575f80fd5b5061089e611676565b60405161033b929190614bee565b3480156108b7575f80fd5b506103316108c6366004614c11565b611721565b3480156108d6575f80fd5b506103316108e536600461485f565b611762565b3480156108f5575f80fd5b506103b16117a4565b348015610909575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b34801561093c575f80fd5b5061045261094b36600461454e565b6117b3565b34801561095b575f80fd5b5061045261096a366004614caa565b6118ac565b34801561097a575f80fd5b506103b1604051806040016040528060058152602001640352e302e360dc1b81525081565b3480156109aa575f80fd5b506109be6109b9366004614cd6565b6118b7565b6040516001600160e01b0319909116815260200161033b565b3480156109e2575f80fd5b506104526109f1366004614520565b611a4f565b348015610a01575f80fd5b50610487610a1036600461454e565b611ac3565b348015610a20575f80fd5b50610487610a2f36600461454e565b611acd565b348015610a3f575f80fd5b50610363610a4e366004614520565b611b05565b348015610a5e575f80fd5b50610363610a6d366004614bc3565b611b20565b348015610a7d575f80fd5b50610363610a8c366004614bc3565b611b34565b348015610a9c575f80fd5b50610487610aab36600461485f565b611b48565b348015610abb575f80fd5b50610363610aca366004614d8c565b611bbd565b348015610ada575f80fd5b506109be610ae9366004614db8565b611bea565b348015610af9575f80fd5b50610452610b08366004614e2e565b611dda565b348015610b18575f80fd5b50610363610b27366004614ba8565b50600190565b348015610b38575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b348015610b6b575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b5f6001600160a01b03831615801590610bc55750826001600160a01b0316610bba8361156d565b6001600160a01b0316145b610bcf575f610bd2565b60015b60ff1690505b92915050565b5f63e01aaa1160e01b6001600160e01b031983161480610c0e575063b0f3d36760e01b6001600160e01b03198316145b80610c29575063f41a143d60e01b6001600160e01b03198316145b80610bd85750610bd882611df1565b5f8083610c46828233611e15565b610c535f86866001611e4a565b95945050505050565b610107546060906001600160a01b0316610cff576101068054610c7e90614e91565b80601f0160208091040260200160405190810160405280929190818152602001828054610caa90614e91565b8015610cf55780601f10610ccc57610100808354040283529160200191610cf5565b820191905f5260205f20905b815481529060010190602001808311610cd857829003601f168201915b5050505050610bd8565b61010754604051636c55e19b60e01b8152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610d4c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bd89190810190614eff565b5f610d86610d8084610f6c565b83611f5a565b9392505050565b5f610d9782611f71565b600101546001600160401b031692915050565b5f610bd882610db884611f71565b611f8a565b5f610dc6611fa8565b805490915060ff600160401b82041615906001600160401b03165f81158015610dec5750825b90505f826001600160401b03166001148015610e075750303b155b905081158015610e15575080155b15610e335760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610e5d57845460ff60401b1916600160401b1785555b6102098a905561010480546001600160a01b0319166001600160a01b038b16179055610105610e8d888a83614f9b565b5061020a8690556040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a1610104546040516001600160a01b03918216918291908c16907fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff490610f04908d908d90615077565b60405180910390a3610f185f88835f611e4a565b50508315610f6057845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b5f610bd882610f7a84611f71565b611fd0565b610f898533612029565b610f968585858585612083565b5050505050565b5f610bd8610faa83610f6c565b5f9081526003602052604090205490565b5f80610fca84621000006120e3565b8054600160401b600160e01b031916600160401b6001600160a01b038716908102919091178255604051929450909250339184907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a450505050565b5f8061107161106c85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b611f71565b60018101549091506001600160401b03164210156110a0578054600160401b90046001600160a01b03166110a2565b5f5b949350505050565b5f806110be6110b885610f6c565b8461214c565b915091505b9250929050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101829052906110fd83611f71565b60018101546001600160401b0316602084018190529091505f6111208584611f8a565b6060850181905290506111338584611fd0565b60808501525f6111428261216f565b6001600160a01b0381166040870152905061115d8382612189565b859060028111156111705761117061489d565b908160028111156111835761118361489d565b8152505050505050919050565b6410000000006111a15f82336121bf565b6101066111af848683614f9b565b5061010780546001600160a01b0319166001600160a01b03841617905560405133907fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd5906112029087908790879061508a565b60405180910390a250505050565b606081518351146112465781518351604051635b05999160e01b8152600481019290925260248201526044015b60405180910390fd5b5f83516001600160401b0381111561126057611260614674565b604051908082528060200260200182016040528015611289578160200160208202803683370190505b5090505f5b84518110156112d7576020808202860101516112b290602080840287010151610b93565b8282815181106112c4576112c46150b5565b602090810291909101015260010161128e565b509392505050565b6112e76121f2565b6112f082612298565b6112fa8282612352565b5050565b5f611307612405565b505f8051602061583c83398151915290565b6101006113275f82336121bf565b61010480546001600160a01b0319166001600160a01b03851617905561010561135083826150c9565b50336001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff4846040516113949190614593565b60405180910390a3505050565b5f6113ab83611f71565b90505f6113b88483611f8a565b60018301549091506001600160401b0316428111611413576001600160401b03811615806113ed57506113eb823361244e565b155b1561140e5760405163311388dd60e21b81526004810183905260240161123d565b61142a565b61142a6114208685611fd0565b62010000336121bf565b806001600160401b0316846001600160401b0316101561147057604051633460a12d60e11b81526001600160401b0380831660048301528516602482015260440161123d565b60018301805467ffffffffffffffff19166001600160401b03861690811790915560405133919084907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a45050505050565b5f610d866114d284610f6c565b8361246a565b5f806114e383611f71565b6001810154909150610d86906001600160401b031661150a6115058685611f8a565b61216f565b612189565b333014611531573360405163d86ad9cf60e01b815260040161123d9190614660565b82811461155b57604051635b05999160e01b8152600481018490526024810182905260440161123d565b61156784848484612475565b50505050565b5f8061157883611f71565b90506115848382611f8a565b8314158061159f575060018101546001600160401b03164210155b6115b1576115ac8361216f565b610d86565b5f9392505050565b5f610d86610a2f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b5f610bd8600160781b8361164c565b5f610d866103f784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b5f82836116595f85612bf9565b16149392505050565b5f6110a261166f85610f6c565b8484612cbb565b6101045461010580545f926060926001600160a01b0390911691819061169b90614e91565b80601f01602080910402602001604051908101604052809291908181526020018280546116c790614e91565b80156117125780601f106116e957610100808354040283529160200191611712565b820191905f5260205f20905b8154815290600101906020018083116116f557829003601f168201915b50505050509050915091509091565b5f61172b87612cfe565b1561174957604051630811f43760e31b815260040160405180910390fd5b611757878787878787612e78565b979650505050505050565b5f610d8661042e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b60606117ae612e89565b905090565b5f806117c1836110006120e3565b6040519193509150339083907f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea8905f90a35f6117fc8361216f565b90506001600160a01b0381161561188a5761181981846001612f23565b815482905f9061182e9063ffffffff16615193565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff1661186b90615193565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff1916426001600160401b03161790555050565b6112fa338383612f77565b5f336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461193b5761193b63d86ad9cf60e01b336040516024016119049190614660565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613003565b828261194860e0896151b5565b6119539060406151cc565b8082101561198d576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261198d90613003565b5f61199a8688018861527a565b604051635d05f04960e01b81529091503090635d05f049906119c4908e908e9086906004016153b1565b5f604051808303815f87803b1580156119db575f80fd5b505af19250505080156119ec575060015b611a2e573d808015611a19576040519150601f19603f3d011682016040523d82523d5f602084013e611a1e565b606091505b50611a2881613003565b50611a3e565b5063bc197c8160e01b9350611a40565b505b50505098975050505050505050565b5f80611a5f8463010000006120e3565b600181018054600160401b600160e01b031916600160401b6001600160a01b03881690810291909117909155604051929450909250339184907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a450505050565b5f610bd88261216f565b5f611ae9611ada83610d8d565b6001600160401b031642101590565b611afe57611af961150583610daa565b610bd8565b5f92915050565b5f8083611b13828233613016565b610c535f8686600161304b565b5f6110a2611b2d85610f6c565b84846130b7565b5f6110a2611b4185610f6c565b84846130ce565b5f611b8783838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612cfe92505050565b611b95576115ac8383613107565b507f000000000000000000000000000000000000000000000000000000000000000092915050565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611c3757611c3763d86ad9cf60e01b336040516024016119049190614660565b828260e080821015611c75576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b179052611c7590613003565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f19909201910181611cad57905050905089825f81518110611cf557611cf56150b5565b6020908102919091010152611d0c878901896153f5565b815f81518110611d1e57611d1e6150b5565b6020908102919091010152604051635d05f04960e01b81523090635d05f04990611d4e9085908590600401615426565b5f604051808303815f87803b158015611d65575f80fd5b505af1925050508015611d76575060015b611db8573d808015611da3576040519150601f19603f3d011682016040523d82523d5f602084013e611da8565b606091505b50611db281613003565b50611dca565b5063f23a6e6160e01b9450611dcd9050565b50505b5050509695505050505050565b611de48533612029565b610f96858585858561317c565b5f6001600160e01b03198216630271189760e51b1480610bd85750610bd8826131eb565b5f611e2084836132b1565b905080198316156115675783838360405163d1a3b35560e01b815260040161123d9392919061544a565b5f835f03611e5957505f6110a2565b611e62846132d5565b6001600160a01b038316611e895760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611f4e575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616611ee98882600161331c565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a38415611f4257611f42888785858b613403565b600193505050506110a2565b505f9695505050505050565b5f80611f6684846110aa565b501515949350505050565b63ffffffff8116185f9081526101086020526040902090565b80545f9063ffffffff80851685186401000000009092041618610d86565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610bd8565b5f82611fdd575081610bd8565b6001820154610d869084906001600160401b031642101561200557835463ffffffff16612018565b83546120189063ffffffff166001615469565b63ffffffff82811690921891161890565b806001600160a01b0316826001600160a01b03161415801561205257506120508282611bbd565b155b156112fa5760405163711bec9160e11b81526001600160a01b0380831660048301528316602482015260440161123d565b6001600160a01b0384166120ac575f604051632bfa23e760e11b815260040161123d9190614660565b6001600160a01b0385166120d4575f604051626a0d4560e21b815260040161123d9190614660565b610f968585858585600161340c565b5f806120ee84611f71565b90506120fa8482611f8a565b60018201549092506001600160401b0316421061212d5760405163311388dd60e21b81526004810183905260240161123d565b6110c361213a8583611fd0565b84336121bf565b805160209091012090565b5f8061215783613463565b5f948552600360205260409094205484169492505050565b5f908152602081905260409020546001600160a01b031690565b5f6001600160401b03831642106121a157505f610bd8565b6001600160a01b0382166121b757506001610bd8565b506002610bd8565b6121ca838383611b20565b6121ed57828282604051634b27a13360e01b815260040161123d9392919061544a565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061227857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661226c5f8051602061583c833981519152546001600160a01b031690565b6001600160a01b031614155b156122965760405163703e46dd60e11b815260040160405180910390fd5b565b6001607c1b6122a85f82336121bf565b604051634b5bc65f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906396b78cbe906122f4908590600401614660565b602060405180830381865afa15801561230f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123339190615486565b6112fa5781604051630f74d7dd60e41b815260040161123d9190614660565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156123ac575060408051601f3d908101601f191682019092526123a9918101906154a1565b60015b6123cb5781604051634c9c8ce360e01b815260040161123d9190614660565b5f8051602061583c83398151915281146123fb57604051632a87526960e21b81526004810182905260240161123d565b6121ed838361347d565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146122965760405163703e46dd60e11b815260040160405180910390fd5b5f600161020a54165f14158015610d865750610d8683836134d2565b5f610d868383612bf9565b6102095430905f5b85811015612bf0575f858583818110612498576124986150b5565b90506020028101906124aa91906154b8565b6124b3906154d6565b60208101519091506001600160a01b03166124e1576040516349e27cff60e01b815260040160405180910390fd5b5f8888848181106124f4576124f46150b5565b8451805160209182012091029290920135925061251c905085825f9182526020526040902090565b821461253e5760405163edec356960e01b81526004810183905260240161123d565b6060830151604051630178fe3f60e01b8152600481018490525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156125aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125ce91906154e1565b92509250506125df82600116151590565b15612a5f576040821615801590612686575060405163020604bf60e21b8152600481018690525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063081812fc90602401602060405180830381865afa158015612656573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267a9190615528565b6001600160a01b031614155b156126a75760405163a4f0771360e01b81526004810186905260240161123d565b600882165f0361273157604051630c4b7b8560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631896f70a906126ff9088905f90600401615543565b5f604051808303815f87803b158015612716575f80fd5b505af1158015612728573d5f803e3d5ffd5b50505050612881565b604051630178b8bf60e01b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178b8bf90602401602060405180830381865afa158015612794573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127b89190615528565b92506001600160a01b038316158015906128585750604051630d76f7ed60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631aedefda90612819908690600401614660565b602060405180830381865afa158015612834573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128589190615486565b15612881577f000000000000000000000000000000000000000000000000000000000000000092505b604051637921219560e11b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526001606483015260a060848301525f60a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c4015f604051808303815f87803b158015612922575f80fd5b505af1158015612934573d5f803e3d5ffd5b505050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d84121a7f0000000000000000000000000000000000000000000000000000000000000000885f1c898e8c5f015161299b8a6134e0565b6040516024016129ae949392919061555a565b60408051601f198184030181529181526020820180516001600160e01b0316630aa1600d60e11b179052516001600160e01b031960e086901b1681526129f993929190600401615594565b6020604051808303815f875af1158015612a15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a399190615528565b9050612a58875f015188602001518387612a528861350e565b87613555565b5050612bdf565b6201000062030000831603612bc357604051630c4b7b8560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631896f70a90612abc9088905f90600401615543565b5f604051808303815f87803b158015612ad3575f80fd5b505af1158015612ae5573d5f803e3d5ffd5b5050604051636c64c90d60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063d8c9921a9150612b59908b9088907f00000000000000000000000000000000000000000000000000000000000000009060040161544a565b5f604051808303815f87803b158015612b70575f80fd5b505af1158015612b82573d5f803e3d5ffd5b50630110000061011160941b019250505062040000831615612baa5762010000600160901b01175b612a58875f015188602001518960400151878587613555565b604051630dff478560e11b81526004810186905260240161123d565b50505050505080600101905061247d565b50505050505050565b5f82612cb157610104546001600160a01b03168015801590612c9857506040516331ab054760e11b81526001600160a01b038216906363560a8e90612c4490610105906004016155ba565b602060405180830381865afa158015612c5f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c839190615528565b6001600160a01b0316836001600160a01b0316145b15612caf57612ca78482613565565b915050610bd8565b505b610d868383613565565b5f8383612cc9828233611e15565b85612ce757604051631850848b60e31b815260040160405180910390fd5b612cf48686866001611e4a565b9695505050505050565b805160208201205f905f612d1182610d8d565b6001600160401b03161115612d2857505f92915050565b610209545f908152602082905260408120604051630178fe3f60e01b8152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015612da1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dc591906154e1565b5091505062010000620300008216148015610c5357506040516302571be360e01b8152600481018390525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015612e40573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e649190615528565b6001600160a01b0316141595945050505050565b5f61175787878787878760016135da565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166320c38e2b612ec46102095490565b6040518263ffffffff1660e01b8152600401612ee291815260200190565b5f60405180830381865afa158015612efc573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526117ae9190810190614eff565b6001600160a01b038316612f4b575f604051626a0d4560e21b815260040161123d9190614660565b5f80612f578484613a62565b91509150610f96855f848460405180602001604052805f8152505f61340c565b6001600160a01b038216612f9f575f60405162ced3e160e81b815260040161123d9190614660565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611394565b61300c81613a8a565b9050805160208201fd5b5f6130218483613b44565b90508019831615611567578383836040516314c09c6360e31b815260040161123d9392919061544a565b5f613055846132d5565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611f4e575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690611ee9908990839061331c565b5f82836130c48685613b67565b1614949350505050565b5f83836130dc828233613016565b856130fa57604051631850848b60e31b815260040160405180910390fd5b612cf4868686600161304b565b5f8061314a61106c85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b60018101549091506001600160401b03164210156110a0576001810154600160401b90046001600160a01b03166110a2565b6001600160a01b0384166131a5575f604051632bfa23e760e11b815260040161123d9190614660565b6001600160a01b0385166131cd575f604051626a0d4560e21b815260040161123d9190614660565b5f806131d98585613a62565b91509150612bf087878484875f61340c565b5f6001600160e01b03198216636be50c6960e01b148061321b57506001600160e01b03198216632e112adb60e21b145b8061323657506001600160e01b031982166391b3c03760e01b145b8061325157506001600160e01b031982166337a9be3960e11b145b8061326c57506001600160e01b031982166331ab054760e11b145b8061328757506001600160e01b03198216630147d9fd60e61b145b806132a257506001600160e01b0319821663379ffb9360e11b145b80610bd85750610bd882613b84565b5f806132bd8484613ba8565b905083156132cb57806110a2565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561331957604051630153d96960e51b81526004810182905260240161123d565b50565b5f61332683613463565b90508115613398575f8481526003602052604090205461334890821619613bf1565b1561337057604051631f22ca6960e31b8152600481018590526024810184905260440161123d565b5f848152600360205260408120805485929061338d9084906151cc565b909155506115679050565b5f848152600360205260409020546133b39019821619613bf1565b156133db57604051631f80c19b60e01b8152600481018590526024810184905260440161123d565b5f84815260036020526040812080548592906133f8908490615644565b909155505050505050565b610f9685613c40565b61341886868686613d09565b6001600160a01b0385161561345b5780156134405761343b338787878787613dd0565b61345b565b60208481015190840151613458338989858589613edf565b50505b505050505050565b5f61346d826132d5565b50600181901b17600281901b1790565b61348682613fbd565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156134ca576121ed8282614017565b6112fa614080565b5f610d86620100008361164c565b5f6020821681036134ef576001175b62010000601160781b01176002821661350957608081901b175b919050565b5f620400008216156135205762010000175b600882165f03613531576301000000175b6002821661354057608081901b175b600482165f03613509576001609c1b17919050565b5f6117578787878787875f6135da565b5f613570838361409f565b90508215610bd8575f61358284611acd565b90506001600160a01b038116158015906135ae5750826001600160a01b0316816001600160a01b031614155b80156135bf57506135bf8184611bbd565b156135d3576135ce848261409f565b821791505b5092915050565b60405163bf53096960e01b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990613628908b90600401614593565b5f604051808303815f87803b15801561363f575f80fd5b505af1158015613651573d5f803e3d5ffd5b5050895160208b012091505f905061366882611f71565b90506136748282611f8a565b92505f6136808461216f565b60018301549091506001600160401b031642106136e85784156136a9576136a95f6001336121bf565b6001600160a01b038a161580156136bf57508615155b156136e3575f873360405163d1a3b35560e01b815260040161123d9392919061544a565b613779565b6001600160a01b03811615613712578a6040516337bd516960e21b815260040161123d9190614593565b6001600160a01b038a1661373b578a6040516307b03acf60e51b815260040161123d9190614593565b841561374d5761374d5f6010336121bf565b856001600160401b03165f0361376e5760018201546001600160401b031695505b640100000000871796505b6001600160a01b038a161561379a576001600160401b0386164210156137a6565b6001600160401b038616155b156137cf5760405163f1d446c360e01b81526001600160401b038716600482015260240161123d565b6001600160a01b03811615613867576137ea81856001612f23565b815482905f906137ff9063ffffffff16615193565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff1661383c90615193565b91906101000a81548163ffffffff021916908363ffffffff1602179055506138648483611f8a565b93505b60018201805483546001600160a01b03808d16600160401b908102600160401b600160e01b03199093169290921786558b81169091026001600160e01b03199092166001600160401b038a1617919091179091558a1661390d57336001600160a01b0316835f1b857f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88e8a604051613900929190615657565b60405180910390a46139c6565b336001600160a01b0316835f1b857f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8e8e8b60405161394e93929190615681565b60405180910390a46139718a85600160405180602001604052805f8152506140c6565b5f61397c8584611fd0565b90508061398b5761398b6156bc565b604051819086907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a36139c381898d5f611e4a565b50505b6001600160a01b03891615613a0d5760405133906001600160a01b038b169086907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a45b6001600160a01b03881615613a545760405133906001600160a01b038a169086907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a45b505050979650505050505050565b6040805160018082526020820194909452808201938452606081019290925260808201905291565b60605f8251118015613ab4575062461bcd60e51b613aa7836156d0565b6001600160e01b03191614155b15613b405762461bcd60e51b6f0aee4c2e0e0cac88ae4e4dee4747460f60831b613add8461410d565b604051602001613aee92919061571a565b60408051601f1981840301815290829052613b0b91602401614593565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b5f610d86613b528484613b67565b6001600160801b0319811660809190911c1790565b5f613b728383612bf9565b613b7c5f84612bf9565b179392505050565b5f6001600160e01b031982166347a296b160e11b1480610bd85750610bd882614175565b5f8215801590613bc857505f613bbd84611acd565b6001600160a01b0316145b15613bd457505f610bd8565b5f613bdf8484613b44565b90508315610d8657608081901c6110a2565b80197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef91909101167f888888888888888888888888888888888888888888888888888888888888888816151590565b8015613319575f613c5082611f71565b90505f613c5d8383611f8a565b90505f613c698261216f565b9050613c7781836001612f23565b82548390600490613c9590640100000000900463ffffffff16615193565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f613cbe8385611f8a565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3610f968282600160405180602001604052805f8152506140c6565b613d15848484846141df565b6001600160a01b03831615801590613d3557506001600160a01b03841615155b15611567575f5b8251811015610f96575f838281518110613d5857613d586150b5565b60200260200101519050613d71816001609c1b88611b20565b613d925780866040516372c7b6ad60e11b815260040161123d929190615543565b5f838381518110613da557613da56150b5565b60200260200101511115613dc757613dc7613dbf82610f6c565b87875f614397565b50600101613d3c565b6001600160a01b0384163b1561345b5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613e149089908990889088908890600401615735565b6020604051808303815f875af1925050508015613e4e575060408051601f3d908101601f19168201909252613e4b91810190615792565b60015b613eac573d808015613e7b576040519150601f19603f3d011682016040523d82523d5f602084013e613e80565b606091505b5080515f03613ea45784604051632bfa23e760e11b815260040161123d9190614660565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b14612bf05784604051632bfa23e760e11b815260040161123d9190614660565b6001600160a01b0384163b1561345b5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613f2390899089908890889088906004016157ad565b6020604051808303815f875af1925050508015613f5d575060408051601f3d908101601f19168201909252613f5a91810190615792565b60015b613f8a573d808015613e7b576040519150601f19603f3d011682016040523d82523d5f602084013e613e80565b6001600160e01b0319811663f23a6e6160e01b14612bf05784604051632bfa23e760e11b815260040161123d9190614660565b806001600160a01b03163b5f03613fe95780604051634c9c8ce360e01b815260040161123d9190614660565b5f8051602061583c83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161403391906157e6565b5f60405180830381855af49150503d805f811461406b576040519150601f19603f3d011682016040523d82523d5f602084013e614070565b606091505b5091509150610c538583836143d8565b34156122965760405163b398979f60e01b815260040160405180910390fd5b5f9182526002602090815260408084206001600160a01b0393909316845291905290205490565b6001600160a01b0384166140ef575f604051632bfa23e760e11b815260040161123d9190614660565b5f806140fb8585613a62565b9150915061345b5f878484875f61340c565b805160609060011b806001600160401b0381111561412d5761412d614674565b6040519080825280601f01601f191660200182016040528015614157576020820181803683370190505b509150602083810190830161416d828285614426565b505050919050565b5f6001600160e01b03198216636cdb3d1360e11b14806141a557506001600160e01b031982166331a9108f60e11b145b806141c057506001600160e01b031982166303a24d0760e21b145b80610bd857506301ffc9a760e01b6001600160e01b0319831614610bd8565b805182511461420e5781518151604051635b05999160e01b81526004810192909252602482015260440161123d565b5f5b82518110156142d15760208181028481018201519084019091015180156142c7575f828152602081905260409020546001600160a01b03908116908816811461427457875f83856040516303dee4c560e01b815260040161123d94939291906157f1565b600182111561429f5787600183856040516303dee4c560e01b815260040161123d94939291906157f1565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0388161790555b5050600101614210565b50815160010361433a576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050611567565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051614389929190615817565b60405180910390a450505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015610f96576143cb8582868561304b565b5061345b85828585611e4a565b6060826143e8576115ac82614489565b81511580156143ff57506001600160a01b0384163b155b1561441f5783604051639996b31560e01b815260040161123d9190614660565b5080610d86565b8181015b808310156115675783516101005b828510801561444657505f81115b1561447c5760031901600f82821c16600a8110614466578060570161446b565b806030015b905080865350600190940193614438565b505060208401935061442a565b8051156144995780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b6001600160a01b0381168114613319575f80fd5b5f80604083850312156144d7575f80fd5b82356144e2816144b2565b946020939093013593505050565b6001600160e01b031981168114613319575f80fd5b5f60208284031215614515575f80fd5b8135610d86816144f0565b5f8060408385031215614531575f80fd5b823591506020830135614543816144b2565b809150509250929050565b5f6020828403121561455e575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610d866020830184614565565b5f80604083850312156145b6575f80fd5b50508035926020909101359150565b5f8083601f8401126145d5575f80fd5b5081356001600160401b038111156145eb575f80fd5b6020830191508360208285010111156110c3575f80fd5b5f805f805f60808688031215614616575f80fd5b853594506020860135614628816144b2565b935060408601356001600160401b03811115614642575f80fd5b61464e888289016145c5565b96999598509660600135949350505050565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156146b0576146b0614674565b604052919050565b5f6001600160401b038211156146d0576146d0614674565b5060051b60200190565b5f82601f8301126146e9575f80fd5b813560206146fe6146f9836146b8565b614688565b8083825260208201915060208460051b87010193508684111561471f575f80fd5b602086015b8481101561473b5780358352918301918301614724565b509695505050505050565b5f6001600160401b0382111561475e5761475e614674565b50601f01601f191660200190565b5f82601f83011261477b575f80fd5b81356147896146f982614746565b81815284602083860101111561479d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a086880312156147cd575f80fd5b85356147d8816144b2565b945060208601356147e8816144b2565b935060408601356001600160401b0380821115614803575f80fd5b61480f89838a016146da565b94506060880135915080821115614824575f80fd5b61483089838a016146da565b93506080880135915080821115614845575f80fd5b506148528882890161476c565b9150509295509295909350565b5f8060208385031215614870575f80fd5b82356001600160401b03811115614885575f80fd5b614891858286016145c5565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600381106148cd57634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506148e38284516148b1565b6001600160401b03602084015116602083015260018060a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f60408486031215614934575f80fd5b83356001600160401b03811115614949575f80fd5b614955868287016145c5565b9094509250506020840135614969816144b2565b809150509250925092565b5f8060408385031215614985575f80fd5b82356001600160401b038082111561499b575f80fd5b818501915085601f8301126149ae575f80fd5b813560206149be6146f9836146b8565b82815260059290921b840181019181810190898411156149dc575f80fd5b948201945b83861015614a035785356149f4816144b2565b825294820194908201906149e1565b96505086013592505080821115614a18575f80fd5b50614a25858286016146da565b9150509250929050565b5f815180845260208085019450602084015f5b83811015614a5e57815187529582019590820190600101614a42565b509495945050505050565b602081525f610d866020830184614a2f565b5f8060408385031215614a8c575f80fd5b8235614a97816144b2565b915060208301356001600160401b03811115614ab1575f80fd5b614a258582860161476c565b6001600160401b0381168114613319575f80fd5b5f8060408385031215614ae2575f80fd5b82359150602083013561454381614abd565b60208101610bd882846148b1565b5f8083601f840112614b12575f80fd5b5081356001600160401b03811115614b28575f80fd5b6020830191508360208260051b85010111156110c3575f80fd5b5f805f8060408587031215614b55575f80fd5b84356001600160401b0380821115614b6b575f80fd5b614b7788838901614b02565b90965094506020870135915080821115614b8f575f80fd5b50614b9c87828801614b02565b95989497509550505050565b5f60208284031215614bb8575f80fd5b8135610d86816144b2565b5f805f60608486031215614bd5575f80fd5b83359250602084013591506040840135614969816144b2565b6001600160a01b03831681526040602082018190525f906110a290830184614565565b5f805f805f8060c08789031215614c26575f80fd5b86356001600160401b03811115614c3b575f80fd5b614c4789828a0161476c565b9650506020870135614c58816144b2565b94506040870135614c68816144b2565b93506060870135614c78816144b2565b92506080870135915060a0870135614c8f81614abd565b809150509295509295509295565b8015158114613319575f80fd5b5f8060408385031215614cbb575f80fd5b8235614cc6816144b2565b9150602083013561454381614c9d565b5f805f805f805f8060a0898b031215614ced575f80fd5b8835614cf8816144b2565b97506020890135614d08816144b2565b965060408901356001600160401b0380821115614d23575f80fd5b614d2f8c838d01614b02565b909850965060608b0135915080821115614d47575f80fd5b614d538c838d01614b02565b909650945060808b0135915080821115614d6b575f80fd5b50614d788b828c016145c5565b999c989b5096995094979396929594505050565b5f8060408385031215614d9d575f80fd5b8235614da8816144b2565b91506020830135614543816144b2565b5f805f805f8060a08789031215614dcd575f80fd5b8635614dd8816144b2565b95506020870135614de8816144b2565b9450604087013593506060870135925060808701356001600160401b03811115614e10575f80fd5b614e1c89828a016145c5565b979a9699509497509295939492505050565b5f805f805f60a08688031215614e42575f80fd5b8535614e4d816144b2565b94506020860135614e5d816144b2565b9350604086013592506060860135915060808601356001600160401b03811115614e85575f80fd5b6148528882890161476c565b600181811c90821680614ea557607f821691505b602082108103614ec357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f614ed66146f984614746565b9050828152838383011115614ee9575f80fd5b8282602083015e5f602084830101529392505050565b5f60208284031215614f0f575f80fd5b81516001600160401b03811115614f24575f80fd5b8201601f81018413614f34575f80fd5b6110a284825160208401614ec9565b601f8211156121ed57805f5260205f20601f840160051c81016020851015614f685750805b601f840160051c820191505b81811015610f96575f8155600101614f74565b5f19600383901b1c191660019190911b1790565b6001600160401b03831115614fb257614fb2614674565b614fc683614fc08354614e91565b83614f43565b5f601f841160018114614ff2575f8515614fe05750838201355b614fea8682614f87565b845550610f96565b5f83815260208120601f198716915b828110156150215786850135825560209485019460019092019101615001565b508682101561503d575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f6110a260208301848661504f565b604081525f61509d60408301858761504f565b905060018060a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b81516001600160401b038111156150e2576150e2614674565b6150f6816150f08454614e91565b84614f43565b602080601f831160018114615124575f84156151125750858301515b61511c8582614f87565b86555061345b565b5f85815260208120601f198616915b8281101561515257888601518255948401946001909101908401615133565b508582101561516f57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036151ab576151ab61517f565b6001019392505050565b8082028115828204841417610bd857610bd861517f565b80820180821115610bd857610bd861517f565b5f608082840312156151ef575f80fd5b604051608081016001600160401b03828210818311171561521257615212614674565b816040528293508435915080821115615229575f80fd5b506152368582860161476c565b8252506020830135615247816144b2565b6020820152604083013561525a816144b2565b6040820152606083013561526d816144b2565b6060919091015292915050565b5f602080838503121561528b575f80fd5b82356001600160401b03808211156152a1575f80fd5b818501915085601f8301126152b4575f80fd5b81356152c26146f9826146b8565b81815260059190911b830184019084810190888311156152e0575f80fd5b8585015b83811015615316578035858111156152fa575f80fd5b6153088b89838a01016151df565b8452509186019186016152e4565b5098975050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b848110156153a457601f1986840301895281516080815181865261536482870182614565565b838801516001600160a01b03908116888a01526040808601518216908901526060948501511693909601929092525050978301979083019060010161533e565b5090979650505050505050565b604080825281018390525f6001600160fb1b038411156153cf575f80fd5b8360051b80866060850137820182810360609081016020850152612cf490820185615323565b5f60208284031215615405575f80fd5b81356001600160401b0381111561541a575f80fd5b6110a2848285016151df565b604081525f6154386040830185614a2f565b8281036020840152610c538185615323565b92835260208301919091526001600160a01b0316604082015260600190565b63ffffffff8181168382160190808211156135d3576135d361517f565b5f60208284031215615496575f80fd5b8151610d8681614c9d565b5f602082840312156154b1575f80fd5b5051919050565b5f8235607e198336030181126154cc575f80fd5b9190910192915050565b5f610bd836836151df565b5f805f606084860312156154f3575f80fd5b83516154fe816144b2565b602085015190935063ffffffff81168114615517575f80fd5b604085015190925061496981614abd565b5f60208284031215615538575f80fd5b8151610d86816144b2565b9182526001600160a01b0316602082015260400190565b8481526001600160a01b03841660208201526080604082018190525f9061558390830185614565565b905082606083015295945050505050565b60018060a01b0384168152826020820152606060408201525f610c536060830184614565565b5f60208083525f84546155cc81614e91565b806020870152604060018084165f81146155ed576001811461560957615636565b60ff19851660408a0152604084151560051b8a01019550615636565b895f5260205f205f5b8581101561562d5781548b8201860152908301908801615612565b8a016040019650505b509398975050505050505050565b81810381811115610bd857610bd861517f565b604081525f6156696040830185614565565b90506001600160401b03831660208301529392505050565b606081525f6156936060830186614565565b6001600160a01b03949094166020830152506001600160401b0391909116604090910152919050565b634e487b7160e01b5f52600160045260245ffd5b805160208201516001600160e01b0319808216929190600483101561416d5760049290920360031b82901b161692915050565b5f81518060208401855e5f93019283525090919050565b6001600160801b0319831681525f6110a26010830184615703565b6001600160a01b0386811682528516602082015260a0604082018190525f9061576090830186614a2f565b82810360608401526157728186614a2f565b905082810360808401526157868185614565565b98975050505050505050565b5f602082840312156157a2575f80fd5b8151610d86816144f0565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f9061175790830184614565565b5f610d868284615703565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b604081525f6158296040830185614a2f565b8281036020840152610c538185614a2f56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220bb51201f914d69564c58c14c847a781374c2ee205be2913bbb1bf12ecfca285a64736f6c634300081900338888888888888888888888888888888888888888888888888888888888888888eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef", + "deployedBytecode": "0x60806040526004361061030e575f3560e01c80635d05f04911610197578063ad3cb1cc116100df578063dfa70d8b1161008e578063dfa70d8b14610a72578063e4ae7d7714610a91578063e985e9c514610ab0578063f23a6e6114610acf578063f242432a14610aee578063f41a143d14610b0d578063f923b68514610b2d578063ffeb4a3014610b60575f80fd5b8063ad3cb1cc1461096f578063bc197c811461099f578063bc7b6d62146109d7578063bd242bcb146109f6578063c41a360a14610a15578063ce156e8214610a34578063d3bf89b114610a53575f80fd5b80637c300586116101465780637c3005861461086b57806380f760211461088a57806385f3e643146108ac57806391b3c037146108cb5780639b224b1d146108ea5780639dbba19d146108fe578063a02b161e14610931578063a22cb46514610950575f80fd5b80635d05f0491461079c5780636352211e146107bb57806363560a8e146107da5780636e7a2116146107f95780636f3ff7261461080e5780636f537c721461082d578063781ef8db1461084c575f80fd5b806335af62161161025a5780634f1ef286116102095780634f1ef2861461068657806352d1902d146106995780635357263f146106ad578063547c9d2d146106cc5780635569f33d146106ff5780635adf47241461071e5780635c1a6b681461073d5780635c622a0e14610770575f80fd5b806335af6216146105565780633634f9111461057557806344c9af28146105a957806348688f95146105d55780634b2dc431146105f45780634b30228c146106275780634e1273f41461065a575f80fd5b80631542c01a116102c15780631542c01a1461043357806318ad9b7114610454578063192cf07d146104945780631c3fc3eb146104c75780631e8fca2d146104da5780632eb2c2d6146104f95780632f27fa2414610518578063341ec55914610537575f80fd5b8062fdd58e1461031257806301ffc9a714610344578063072d5d77146103735780630e89341c1461039257806311b8e00a146103be57806313c72608146103dd57806314ff5ea314610414575b5f80fd5b34801561031d575f80fd5b5061033161032c3660046144c6565b610b93565b6040519081526020015b60405180910390f35b34801561034f575f80fd5b5061036361035e366004614505565b610bde565b604051901515815260200161033b565b34801561037e575f80fd5b5061036361038d366004614520565b610c38565b34801561039d575f80fd5b506103b16103ac36600461454e565b610c5c565b60405161033b9190614593565b3480156103c9575f80fd5b506103636103d83660046145a5565b610d73565b3480156103e8575f80fd5b506103fc6103f736600461454e565b610d8d565b6040516001600160401b03909116815260200161033b565b34801561041f575f80fd5b5061033161042e36600461454e565b610daa565b34801561043e575f80fd5b5061045261044d366004614602565b610dbd565b005b34801561045f575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b60405161033b9190614660565b34801561049f575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d2575f80fd5b506103315f81565b3480156104e5575f80fd5b506103316104f436600461454e565b610f6c565b348015610504575f80fd5b506104526105133660046147b9565b610f7f565b348015610523575f80fd5b5061033161053236600461454e565b610f9d565b348015610542575f80fd5b50610452610551366004614520565b610fbb565b348015610561575f80fd5b5061048761057036600461485f565b611029565b348015610580575f80fd5b5061059461058f3660046145a5565b6110aa565b6040805192835260208301919091520161033b565b3480156105b4575f80fd5b506105c86105c336600461454e565b6110ca565b60405161033b91906148d1565b3480156105e0575f80fd5b506104526105ef366004614922565b611190565b3480156105ff575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b348015610632575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b348015610665575f80fd5b50610679610674366004614974565b611210565b60405161033b9190614a69565b610452610694366004614a7b565b6112df565b3480156106a4575f80fd5b506103316112fe565b3480156106b8575f80fd5b506104526106c7366004614a7b565b611319565b3480156106d7575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b34801561070a575f80fd5b50610452610719366004614ad1565b6113a1565b348015610729575f80fd5b50610331610738366004614520565b6114c5565b348015610748575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b34801561077b575f80fd5b5061078f61078a36600461454e565b6114d8565b60405161033b9190614af4565b3480156107a7575f80fd5b506104526107b6366004614b42565b61150f565b3480156107c6575f80fd5b506104876107d536600461454e565b61156d565b3480156107e5575f80fd5b506104876107f436600461485f565b6115b9565b348015610804575f80fd5b5061020954610331565b348015610819575f80fd5b50610363610828366004614ba8565b6115fb565b348015610838575f80fd5b506103fc61084736600461485f565b61160a565b348015610857575f80fd5b50610363610866366004614520565b61164c565b348015610876575f80fd5b50610363610885366004614bc3565b611662565b348015610895575f80fd5b5061089e611676565b60405161033b929190614bee565b3480156108b7575f80fd5b506103316108c6366004614c11565b611721565b3480156108d6575f80fd5b506103316108e536600461485f565b611762565b3480156108f5575f80fd5b506103b16117a4565b348015610909575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b34801561093c575f80fd5b5061045261094b36600461454e565b6117b3565b34801561095b575f80fd5b5061045261096a366004614caa565b6118ac565b34801561097a575f80fd5b506103b1604051806040016040528060058152602001640352e302e360dc1b81525081565b3480156109aa575f80fd5b506109be6109b9366004614cd6565b6118b7565b6040516001600160e01b0319909116815260200161033b565b3480156109e2575f80fd5b506104526109f1366004614520565b611a4f565b348015610a01575f80fd5b50610487610a1036600461454e565b611ac3565b348015610a20575f80fd5b50610487610a2f36600461454e565b611acd565b348015610a3f575f80fd5b50610363610a4e366004614520565b611b05565b348015610a5e575f80fd5b50610363610a6d366004614bc3565b611b20565b348015610a7d575f80fd5b50610363610a8c366004614bc3565b611b34565b348015610a9c575f80fd5b50610487610aab36600461485f565b611b48565b348015610abb575f80fd5b50610363610aca366004614d8c565b611bbd565b348015610ada575f80fd5b506109be610ae9366004614db8565b611bea565b348015610af9575f80fd5b50610452610b08366004614e2e565b611dda565b348015610b18575f80fd5b50610363610b27366004614ba8565b50600190565b348015610b38575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b348015610b6b575f80fd5b506104877f000000000000000000000000000000000000000000000000000000000000000081565b5f6001600160a01b03831615801590610bc55750826001600160a01b0316610bba8361156d565b6001600160a01b0316145b610bcf575f610bd2565b60015b60ff1690505b92915050565b5f63e01aaa1160e01b6001600160e01b031983161480610c0e575063b0f3d36760e01b6001600160e01b03198316145b80610c29575063f41a143d60e01b6001600160e01b03198316145b80610bd85750610bd882611df1565b5f8083610c46828233611e15565b610c535f86866001611e4a565b95945050505050565b610107546060906001600160a01b0316610cff576101068054610c7e90614e91565b80601f0160208091040260200160405190810160405280929190818152602001828054610caa90614e91565b8015610cf55780601f10610ccc57610100808354040283529160200191610cf5565b820191905f5260205f20905b815481529060010190602001808311610cd857829003601f168201915b5050505050610bd8565b61010754604051636c55e19b60e01b8152306004820152602481018490526001600160a01b0390911690636c55e19b906044015f60405180830381865afa158015610d4c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bd89190810190614eff565b5f610d86610d8084610f6c565b83611f5a565b9392505050565b5f610d9782611f71565b600101546001600160401b031692915050565b5f610bd882610db884611f71565b611f8a565b5f610dc6611fa8565b805490915060ff600160401b82041615906001600160401b03165f81158015610dec5750825b90505f826001600160401b03166001148015610e075750303b155b905081158015610e15575080155b15610e335760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610e5d57845460ff60401b1916600160401b1785555b6102098a905561010480546001600160a01b0319166001600160a01b038b16179055610105610e8d888a83614f9b565b5061020a8690556040517fce2f8c55f0f6fbc489417a09291281b739419d412c063df417ab075e6f052687905f90a1610104546040516001600160a01b03918216918291908c16907fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff490610f04908d908d90615077565b60405180910390a3610f185f88835f611e4a565b50508315610f6057845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050505050565b5f610bd882610f7a84611f71565b611fd0565b610f898533612029565b610f968585858585612083565b5050505050565b5f610bd8610faa83610f6c565b5f9081526003602052604090205490565b5f80610fca84621000006120e3565b8054600160401b600160e01b031916600160401b6001600160a01b038716908102919091178255604051929450909250339184907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a450505050565b5f8061107161106c85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b611f71565b60018101549091506001600160401b03164210156110a0578054600160401b90046001600160a01b03166110a2565b5f5b949350505050565b5f806110be6110b885610f6c565b8461214c565b915091505b9250929050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101829052906110fd83611f71565b60018101546001600160401b0316602084018190529091505f6111208584611f8a565b6060850181905290506111338584611fd0565b60808501525f6111428261216f565b6001600160a01b0381166040870152905061115d8382612189565b859060028111156111705761117061489d565b908160028111156111835761118361489d565b8152505050505050919050565b6410000000006111a15f82336121bf565b6101066111af848683614f9b565b5061010780546001600160a01b0319166001600160a01b03841617905560405133907fdf7e6d8d00864b80de2e2154ae6ccd74c37a89c700f024bda1d74d03406aafd5906112029087908790879061508a565b60405180910390a250505050565b606081518351146112465781518351604051635b05999160e01b8152600481019290925260248201526044015b60405180910390fd5b5f83516001600160401b0381111561126057611260614674565b604051908082528060200260200182016040528015611289578160200160208202803683370190505b5090505f5b84518110156112d7576020808202860101516112b290602080840287010151610b93565b8282815181106112c4576112c46150b5565b602090810291909101015260010161128e565b509392505050565b6112e76121f2565b6112f082612298565b6112fa8282612352565b5050565b5f611307612405565b505f8051602061583c83398151915290565b6101006113275f82336121bf565b61010480546001600160a01b0319166001600160a01b03851617905561010561135083826150c9565b50336001600160a01b0316836001600160a01b03167fe49f02c945e0ee4a8d961a371289bd054aa21d9ca1b73250ffd4880eb708cff4846040516113949190614593565b60405180910390a3505050565b5f6113ab83611f71565b90505f6113b88483611f8a565b60018301549091506001600160401b0316428111611413576001600160401b03811615806113ed57506113eb823361244e565b155b1561140e5760405163311388dd60e21b81526004810183905260240161123d565b61142a565b61142a6114208685611fd0565b62010000336121bf565b806001600160401b0316846001600160401b0316101561147057604051633460a12d60e11b81526001600160401b0380831660048301528516602482015260440161123d565b60018301805467ffffffffffffffff19166001600160401b03861690811790915560405133919084907f3260962d42d8f7ae0af25cbfdb2983c214a859cfa2ac6df8ea29b534c267d429905f90a45050505050565b5f610d866114d284610f6c565b8361246a565b5f806114e383611f71565b6001810154909150610d86906001600160401b031661150a6115058685611f8a565b61216f565b612189565b333014611531573360405163d86ad9cf60e01b815260040161123d9190614660565b82811461155b57604051635b05999160e01b8152600481018490526024810182905260440161123d565b61156784848484612475565b50505050565b5f8061157883611f71565b90506115848382611f8a565b8314158061159f575060018101546001600160401b03164210155b6115b1576115ac8361216f565b610d86565b5f9392505050565b5f610d86610a2f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b5f610bd8600160781b8361164c565b5f610d866103f784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b5f82836116595f85612bf9565b16149392505050565b5f6110a261166f85610f6c565b8484612cbb565b6101045461010580545f926060926001600160a01b0390911691819061169b90614e91565b80601f01602080910402602001604051908101604052809291908181526020018280546116c790614e91565b80156117125780601f106116e957610100808354040283529160200191611712565b820191905f5260205f20905b8154815290600101906020018083116116f557829003601f168201915b50505050509050915091509091565b5f61172b87612cfe565b1561174957604051630811f43760e31b815260040160405180910390fd5b611757878787878787612e78565b979650505050505050565b5f610d8661042e84848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b60606117ae612e89565b905090565b5f806117c1836110006120e3565b6040519193509150339083907f5293e83951c7b759c1ef192ceed240dc2caa652e29ddbd95cafe1d88e5a9cea8905f90a35f6117fc8361216f565b90506001600160a01b0381161561188a5761181981846001612f23565b815482905f9061182e9063ffffffff16615193565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff1661186b90615193565b91906101000a81548163ffffffff021916908363ffffffff1602179055505b50600101805467ffffffffffffffff1916426001600160401b03161790555050565b6112fa338383612f77565b5f336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461193b5761193b63d86ad9cf60e01b336040516024016119049190614660565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613003565b828261194860e0896151b5565b6119539060406151cc565b8082101561198d576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b17905261198d90613003565b5f61199a8688018861527a565b604051635d05f04960e01b81529091503090635d05f049906119c4908e908e9086906004016153b1565b5f604051808303815f87803b1580156119db575f80fd5b505af19250505080156119ec575060015b611a2e573d808015611a19576040519150601f19603f3d011682016040523d82523d5f602084013e611a1e565b606091505b50611a2881613003565b50611a3e565b5063bc197c8160e01b9350611a40565b505b50505098975050505050505050565b5f80611a5f8463010000006120e3565b600181018054600160401b600160e01b031916600160401b6001600160a01b03881690810291909117909155604051929450909250339184907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a450505050565b5f610bd88261216f565b5f611ae9611ada83610d8d565b6001600160401b031642101590565b611afe57611af961150583610daa565b610bd8565b5f92915050565b5f8083611b13828233613016565b610c535f8686600161304b565b5f6110a2611b2d85610f6c565b84846130b7565b5f6110a2611b4185610f6c565b84846130ce565b5f611b8783838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612cfe92505050565b611b95576115ac8383613107565b507f000000000000000000000000000000000000000000000000000000000000000092915050565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205460ff1690565b5f336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611c3757611c3763d86ad9cf60e01b336040516024016119049190614660565b828260e080821015611c75576040805160048152602481019091526020810180516001600160e01b0316635cb045db60e01b179052611c7590613003565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f929150602082015b6040805160808101825260608082525f60208084018290529383018190529082015282525f19909201910181611cad57905050905089825f81518110611cf557611cf56150b5565b6020908102919091010152611d0c878901896153f5565b815f81518110611d1e57611d1e6150b5565b6020908102919091010152604051635d05f04960e01b81523090635d05f04990611d4e9085908590600401615426565b5f604051808303815f87803b158015611d65575f80fd5b505af1925050508015611d76575060015b611db8573d808015611da3576040519150601f19603f3d011682016040523d82523d5f602084013e611da8565b606091505b50611db281613003565b50611dca565b5063f23a6e6160e01b9450611dcd9050565b50505b5050509695505050505050565b611de48533612029565b610f96858585858561317c565b5f6001600160e01b03198216630271189760e51b1480610bd85750610bd8826131eb565b5f611e2084836132b1565b905080198316156115675783838360405163d1a3b35560e01b815260040161123d9392919061544a565b5f835f03611e5957505f6110a2565b611e62846132d5565b6001600160a01b038316611e895760405163761fe2c960e11b815260040160405180910390fd5b5f8581526002602090815260408083206001600160a01b0387168452909152902054848117808214611f4e575f8781526002602090815260408083206001600160a01b0389168452909152902081905581198616611ee98882600161331c565b60408051848152602081018490526001600160a01b038816918a917f0d35bf721a39b614de00ca5038e1deb0cb0c69a278645e83405a7226cf80ba3c910160405180910390a38415611f4257611f42888785858b613403565b600193505050506110a2565b505f9695505050505050565b5f80611f6684846110aa565b501515949350505050565b63ffffffff8116185f9081526101086020526040902090565b80545f9063ffffffff80851685186401000000009092041618610d86565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610bd8565b5f82611fdd575081610bd8565b6001820154610d869084906001600160401b031642101561200557835463ffffffff16612018565b83546120189063ffffffff166001615469565b63ffffffff82811690921891161890565b806001600160a01b0316826001600160a01b03161415801561205257506120508282611bbd565b155b156112fa5760405163711bec9160e11b81526001600160a01b0380831660048301528316602482015260440161123d565b6001600160a01b0384166120ac575f604051632bfa23e760e11b815260040161123d9190614660565b6001600160a01b0385166120d4575f604051626a0d4560e21b815260040161123d9190614660565b610f968585858585600161340c565b5f806120ee84611f71565b90506120fa8482611f8a565b60018201549092506001600160401b0316421061212d5760405163311388dd60e21b81526004810183905260240161123d565b6110c361213a8583611fd0565b84336121bf565b805160209091012090565b5f8061215783613463565b5f948552600360205260409094205484169492505050565b5f908152602081905260409020546001600160a01b031690565b5f6001600160401b03831642106121a157505f610bd8565b6001600160a01b0382166121b757506001610bd8565b506002610bd8565b6121ca838383611b20565b6121ed57828282604051634b27a13360e01b815260040161123d9392919061544a565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061227857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661226c5f8051602061583c833981519152546001600160a01b031690565b6001600160a01b031614155b156122965760405163703e46dd60e11b815260040160405180910390fd5b565b6001607c1b6122a85f82336121bf565b604051634b5bc65f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906396b78cbe906122f4908590600401614660565b602060405180830381865afa15801561230f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123339190615486565b6112fa5781604051630f74d7dd60e41b815260040161123d9190614660565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156123ac575060408051601f3d908101601f191682019092526123a9918101906154a1565b60015b6123cb5781604051634c9c8ce360e01b815260040161123d9190614660565b5f8051602061583c83398151915281146123fb57604051632a87526960e21b81526004810182905260240161123d565b6121ed838361347d565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146122965760405163703e46dd60e11b815260040160405180910390fd5b5f600161020a54165f14158015610d865750610d8683836134d2565b5f610d868383612bf9565b6102095430905f5b85811015612bf0575f858583818110612498576124986150b5565b90506020028101906124aa91906154b8565b6124b3906154d6565b60208101519091506001600160a01b03166124e1576040516349e27cff60e01b815260040160405180910390fd5b5f8888848181106124f4576124f46150b5565b8451805160209182012091029290920135925061251c905085825f9182526020526040902090565b821461253e5760405163edec356960e01b81526004810183905260240161123d565b6060830151604051630178fe3f60e01b8152600481018490525f9081907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa1580156125aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125ce91906154e1565b92509250506125df82600116151590565b15612a5f576040821615801590612686575060405163020604bf60e21b8152600481018690525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063081812fc90602401602060405180830381865afa158015612656573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267a9190615528565b6001600160a01b031614155b156126a75760405163a4f0771360e01b81526004810186905260240161123d565b600882165f0361273157604051630c4b7b8560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631896f70a906126ff9088905f90600401615543565b5f604051808303815f87803b158015612716575f80fd5b505af1158015612728573d5f803e3d5ffd5b50505050612881565b604051630178b8bf60e01b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178b8bf90602401602060405180830381865afa158015612794573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127b89190615528565b92506001600160a01b038316158015906128585750604051630d76f7ed60e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631aedefda90612819908690600401614660565b602060405180830381865afa158015612834573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128589190615486565b15612881577f000000000000000000000000000000000000000000000000000000000000000092505b604051637921219560e11b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152604482018790526001606483015260a060848301525f60a48301527f0000000000000000000000000000000000000000000000000000000000000000169063f242432a9060c4015f604051808303815f87803b158015612922575f80fd5b505af1158015612934573d5f803e3d5ffd5b505050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d84121a7f0000000000000000000000000000000000000000000000000000000000000000885f1c898e8c5f015161299b8a6134e0565b6040516024016129ae949392919061555a565b60408051601f198184030181529181526020820180516001600160e01b0316630aa1600d60e11b179052516001600160e01b031960e086901b1681526129f993929190600401615594565b6020604051808303815f875af1158015612a15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a399190615528565b9050612a58875f015188602001518387612a528861350e565b87613555565b5050612bdf565b6201000062030000831603612bc357604051630c4b7b8560e11b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631896f70a90612abc9088905f90600401615543565b5f604051808303815f87803b158015612ad3575f80fd5b505af1158015612ae5573d5f803e3d5ffd5b5050604051636c64c90d60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063d8c9921a9150612b59908b9088907f00000000000000000000000000000000000000000000000000000000000000009060040161544a565b5f604051808303815f87803b158015612b70575f80fd5b505af1158015612b82573d5f803e3d5ffd5b50630110000061011160941b019250505062040000831615612baa5762010000600160901b01175b612a58875f015188602001518960400151878587613555565b604051630dff478560e11b81526004810186905260240161123d565b50505050505080600101905061247d565b50505050505050565b5f82612cb157610104546001600160a01b03168015801590612c9857506040516331ab054760e11b81526001600160a01b038216906363560a8e90612c4490610105906004016155ba565b602060405180830381865afa158015612c5f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c839190615528565b6001600160a01b0316836001600160a01b0316145b15612caf57612ca78482613565565b915050610bd8565b505b610d868383613565565b5f8383612cc9828233611e15565b85612ce757604051631850848b60e31b815260040160405180910390fd5b612cf48686866001611e4a565b9695505050505050565b805160208201205f905f612d1182610d8d565b6001600160401b03161115612d2857505f92915050565b610209545f908152602082905260408120604051630178fe3f60e01b8152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630178fe3f90602401606060405180830381865afa158015612da1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dc591906154e1565b5091505062010000620300008216148015610c5357506040516302571be360e01b8152600481018390525f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906302571be390602401602060405180830381865afa158015612e40573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e649190615528565b6001600160a01b0316141595945050505050565b5f61175787878787878760016135da565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166320c38e2b612ec46102095490565b6040518263ffffffff1660e01b8152600401612ee291815260200190565b5f60405180830381865afa158015612efc573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526117ae9190810190614eff565b6001600160a01b038316612f4b575f604051626a0d4560e21b815260040161123d9190614660565b5f80612f578484613a62565b91509150610f96855f848460405180602001604052805f8152505f61340c565b6001600160a01b038216612f9f575f60405162ced3e160e81b815260040161123d9190614660565b6001600160a01b038381165f81815260016020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c319101611394565b61300c81613a8a565b9050805160208201fd5b5f6130218483613b44565b90508019831615611567578383836040516314c09c6360e31b815260040161123d9392919061544a565b5f613055846132d5565b5f8581526002602090815260408083206001600160a01b038716845290915290205484198116808214611f4e575f8781526002602090815260408083206001600160a01b0389168452909152812082905586831690611ee9908990839061331c565b5f82836130c48685613b67565b1614949350505050565b5f83836130dc828233613016565b856130fa57604051631850848b60e31b815260040160405180910390fd5b612cf4868686600161304b565b5f8061314a61106c85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061214192505050565b60018101549091506001600160401b03164210156110a0576001810154600160401b90046001600160a01b03166110a2565b6001600160a01b0384166131a5575f604051632bfa23e760e11b815260040161123d9190614660565b6001600160a01b0385166131cd575f604051626a0d4560e21b815260040161123d9190614660565b5f806131d98585613a62565b91509150612bf087878484875f61340c565b5f6001600160e01b03198216636be50c6960e01b148061321b57506001600160e01b03198216632e112adb60e21b145b8061323657506001600160e01b031982166391b3c03760e01b145b8061325157506001600160e01b031982166337a9be3960e11b145b8061326c57506001600160e01b031982166331ab054760e11b145b8061328757506001600160e01b03198216630147d9fd60e61b145b806132a257506001600160e01b0319821663379ffb9360e11b145b80610bd85750610bd882613b84565b5f806132bd8484613ba8565b905083156132cb57806110a2565b60801c9392505050565b7feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81161561331957604051630153d96960e51b81526004810182905260240161123d565b50565b5f61332683613463565b90508115613398575f8481526003602052604090205461334890821619613bf1565b1561337057604051631f22ca6960e31b8152600481018590526024810184905260440161123d565b5f848152600360205260408120805485929061338d9084906151cc565b909155506115679050565b5f848152600360205260409020546133b39019821619613bf1565b156133db57604051631f80c19b60e01b8152600481018590526024810184905260440161123d565b5f84815260036020526040812080548592906133f8908490615644565b909155505050505050565b610f9685613c40565b61341886868686613d09565b6001600160a01b0385161561345b5780156134405761343b338787878787613dd0565b61345b565b60208481015190840151613458338989858589613edf565b50505b505050505050565b5f61346d826132d5565b50600181901b17600281901b1790565b61348682613fbd565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156134ca576121ed8282614017565b6112fa614080565b5f610d86620100008361164c565b5f6020821681036134ef576001175b62010000601160781b01176002821661350957608081901b175b919050565b5f620400008216156135205762010000175b600882165f03613531576301000000175b6002821661354057608081901b175b600482165f03613509576001609c1b17919050565b5f6117578787878787875f6135da565b5f613570838361409f565b90508215610bd8575f61358284611acd565b90506001600160a01b038116158015906135ae5750826001600160a01b0316816001600160a01b031614155b80156135bf57506135bf8184611bbd565b156135d3576135ce848261409f565b821791505b5092915050565b60405163bf53096960e01b81525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bf53096990613628908b90600401614593565b5f604051808303815f87803b15801561363f575f80fd5b505af1158015613651573d5f803e3d5ffd5b5050895160208b012091505f905061366882611f71565b90506136748282611f8a565b92505f6136808461216f565b60018301549091506001600160401b031642106136e85784156136a9576136a95f6001336121bf565b6001600160a01b038a161580156136bf57508615155b156136e3575f873360405163d1a3b35560e01b815260040161123d9392919061544a565b613779565b6001600160a01b03811615613712578a6040516337bd516960e21b815260040161123d9190614593565b6001600160a01b038a1661373b578a6040516307b03acf60e51b815260040161123d9190614593565b841561374d5761374d5f6010336121bf565b856001600160401b03165f0361376e5760018201546001600160401b031695505b640100000000871796505b6001600160a01b038a161561379a576001600160401b0386164210156137a6565b6001600160401b038616155b156137cf5760405163f1d446c360e01b81526001600160401b038716600482015260240161123d565b6001600160a01b03811615613867576137ea81856001612f23565b815482905f906137ff9063ffffffff16615193565b91906101000a81548163ffffffff021916908363ffffffff160217905550815f01600481819054906101000a900463ffffffff1661383c90615193565b91906101000a81548163ffffffff021916908363ffffffff1602179055506138648483611f8a565b93505b60018201805483546001600160a01b03808d16600160401b908102600160401b600160e01b03199093169290921786558b81169091026001600160e01b03199092166001600160401b038a1617919091179091558a1661390d57336001600160a01b0316835f1b857f734822851860327a80c624af1471efac6bb0ac641852fc6c7bfeeee3202ae6a88e8a604051613900929190615657565b60405180910390a46139c6565b336001600160a01b0316835f1b857f2fe093918572373e9f1f0368f414dffd0043a74ae8c9fd7b0e390b26a0d20b6e8e8e8b60405161394e93929190615681565b60405180910390a46139718a85600160405180602001604052805f8152506140c6565b5f61397c8584611fd0565b90508061398b5761398b6156bc565b604051819086907f35190fb7cb1f442974e3c68fa2be9cf56828d0043b1cfcfbd17b4efa85669296905f90a36139c381898d5f611e4a565b50505b6001600160a01b03891615613a0d5760405133906001600160a01b038b169086907fca9c8d517128edd416adf5719242ca6ff93ce234442d95234da53c0ae8a10540905f90a45b6001600160a01b03881615613a545760405133906001600160a01b038a169086907f9b6b420ff87c91604d447e507cbeedda5df2fa669a6b6534375e41fd3905a8d5905f90a45b505050979650505050505050565b6040805160018082526020820194909452808201938452606081019290925260808201905291565b60605f8251118015613ab4575062461bcd60e51b613aa7836156d0565b6001600160e01b03191614155b15613b405762461bcd60e51b6f0aee4c2e0e0cac88ae4e4dee4747460f60831b613add8461410d565b604051602001613aee92919061571a565b60408051601f1981840301815290829052613b0b91602401614593565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915291505b5090565b5f610d86613b528484613b67565b6001600160801b0319811660809190911c1790565b5f613b728383612bf9565b613b7c5f84612bf9565b179392505050565b5f6001600160e01b031982166347a296b160e11b1480610bd85750610bd882614175565b5f8215801590613bc857505f613bbd84611acd565b6001600160a01b0316145b15613bd457505f610bd8565b5f613bdf8484613b44565b90508315610d8657608081901c6110a2565b80197feeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef91909101167f888888888888888888888888888888888888888888888888888888888888888816151590565b8015613319575f613c5082611f71565b90505f613c5d8383611f8a565b90505f613c698261216f565b9050613c7781836001612f23565b82548390600490613c9590640100000000900463ffffffff16615193565b91906101000a81548163ffffffff021916908363ffffffff1602179055505f613cbe8385611f8a565b905080837f4adeae13ec8831392865da923fda1c23d6894f7acb41defa2472480cd4b47d5860405160405180910390a3610f968282600160405180602001604052805f8152506140c6565b613d15848484846141df565b6001600160a01b03831615801590613d3557506001600160a01b03841615155b15611567575f5b8251811015610f96575f838281518110613d5857613d586150b5565b60200260200101519050613d71816001609c1b88611b20565b613d925780866040516372c7b6ad60e11b815260040161123d929190615543565b5f838381518110613da557613da56150b5565b60200260200101511115613dc757613dc7613dbf82610f6c565b87875f614397565b50600101613d3c565b6001600160a01b0384163b1561345b5760405163bc197c8160e01b81526001600160a01b0385169063bc197c8190613e149089908990889088908890600401615735565b6020604051808303815f875af1925050508015613e4e575060408051601f3d908101601f19168201909252613e4b91810190615792565b60015b613eac573d808015613e7b576040519150601f19603f3d011682016040523d82523d5f602084013e613e80565b606091505b5080515f03613ea45784604051632bfa23e760e11b815260040161123d9190614660565b805181602001fd5b6001600160e01b0319811663bc197c8160e01b14612bf05784604051632bfa23e760e11b815260040161123d9190614660565b6001600160a01b0384163b1561345b5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190613f2390899089908890889088906004016157ad565b6020604051808303815f875af1925050508015613f5d575060408051601f3d908101601f19168201909252613f5a91810190615792565b60015b613f8a573d808015613e7b576040519150601f19603f3d011682016040523d82523d5f602084013e613e80565b6001600160e01b0319811663f23a6e6160e01b14612bf05784604051632bfa23e760e11b815260040161123d9190614660565b806001600160a01b03163b5f03613fe95780604051634c9c8ce360e01b815260040161123d9190614660565b5f8051602061583c83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b03168460405161403391906157e6565b5f60405180830381855af49150503d805f811461406b576040519150601f19603f3d011682016040523d82523d5f602084013e614070565b606091505b5091509150610c538583836143d8565b34156122965760405163b398979f60e01b815260040160405180910390fd5b5f9182526002602090815260408084206001600160a01b0393909316845291905290205490565b6001600160a01b0384166140ef575f604051632bfa23e760e11b815260040161123d9190614660565b5f806140fb8585613a62565b9150915061345b5f878484875f61340c565b805160609060011b806001600160401b0381111561412d5761412d614674565b6040519080825280601f01601f191660200182016040528015614157576020820181803683370190505b509150602083810190830161416d828285614426565b505050919050565b5f6001600160e01b03198216636cdb3d1360e11b14806141a557506001600160e01b031982166331a9108f60e11b145b806141c057506001600160e01b031982166303a24d0760e21b145b80610bd857506301ffc9a760e01b6001600160e01b0319831614610bd8565b805182511461420e5781518151604051635b05999160e01b81526004810192909252602482015260440161123d565b5f5b82518110156142d15760208181028481018201519084019091015180156142c7575f828152602081905260409020546001600160a01b03908116908816811461427457875f83856040516303dee4c560e01b815260040161123d94939291906157f1565b600182111561429f5787600183856040516303dee4c560e01b815260040161123d94939291906157f1565b505f82815260208190526040902080546001600160a01b0319166001600160a01b0388161790555b5050600101614210565b50815160010361433a576020828101518282015160408051838152938401829052919290916001600160a01b03808816929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a45050611567565b826001600160a01b0316846001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8585604051614389929190615817565b60405180910390a450505050565b5f8481526002602090815260408083206001600160a01b03871684529091529020548015610f96576143cb8582868561304b565b5061345b85828585611e4a565b6060826143e8576115ac82614489565b81511580156143ff57506001600160a01b0384163b155b1561441f5783604051639996b31560e01b815260040161123d9190614660565b5080610d86565b8181015b808310156115675783516101005b828510801561444657505f81115b1561447c5760031901600f82821c16600a8110614466578060570161446b565b806030015b905080865350600190940193614438565b505060208401935061442a565b8051156144995780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b6001600160a01b0381168114613319575f80fd5b5f80604083850312156144d7575f80fd5b82356144e2816144b2565b946020939093013593505050565b6001600160e01b031981168114613319575f80fd5b5f60208284031215614515575f80fd5b8135610d86816144f0565b5f8060408385031215614531575f80fd5b823591506020830135614543816144b2565b809150509250929050565b5f6020828403121561455e575f80fd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610d866020830184614565565b5f80604083850312156145b6575f80fd5b50508035926020909101359150565b5f8083601f8401126145d5575f80fd5b5081356001600160401b038111156145eb575f80fd5b6020830191508360208285010111156110c3575f80fd5b5f805f805f60808688031215614616575f80fd5b853594506020860135614628816144b2565b935060408601356001600160401b03811115614642575f80fd5b61464e888289016145c5565b96999598509660600135949350505050565b6001600160a01b0391909116815260200190565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156146b0576146b0614674565b604052919050565b5f6001600160401b038211156146d0576146d0614674565b5060051b60200190565b5f82601f8301126146e9575f80fd5b813560206146fe6146f9836146b8565b614688565b8083825260208201915060208460051b87010193508684111561471f575f80fd5b602086015b8481101561473b5780358352918301918301614724565b509695505050505050565b5f6001600160401b0382111561475e5761475e614674565b50601f01601f191660200190565b5f82601f83011261477b575f80fd5b81356147896146f982614746565b81815284602083860101111561479d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a086880312156147cd575f80fd5b85356147d8816144b2565b945060208601356147e8816144b2565b935060408601356001600160401b0380821115614803575f80fd5b61480f89838a016146da565b94506060880135915080821115614824575f80fd5b61483089838a016146da565b93506080880135915080821115614845575f80fd5b506148528882890161476c565b9150509295509295909350565b5f8060208385031215614870575f80fd5b82356001600160401b03811115614885575f80fd5b614891858286016145c5565b90969095509350505050565b634e487b7160e01b5f52602160045260245ffd5b600381106148cd57634e487b7160e01b5f52602160045260245ffd5b9052565b5f60a0820190506148e38284516148b1565b6001600160401b03602084015116602083015260018060a01b036040840151166040830152606083015160608301526080830151608083015292915050565b5f805f60408486031215614934575f80fd5b83356001600160401b03811115614949575f80fd5b614955868287016145c5565b9094509250506020840135614969816144b2565b809150509250925092565b5f8060408385031215614985575f80fd5b82356001600160401b038082111561499b575f80fd5b818501915085601f8301126149ae575f80fd5b813560206149be6146f9836146b8565b82815260059290921b840181019181810190898411156149dc575f80fd5b948201945b83861015614a035785356149f4816144b2565b825294820194908201906149e1565b96505086013592505080821115614a18575f80fd5b50614a25858286016146da565b9150509250929050565b5f815180845260208085019450602084015f5b83811015614a5e57815187529582019590820190600101614a42565b509495945050505050565b602081525f610d866020830184614a2f565b5f8060408385031215614a8c575f80fd5b8235614a97816144b2565b915060208301356001600160401b03811115614ab1575f80fd5b614a258582860161476c565b6001600160401b0381168114613319575f80fd5b5f8060408385031215614ae2575f80fd5b82359150602083013561454381614abd565b60208101610bd882846148b1565b5f8083601f840112614b12575f80fd5b5081356001600160401b03811115614b28575f80fd5b6020830191508360208260051b85010111156110c3575f80fd5b5f805f8060408587031215614b55575f80fd5b84356001600160401b0380821115614b6b575f80fd5b614b7788838901614b02565b90965094506020870135915080821115614b8f575f80fd5b50614b9c87828801614b02565b95989497509550505050565b5f60208284031215614bb8575f80fd5b8135610d86816144b2565b5f805f60608486031215614bd5575f80fd5b83359250602084013591506040840135614969816144b2565b6001600160a01b03831681526040602082018190525f906110a290830184614565565b5f805f805f8060c08789031215614c26575f80fd5b86356001600160401b03811115614c3b575f80fd5b614c4789828a0161476c565b9650506020870135614c58816144b2565b94506040870135614c68816144b2565b93506060870135614c78816144b2565b92506080870135915060a0870135614c8f81614abd565b809150509295509295509295565b8015158114613319575f80fd5b5f8060408385031215614cbb575f80fd5b8235614cc6816144b2565b9150602083013561454381614c9d565b5f805f805f805f8060a0898b031215614ced575f80fd5b8835614cf8816144b2565b97506020890135614d08816144b2565b965060408901356001600160401b0380821115614d23575f80fd5b614d2f8c838d01614b02565b909850965060608b0135915080821115614d47575f80fd5b614d538c838d01614b02565b909650945060808b0135915080821115614d6b575f80fd5b50614d788b828c016145c5565b999c989b5096995094979396929594505050565b5f8060408385031215614d9d575f80fd5b8235614da8816144b2565b91506020830135614543816144b2565b5f805f805f8060a08789031215614dcd575f80fd5b8635614dd8816144b2565b95506020870135614de8816144b2565b9450604087013593506060870135925060808701356001600160401b03811115614e10575f80fd5b614e1c89828a016145c5565b979a9699509497509295939492505050565b5f805f805f60a08688031215614e42575f80fd5b8535614e4d816144b2565b94506020860135614e5d816144b2565b9350604086013592506060860135915060808601356001600160401b03811115614e85575f80fd5b6148528882890161476c565b600181811c90821680614ea557607f821691505b602082108103614ec357634e487b7160e01b5f52602260045260245ffd5b50919050565b5f614ed66146f984614746565b9050828152838383011115614ee9575f80fd5b8282602083015e5f602084830101529392505050565b5f60208284031215614f0f575f80fd5b81516001600160401b03811115614f24575f80fd5b8201601f81018413614f34575f80fd5b6110a284825160208401614ec9565b601f8211156121ed57805f5260205f20601f840160051c81016020851015614f685750805b601f840160051c820191505b81811015610f96575f8155600101614f74565b5f19600383901b1c191660019190911b1790565b6001600160401b03831115614fb257614fb2614674565b614fc683614fc08354614e91565b83614f43565b5f601f841160018114614ff2575f8515614fe05750838201355b614fea8682614f87565b845550610f96565b5f83815260208120601f198716915b828110156150215786850135825560209485019460019092019101615001565b508682101561503d575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f6110a260208301848661504f565b604081525f61509d60408301858761504f565b905060018060a01b0383166020830152949350505050565b634e487b7160e01b5f52603260045260245ffd5b81516001600160401b038111156150e2576150e2614674565b6150f6816150f08454614e91565b84614f43565b602080601f831160018114615124575f84156151125750858301515b61511c8582614f87565b86555061345b565b5f85815260208120601f198616915b8281101561515257888601518255948401946001909101908401615133565b508582101561516f57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b5f63ffffffff8083168181036151ab576151ab61517f565b6001019392505050565b8082028115828204841417610bd857610bd861517f565b80820180821115610bd857610bd861517f565b5f608082840312156151ef575f80fd5b604051608081016001600160401b03828210818311171561521257615212614674565b816040528293508435915080821115615229575f80fd5b506152368582860161476c565b8252506020830135615247816144b2565b6020820152604083013561525a816144b2565b6040820152606083013561526d816144b2565b6060919091015292915050565b5f602080838503121561528b575f80fd5b82356001600160401b03808211156152a1575f80fd5b818501915085601f8301126152b4575f80fd5b81356152c26146f9826146b8565b81815260059190911b830184019084810190888311156152e0575f80fd5b8585015b83811015615316578035858111156152fa575f80fd5b6153088b89838a01016151df565b8452509186019186016152e4565b5098975050505050505050565b5f82825180855260208086019550808260051b8401018186015f5b848110156153a457601f1986840301895281516080815181865261536482870182614565565b838801516001600160a01b03908116888a01526040808601518216908901526060948501511693909601929092525050978301979083019060010161533e565b5090979650505050505050565b604080825281018390525f6001600160fb1b038411156153cf575f80fd5b8360051b80866060850137820182810360609081016020850152612cf490820185615323565b5f60208284031215615405575f80fd5b81356001600160401b0381111561541a575f80fd5b6110a2848285016151df565b604081525f6154386040830185614a2f565b8281036020840152610c538185615323565b92835260208301919091526001600160a01b0316604082015260600190565b63ffffffff8181168382160190808211156135d3576135d361517f565b5f60208284031215615496575f80fd5b8151610d8681614c9d565b5f602082840312156154b1575f80fd5b5051919050565b5f8235607e198336030181126154cc575f80fd5b9190910192915050565b5f610bd836836151df565b5f805f606084860312156154f3575f80fd5b83516154fe816144b2565b602085015190935063ffffffff81168114615517575f80fd5b604085015190925061496981614abd565b5f60208284031215615538575f80fd5b8151610d86816144b2565b9182526001600160a01b0316602082015260400190565b8481526001600160a01b03841660208201526080604082018190525f9061558390830185614565565b905082606083015295945050505050565b60018060a01b0384168152826020820152606060408201525f610c536060830184614565565b5f60208083525f84546155cc81614e91565b806020870152604060018084165f81146155ed576001811461560957615636565b60ff19851660408a0152604084151560051b8a01019550615636565b895f5260205f205f5b8581101561562d5781548b8201860152908301908801615612565b8a016040019650505b509398975050505050505050565b81810381811115610bd857610bd861517f565b604081525f6156696040830185614565565b90506001600160401b03831660208301529392505050565b606081525f6156936060830186614565565b6001600160a01b03949094166020830152506001600160401b0391909116604090910152919050565b634e487b7160e01b5f52600160045260245ffd5b805160208201516001600160e01b0319808216929190600483101561416d5760049290920360031b82901b161692915050565b5f81518060208401855e5f93019283525090919050565b6001600160801b0319831681525f6110a26010830184615703565b6001600160a01b0386811682528516602082015260a0604082018190525f9061576090830186614a2f565b82810360608401526157728186614a2f565b905082810360808401526157868185614565565b98975050505050505050565b5f602082840312156157a2575f80fd5b8151610d86816144f0565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190525f9061175790830184614565565b5f610d868284615703565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b604081525f6158296040830185614a2f565b8281036020840152610c538185614a2f56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220bb51201f914d69564c58c14c847a781374c2ee205be2913bbb1bf12ecfca285a64736f6c63430008190033", + "linkReferences": {}, + "deployedLinkReferences": {}, + "immutableReferences": { + "2865": [ + { + "length": 32, + "start": 8701 + }, + { + "length": 32, + "start": 8742 + }, + { + "length": 32, + "start": 9232 + } + ], + "12006": [ + { + "length": 32, + "start": 1189 + }, + { + "length": 32, + "start": 6339 + }, + { + "length": 32, + "start": 7158 + }, + { + "length": 32, + "start": 9565 + }, + { + "length": 32, + "start": 9745 + }, + { + "length": 32, + "start": 9928 + }, + { + "length": 32, + "start": 10465 + }, + { + "length": 32, + "start": 10885 + }, + { + "length": 32, + "start": 11006 + }, + { + "length": 32, + "start": 11604 + }, + { + "length": 32, + "start": 11917 + } + ], + "12009": [ + { + "length": 32, + "start": 1870 + }, + { + "length": 32, + "start": 10398 + }, + { + "length": 32, + "start": 11057 + } + ], + "12013": [ + { + "length": 32, + "start": 10055 + }, + { + "length": 32, + "start": 11771 + } + ], + "12366": [ + { + "length": 32, + "start": 1125 + }, + { + "length": 32, + "start": 10555 + } + ], + "12369": [ + { + "length": 32, + "start": 1757 + }, + { + "length": 32, + "start": 10602 + } + ], + "12373": [ + { + "length": 32, + "start": 2878 + }, + { + "length": 32, + "start": 10212 + } + ], + "12376": [ + { + "length": 32, + "start": 2929 + }, + { + "length": 32, + "start": 10335 + } + ], + "14334": [ + { + "length": 32, + "start": 2319 + }, + { + "length": 32, + "start": 13811 + } + ], + "16160": [ + { + "length": 32, + "start": 1592 + }, + { + "length": 32, + "start": 7064 + } + ], + "16164": [ + { + "length": 32, + "start": 1541 + }, + { + "length": 32, + "start": 8895 + } + ] + }, + "inputSourceName": "project/src/registry/WrapperRegistry.sol", + "devdoc": { + "errors": { + "AddressEmptyCode(address)": [ + { + "details": "There's no code at `target` (it is not a contract)." + } + ], + "CannotReduceExpiry(uint64,uint64)": [ + { + "details": "Error selector: `0x68c1425a`" + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "details": "Error selector: `0xf1d446c3`" + } + ], + "EACCannotGrantRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xd1a3b355`" + } + ], + "EACCannotRevokeRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0xa604e318`" + } + ], + "EACInvalidAccount()": [ + { + "details": "Error selector: `0xec3fc592`" + } + ], + "EACInvalidRoleBitmap(uint256)": [ + { + "details": "Error selector: `0x2a7b2d20`" + } + ], + "EACMaxAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0xf9165348`" + } + ], + "EACMinAssignees(uint256,uint256)": [ + { + "details": "Error selector: `0x1f80c19b`" + } + ], + "EACRootResourceNotAllowed()": [ + { + "details": "Error selector: `0xc2842458`" + } + ], + "EACUnauthorizedAccountRoles(uint256,uint256,address)": [ + { + "details": "Error selector: `0x4b27a133`" + } + ], + "ERC1155InsufficientBalance(address,uint256,uint256,uint256)": [ + { + "details": "Indicates an error related to the current `balance` of a `sender`. Used in transfers.", + "params": { + "balance": "Current balance for the interacting account.", + "needed": "Minimum amount required to perform a transfer.", + "sender": "Address whose tokens are being transferred.", + "tokenId": "Identifier number of a token." + } + } + ], + "ERC1155InvalidApprover(address)": [ + { + "details": "Indicates a failure with the `approver` of a token to be approved. Used in approvals.", + "params": { + "approver": "Address initiating an approval operation." + } + } + ], + "ERC1155InvalidArrayLength(uint256,uint256)": [ + { + "details": "Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.", + "params": { + "idsLength": "Length of the array of token identifiers", + "valuesLength": "Length of the array of token amounts" + } + } + ], + "ERC1155InvalidOperator(address)": [ + { + "details": "Indicates a failure with the `operator` to be approved. Used in approvals.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner." + } + } + ], + "ERC1155InvalidReceiver(address)": [ + { + "details": "Indicates a failure with the token `receiver`. Used in transfers.", + "params": { + "receiver": "Address to which tokens are being transferred." + } + } + ], + "ERC1155InvalidSender(address)": [ + { + "details": "Indicates a failure with the token `sender`. Used in transfers.", + "params": { + "sender": "Address whose tokens are being transferred." + } + } + ], + "ERC1155MissingApprovalForAll(address,address)": [ + { + "details": "Indicates a failure with the `operator`’s approval. Used in transfers.", + "params": { + "operator": "Address that may be allowed to operate on tokens without being their owner.", + "owner": "Address of the current owner of a token." + } + } + ], + "ERC1967InvalidImplementation(address)": [ + { + "details": "The `implementation` of the proxy is invalid." + } + ], + "ERC1967NonPayable()": [ + { + "details": "An upgrade function sees `msg.value > 0` that may be lost." + } + ], + "FailedCall()": [ + { + "details": "A call to an address target failed. The target may have reverted." + } + ], + "FrozenTokenApproval(uint256)": [ + { + "details": "Error selector: `0xa4f07713`" + } + ], + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "InvalidOwner()": [ + { + "details": "Error selector: `0x49e27cff`" + } + ], + "LabelAlreadyRegistered(string)": [ + { + "details": "Error selector: `0xdef545a4`" + } + ], + "LabelAlreadyReserved(string)": [ + { + "details": "Error selector: `0xf60759e0`" + } + ], + "LabelExpired(uint256)": [ + { + "details": "Error selector: `0xc44e2374`" + } + ], + "NameDataMismatch(uint256)": [ + { + "details": "Error selector: `0xedec3569`" + } + ], + "NameNotLocked(uint256)": [ + { + "details": "Error selector: `0x1bfe8f0a`" + } + ], + "NameRequiresMigration()": [ + { + "details": "Error selector: `0x408fa1b8`" + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "details": "Error selector: `0xe58f6d5a`" + } + ], + "UUPSUnauthorizedCallContext()": [ + { + "details": "The call is from an unauthorized context." + } + ], + "UUPSUnsupportedProxiableUUID(bytes32)": [ + { + "details": "The storage `slot` is unsupported as a UUID." + } + ], + "UnauthorizedCaller(address)": [ + { + "details": "Error selector: `0xd86ad9cf`", + "params": { + "caller": "The address that attempted the unauthorized operation" + } + } + ], + "UpgradeTargetNotApproved(address)": [ + { + "details": "Error selector: `0xf74d7dd0`", + "params": { + "implementation": "The disallowed implementation address." + } + } + ] + }, + "events": { + "ApprovalForAll(address,address,bool)": { + "details": "Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`." + }, + "EACRolesChanged(uint256,address,uint256,uint256)": { + "params": { + "account": "The account that the roles were changed for.", + "newRoleBitmap": "The new roles for the account.", + "oldRoleBitmap": "The old roles for the account.", + "resource": "The resource that the roles were changed within." + } + }, + "ExpiryUpdated(uint256,uint64,address)": { + "params": { + "newExpiry": "The new expiry of the label.", + "sender": "The sender of the call to update the expiry.", + "tokenId": "The token ID of the label." + } + }, + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label registered.", + "labelHash": "The label hash registered.", + "owner": "The owner of the label.", + "sender": "The sender of the call to register.", + "tokenId": "The token ID registered." + } + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "params": { + "expiry": "The expiry of the label.", + "label": "The label reserved.", + "labelHash": "The label hash reserved.", + "sender": "The sender of the call to reserve.", + "tokenId": "The token ID reserved." + } + }, + "LabelUnregistered(uint256,address)": { + "params": { + "sender": "The sender of the call to unregister.", + "tokenId": "The token ID unregistered." + } + }, + "ParentUpdated(address,string,address)": { + "params": { + "label": "The new label.", + "parent": "The new parent.", + "sender": "The sender of the call to update the parent." + } + }, + "ResolverUpdated(uint256,address,address)": { + "params": { + "resolver": "The new resolver.", + "sender": "The sender of the call to update the resolver.", + "tokenId": "The token ID of the label." + } + }, + "SubregistryUpdated(uint256,address,address)": { + "params": { + "sender": "The sender of the call to update the subregistry.", + "subregistry": "The new subregistry.", + "tokenId": "The token ID of the label." + } + }, + "TokenRegenerated(uint256,uint256)": { + "params": { + "newTokenId": "The new token ID.", + "oldTokenId": "The old token ID." + } + }, + "TokenResource(uint256,uint256)": { + "params": { + "resource": "The EAC resource.", + "tokenId": "The token ID." + } + }, + "TransferBatch(address,address,address,uint256[],uint256[])": { + "details": "Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers." + }, + "TransferSingle(address,address,address,uint256,uint256)": { + "details": "Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`." + }, + "URI(string,uint256)": { + "details": "Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}." + }, + "URIUpdated(string,address,address)": { + "params": { + "renderer": "The new render address.", + "sender": "The sender of the call to update the URI.", + "uri": "The new URI." + } + }, + "Upgraded(address)": { + "details": "Emitted when the implementation is upgraded." + } + }, + "kind": "dev", + "methods": { + "balanceOf(address,uint256)": { + "params": { + "account": "The account to get the balance for.", + "id": "The token ID." + }, + "returns": { + "_0": "balance The balance of the token for the account. This will only ever be 1 or 0." + } + }, + "balanceOfBatch(address[],uint256[])": { + "details": "`accounts` and `ids` must have the same length.", + "params": { + "accounts": "The accounts to get the balances for.", + "ids": "The token IDs." + }, + "returns": { + "_0": "batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0." + } + }, + "canUpgradeFrom(address)": { + "details": "Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call, including the wrapper upgrade target allowlist.", + "params": { + "": "{previousImplementation} Ignored." + }, + "returns": { + "allowed": "Always `true` for implementations in this wrapper registry family." + } + }, + "constructor": { + "params": { + "ensV1Resolver": "The ENSv1 resolver.", + "graveyard": "The ENSv1 `BaseRegistrar` token graveyard.", + "labelStore": "The shared label database.", + "nameWrapper": "The ENSv1 NameWrapper.", + "namer": "The implementation namer.", + "publicResolver": "The replacement `PublicResolver`.", + "publicResolverSet": "The approved list of `PublicResolver` contracts.", + "upgradeGate": "The upgrade target allowlist.", + "verifiableFactory": "The VerifiableFactory." + } + }, + "findExpiry(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The expiry of the label." + } + }, + "findOwner(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The owner of the label." + } + }, + "findTokenId(string)": { + "params": { + "label": "The label to query." + }, + "returns": { + "_0": "The token ID of the label." + } + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "details": "Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts", + "params": { + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated.", + "mds": "The migration parameters for each name, indexed in parallel with `ids`." + } + }, + "getAssigneeCount(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "counts": "The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.", + "mask": "The mask for the given role bitmap." + } + }, + "getExpiry(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The expiry of the label, in seconds." + } + }, + "getOwner(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token owner." + } + }, + "getParent()": { + "returns": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "getResolver(string)": { + "details": "Return `V1_RESOLVER` upon visiting migratable children.", + "params": { + "label": "The label to fetch a resolver for." + }, + "returns": { + "_0": "resolver The address of a resolver responsible for this label, or `address(0)` if none exists." + } + }, + "getResource(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The resource." + } + }, + "getState(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "state": "The state of the label." + } + }, + "getStatus(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The status of the label." + } + }, + "getSubregistry(string)": { + "params": { + "label": "The label to resolve." + }, + "returns": { + "_0": "The address of the registry for this label, or `address(0)` if none exists." + } + }, + "getTokenId(uint256)": { + "params": { + "anyId": "The labelhash, token ID, or resource." + }, + "returns": { + "_0": "The token ID." + } + }, + "grantRoles(uint256,uint256,address)": { + "params": { + "account": "The account to grant roles to.", + "resource": "The resource to grant roles within.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "grantRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being granted.", + "params": { + "account": "The account to grant roles to.", + "roleBitmap": "The roles bitmap to grant." + }, + "returns": { + "_0": "`true` if the roles were granted, `false` otherwise." + } + }, + "hasAssignees(uint256,uint256)": { + "params": { + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if any of the roles in the given role bitmap has assignees, `false` otherwise." + } + }, + "hasRoles(uint256,uint256,address)": { + "params": { + "account": "The account to check.", + "resource": "The resource to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "hasRootRoles(uint256,address)": { + "params": { + "account": "The account to check.", + "roleBitmap": "The roles bitmap to check." + }, + "returns": { + "_0": "`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise." + } + }, + "initialize(bytes32,address,string,uint256)": { + "params": { + "childLabel": "The subdomain for this registry.", + "node": "Namehash of this registry.", + "parentRegistry": "The parent of this registry.", + "roleBitmap": "The role bitmap granted to the virtual admin." + } + }, + "isApprovedForAll(address,address)": { + "params": { + "account": "The account to get the approval for.", + "operator": "The operator to get the approval for." + }, + "returns": { + "_0": "approved The approval status." + } + }, + "isContractNamer(address)": { + "params": { + "namer": "The address to check." + }, + "returns": { + "_0": "`true` if authorized." + } + }, + "latestOwnerOf(uint256)": { + "params": { + "tokenId": "The token ID to query." + }, + "returns": { + "_0": "The latest owner address." + } + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.", + "ids": "The NameWrapper token IDs (namehashes) of the names being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed" + } + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "details": "Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.", + "params": { + "data": "ABI-encoded `LibMigration.Data` struct containing migration parameters.", + "id": "The NameWrapper token ID (namehash) of the name being migrated." + }, + "returns": { + "_0": "`bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed" + } + }, + "ownerOf(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The owner of the token." + } + }, + "proxiableUUID()": { + "details": "Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier." + }, + "register(string,address,address,address,uint256,uint64)": { + "details": "Blocks registration of emancipated children.", + "params": { + "expiry": "The expiry of the label, in seconds.", + "label": "The label to register.", + "owner": "The address of the owner of the label.", + "registry": "The registry to set as the label.", + "resolver": "The resolver to set for the label.", + "roleBitmap": "The role bitmap to set for the label." + }, + "returns": { + "tokenId": "The token ID." + } + }, + "renew(uint256,uint64)": { + "details": "If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.", + "params": { + "anyId": "The labelhash, token ID, or resource.", + "newExpiry": "The new expiry, in seconds." + } + }, + "revokeRoles(uint256,uint256,address)": { + "params": { + "account": "The account to revoke roles from.", + "resource": "The resource to revoke roles within.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "revokeRootRoles(uint256,address)": { + "details": "The caller must have all the necessary admin roles for the roles being revoked.", + "params": { + "account": "The account to revoke roles from.", + "roleBitmap": "The roles bitmap to revoke." + }, + "returns": { + "_0": "`true` if the roles were revoked, `false` otherwise." + } + }, + "roleCount(uint256)": { + "params": { + "resource": "The resource to get the role count for." + }, + "returns": { + "_0": "count The role count bitmap for the resource." + } + }, + "roles(uint256,address)": { + "params": { + "account": "The account to get the roles for.", + "resource": "The resource to get the roles for." + }, + "returns": { + "_0": "The roles bitmap for the account in the resource." + } + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "details": "`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the tokens from.", + "ids": "The token IDs.", + "to": "The address to transfer the tokens to.", + "values": "The amounts of tokens to transfer." + } + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "details": "`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.", + "params": { + "data": "Additional data to pass to the receiver.", + "from": "The address to transfer the token from.", + "id": "The token ID.", + "to": "The address to transfer the token to.", + "value": "The amount of tokens to transfer." + } + }, + "setApprovalForAll(address,bool)": { + "params": { + "approved": "The approval status.", + "operator": "The operator to set the approval for." + } + }, + "setParent(address,string)": { + "details": "Should emit `ParentUpdated`.", + "params": { + "label": "The canonical subdomain of this registry.", + "parent": "The canonical parent of this registry." + } + }, + "setResolver(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "resolver": "The new resolver." + } + }, + "setSubregistry(uint256,address)": { + "params": { + "anyId": "The labelhash, token ID, or resource.", + "registry": "The new registry." + } + }, + "setURI(string,address)": { + "params": { + "renderer": "The new renderer address.", + "uri_": "The new URI." + } + }, + "supportsInterface(bytes4)": { + "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas." + }, + "unregister(uint256)": { + "details": "Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.", + "params": { + "anyId": "The labelhash, token ID, or resource." + } + }, + "upgradeToAndCall(address,bytes)": { + "custom:oz-upgrades-unsafe-allow-reachable": "delegatecall", + "details": "Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event." + }, + "uri(uint256)": { + "params": { + "id": "The token ID." + }, + "returns": { + "_0": "The URI for the token." + } + } + }, + "stateVariables": { + "_initialRoleBitmap": { + "details": "The initial roles derived from the NameWrapper." + }, + "_node": { + "details": "The namehash of this registry." + } + }, + "version": 1 + }, + "evm": { + "gasEstimates": { + "creation": { + "codeDepositCost": "4534600", + "executionCost": "infinite", + "totalCost": "infinite" + }, + "external": { + "GRAVEYARD()": "infinite", + "LABEL_STORE()": "infinite", + "NAME_WRAPPER()": "infinite", + "PUBLIC_RESOLVER()": "infinite", + "PUBLIC_RESOLVER_SET()": "infinite", + "ROOT_RESOURCE()": "294", + "UPGRADE_GATE()": "infinite", + "UPGRADE_INTERFACE_VERSION()": "infinite", + "V1_RESOLVER()": "infinite", + "VERIFIABLE_FACTORY()": "infinite", + "WRAPPER_REGISTRY_IMPL()": "infinite", + "balanceOf(address,uint256)": "infinite", + "balanceOfBatch(address[],uint256[])": "infinite", + "canUpgradeFrom(address)": "507", + "findExpiry(string)": "infinite", + "findOwner(string)": "infinite", + "findTokenId(string)": "infinite", + "finishERC1155Migration(uint256[],(string,address,address,address)[])": "infinite", + "getAssigneeCount(uint256,uint256)": "7374", + "getExpiry(uint256)": "2700", + "getOwner(uint256)": "infinite", + "getParent()": "infinite", + "getResolver(string)": "infinite", + "getResource(uint256)": "4986", + "getState(uint256)": "infinite", + "getStatus(uint256)": "infinite", + "getSubregistry(string)": "infinite", + "getTokenId(uint256)": "2763", + "getWrappedName()": "infinite", + "getWrappedNode()": "2392", + "grantRoles(uint256,uint256,address)": "infinite", + "grantRootRoles(uint256,address)": "infinite", + "hasAssignees(uint256,uint256)": "infinite", + "hasRoles(uint256,uint256,address)": "infinite", + "hasRootRoles(uint256,address)": "infinite", + "initialize(bytes32,address,string,uint256)": "infinite", + "isApprovedForAll(address,address)": "infinite", + "isContractNamer(address)": "infinite", + "latestOwnerOf(uint256)": "2663", + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": "infinite", + "onERC1155Received(address,address,uint256,uint256,bytes)": "infinite", + "ownerOf(uint256)": "infinite", + "proxiableUUID()": "infinite", + "register(string,address,address,address,uint256,uint64)": "infinite", + "renew(uint256,uint64)": "infinite", + "revokeRoles(uint256,uint256,address)": "infinite", + "revokeRootRoles(uint256,address)": "infinite", + "roleCount(uint256)": "infinite", + "roles(uint256,address)": "infinite", + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": "infinite", + "safeTransferFrom(address,address,uint256,uint256,bytes)": "infinite", + "setApprovalForAll(address,bool)": "infinite", + "setParent(address,string)": "infinite", + "setResolver(uint256,address)": "infinite", + "setSubregistry(uint256,address)": "infinite", + "setURI(string,address)": "infinite", + "supportsInterface(bytes4)": "infinite", + "unregister(uint256)": "infinite", + "upgradeToAndCall(address,bytes)": "infinite", + "uri(uint256)": "infinite" + }, + "internal": { + "_authorizeUpgrade(address)": "infinite", + "_canRevive(uint256,address)": "infinite", + "_getRegistry()": "infinite", + "_getRoles(uint256,address)": "infinite", + "_getSettableRoles(uint256,address)": "infinite", + "_inject(string memory,address,contract IRegistry,address,uint256,uint64)": "infinite", + "_isMigratableChild(string memory)": "infinite" + } + } + }, + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"nameWrapper\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"graveyard\",\"type\":\"address\"},{\"internalType\":\"contract IVerifiableFactory\",\"name\":\"verifiableFactory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"ensV1Resolver\",\"type\":\"address\"},{\"internalType\":\"contract ApprovedUpgradeGate\",\"name\":\"upgradeGate\",\"type\":\"address\"},{\"internalType\":\"contract ILabelStore\",\"name\":\"labelStore\",\"type\":\"address\"},{\"internalType\":\"contract IAddressSet\",\"name\":\"publicResolverSet\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"publicResolver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"oldExpiry\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"CannotReduceExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"CannotSetPastExpiry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotGrantRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACCannotRevokeRoles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACInvalidAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACInvalidRoleBitmap\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMaxAssignees\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"role\",\"type\":\"uint256\"}],\"name\":\"EACMinAssignees\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EACRootResourceNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"EACUnauthorizedAccountRoles\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"needed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC1155InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidApprover\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"idsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"valuesLength\",\"type\":\"uint256\"}],\"name\":\"ERC1155InvalidArrayLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidOperator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ERC1155InvalidSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"ERC1155MissingApprovalForAll\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"ERC1967InvalidImplementation\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ERC1967NonPayable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"FrozenTokenApproval\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"LabelAlreadyReserved\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"LabelExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"NameNotLocked\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NameRequiresMigration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"}],\"name\":\"TransferDisallowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UUPSUnauthorizedCallContext\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"slot\",\"type\":\"bytes32\"}],\"name\":\"UUPSUnsupportedProxiableUUID\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"UpgradeTargetNotApproved\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldRoleBitmap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newRoleBitmap\",\"type\":\"uint256\"}],\"name\":\"EACRolesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ExpiryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"labelHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelReserved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"LabelUnregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ParentUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RegistryCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"ResolverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SubregistryUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"oldTokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"newTokenId\",\"type\":\"uint256\"}],\"name\":\"TokenRegenerated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"name\":\"TokenResource\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"uri\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"renderer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"URIUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"GRAVEYARD\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LABEL_STORE\",\"outputs\":[{\"internalType\":\"contract ILabelStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NAME_WRAPPER\",\"outputs\":[{\"internalType\":\"contract INameWrapper\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PUBLIC_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PUBLIC_RESOLVER_SET\",\"outputs\":[{\"internalType\":\"contract IAddressSet\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ROOT_RESOURCE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADE_GATE\",\"outputs\":[{\"internalType\":\"contract ApprovedUpgradeGate\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPGRADE_INTERFACE_VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"V1_RESOLVER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERIFIABLE_FACTORY\",\"outputs\":[{\"internalType\":\"contract IVerifiableFactory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"WRAPPER_REGISTRY_IMPL\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"canUpgradeFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"findTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"subregistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"internalType\":\"struct LibMigration.Data[]\",\"name\":\"mds\",\"type\":\"tuple[]\"}],\"name\":\"finishERC1155Migration\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"getAssigneeCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"counts\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mask\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getExpiry\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getParent\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getResolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getResource\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"latestOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resource\",\"type\":\"uint256\"}],\"internalType\":\"struct IPermissionedRegistry.State\",\"name\":\"state\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getStatus\",\"outputs\":[{\"internalType\":\"enum IPermissionedRegistry.Status\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"getSubregistry\",\"outputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"getTokenId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedName\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNode\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"hasAssignees\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"node\",\"type\":\"bytes32\"},{\"internalType\":\"contract IRegistry\",\"name\":\"parentRegistry\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"childLabel\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"namer\",\"type\":\"address\"}],\"name\":\"isContractNamer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"latestOwnerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155BatchReceived\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onERC1155Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"expiry\",\"type\":\"uint64\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"newExpiry\",\"type\":\"uint64\"}],\"name\":\"renew\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"roleBitmap\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRootRoles\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"roleCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"roles\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistry\",\"name\":\"parent\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"setParent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"},{\"internalType\":\"contract IRegistry\",\"name\":\"registry\",\"type\":\"address\"}],\"name\":\"setSubregistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"uri_\",\"type\":\"string\"},{\"internalType\":\"contract IRegistryURIRenderer\",\"name\":\"renderer\",\"type\":\"address\"}],\"name\":\"setURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"anyId\",\"type\":\"uint256\"}],\"name\":\"unregister\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AddressEmptyCode(address)\":[{\"details\":\"There's no code at `target` (it is not a contract).\"}],\"CannotReduceExpiry(uint64,uint64)\":[{\"details\":\"Error selector: `0x68c1425a`\"}],\"CannotSetPastExpiry(uint64)\":[{\"details\":\"Error selector: `0xf1d446c3`\"}],\"EACCannotGrantRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xd1a3b355`\"}],\"EACCannotRevokeRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0xa604e318`\"}],\"EACInvalidAccount()\":[{\"details\":\"Error selector: `0xec3fc592`\"}],\"EACInvalidRoleBitmap(uint256)\":[{\"details\":\"Error selector: `0x2a7b2d20`\"}],\"EACMaxAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0xf9165348`\"}],\"EACMinAssignees(uint256,uint256)\":[{\"details\":\"Error selector: `0x1f80c19b`\"}],\"EACRootResourceNotAllowed()\":[{\"details\":\"Error selector: `0xc2842458`\"}],\"EACUnauthorizedAccountRoles(uint256,uint256,address)\":[{\"details\":\"Error selector: `0x4b27a133`\"}],\"ERC1155InsufficientBalance(address,uint256,uint256,uint256)\":[{\"details\":\"Indicates an error related to the current `balance` of a `sender`. Used in transfers.\",\"params\":{\"balance\":\"Current balance for the interacting account.\",\"needed\":\"Minimum amount required to perform a transfer.\",\"sender\":\"Address whose tokens are being transferred.\",\"tokenId\":\"Identifier number of a token.\"}}],\"ERC1155InvalidApprover(address)\":[{\"details\":\"Indicates a failure with the `approver` of a token to be approved. Used in approvals.\",\"params\":{\"approver\":\"Address initiating an approval operation.\"}}],\"ERC1155InvalidArrayLength(uint256,uint256)\":[{\"details\":\"Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. Used in batch transfers.\",\"params\":{\"idsLength\":\"Length of the array of token identifiers\",\"valuesLength\":\"Length of the array of token amounts\"}}],\"ERC1155InvalidOperator(address)\":[{\"details\":\"Indicates a failure with the `operator` to be approved. Used in approvals.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\"}}],\"ERC1155InvalidReceiver(address)\":[{\"details\":\"Indicates a failure with the token `receiver`. Used in transfers.\",\"params\":{\"receiver\":\"Address to which tokens are being transferred.\"}}],\"ERC1155InvalidSender(address)\":[{\"details\":\"Indicates a failure with the token `sender`. Used in transfers.\",\"params\":{\"sender\":\"Address whose tokens are being transferred.\"}}],\"ERC1155MissingApprovalForAll(address,address)\":[{\"details\":\"Indicates a failure with the `operator`\\u2019s approval. Used in transfers.\",\"params\":{\"operator\":\"Address that may be allowed to operate on tokens without being their owner.\",\"owner\":\"Address of the current owner of a token.\"}}],\"ERC1967InvalidImplementation(address)\":[{\"details\":\"The `implementation` of the proxy is invalid.\"}],\"ERC1967NonPayable()\":[{\"details\":\"An upgrade function sees `msg.value > 0` that may be lost.\"}],\"FailedCall()\":[{\"details\":\"A call to an address target failed. The target may have reverted.\"}],\"FrozenTokenApproval(uint256)\":[{\"details\":\"Error selector: `0xa4f07713`\"}],\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"InvalidOwner()\":[{\"details\":\"Error selector: `0x49e27cff`\"}],\"LabelAlreadyRegistered(string)\":[{\"details\":\"Error selector: `0xdef545a4`\"}],\"LabelAlreadyReserved(string)\":[{\"details\":\"Error selector: `0xf60759e0`\"}],\"LabelExpired(uint256)\":[{\"details\":\"Error selector: `0xc44e2374`\"}],\"NameDataMismatch(uint256)\":[{\"details\":\"Error selector: `0xedec3569`\"}],\"NameNotLocked(uint256)\":[{\"details\":\"Error selector: `0x1bfe8f0a`\"}],\"NameRequiresMigration()\":[{\"details\":\"Error selector: `0x408fa1b8`\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"TransferDisallowed(uint256,address)\":[{\"details\":\"Error selector: `0xe58f6d5a`\"}],\"UUPSUnauthorizedCallContext()\":[{\"details\":\"The call is from an unauthorized context.\"}],\"UUPSUnsupportedProxiableUUID(bytes32)\":[{\"details\":\"The storage `slot` is unsupported as a UUID.\"}],\"UnauthorizedCaller(address)\":[{\"details\":\"Error selector: `0xd86ad9cf`\",\"params\":{\"caller\":\"The address that attempted the unauthorized operation\"}}],\"UpgradeTargetNotApproved(address)\":[{\"details\":\"Error selector: `0xf74d7dd0`\",\"params\":{\"implementation\":\"The disallowed implementation address.\"}}]},\"events\":{\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to `approved`.\"},\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"params\":{\"account\":\"The account that the roles were changed for.\",\"newRoleBitmap\":\"The new roles for the account.\",\"oldRoleBitmap\":\"The old roles for the account.\",\"resource\":\"The resource that the roles were changed within.\"}},\"ExpiryUpdated(uint256,uint64,address)\":{\"params\":{\"newExpiry\":\"The new expiry of the label.\",\"sender\":\"The sender of the call to update the expiry.\",\"tokenId\":\"The token ID of the label.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label registered.\",\"labelHash\":\"The label hash registered.\",\"owner\":\"The owner of the label.\",\"sender\":\"The sender of the call to register.\",\"tokenId\":\"The token ID registered.\"}},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"params\":{\"expiry\":\"The expiry of the label.\",\"label\":\"The label reserved.\",\"labelHash\":\"The label hash reserved.\",\"sender\":\"The sender of the call to reserve.\",\"tokenId\":\"The token ID reserved.\"}},\"LabelUnregistered(uint256,address)\":{\"params\":{\"sender\":\"The sender of the call to unregister.\",\"tokenId\":\"The token ID unregistered.\"}},\"ParentUpdated(address,string,address)\":{\"params\":{\"label\":\"The new label.\",\"parent\":\"The new parent.\",\"sender\":\"The sender of the call to update the parent.\"}},\"ResolverUpdated(uint256,address,address)\":{\"params\":{\"resolver\":\"The new resolver.\",\"sender\":\"The sender of the call to update the resolver.\",\"tokenId\":\"The token ID of the label.\"}},\"SubregistryUpdated(uint256,address,address)\":{\"params\":{\"sender\":\"The sender of the call to update the subregistry.\",\"subregistry\":\"The new subregistry.\",\"tokenId\":\"The token ID of the label.\"}},\"TokenRegenerated(uint256,uint256)\":{\"params\":{\"newTokenId\":\"The new token ID.\",\"oldTokenId\":\"The old token ID.\"}},\"TokenResource(uint256,uint256)\":{\"params\":{\"resource\":\"The EAC resource.\",\"tokenId\":\"The token ID.\"}},\"TransferBatch(address,address,address,uint256[],uint256[])\":{\"details\":\"Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all transfers.\"},\"TransferSingle(address,address,address,uint256,uint256)\":{\"details\":\"Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.\"},\"URI(string,uint256)\":{\"details\":\"Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. If an {URI} event was emitted for `id`, the standard https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value returned by {IERC1155MetadataURI-uri}.\"},\"URIUpdated(string,address,address)\":{\"params\":{\"renderer\":\"The new render address.\",\"sender\":\"The sender of the call to update the URI.\",\"uri\":\"The new URI.\"}},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"balanceOf(address,uint256)\":{\"params\":{\"account\":\"The account to get the balance for.\",\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"balance The balance of the token for the account. This will only ever be 1 or 0.\"}},\"balanceOfBatch(address[],uint256[])\":{\"details\":\"`accounts` and `ids` must have the same length.\",\"params\":{\"accounts\":\"The accounts to get the balances for.\",\"ids\":\"The token IDs.\"},\"returns\":{\"_0\":\"batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0.\"}},\"canUpgradeFrom(address)\":{\"details\":\"Upgrade authorization is still enforced by the current implementation during the UUPS upgrade call, including the wrapper upgrade target allowlist.\",\"params\":{\"\":\"{previousImplementation} Ignored.\"},\"returns\":{\"allowed\":\"Always `true` for implementations in this wrapper registry family.\"}},\"constructor\":{\"params\":{\"ensV1Resolver\":\"The ENSv1 resolver.\",\"graveyard\":\"The ENSv1 `BaseRegistrar` token graveyard.\",\"labelStore\":\"The shared label database.\",\"nameWrapper\":\"The ENSv1 NameWrapper.\",\"namer\":\"The implementation namer.\",\"publicResolver\":\"The replacement `PublicResolver`.\",\"publicResolverSet\":\"The approved list of `PublicResolver` contracts.\",\"upgradeGate\":\"The upgrade target allowlist.\",\"verifiableFactory\":\"The VerifiableFactory.\"}},\"findExpiry(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The expiry of the label.\"}},\"findOwner(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The owner of the label.\"}},\"findTokenId(string)\":{\"params\":{\"label\":\"The label to query.\"},\"returns\":{\"_0\":\"The token ID of the label.\"}},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"details\":\"Only callable by ourself and invoked by our `IERC1155Receiver` handlers. TODO: gas analysis and optimization NOTE: converting this to an internal call requires catching many reverts\",\"params\":{\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\",\"mds\":\"The migration parameters for each name, indexed in parallel with `ids`.\"}},\"getAssigneeCount(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"counts\":\"The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints.\",\"mask\":\"The mask for the given role bitmap.\"}},\"getExpiry(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The expiry of the label, in seconds.\"}},\"getOwner(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token owner.\"}},\"getParent()\":{\"returns\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"getResolver(string)\":{\"details\":\"Return `V1_RESOLVER` upon visiting migratable children.\",\"params\":{\"label\":\"The label to fetch a resolver for.\"},\"returns\":{\"_0\":\"resolver The address of a resolver responsible for this label, or `address(0)` if none exists.\"}},\"getResource(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The resource.\"}},\"getState(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"state\":\"The state of the label.\"}},\"getStatus(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The status of the label.\"}},\"getSubregistry(string)\":{\"params\":{\"label\":\"The label to resolve.\"},\"returns\":{\"_0\":\"The address of the registry for this label, or `address(0)` if none exists.\"}},\"getTokenId(uint256)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"},\"returns\":{\"_0\":\"The token ID.\"}},\"grantRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to grant roles to.\",\"resource\":\"The resource to grant roles within.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"grantRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being granted.\",\"params\":{\"account\":\"The account to grant roles to.\",\"roleBitmap\":\"The roles bitmap to grant.\"},\"returns\":{\"_0\":\"`true` if the roles were granted, `false` otherwise.\"}},\"hasAssignees(uint256,uint256)\":{\"params\":{\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if any of the roles in the given role bitmap has assignees, `false` otherwise.\"}},\"hasRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"resource\":\"The resource to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise.\"}},\"hasRootRoles(uint256,address)\":{\"params\":{\"account\":\"The account to check.\",\"roleBitmap\":\"The roles bitmap to check.\"},\"returns\":{\"_0\":\"`true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise.\"}},\"initialize(bytes32,address,string,uint256)\":{\"params\":{\"childLabel\":\"The subdomain for this registry.\",\"node\":\"Namehash of this registry.\",\"parentRegistry\":\"The parent of this registry.\",\"roleBitmap\":\"The role bitmap granted to the virtual admin.\"}},\"isApprovedForAll(address,address)\":{\"params\":{\"account\":\"The account to get the approval for.\",\"operator\":\"The operator to get the approval for.\"},\"returns\":{\"_0\":\"approved The approval status.\"}},\"isContractNamer(address)\":{\"params\":{\"namer\":\"The address to check.\"},\"returns\":{\"_0\":\"`true` if authorized.\"}},\"latestOwnerOf(uint256)\":{\"params\":{\"tokenId\":\"The token ID to query.\"},\"returns\":{\"_0\":\"The latest owner address.\"}},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name.\",\"ids\":\"The NameWrapper token IDs (namehashes) of the names being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\"}},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"details\":\"Only callable by NameWrapper. Reverts require `WrappedErrorLib.unwrap()` before processing.\",\"params\":{\"data\":\"ABI-encoded `LibMigration.Data` struct containing migration parameters.\",\"id\":\"The NameWrapper token ID (namehash) of the name being migrated.\"},\"returns\":{\"_0\":\"`bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\"}},\"ownerOf(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The owner of the token.\"}},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"register(string,address,address,address,uint256,uint64)\":{\"details\":\"Blocks registration of emancipated children.\",\"params\":{\"expiry\":\"The expiry of the label, in seconds.\",\"label\":\"The label to register.\",\"owner\":\"The address of the owner of the label.\",\"registry\":\"The registry to set as the label.\",\"resolver\":\"The resolver to set for the label.\",\"roleBitmap\":\"The role bitmap to set for the label.\"},\"returns\":{\"tokenId\":\"The token ID.\"}},\"renew(uint256,uint64)\":{\"details\":\"If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"newExpiry\":\"The new expiry, in seconds.\"}},\"revokeRoles(uint256,uint256,address)\":{\"params\":{\"account\":\"The account to revoke roles from.\",\"resource\":\"The resource to revoke roles within.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"revokeRootRoles(uint256,address)\":{\"details\":\"The caller must have all the necessary admin roles for the roles being revoked.\",\"params\":{\"account\":\"The account to revoke roles from.\",\"roleBitmap\":\"The roles bitmap to revoke.\"},\"returns\":{\"_0\":\"`true` if the roles were revoked, `false` otherwise.\"}},\"roleCount(uint256)\":{\"params\":{\"resource\":\"The resource to get the role count for.\"},\"returns\":{\"_0\":\"count The role count bitmap for the resource.\"}},\"roles(uint256,address)\":{\"params\":{\"account\":\"The account to get the roles for.\",\"resource\":\"The resource to get the roles for.\"},\"returns\":{\"_0\":\"The roles bitmap for the account in the resource.\"}},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"details\":\"`ids` and `values` must have the same length.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the tokens from.\",\"ids\":\"The token IDs.\",\"to\":\"The address to transfer the tokens to.\",\"values\":\"The amounts of tokens to transfer.\"}},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"details\":\"`to` cannot be the zero address.If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`.`from` must have a balance of tokens of type `id` of at least `value` amount.If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the acceptance magic value.\",\"params\":{\"data\":\"Additional data to pass to the receiver.\",\"from\":\"The address to transfer the token from.\",\"id\":\"The token ID.\",\"to\":\"The address to transfer the token to.\",\"value\":\"The amount of tokens to transfer.\"}},\"setApprovalForAll(address,bool)\":{\"params\":{\"approved\":\"The approval status.\",\"operator\":\"The operator to set the approval for.\"}},\"setParent(address,string)\":{\"details\":\"Should emit `ParentUpdated`.\",\"params\":{\"label\":\"The canonical subdomain of this registry.\",\"parent\":\"The canonical parent of this registry.\"}},\"setResolver(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"resolver\":\"The new resolver.\"}},\"setSubregistry(uint256,address)\":{\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\",\"registry\":\"The new registry.\"}},\"setURI(string,address)\":{\"params\":{\"renderer\":\"The new renderer address.\",\"uri_\":\"The new URI.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"unregister(uint256)\":{\"details\":\"Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`.\",\"params\":{\"anyId\":\"The labelhash, token ID, or resource.\"}},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"uri(uint256)\":{\"params\":{\"id\":\"The token ID.\"},\"returns\":{\"_0\":\"The URI for the token.\"}}},\"stateVariables\":{\"_initialRoleBitmap\":{\"details\":\"The initial roles derived from the NameWrapper.\"},\"_node\":{\"details\":\"The namehash of this registry.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"CannotReduceExpiry(uint64,uint64)\":[{\"notice\":\"Label expiry cannot be reduced.\"}],\"CannotSetPastExpiry(uint64)\":[{\"notice\":\"Label expiry cannot be before now.\"}],\"FrozenTokenApproval(uint256)\":[{\"notice\":\"NameWrapper token has existing approval and burned `CANNOT_APPROVE`.\"}],\"InvalidOwner()\":[{\"notice\":\"Expected valid owner.\"}],\"LabelAlreadyRegistered(string)\":[{\"notice\":\"Label is already registered.\"}],\"LabelAlreadyReserved(string)\":[{\"notice\":\"Label cannot be reserved again.\"}],\"LabelExpired(uint256)\":[{\"notice\":\"Label is expired/unregistered.\"}],\"NameDataMismatch(uint256)\":[{\"notice\":\"NameWrapper or BaseRegistrar token does not match supplied data.\"}],\"NameNotLocked(uint256)\":[{\"notice\":\"NameWrapper token is unlocked.\"}],\"NameRequiresMigration()\":[{\"notice\":\"Name cannot be registered because unmigrated NameWrapper token exists.\"}],\"TransferDisallowed(uint256,address)\":[{\"notice\":\"Transfer is not allowed due to missing transfer admin role.\"}],\"UnauthorizedCaller(address)\":[{\"notice\":\"Thrown when a caller is not authorized to perform the requested operation\"}],\"UpgradeTargetNotApproved(address)\":[{\"notice\":\"Upgrade target is not approved for `WrapperRegistry` proxies.\"}]},\"events\":{\"EACRolesChanged(uint256,address,uint256,uint256)\":{\"notice\":\"Emitted when roles are changed.\"},\"ExpiryUpdated(uint256,uint64,address)\":{\"notice\":\"Expiry of label was changed.\"},\"LabelRegistered(uint256,bytes32,string,address,uint64,address)\":{\"notice\":\"A label was registered.\"},\"LabelReserved(uint256,bytes32,string,uint64,address)\":{\"notice\":\"A label was reserved.\"},\"LabelUnregistered(uint256,address)\":{\"notice\":\"A label was unregistered.\"},\"ParentUpdated(address,string,address)\":{\"notice\":\"Parent was changed.\"},\"RegistryCreated()\":{\"notice\":\"A registry was created/initialized.\"},\"ResolverUpdated(uint256,address,address)\":{\"notice\":\"Resolver of label was changed.\"},\"SubregistryUpdated(uint256,address,address)\":{\"notice\":\"Subregistry of label was changed.\"},\"TokenRegenerated(uint256,uint256)\":{\"notice\":\"Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance.\"},\"TokenResource(uint256,uint256)\":{\"notice\":\"Associate a token with an EAC resource.\"},\"URIUpdated(string,address,address)\":{\"notice\":\"URI was changed.\"}},\"kind\":\"user\",\"methods\":{\"GRAVEYARD()\":{\"notice\":\"The ENSv1 `BaseRegistrar` token graveyard.\"},\"LABEL_STORE()\":{\"notice\":\"The shared label database.\"},\"NAME_WRAPPER()\":{\"notice\":\"The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens.\"},\"PUBLIC_RESOLVER()\":{\"notice\":\"The replacement `PublicResolver`.\"},\"PUBLIC_RESOLVER_SET()\":{\"notice\":\"The list of `PublicResolver` contracts that require replacement.\"},\"ROOT_RESOURCE()\":{\"notice\":\"The `ROOT_RESOURCE`.\"},\"UPGRADE_GATE()\":{\"notice\":\"Gate for approved implementation upgrade targets.\"},\"V1_RESOLVER()\":{\"notice\":\"Fallback resolver for ENSv1 resolution.\"},\"VERIFIABLE_FACTORY()\":{\"notice\":\"The shared factory for verifiable deployments.\"},\"WRAPPER_REGISTRY_IMPL()\":{\"notice\":\"The `WrapperRegistry` implementation contract.\"},\"balanceOf(address,uint256)\":{\"notice\":\"Returns the balance of a token for an account.\"},\"balanceOfBatch(address[],uint256[])\":{\"notice\":\"Returns the balances of a batch of tokens for an account.\"},\"canUpgradeFrom(address)\":{\"notice\":\"Declares this implementation as an eligible verifiable proxy upgrade target.\"},\"findExpiry(string)\":{\"notice\":\"Fetches the label expiry.\"},\"findOwner(string)\":{\"notice\":\"Fetches the label owner.\"},\"findTokenId(string)\":{\"notice\":\"Fetches the token ID for a label.\"},\"finishERC1155Migration(uint256[],(string,address,address,address)[])\":{\"notice\":\"Convert NameWrapper tokens to their equivalent ENSv2 form.\"},\"getAssigneeCount(uint256,uint256)\":{\"notice\":\"Returns the number of assignees for the roles in the given role bitmap.\"},\"getExpiry(uint256)\":{\"notice\":\"Get expiry of label.\"},\"getOwner(uint256)\":{\"notice\":\"Get token owner from `anyId`.\"},\"getParent()\":{\"notice\":\"Get canonical \\\"location\\\" of this registry.\"},\"getResolver(string)\":{\"notice\":\"Fetches the resolver responsible for the specified label.\"},\"getResource(uint256)\":{\"notice\":\"Get `resource` from `anyId`.\"},\"getState(uint256)\":{\"notice\":\"Get the state of a label.\"},\"getStatus(uint256)\":{\"notice\":\"Get `Status` from `anyId`.\"},\"getSubregistry(string)\":{\"notice\":\"Fetches the registry for a label.\"},\"getTokenId(uint256)\":{\"notice\":\"Get `tokenId` from `anyId`.\"},\"getWrappedName()\":{\"notice\":\"Returns the DNS-encoded name for this registry.\"},\"getWrappedNode()\":{\"notice\":\"Returns the NameWrapper node (namehash).\"},\"grantRoles(uint256,uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account`.\"},\"grantRootRoles(uint256,address)\":{\"notice\":\"Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE.\"},\"hasAssignees(uint256,uint256)\":{\"notice\":\"Checks if any of the roles in the given role bitmap has assignees.\"},\"hasRoles(uint256,uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`.\"},\"hasRootRoles(uint256,address)\":{\"notice\":\"Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`.\"},\"initialize(bytes32,address,string,uint256)\":{\"notice\":\"Initializes WrapperRegistry.\"},\"isApprovedForAll(address,address)\":{\"notice\":\"Returns the approval for all operator.\"},\"isContractNamer(address)\":{\"notice\":\"Determine if an account is authorized to name this contract. Called by reverse registrars.\"},\"latestOwnerOf(uint256)\":{\"notice\":\"Get the latest owner of a token. If the token was burned, returns null.\"},\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`.\"},\"onERC1155Received(address,address,uint256,uint256,bytes)\":{\"notice\":\"Migrate one NameWrapper token via `safeTransferFrom()`.\"},\"ownerOf(uint256)\":{\"notice\":\"Returns the owner of a token.\"},\"register(string,address,address,address,uint256,uint64)\":{\"notice\":\"Registers a new label.\"},\"renew(uint256,uint64)\":{\"notice\":\"Renew a label.\"},\"revokeRoles(uint256,uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account`.\"},\"revokeRootRoles(uint256,address)\":{\"notice\":\"Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE.\"},\"roleCount(uint256)\":{\"notice\":\"Returns the role count bitmap for a resource.\"},\"roles(uint256,address)\":{\"notice\":\"Returns the roles bitmap for an account in a resource.\"},\"safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)\":{\"notice\":\"Transfers multiple tokens from one address to another.\"},\"safeTransferFrom(address,address,uint256,uint256,bytes)\":{\"notice\":\"Transfers a single token from one address to another.\"},\"setApprovalForAll(address,bool)\":{\"notice\":\"Sets the approval for all operator.\"},\"setParent(address,string)\":{\"notice\":\"Change canonical \\\"location\\\".\"},\"setResolver(uint256,address)\":{\"notice\":\"Change resolver of label.\"},\"setSubregistry(uint256,address)\":{\"notice\":\"Change registry of label.\"},\"setURI(string,address)\":{\"notice\":\"Set the URI for the registry.\"},\"unregister(uint256)\":{\"notice\":\"Delete a label.\"},\"uri(uint256)\":{\"notice\":\"Returns the URI for a token.\"}},\"notice\":\"UUPS-upgradeable registry that wraps an ENSv1 NameWrapper, supporting migration of wrapped names into the namechain registry system.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"project/src/registry/WrapperRegistry.sol\":\"WrapperRegistry\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":100},\"remappings\":[\"project/:@ens/contracts/=project/lib/ens-contracts/contracts/\",\"project/:@ensdomains/verifiable-factory/=project/lib/verifiable-factory/src/\",\"project/:@openzeppelin/contracts-upgradeable/=project/lib/openzeppelin-contracts-upgradeable/contracts/\",\"project/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts/contracts/\",\"project/lib/ens-contracts/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-v4/contracts/\",\"project/lib/openzeppelin-contracts-upgradeable/:@openzeppelin/contracts/=project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/\"]},\"sources\":{\"project/lib/ens-contracts/contracts/ethregistrar/IBaseRegistrar.sol\":{\"keccak256\":\"0x984447817adfb8fc76447da9c24a492379bcfa4cd4e7ed8e795ea1981be3db83\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://10dc5a91b042cc3b5de7c06163532355e9d616ee2182dc28910dddf7dc4c6197\",\"dweb:/ipfs/QmQTuQRA96EFZxGaMnenrz33keRD2GMVnNygLFu4fkywYv\"]},\"project/lib/ens-contracts/contracts/registry/ENS.sol\":{\"keccak256\":\"0x8e208b44d5dbf22552fe72d79b45c640855b84fbc9ee21f4c3bb4bfe81cbe8db\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fcf03e1a9386d80ff6b8e31870063424454f69d2626c0efb2c8cf55e69151489\",\"dweb:/ipfs/QmVYgfMSc1ve5JWePqiAGSXEfD76emw3oLsCM1krstmJq5\"]},\"project/lib/ens-contracts/contracts/utils/BytesUtils.sol\":{\"keccak256\":\"0xcda2585a719e1a8974b5b44357e5d21417e1308b1d1f4d26b244d4ff0bb5b02d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://603aabc890496db91c17f8b946bfee9e33d2192275e59fc172d1fb4fba9e4f0d\",\"dweb:/ipfs/QmZZuSHAGWWhgQdQKYU3KzNHssyW1L5EGbVFaQZADs4AGe\"]},\"project/lib/ens-contracts/contracts/utils/HexUtils.sol\":{\"keccak256\":\"0xab784cab15b7a06154be3555edf0d25bcdad8e6bf116aa2016119a233875b02b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8042fdeb4d5e58dd33105c1b903ce3bece8c894e7493b7aa888a03cf09aff793\",\"dweb:/ipfs/QmW9YsQaERFrYoxoZooReX9m7eteK6JPo2RbaUhm9NcNe8\"]},\"project/lib/ens-contracts/contracts/utils/LibMem/LibMem.sol\":{\"keccak256\":\"0x066f29ad3a39392786ff3caf9ba120104ffaa55502f71158631411db46d1ec89\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://561155e2b3dce64c470feb854544ca2474e0a8e2e31a92f6304ad1955631c619\",\"dweb:/ipfs/QmPDfTbsiQGHcdvq7piJvXDgD465f7qdr7FDai3dtvBgfX\"]},\"project/lib/ens-contracts/contracts/utils/NameCoder.sol\":{\"keccak256\":\"0xe2152baacde56f8725de800767c8155f916b6e18c1348cdec82e16d2d3bee35a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3e7594410b4f3efd266274e25bed905e4d1d1bbb071d0de35b6824003fcb4409\",\"dweb:/ipfs/QmNNtwjjf1xdSmFVj19V9uBkzp1uA27aAgPHAgRMCMrug2\"]},\"project/lib/ens-contracts/contracts/wrapper/IMetadataService.sol\":{\"keccak256\":\"0xb3f1cf6df01ed7b15e5f2318f6823afbdb586ca38c2124c67955c645647ae9a2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://71aa1053dd87829c5eb25d32840d7b0d33cd9d54d22e905a01436bf97cc32b8c\",\"dweb:/ipfs/QmeMNnGKqf3oZyYwDQzEuQhti58UCCMRCMAD2EBx5T8dSH\"]},\"project/lib/ens-contracts/contracts/wrapper/INameWrapper.sol\":{\"keccak256\":\"0x70310eb67146d7290731c31841399640ac3b6a949eadc6598bc150123d185c57\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a85d9e2d6b235900131129386047fae5fb77438806b681ac566119868be5a502\",\"dweb:/ipfs/Qmd9ys5jeRx77TDVeRqWUme7a5LUDT4k7wQ91wVSayDpTR\"]},\"project/lib/ens-contracts/contracts/wrapper/INameWrapperUpgrade.sol\":{\"keccak256\":\"0x42e0cec6cd9d1a62d51d45b678f69d3e4ad5555e659b197e41257b308346bb8a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5afeadfdf2232a2333afb5345b65a25f7199b62ed6fde403273b762c91f5e9af\",\"dweb:/ipfs/QmWKhi3FuqX2KgRrBdh65gB3pmiwA2QMYPeiDbsMKv6a88\"]},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x13c2d19041c51b246233f96874a66c0094b8a5ff78af3b85ea27867f302dcbbb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f1bc47de2e6e12b3680e47a4dd5b6e3c1e85b65851378aa1d617309edbc1200d\",\"dweb:/ipfs/QmSPcJ9HmkmsSDvMS4KZijnxoGMAEn8HbQuY4fe8DroZEE\"]},\"project/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"keccak256\":\"0xe1448f559716952220b5c696a5cc34d1f11f958bfbfcd05988543f6fd8bfff96\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ebd19cec65d3998dad25dc9beecd33055b1900f26c3f61377c78926ca0637c9a\",\"dweb:/ipfs/QmUda1jFjWf2ptQrahTgU6953SZY7ZWksRaTo2dKGX4BMK\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol\":{\"keccak256\":\"0xb25a4f11fa80c702bf5cd85adec90e6f6f507f32f4a8e6f5dbc31e8c10029486\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6917f8a323e7811f041aecd4d9fd6e92455a6fba38a797ac6f6e208c7912b79d\",\"dweb:/ipfs/QmShuYv55wYHGi4EFkDB8QfF7ZCHoKk2efyz3AWY1ExSq7\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol\":{\"keccak256\":\"0xc42facb5094f2f35f066a7155bda23545e39a3156faef3ddc00185544443ba7d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d3b36282ab029b46bd082619a308a2ea11c309967b9425b7b7a6eb0b0c1c3196\",\"dweb:/ipfs/QmP2YVfDB2FoREax3vJu7QhDnyYRMw52WPrCD4vdT2kuDA\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Utils.sol\":{\"keccak256\":\"0x8decfa54cec979c824b044b8128cd91d713f72c71fd7dfa54974624d8c949898\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://271f914261a19d87117a777e0924ada545c16191ef9b00cc40b0134fc14ebc70\",\"dweb:/ipfs/QmdvVNWHGHQrGGPonZJs5NuzTevTjZRM2zayKrDJf7WBA2\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"keccak256\":\"0xc59a78b07b44b2cf2e8ab4175fca91e8eca1eee2df7357b8d2a8833e5ea1f64c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5aa4f07e65444784c29cd7bfcc2341b34381e4e5b5da9f0c5bd00d7f430e66fa\",\"dweb:/ipfs/QmWRMh4Q9DpaU9GvsiXmDdoNYMyyece9if7hnfLz7uqzWM\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xaaa1d17c1129b127a4a401db2fbd72960e2671474be3d08cae71ccdc42f7624c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cb2f27cd3952aa667e198fba0d9b7bcec52fbb12c16f013c25fe6fb52b29cc0e\",\"dweb:/ipfs/QmeuohBFoeyDPZA9JNCTEDz3VBfBD4EABWuWXVhHAuEpKR\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/Errors.sol\":{\"keccak256\":\"0x6afa713bfd42cf0f7656efa91201007ac465e42049d7de1d50753a373648c123\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ba1d02f4847670a1b83dec9f7d37f0b0418d6043447b69f3a29a5f9efc547fcf\",\"dweb:/ipfs/QmQ7iH2keLNUKgq2xSWcRmuBE5eZ3F5whYAkAGzCNNoEWB\"]},\"project/lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC1155/IERC1155.sol\":{\"keccak256\":\"0xcab667ddad478ff0d39c2053ca77fac778af8483c18ab07d810277b4216fd582\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://919c7ea27c77275c3c341da0c4a26a66a20ed27605fbe8becf11f58ec3bc65bf\",\"dweb:/ipfs/QmRLKyVE2n7e2Jo4bLNn8eLgqqhNGYnVQyjJPWdr8poskf\"]},\"project/lib/openzeppelin-contracts-v4/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7e66dfde185df46104c11bc89d08fa0760737aa59a2b8546a656473d810a8ea4\",\"dweb:/ipfs/QmXvyqtXPaPss2PD7eqPoSao5Szm2n6UMoiG8TZZDjmChR\"]},\"project/lib/openzeppelin-contracts-v4/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"project/lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC1363.sol\":{\"keccak256\":\"0x9b6b3e7803bc5f2f8cd7ad57db8ac1def61a9930a5a3107df4882e028a9605d7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da62d6be1f5c6edf577f0cb45666a8aa9c2086a4bac87d95d65f02e2f4c36a4b\",\"dweb:/ipfs/QmNkpvBpoCMvX8JwAFNSc5XxJ2q5BXJpL5L1txb4QkqVFF\"]},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0xde7e9fd9aee8d4f40772f96bb3b58836cbc6dfc0227014a061947f8821ea9724\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://11fea9f8bc98949ac6709f0c1699db7430d2948137aa94d5a9e95a91f61a710a\",\"dweb:/ipfs/QmQdfRXxQjwP6yn3DVo1GHPpriKNcFghSPi94Z1oKEFUNS\"]},\"project/lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol\":{\"keccak256\":\"0xce41876e78d1badc0512229b4d14e4daf83bc1003d7f83978d18e0e56f965b9c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a2608291cb038b388d80b79a06b6118a42f7894ff67b7da10ec0dbbf5b2973ba\",\"dweb:/ipfs/QmWohqcBLbcxmA4eGPhZDXe5RYMMEEpFq22nfkaUMvTfw1\"]},\"project/lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol\":{\"keccak256\":\"0x880da465c203cec76b10d72dbd87c80f387df4102274f23eea1f9c9b0918792b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://399594cd8bb0143bc9e55e0f1d071d0d8c850a394fb7a319d50edd55d9ed822b\",\"dweb:/ipfs/QmbPZzgtT6LEm9CMqWfagQFwETbV1ztpECBB1DtQHrKiRz\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol\":{\"keccak256\":\"0x1d7a05b3219532ea5ece50a80cf390cac9109dc74e07763adfa463ab5a3af0dc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://687e2ec572d0e63827bb0025b91f2246be4c938f830ef4b4c288ee2e3727d5ca\",\"dweb:/ipfs/QmZXWSAQ9ftVrqNEa5ZTpN4wxvzCgsSW12cgiSRkrLTpQ8\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"keccak256\":\"0x61a23d601c2ab69dd726ac55058604cbda98e1d728ba31a51c379a3f9eeea715\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d8cbb06152d82ebdd5ba1d33454e5759492040f309a82637c7e99c948a04fa20\",\"dweb:/ipfs/QmQQuLr6WSfLu97pMEh6XLefk99TSj9k5Qu1zXGPepwGiK\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol\":{\"keccak256\":\"0x35d120c427299af1525aaf07955314d9e36a62f14408eb93dec71a2e001f74d3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://743e38acf441eece428c008be399c40a3ca5b2d595d58faf656cbdbac1a45374\",\"dweb:/ipfs/QmcWDuWkndox3dxa5P7ZgpKy3iuQKkxBq1cR9hPV1ZzAfa\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC1155/utils/ERC1155Utils.sol\":{\"keccak256\":\"0x22f099c02c252dd1f6ddc464916ce683294a63b23b3c6ee3d290b77398e2474b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://82d2ba4b77ecc4f70211e0de1a920e3ea29eb86c3e16ef8f2a7d746c72a97f1e\",\"dweb:/ipfs/QmYBqATARQEnxd33jW6iYCuEPaL6KdYyYSoQrjFXZka3of\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0xe06a3f08a987af6ad2e1c1e774405d4fe08f1694b67517438b467cecf0da0ef7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://df6f0c459663c9858b6cba2cda1d14a7d05a985bed6d2de72bd8e78c25ee79db\",\"dweb:/ipfs/QmeTTxZ7qVk9rjEv2R4CpCwdf8UMCcRqDNMvzNxHc3Fnn9\"]},\"project/lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0x982c5cb790ab941d1e04f807120a71709d4c313ba0bfc16006447ffbd27fbbd5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8150ceb4ac947e8a442b2a9c017e01e880b2be2dd958f1fa9bc405f4c5a86508\",\"dweb:/ipfs/QmbcBmFX66AY6Kbhnd5gx7zpkgqnUafo43XnmayAM7zVdB\"]},\"project/lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0x55a4fdb408e3db950b48f4a6131e538980be8c5f48ee59829d92d66477140cd6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3e1ad251e692822ce1494135a4ecb5b97c19b90aa82418fd2959ce32017953fd\",\"dweb:/ipfs/QmT6N7mf6heZYhY2BAQ5kwZp9o3SXzGVdkMqUszx67WRDN\"]},\"project/lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"project/lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"project/lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"project/lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x67672e4ca1dafdcc661d4eba8475cfac631fa0933309258e3af7644b92e1fb26\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://30192451f05ea5ddb0c18bd0f9003f098505836ba19c08a9c365adf829454da2\",\"dweb:/ipfs/QmfCuZSCTyCdFoSKn7MSaN6hZksnQn9ZhrZDAdRTCbwGu2\"]},\"project/lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0xddce8e17e3d3f9ed818b4f4c4478a8262aab8b11ed322f1bf5ed705bb4bd97fa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8084aa71a4cc7d2980972412a88fe4f114869faea3fefa5436431644eb5c0287\",\"dweb:/ipfs/Qmbqfs5dRdPvHVKY8kTaeyc65NdqXRQwRK7h9s5UJEhD1p\"]},\"project/lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x79796192ec90263f21b464d5bc90b777a525971d3de8232be80d9c4f9fb353b8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f6fda447a62815e8064f47eff0dd1cf58d9207ad69b5d32280f8d7ed1d1e4621\",\"dweb:/ipfs/QmfDRc7pxfaXB2Dh9np5Uf29Na3pQ7tafRS684wd3GLjVL\"]},\"project/lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x1225214420c83ebcca88f2ae2b50f053aaa7df7bd684c3e878d334627f2edfc6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c5fab4970634f9ab9a620983dc1c8a30153981a0b1a521666e269d0a11399d3\",\"dweb:/ipfs/QmVRnBC575MESGkEHndjujtR7qub2FzU9RWy9eKLp4hPZB\"]},\"project/lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0x195533c86d0ef72bcc06456a4f66a9b941f38eb403739b00f21fd7c1abd1ae54\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b1d578337048cad08c1c03041cca5978eff5428aa130c781b271ad9e5566e1f8\",\"dweb:/ipfs/QmPFKL2r9CBsMwmUqqdcFPfHZB2qcs9g1HDrPxzWSxomvy\"]},\"project/lib/verifiable-factory/src/IProxyAuthorization.sol\":{\"keccak256\":\"0x4673387a703cc87c280a44e6682cdf77797600b0a75de37f2d64af731fa8cb9e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40f30fe28a969241e3dcfc38561ccb8e0104828a09ea27ec242acf4cf17813b3\",\"dweb:/ipfs/QmZakqRvVvZaoePUKMsUJ6F5iEuGKCcDBb9z4WxB9wvXak\"]},\"project/lib/verifiable-factory/src/IVerifiableFactory.sol\":{\"keccak256\":\"0xe6c1b487e41bb6e89383f8f63942d6db67bd140539df2755b82d999624c6050a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dca6e0fc73587d2c427468d8861d575600e8a5ff522309cae9a5741d1056b3b8\",\"dweb:/ipfs/QmemFDNL52CMWDZvbnMSBCSXL7RLXkRDugWxDp6d35hL8T\"]},\"project/src/CommonErrors.sol\":{\"keccak256\":\"0xab84f8f995fb2932d348f783897bd4bb9ddb73a474fd2b3b6dcf87d4fb3538b0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://294480f5f2584f2eb48760131c1974384180f90021fc6c0a8ad652636797099c\",\"dweb:/ipfs/QmX5LKhT7nSU88ERQARjyhtEB7ePDmFkF3nE5aYhzWTjvU\"]},\"project/src/access-control/EnhancedAccessControl.sol\":{\"keccak256\":\"0x934655016f502e7a2f8e5cbd294ef48e85f238821f5608de5675c023f48037af\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://40009845464d00f22004a71922dc5f572b56d75a482a5cb2fa17dc572da6178d\",\"dweb:/ipfs/QmUq4xPk9vxfEjoAEumN3J8CfXFdwjzHRBWcpcbGv3GYib\"]},\"project/src/access-control/interfaces/IEnhancedAccessControl.sol\":{\"keccak256\":\"0x921ed70f906f9449dbe6d560a7b8917a92ccc7c41779d3e2423ed20185983460\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://72fa6513382456e23d04f041fafcc86973593ea04690a46256593b3d6b7f690a\",\"dweb:/ipfs/QmUHZ6d5VhQd38AejUARFDNYSagMYfRk7zywNdMniko9os\"]},\"project/src/access-control/libraries/EACBaseRolesLib.sol\":{\"keccak256\":\"0xc14f05abd508e75c9f16a35e31d0fb9f1f1dd904b65d058201c788a9ddd562eb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://522f2dd2bdb06c7bc0a3feef73e5445fbb21f44d939c7d97ed0798d05a498524\",\"dweb:/ipfs/QmeiMzic95fRSoKruyqReuza6c3AfaJi2be9fmrcuVaQhb\"]},\"project/src/erc1155/ERC1155Singleton.sol\":{\"keccak256\":\"0x7e1c260a1b1791a63a658f049251b2b5390d9e11cdb20d99a2d115083251d37e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://334b33cb5954d668993933f3bb7ac4681b8b1d1d4e9babaa4b0ca50496005fee\",\"dweb:/ipfs/QmTUmVA87TJJC552saKMXTZAy8yrgfvNqdpuTd1dutcsGd\"]},\"project/src/erc1155/interfaces/IERC1155Singleton.sol\":{\"keccak256\":\"0x5b96cdd5e414b3e02d2e25fa14c16a5c2fd799209c561a3eeb8d5e9195b4fd79\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0a6e8c9d901d39d587f24337783a8b91cbbb95683b746481754071693790bfe5\",\"dweb:/ipfs/QmZy1bPciKVPF5W5DDekDquHBfwk1cM7XNBqhzoC8RP5ES\"]},\"project/src/migration/AbstractWrapperReceiver.sol\":{\"keccak256\":\"0x0c15f9f657ba58bf5081cbff88c385c9e673ba87aed2032397ec2c5448d7fe1a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fd118194db53d6d1cf7ebc891cc673cc356cd2a3363f75f4646c0cf1c52cced3\",\"dweb:/ipfs/QmSepYZ5w8bf9rYwaEEyCJe7U1Jpy8wP2LxUyd2YBX2Nkp\"]},\"project/src/migration/LockedWrapperReceiver.sol\":{\"keccak256\":\"0x73f231bff59f29d80527b5b385b5b9aa7878ec727cf4732da2a07a55c229f5cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3f2496ed4947c1835794d4c2210fa8607eb905a8adfad55b48a7e18562280fc7\",\"dweb:/ipfs/QmdkK8d13wvGYAXDYXcVAqu5oijbVKTmAVfws9NsY86w4G\"]},\"project/src/migration/libraries/LibMigration.sol\":{\"keccak256\":\"0x82c10ce5a4d26861a12eb774b5ee317ee6bc312bfe409d8cf20d269e6201150e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c0751f78faa3a3d37b4bbd9c28ebab22af6d47bd33c97fcaee433b90dbe03c61\",\"dweb:/ipfs/QmcGVP9FskRV1qTbicgVMMVWJnFd5tk9LBWb1ckKwkKC2c\"]},\"project/src/registrar/AbstractETHRegistrar.sol\":{\"keccak256\":\"0x03c6381eaa4b6f36c842a32396b8f9a5a573a4257d7a9d263e77c015486a9458\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://26c7b9df928f94daceecce8c0e655f066073c661aefb735a7bf7638f80f31d13\",\"dweb:/ipfs/QmeDv6zHXTwz6mqeMPMnVzBTUuQqRxoG1PYQ1JHonfXa2b\"]},\"project/src/registrar/ETHRegistrar.sol\":{\"keccak256\":\"0x601a5929b1b2eba60dd566dd6967c3dba1a471d6b24ffe292f4aa660af1cd5f1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a2cdc1a4c3b08fa9f5f95d4099be764c43915ea8cb0d3148efd267e73c90f2f1\",\"dweb:/ipfs/QmQJ9iAVDHwRrxMQF3V5RraXB8jjoJN7L1zHpDUp7izmeo\"]},\"project/src/registrar/interfaces/IETHRegistrar.sol\":{\"keccak256\":\"0x7e824c5019f8eb7d7a283451700234716353e01d649c811b5ced5cf58b476289\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a8d5f251631a78e681db6dc3680f4dbdd67eaee6ecf4491260d2347a640dfe69\",\"dweb:/ipfs/QmZDUmKJpEUJoHJ8wAkWCN8jgUut4xkHgjw94RFphk2oqz\"]},\"project/src/registrar/interfaces/IETHRenewer.sol\":{\"keccak256\":\"0x05aaf084d6a9847c1e80da21b5079a98c2da5c8c392b8cf431e65f633c6b795e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f67fa758790fef15907887f9f93dcfbdc4907d700addce8b593f86c9299d2f73\",\"dweb:/ipfs/QmPN3EXTMVLJucoRNqMWyuiQALNC7SRmKRHX7DbbCnc4NF\"]},\"project/src/registrar/interfaces/IRentPriceOracle.sol\":{\"keccak256\":\"0x822ce397c38c82d7830e93276c3574e790d85e461c4e1641e45f18c8c6a0a86c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dc0fdf679eddd0a120667b75767a176a4ab3d6da460b902517edbcf08a4ffc6b\",\"dweb:/ipfs/QmVzwpvBLoWyUfeGu1P5H6gvDqUD8B7KF5K7GbfPWGVHPu\"]},\"project/src/registry/ApprovedUpgradeGate.sol\":{\"keccak256\":\"0xecaf823f2344fb8336d18f889905de806299edfa6424796a24ce584eeda1eb2f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dfdc8a8bf29fa23db93e9ab126ba64c8866b31600b568046ba8e2e68d45d06e9\",\"dweb:/ipfs/QmT8WEix9RkyKB7CcAqS8V84Vj3NfGoNRkHh1CMQHMTqMZ\"]},\"project/src/registry/PermissionedRegistry.sol\":{\"keccak256\":\"0x7df0d16fb74e67612b88f2143f142410c70a4079a21c0980b2063824e291942b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac3264e0c2471d6b4aa495279e9a1493de0f5af8943c4eef75ccb5eab99fd3a9\",\"dweb:/ipfs/QmQwdBpZTLeLVAQTuyBBYjHyLqvSPsunR9RhyCLfoTL52P\"]},\"project/src/registry/WrapperRegistry.sol\":{\"keccak256\":\"0xa27a6b48c64bbe3b13169381b9ddbe4204b47844cefb9d7cd41ad3d5573335ee\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dd0284f8f8751621c17120311704bbec9f251e31b202112eabf5ec4205a01af1\",\"dweb:/ipfs/QmQQZmqJbEvfrRSdBAAKqpDz7UTJCjzSKq7Z7oJB3wgqQD\"]},\"project/src/registry/interfaces/IOwnedRegistry.sol\":{\"keccak256\":\"0xad90cea7ad01c97fbbaf1059beef1bdd4356e57993bcca2c55eb9a31b521018e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c9f7beea3328330b481de31e0d8dd2da1c416540ec41339d674bf2e13f2d8254\",\"dweb:/ipfs/Qmbftc1CSyFCAxRfwaXpyRMwRn1Rryxb7KLfwB5FM5Siio\"]},\"project/src/registry/interfaces/IPermissionedRegistry.sol\":{\"keccak256\":\"0xa4d7af7234ab28e8acd8231a0ccbf8e73d32f75a425f5773f29e2ecd43474b99\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://952c1834ca09f369b348fad8d6ffaa1023e8fdddf00adc6cd31fc4565ac0b20c\",\"dweb:/ipfs/QmNme2feYXueFemcmKraot2rcsHeZn2LRRfNkDAjEQb9Yb\"]},\"project/src/registry/interfaces/IRegistry.sol\":{\"keccak256\":\"0x13897e5eb2420a53ae4cb3dedd42d7595f72d414c4cea5bf564827e5109884d4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://dce497e971fcd006e10a3de52335eaf137d8f864641592270bc2e1a682e286fa\",\"dweb:/ipfs/QmbBXJCyQYjGgmFVWc33T9wu4qn1kgQ1TSEvwGkCfH6keK\"]},\"project/src/registry/interfaces/IRegistryEvents.sol\":{\"keccak256\":\"0x97399c29b20df503b4c1039c5cdad89eca90b5306f1a664983ba1b0a179947ad\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8755e9aa5e8541d05aa0470a189804d19c3305269e39bc1a5f1b096b90b446b8\",\"dweb:/ipfs/QmehAS72QYkDiEyD3kC29efwJGJHjzGboD1DcosNcHvpeh\"]},\"project/src/registry/interfaces/IRegistryURIRenderer.sol\":{\"keccak256\":\"0xa6ea64ff73d10fa58118ae9c0d0c2caa72f2f3488776227a22bd0cd9cd6586f6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fad26d2e735225585dc459ffd90467e9cecd407215120d02ef848ad8856eb718\",\"dweb:/ipfs/QmXNtf6FdxnFH7pGU6UNhWdGs46CUm8scJBV1zRpMTUXSe\"]},\"project/src/registry/interfaces/IStandardRegistry.sol\":{\"keccak256\":\"0x26a0bb73b7f2cc6320beceebdcc08ec42ffd7f15666ae9b75733789deef9b605\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://67ae762c75c392a1ccd9cd5d97dd8d5f737e3a7661799a688805110b0af5190f\",\"dweb:/ipfs/Qmc6Rug6vgZCkCWKHXfroav73ryKnL8jicWd9jnYZ5YKYq\"]},\"project/src/registry/interfaces/ITemporalRegistry.sol\":{\"keccak256\":\"0x184004674bac5d81776ed678f75de0518ca7d5b5e81130eb46ca0d34a06506b3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35dc26d4e8040334099ea2d86c1821d8c14c5dc1d47ffd5dbaaf5679f863775d\",\"dweb:/ipfs/QmXV5gJpSKEqBndXx3RuTpncBkty3XHd5FEdFP3NrL5yVk\"]},\"project/src/registry/interfaces/ITokenizedRegistry.sol\":{\"keccak256\":\"0x09cea76832b5e4def77ad453c1aace7d1ef4fafdf87edf0cf49d7ecdd1e96b38\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://18708b341e61090e3dc9c0efc7ed54d1f79bd5f2658fc3cb0ce1b57962630363\",\"dweb:/ipfs/QmXKYpjoCj2GDtMDqNRApijEmKMLvk1xQRXepztRJaEFrg\"]},\"project/src/registry/interfaces/IWrapperRegistry.sol\":{\"keccak256\":\"0xe3e62e3df99cfaa38a4684c6369a31b41b3c89e02f851698e28954475bdb9775\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://899300dfa86888acac0c5b785f9a1ab9d4a3a8fa3545c91087069d0fc01820bf\",\"dweb:/ipfs/QmfZAP5s7H1eXAgRjeETxWowzFyLdLKmKzf17jdkYcHH4S\"]},\"project/src/registry/libraries/RegistryRolesLib.sol\":{\"keccak256\":\"0x01771816c1c5b16c10f29b33083dbd1cc2eb64dbfec60fb45a1a1969cec06624\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a5bf16a254461adcc6d85326ccc78f0a99c668d400b89923ad29385ccfbc8e74\",\"dweb:/ipfs/QmWfCpXsVasE2FkY1beYQBUeMokM7miu2krmYMRxNuQdq1\"]},\"project/src/reverse-registrar/interfaces/IContractNamer.sol\":{\"keccak256\":\"0x1f8b1ba58195ba6e1b84767523ee59a40547db34f3a74a640edba0d335a0ede3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1b852474bf93262c0d27b220a6ab014a612a80f0a3d9bafda8eb5393b22ea22e\",\"dweb:/ipfs/QmTtJ69KTVTdHtwYVpyFBnPBJJX8cB3QU8SHMwyY2XbrN6\"]},\"project/src/utils/LibLabel.sol\":{\"keccak256\":\"0x75e19c9c12d2124ba00ef78294f4d67fcb40b46798184766f342143d4e8a0d97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ae17071bb62753a811050a33f8280256d6ffa43107f1b6409c60c2f3cb207662\",\"dweb:/ipfs/QmU6fQikpmCa7EebwLbtDbEmsfSgiQDUqXMbyyombnFAts\"]},\"project/src/utils/WrappedErrorLib.sol\":{\"keccak256\":\"0xf92862b6509cf553bd542925617318a2509bfdc6457e8b5d102c8e9658c610e4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e2d2a9fc03c7c18699d435477489167a1c9f97ac7558931c28a59f37a09c2b7f\",\"dweb:/ipfs/QmUYYjDXhoFHYSu2zzWSHzqwakY2gozQz3i5YGrE8S5ihb\"]},\"project/src/utils/interfaces/IAddressSet.sol\":{\"keccak256\":\"0xcb4f9c6364c1cf8a737591088f488ede7a7c6bc9d7d87f2dbdac731b492bd862\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://68ad6de4f0bbef675c58894dc19356d7e724fe8c19d5626d8450284b5f370fe5\",\"dweb:/ipfs/QmTNQ6LpeuAwC4X76nEKezwwixrAfQjmiXvcpvJ9KQGN1x\"]},\"project/src/utils/interfaces/ILabelStore.sol\":{\"keccak256\":\"0x271aab59b3c64e7649277ff027da10a3e413772bac9e0a2b98051a02e22d1e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://553cf61818e8737861d4b0acc58603e877db221b0779eccf01f0ccceeaf14915\",\"dweb:/ipfs/QmNzjoJrE7cAjPmZWKS8DKTJbEgGEfNZRqkUJ64BwfKGYf\"]}},\"version\":1}", + "storageLayout": { + "storage": [ + { + "astId": 11185, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_owners", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_uint256,t_address)" + }, + { + "astId": 11192, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_operatorApprovals", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 10017, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_roles", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))" + }, + { + "astId": 10022, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_roleCount", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_uint256)" + }, + { + "astId": 10027, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "__gap", + "offset": 0, + "slot": "4", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 14338, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_parentRegistry", + "offset": 0, + "slot": "260", + "type": "t_contract(IRegistry)16807" + }, + { + "astId": 14341, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_childLabel", + "offset": 0, + "slot": "261", + "type": "t_string_storage" + }, + { + "astId": 14344, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_uri", + "offset": 0, + "slot": "262", + "type": "t_string_storage" + }, + { + "astId": 14348, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_uriRenderer", + "offset": 0, + "slot": "263", + "type": "t_contract(IRegistryURIRenderer)16922" + }, + { + "astId": 14354, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_entries", + "offset": 0, + "slot": "264", + "type": "t_mapping(t_uint256,t_struct(Entry)14330_storage)" + }, + { + "astId": 14359, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "__gap", + "offset": 0, + "slot": "265", + "type": "t_array(t_uint256)256_storage" + }, + { + "astId": 16167, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_node", + "offset": 0, + "slot": "521", + "type": "t_bytes32" + }, + { + "astId": 16170, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "_initialRoleBitmap", + "offset": 0, + "slot": "522", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)256_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[256]", + "numberOfBytes": "8192" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IRegistry)16807": { + "encoding": "inplace", + "label": "contract IRegistry", + "numberOfBytes": "20" + }, + "t_contract(IRegistryURIRenderer)16922": { + "encoding": "inplace", + "label": "contract IRegistryURIRenderer", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "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_address)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_uint256,t_struct(Entry)14330_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct PermissionedRegistry.Entry)", + "numberOfBytes": "32", + "value": "t_struct(Entry)14330_storage" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(Entry)14330_storage": { + "encoding": "inplace", + "label": "struct PermissionedRegistry.Entry", + "members": [ + { + "astId": 14316, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "eacVersionId", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 14319, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "tokenVersionId", + "offset": 4, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 14323, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "subregistry", + "offset": 8, + "slot": "0", + "type": "t_contract(IRegistry)16807" + }, + { + "astId": 14326, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "expiry", + "offset": 0, + "slot": "1", + "type": "t_uint64" + }, + { + "astId": 14329, + "contract": "project/src/registry/WrapperRegistry.sol:WrapperRegistry", + "label": "resolver", + "offset": 8, + "slot": "1", + "type": "t_address" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "encoding": "inplace", + "label": "uint64", + "numberOfBytes": "8" + } + } + }, + "userdoc": { + "errors": { + "CannotReduceExpiry(uint64,uint64)": [ + { + "notice": "Label expiry cannot be reduced." + } + ], + "CannotSetPastExpiry(uint64)": [ + { + "notice": "Label expiry cannot be before now." + } + ], + "FrozenTokenApproval(uint256)": [ + { + "notice": "NameWrapper token has existing approval and burned `CANNOT_APPROVE`." + } + ], + "InvalidOwner()": [ + { + "notice": "Expected valid owner." + } + ], + "LabelAlreadyRegistered(string)": [ + { + "notice": "Label is already registered." + } + ], + "LabelAlreadyReserved(string)": [ + { + "notice": "Label cannot be reserved again." + } + ], + "LabelExpired(uint256)": [ + { + "notice": "Label is expired/unregistered." + } + ], + "NameDataMismatch(uint256)": [ + { + "notice": "NameWrapper or BaseRegistrar token does not match supplied data." + } + ], + "NameNotLocked(uint256)": [ + { + "notice": "NameWrapper token is unlocked." + } + ], + "NameRequiresMigration()": [ + { + "notice": "Name cannot be registered because unmigrated NameWrapper token exists." + } + ], + "TransferDisallowed(uint256,address)": [ + { + "notice": "Transfer is not allowed due to missing transfer admin role." + } + ], + "UnauthorizedCaller(address)": [ + { + "notice": "Thrown when a caller is not authorized to perform the requested operation" + } + ], + "UpgradeTargetNotApproved(address)": [ + { + "notice": "Upgrade target is not approved for `WrapperRegistry` proxies." + } + ] + }, + "events": { + "EACRolesChanged(uint256,address,uint256,uint256)": { + "notice": "Emitted when roles are changed." + }, + "ExpiryUpdated(uint256,uint64,address)": { + "notice": "Expiry of label was changed." + }, + "LabelRegistered(uint256,bytes32,string,address,uint64,address)": { + "notice": "A label was registered." + }, + "LabelReserved(uint256,bytes32,string,uint64,address)": { + "notice": "A label was reserved." + }, + "LabelUnregistered(uint256,address)": { + "notice": "A label was unregistered." + }, + "ParentUpdated(address,string,address)": { + "notice": "Parent was changed." + }, + "RegistryCreated()": { + "notice": "A registry was created/initialized." + }, + "ResolverUpdated(uint256,address,address)": { + "notice": "Resolver of label was changed." + }, + "SubregistryUpdated(uint256,address,address)": { + "notice": "Subregistry of label was changed." + }, + "TokenRegenerated(uint256,uint256)": { + "notice": "Token was regenerated with a new token ID. This occurs when roles are granted or revoked to maintain ERC1155 compliance." + }, + "TokenResource(uint256,uint256)": { + "notice": "Associate a token with an EAC resource." + }, + "URIUpdated(string,address,address)": { + "notice": "URI was changed." + } + }, + "kind": "user", + "methods": { + "GRAVEYARD()": { + "notice": "The ENSv1 `BaseRegistrar` token graveyard." + }, + "LABEL_STORE()": { + "notice": "The shared label database." + }, + "NAME_WRAPPER()": { + "notice": "The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens." + }, + "PUBLIC_RESOLVER()": { + "notice": "The replacement `PublicResolver`." + }, + "PUBLIC_RESOLVER_SET()": { + "notice": "The list of `PublicResolver` contracts that require replacement." + }, + "ROOT_RESOURCE()": { + "notice": "The `ROOT_RESOURCE`." + }, + "UPGRADE_GATE()": { + "notice": "Gate for approved implementation upgrade targets." + }, + "V1_RESOLVER()": { + "notice": "Fallback resolver for ENSv1 resolution." + }, + "VERIFIABLE_FACTORY()": { + "notice": "The shared factory for verifiable deployments." + }, + "WRAPPER_REGISTRY_IMPL()": { + "notice": "The `WrapperRegistry` implementation contract." + }, + "balanceOf(address,uint256)": { + "notice": "Returns the balance of a token for an account." + }, + "balanceOfBatch(address[],uint256[])": { + "notice": "Returns the balances of a batch of tokens for an account." + }, + "canUpgradeFrom(address)": { + "notice": "Declares this implementation as an eligible verifiable proxy upgrade target." + }, + "findExpiry(string)": { + "notice": "Fetches the label expiry." + }, + "findOwner(string)": { + "notice": "Fetches the label owner." + }, + "findTokenId(string)": { + "notice": "Fetches the token ID for a label." + }, + "finishERC1155Migration(uint256[],(string,address,address,address)[])": { + "notice": "Convert NameWrapper tokens to their equivalent ENSv2 form." + }, + "getAssigneeCount(uint256,uint256)": { + "notice": "Returns the number of assignees for the roles in the given role bitmap." + }, + "getExpiry(uint256)": { + "notice": "Get expiry of label." + }, + "getOwner(uint256)": { + "notice": "Get token owner from `anyId`." + }, + "getParent()": { + "notice": "Get canonical \"location\" of this registry." + }, + "getResolver(string)": { + "notice": "Fetches the resolver responsible for the specified label." + }, + "getResource(uint256)": { + "notice": "Get `resource` from `anyId`." + }, + "getState(uint256)": { + "notice": "Get the state of a label." + }, + "getStatus(uint256)": { + "notice": "Get `Status` from `anyId`." + }, + "getSubregistry(string)": { + "notice": "Fetches the registry for a label." + }, + "getTokenId(uint256)": { + "notice": "Get `tokenId` from `anyId`." + }, + "getWrappedName()": { + "notice": "Returns the DNS-encoded name for this registry." + }, + "getWrappedNode()": { + "notice": "Returns the NameWrapper node (namehash)." + }, + "grantRoles(uint256,uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account`." + }, + "grantRootRoles(uint256,address)": { + "notice": "Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE." + }, + "hasAssignees(uint256,uint256)": { + "notice": "Checks if any of the roles in the given role bitmap has assignees." + }, + "hasRoles(uint256,uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`." + }, + "hasRootRoles(uint256,address)": { + "notice": "Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`." + }, + "initialize(bytes32,address,string,uint256)": { + "notice": "Initializes WrapperRegistry." + }, + "isApprovedForAll(address,address)": { + "notice": "Returns the approval for all operator." + }, + "isContractNamer(address)": { + "notice": "Determine if an account is authorized to name this contract. Called by reverse registrars." + }, + "latestOwnerOf(uint256)": { + "notice": "Get the latest owner of a token. If the token was burned, returns null." + }, + "onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)": { + "notice": "Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`." + }, + "onERC1155Received(address,address,uint256,uint256,bytes)": { + "notice": "Migrate one NameWrapper token via `safeTransferFrom()`." + }, + "ownerOf(uint256)": { + "notice": "Returns the owner of a token." + }, + "register(string,address,address,address,uint256,uint64)": { + "notice": "Registers a new label." + }, + "renew(uint256,uint64)": { + "notice": "Renew a label." + }, + "revokeRoles(uint256,uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account`." + }, + "revokeRootRoles(uint256,address)": { + "notice": "Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE." + }, + "roleCount(uint256)": { + "notice": "Returns the role count bitmap for a resource." + }, + "roles(uint256,address)": { + "notice": "Returns the roles bitmap for an account in a resource." + }, + "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)": { + "notice": "Transfers multiple tokens from one address to another." + }, + "safeTransferFrom(address,address,uint256,uint256,bytes)": { + "notice": "Transfers a single token from one address to another." + }, + "setApprovalForAll(address,bool)": { + "notice": "Sets the approval for all operator." + }, + "setParent(address,string)": { + "notice": "Change canonical \"location\"." + }, + "setResolver(uint256,address)": { + "notice": "Change resolver of label." + }, + "setSubregistry(uint256,address)": { + "notice": "Change registry of label." + }, + "setURI(string,address)": { + "notice": "Set the URI for the registry." + }, + "unregister(uint256)": { + "notice": "Delete a label." + }, + "uri(uint256)": { + "notice": "Returns the URI for a token." + } + }, + "notice": "UUPS-upgradeable registry that wraps an ENSv1 NameWrapper, supporting migration of wrapped names into the namechain registry system.", + "version": 1 + }, + "argsData": "0x0000000000000000000000000635513f179d50a207757e05759cbd106d7dfce80000000000000000000000006f4bf58ac55e0018589b2d9734ed8bb82740124d000000000000000000000000118bc31a50d559f7015a8da26d54b3b030cdb70f0000000000000000000000005339161a7896ca9841ecc034a49edca40f7b9491000000000000000000000000c319c9efaae0bd01fec99b7f709fe41510a20595000000000000000000000000b03524289c16424f71802a1794c29c7bd1b9f57700000000000000000000000024be557df149980a52241dd78a376d78f73689a5000000000000000000000000d25f66dd4ff61486c2c5c1e6201a23576698d3df00000000000000000000000084d3a426d4e12e955d1df95db0b24fe26afe39d3", + "transaction": { + "hash": "0xe7d21990dea26c2a43de74f1abff224167b5ca4a2b5796741b480c84fed9a683", + "nonce": "0x5e", + "origin": "0x84d3a426d4e12e955d1df95db0b24fe26afe39d3" + }, + "receipt": { + "blockHash": "0xfd0634288dfe3a9825bbd6880cedf5d8a357fd32f9686bf957d5eec535ddcf5f", + "blockNumber": "0xaa5712", + "transactionIndex": "0x4f" + } +} \ No newline at end of file diff --git a/contracts/deployments/testnet-3939.json b/contracts/deployments/testnet-3939.json deleted file mode 100644 index 3ce326d22..000000000 --- a/contracts/deployments/testnet-3939.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "chainId": 3939, - "deployedAt": "2026-03-06", - "deployer": "0x99999e454138f6be73E2bE82c890bc5765749999", - "contracts": { - "HCAFactory": "0xA1F743Ec27FE749A124cDbCB13c9bDa9859A1636", - "SimpleRegistryMetadata": "0x3aE3852592B87f82d8871109163ec0dDf8586C2D", - "RootRegistry": "0xB1C3a68653105B08c49601A60555CF609f463354", - "DOSTLDRegistry": "0x62BE2a74E9f477A4e044ecA917c594fb11D01Bf4", - "ReverseRegistry": "0xD03057bA1A9Cd3a21f0944446c0041ACAe818B13", - "StandardRentPriceOracle": "0x56cBC9d6E8938EfF8645187ee95d43c593894767", - "DOSRegistrar": "0xCC594C20716630574f95E78d39BfceE9F80e3808", - "PermissionedResolverImpl": "0xB132A5447077ad10Acd4244F96dFA92A1Cd5d6dE", - "UserRegistryImpl": "0x0125578146a98c5Fb32fb5c5F2bf2c48D448CAF1", - "UniversalResolverV2": "0xF2A8df282f636ea0a44D117b2c643C477B4f55C3", - "ResolverProxy": "0x7b92D81E215650A9671102Dcbb69e25BC1a8aE0e" - }, - "config": { - "tld": "dos", - "wdos": "0x1111111111111111111111111111111111111111", - "pricing": { - "1char": "~100 DOS/year", - "2char": "~50 DOS/year", - "3char+": "~10 DOS/year" - }, - "minCommitmentAge": 60, - "maxCommitmentAge": 86400, - "minRegistrationDuration": 2419200 - } -} diff --git a/contracts/deployments/v1/sepolia/.chainId b/contracts/deployments/v1/sepolia/.chainId new file mode 100644 index 000000000..1b144180b --- /dev/null +++ b/contracts/deployments/v1/sepolia/.chainId @@ -0,0 +1 @@ +11155111 diff --git a/contracts/deployments/v1/sepolia/WrappedETHRegistrarController.json b/contracts/deployments/v1/sepolia/WrappedETHRegistrarController.json new file mode 100644 index 000000000..ffeffbbb2 --- /dev/null +++ b/contracts/deployments/v1/sepolia/WrappedETHRegistrarController.json @@ -0,0 +1,21 @@ +{ + "address": "0xFED6a969AaA60E4961FCD3EBF1A2e8913ac65B72", + "abi": [ + { + "type": "function", + "name": "renew", + "stateMutability": "payable", + "inputs": [ + { + "name": "label", + "type": "string" + }, + { + "name": "duration", + "type": "uint256" + } + ], + "outputs": [] + } + ] +} diff --git a/contracts/docs/addresses/sepolia.md b/contracts/docs/addresses/sepolia.md new file mode 100644 index 000000000..31570fec6 --- /dev/null +++ b/contracts/docs/addresses/sepolia.md @@ -0,0 +1,39 @@ +# ENSv2 Sepolia Deployment Addresses + +> Auto-generated by `bun run docs:addresses`. Do not edit by hand. + +- **Network:** sepolia +- **Chain ID:** 11155111 +- **Deployed at:** 2026-06-29T05:35:12.452Z + +| Contract | Address | +| --- | --- | +| ApprovedUpgradeGate | [0xc319c9efaae0bd01fec99b7f709fe41510a20595](https://sepolia.etherscan.io/address/0xc319c9efaae0bd01fec99b7f709fe41510a20595) | +| BatchRegistrar | [0xfe2aab6df1cbff84534ce65d9e4a755ba02d6795](https://sepolia.etherscan.io/address/0xfe2aab6df1cbff84534ce65d9e4a755ba02d6795) | +| ContractNamer | [0x68658a771044873906fc9b6e9f278ac5a0501342](https://sepolia.etherscan.io/address/0x68658a771044873906fc9b6e9f278ac5a0501342) | +| DefaultReverseRegistrarAdapter | [0x1f7b9461d17d5cf43553253c6b78d252d9575954](https://sepolia.etherscan.io/address/0x1f7b9461d17d5cf43553253c6b78d252d9575954) | +| DNSV1MirrorRootBatchRegistrar | [0x08c297214c7ea8de81e2d984d66dcc1684054037](https://sepolia.etherscan.io/address/0x08c297214c7ea8de81e2d984d66dcc1684054037) | +| ENSV1Resolver | [0x5339161a7896ca9841ecc034a49edca40f7b9491](https://sepolia.etherscan.io/address/0x5339161a7896ca9841ecc034a49edca40f7b9491) | +| ENSV2Resolver | [0x6f988f299926ce361450db390d66dd604dcd8b21](https://sepolia.etherscan.io/address/0x6f988f299926ce361450db390d66dd604dcd8b21) | +| ETHRegistrar | [0xa4449a0dd2b83007553d9b1d28b583a46a805a30](https://sepolia.etherscan.io/address/0xa4449a0dd2b83007553d9b1d28b583a46a805a30) | +| ETHRegistry | [0x67b728a792e789a8978b30cf1b3b641f19354b43](https://sepolia.etherscan.io/address/0x67b728a792e789a8978b30cf1b3b641f19354b43) | +| ETHRenewerV1 | [0x1be516ae1b72765ae55bd5e9ca628c9058a1c622](https://sepolia.etherscan.io/address/0x1be516ae1b72765ae55bd5e9ca628c9058a1c622) | +| Graveyard | [0x6f4bf58ac55e0018589b2d9734ed8bb82740124d](https://sepolia.etherscan.io/address/0x6f4bf58ac55e0018589b2d9734ed8bb82740124d) | +| LabelStore | [0xb03524289c16424f71802a1794c29c7bd1b9f577](https://sepolia.etherscan.io/address/0xb03524289c16424f71802a1794c29c7bd1b9f577) | +| LockedMigrationController | [0x681802eff57b83edce99d688c023ab1284495176](https://sepolia.etherscan.io/address/0x681802eff57b83edce99d688c023ab1284495176) | +| ManagedUniversalResolverProxy | [0x6d80F2172CFdEc5730fE683860C33d26fC42e6F1](https://sepolia.etherscan.io/address/0x6d80F2172CFdEc5730fE683860C33d26fC42e6F1) | +| MigrationHelper | [0xd54a53c1567b26f9653c8565dccc39bceb6ab327](https://sepolia.etherscan.io/address/0xd54a53c1567b26f9653c8565dccc39bceb6ab327) | +| MockDAI | [0xe33a01a41ee4a68616b5278183aa88808326ed8e](https://sepolia.etherscan.io/address/0xe33a01a41ee4a68616b5278183aa88808326ed8e) | +| MockUSDC | [0xd3322b29a7bdee707d1684676f149bf41aa3422f](https://sepolia.etherscan.io/address/0xd3322b29a7bdee707d1684676f149bf41aa3422f) | +| PermissionedResolverImpl | [0x7e4b2d59938930168024201752ee5503df402303](https://sepolia.etherscan.io/address/0x7e4b2d59938930168024201752ee5503df402303) | +| PublicResolverSet | [0x24be557df149980a52241dd78a376d78f73689a5](https://sepolia.etherscan.io/address/0x24be557df149980a52241dd78a376d78f73689a5) | +| PublicResolverV2 | [0xd25f66dd4ff61486c2c5c1e6201a23576698d3df](https://sepolia.etherscan.io/address/0xd25f66dd4ff61486c2c5c1e6201a23576698d3df) | +| ReverseRegistrarAdapter | [0x94e64e29e25533f93ba0a430646ae42cb47bf8f3](https://sepolia.etherscan.io/address/0x94e64e29e25533f93ba0a430646ae42cb47bf8f3) | +| RootRegistry | [0x11b5bfbe9078d826b1edbdd1cfc12f5828d9f50c](https://sepolia.etherscan.io/address/0x11b5bfbe9078d826b1edbdd1cfc12f5828d9f50c) | +| StandardRentPriceOracle | [0x09340d50a6489e7bfb2959acc4e32bcbc401e203](https://sepolia.etherscan.io/address/0x09340d50a6489e7bfb2959acc4e32bcbc401e203) | +| UniversalResolverV2 | [0x85edf8b6b7d4211e2b07aa687506b746357b92cf](https://sepolia.etherscan.io/address/0x85edf8b6b7d4211e2b07aa687506b746357b92cf) | +| UnlockedMigrationController | [0xd021a69db7f9e276a59cbbccf06e7f1e5434215c](https://sepolia.etherscan.io/address/0xd021a69db7f9e276a59cbbccf06e7f1e5434215c) | +| UpgradableUniversalResolverProxy | [0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe](https://sepolia.etherscan.io/address/0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe) | +| UserRegistryImpl | [0x840fa461059862ea466a711e8c98c8de732061c0](https://sepolia.etherscan.io/address/0x840fa461059862ea466a711e8c98c8de732061c0) | +| VerifiableFactory | [0x118bc31a50d559f7015a8da26d54b3b030cdb70f](https://sepolia.etherscan.io/address/0x118bc31a50d559f7015a8da26d54b3b030cdb70f) | +| WrapperRegistryImpl | [0xcf9f4863a1b44216cfc0be65f4e47b2b9a043924](https://sepolia.etherscan.io/address/0xcf9f4863a1b44216cfc0be65f4e47b2b9a043924) | diff --git a/contracts/docs/migration.md b/contracts/docs/migration.md new file mode 100644 index 000000000..e74bb9408 --- /dev/null +++ b/contracts/docs/migration.md @@ -0,0 +1,315 @@ +# Phased v1 → v2 Migration + +## Overview + +The v1 → v2 migration runs as seven explicit phases, orchestrated by three pieces: + +- **Operator CLI** — [`script/migration.ts`](../script/migration.ts), run as `bun run migration -- ` from `contracts/`. Each phase is an individual subcommand; `fork full` and `clean-testnet` run all phases end-to-end as rehearsals. +- **Hardhat plugin** — [`plugins/migration/index.ts`](../plugins/migration/index.ts), registering `migration ` tasks. These wrap the same phase functions but derive signers from the configured Hardhat network/keystore: `bunx hardhat --network migration `. +- **Phased deploy scripts** — the scripts under [`deploy/`](../deploy/) carry migration tags (`migration:phase1:deploy-v2`, `migration:phase5:switch-urp-to-managed`, `migration:phase6:upgrade-managed-urp`, `migration:post-cutover:direct-urp-to-v2`) so each on-chain change is bound to a deploy step. Phase 1 (`phase deploy-v2`) runs only the `migration:phase1:deploy-v2` tag by default; the `…switch-urp-to-managed` / `…upgrade-managed-urp` tags drive the resolution cutover in phase 7 (their tag strings predate this numbering and are kept as stable identifiers). + +Phase numbering below matches the console output of the `runForkFull` orchestrator in [`script/migration.ts`](../script/migration.ts). + +> **Ordering note.** Renewal compatibility is enabled early (phase 4) so unmigrated v1 names stay renewable throughout the migration window, and the final pre-migration sync (phase 5) then picks up any renewed expiries. The Universal Resolver is cut over to v2 last (phase 7) so public resolution flips only once everything else is live. + +## Phases + +| Phase | Action | CLI command(s) | Signer | +| --- | --- | --- | --- | +| 0 † | Deploy fresh v1 contracts (clean-testnet only) | part of `clean-testnet` | `deployer` | +| 1 | Deploy all v2 contracts (incl. reverse-registrar adapters), registrar deferred | `phase deploy-v2` | `deployer` / `owner` / `urManager` (+ one `v1Owner` tx, deferrable) | +| 2 | Initial pre-migration: seed v1 names as reserved on v2 | `premigration run` / `resume`, then `premigration verify` | BatchRegistrar owner | +| 3 | Disable v1 registrar controllers (v1 registration freeze) | `phase disable-v1-registrars`, then `phase verify-v1-registrars-disabled` | v1 owner | +| 4 | Authorize `ETHRenewerV1` as a v1 controller so unmigrated names stay renewable | `phase authorize-v1-renewer` | v1 owner | +| 5 | Final pre-migration sync from a fresh post-freeze export (picks up renewed expiries) | `premigration run`, then `premigration verify` | BatchRegistrar owner | +| 6 | Enable the v2 controller: revoke `REGISTRAR \| RENEW` from `BatchRegistrar` → authorize v1 handoff controllers (`Graveyard`, testnet helper) → transfer v1 `BaseRegistrar` ownership to `ETHRenewerV1` → grant `REGISTRAR \| RENEW` to `ETHRegistrar` | `phase disable-batch-registrar`, `phase activate-v1-handoff-controllers`, `phase activate-v1-renewer`, `phase enable-v2-registrar` (+ the matching `verify-*`) | registry root-role admin + v1 owner | +| 7 | Switch Universal Resolver to v2 (resolution cutover): intermediate URP → `UniversalResolverV2` (sepolia reuses the existing top URP → intermediate URP wiring; bootstrap networks first switch top URP → intermediate URP) | `phase upgrade-managed-urp`, then `phase verify-urp` (bootstrap also runs `phase switch-urp-to-managed` first) | `urManager` (intermediate URP admin); bootstrap also needs the top URP admin (DAO on mainnet) for the switch | + +† Phase 0 only exists in `clean-testnet`, which deploys a fresh v1 stack (from `lib/ens-contracts/deploy`) into a `deployments/v1/` directory before running phases 1–7. + +Every phase command takes `--network sepolia|mainnet` plus `--rpc-url` (or the `SEPOLIA_RPC_URL` / `MAINNET_RPC_URL` env var). Contract addresses default to the deployment JSON under `--deployments-dir` / `--deployment-network` (v2) and `--v1-deployments-dir` / `--v1-deployment-network` (v1); explicit address flags override. The v1-owner-signed and URP-admin phase commands (`disable-v1-registrars`, `set-v1-reverse-default-resolver`, `authorize-v1-renewer`, `activate-v1-graveyard`, `activate-v1-handoff-controllers`, `activate-v1-renewer`, `authorize-testnet-v1-premigration-registrar`, `switch-urp-to-managed`, `upgrade-managed-urp`) accept `--calldata-only` to print the transaction target and calldata for multisig execution instead of broadcasting. The registry root-role admin commands (`disable-batch-registrar`, `enable-v2-registrar`) broadcast or impersonate only. + +### Phase 1: deploy v2 contracts + +Runs all deploy scripts tagged `migration:phase1:deploy-v2` with the `deferV2Registrar` tag set, so [`deploy/03_ETHRegistrar.ts`](../deploy/03_ETHRegistrar.ts) deploys `ETHRegistrar` **without** granting it `REGISTRAR | RENEW` at the registry root — that grant is deferred to [phase 6](#phase-6-enable-the-v2-controller). `BatchRegistrar` holds the roles in the meantime for pre-migration seeding. The deploy also sets up the URP proxy chain pointing at the v1 `UniversalResolver` (see [universalResolver.md](./universalResolver.md)) and deploys the v2 reverse-registrar adapters ([`deploy/02_ReverseRegistrarAdapter.ts`](../deploy/02_ReverseRegistrarAdapter.ts) and [`deploy/02_DefaultReverseRegistrarAdapter.ts`](../deploy/02_DefaultReverseRegistrarAdapter.ts)), each authorized as a controller on the corresponding v1 reverse registrar via a v1-owner transaction. + +Several steps require a v1-owner signature: pointing the v1 `.eth` resolver at `ENSV2Resolver` ([`deploy/00_ENSV2Resolver.ts`](../deploy/00_ENSV2Resolver.ts)) and the reverse-adapter controller grants above. With `--defer-v1-owner-transactions` (and `--deferred-v1-owner-transactions-file `) such transactions are recorded to a JSONL file instead of broadcast; the owner executes them later with `phase execute-owner-txs --file --role v1Owner`. + +`--include-testnet-premigration-registrar` additionally deploys `TestnetV1PremigrationRegistrar` (see [premigration.md](./premigration.md)). + +> The migration timeline also lists external deployments (e.g. an HCA component) that live outside this repository; they are out of scope for these contracts and are not driven by `phase deploy-v2`. + +### Phase 2: initial pre-migration + +Seeds every active or in-grace v1 `.eth` 2LD into the v2 registry as a **reserved** entry via `BatchRegistrar`, driven by a registration CSV — see [premigration.md](./premigration.md) for the CSV format, the bonus-period expiry rule, checkpointing, and verification. Each reservation's v2 expiry is the name's v1 expiry plus the configurable `--bonus-period-days` (default 62). + +### Phase 3: disable v1 registrars + +Removes `LegacyETHRegistrarController`, `ETHRegistrarController`, `WrappedETHRegistrarController`, and `NameWrapper` as v1 `BaseRegistrar` controllers (via `RegistrarSecurityController` when deployed, otherwise directly on `BaseRegistrar`). New v1 registrations are frozen from this point. + +### Phase 4: authorize ETHRenewerV1 + +`phase authorize-v1-renewer` authorizes `ETHRenewerV1` as a v1 `BaseRegistrar` controller (via `RegistrarSecurityController` when deployed). `ETHRenewerV1` *only renews* names already reserved on v2, so this does **not** reopen the registration freeze from phase 3 — it keeps unmigrated names renewable throughout the migration window, with each renewal extending both the v1 registration and the v2 reservation in a single transaction. The final lock-down step that transfers v1 `BaseRegistrar` ownership to `ETHRenewerV1` is deferred to phase 6, after the handoff controllers are authorized. + +Because `ETHRenewerV1` can only renew names that are already `RESERVED` on v2, this phase is effective only once the initial pre-migration (phase 2) has completed. + +> **Mainnet renewal continuity.** Renewals are paused between phase 3 (freeze) and phase 4 (authorize), and the phase 5 sync can run for days. When the v1 owner is a DAO/multisig, execute phases 3 and 4 **atomically in one v1-owner batch** — both support `--calldata-only`, so their calldata combines into a single Safe/multisend transaction. + +### Phase 5: final pre-migration sync + +After the freeze, export a fresh registration CSV (Dune for Sepolia, BigQuery for mainnet — see [premigration.md](./premigration.md#cli-reference)) and re-run pre-migration so names registered or renewed since phase 2 are caught up. Names already reserved on v2 are re-reserved with their bonus-adjusted expiry — picking up any expiry extensions from renewals performed via `ETHRenewerV1` since phase 4 — and newly eligible names are reserved for the first time. + +### Phase 6: enable the v2 controller + +The "enable the v2 controller" cutover bundles four owner-gated steps, in order: + +1. **Disable the BatchRegistrar** (`phase disable-batch-registrar`) — revokes `REGISTRAR | RENEW` from `BatchRegistrar` on the v2 `ETHRegistry`, ending pre-migration seeding. On testnets, `TestnetV1PremigrationRegistrar` keeps its roles so test names can still be created. `phase batch-registrar-owner` prints (and optionally verifies) the BatchRegistrar owner beforehand. +2. **Authorize v1 handoff controllers** (`phase activate-v1-handoff-controllers`) — authorizes `Graveyard` as a v1 `BaseRegistrar` controller, and (re-)authorizes `TestnetV1PremigrationRegistrar` when that deployment exists. The individual steps are also available as `phase activate-v1-graveyard` and `phase authorize-testnet-v1-premigration-registrar`. +3. **Transfer v1 `BaseRegistrar` ownership to `ETHRenewerV1`** (`phase activate-v1-renewer`) — the final v1 lock-down (via `RegistrarSecurityController.transferRegistrarOwnership` when deployed). It re-authorizes `ETHRenewerV1` as a controller if needed, but the authorization usually already happened in phase 4. This must run **after** the handoff-controller grants above, because the v1 owner can no longer manage controllers once ownership has moved. +4. **Enable the v2 `ETHRegistrar`** (`phase enable-v2-registrar`) — grants `REGISTRAR | RENEW` on the v2 `ETHRegistry` to `ETHRegistrar`, the grant deferred since phase 1, opening live v2 registrations. `phase verify-v2-registrar` confirms the grant. + +### Phase 7: switch the Universal Resolver to v2 + +The resolution cutover, run last so public resolution flips to v2 only once everything else is live. On **reuse** networks (sepolia) the top `UpgradableUniversalResolverProxy` already fronts the long-lived intermediate `ManagedUniversalResolverProxy`, so the cutover is a single transaction — the intermediate URP admin (`urManager`) upgrades it to `UniversalResolverV2` (`phase upgrade-managed-urp`); the externally-administered top URP is never touched. On **bootstrap** networks (mainnet, fresh chains) the top URP admin first points the top URP at the intermediate URP (`phase switch-urp-to-managed`) before the upgrade. `phase verify-urp` confirms both implementations. See [universalResolver.md](./universalResolver.md) for the proxy chain, deploy scripts, and the optional post-cutover step. + +> **Relation to `prepareMigration.ts`:** phase 6 replaces the all-at-once role swap performed by [prepareMigration.md](./prepareMigration.md); that script remains the path for non-phased deployments. + +## Deployment artifacts + +Phase 1 reads and writes rocketh deployment artifacts under [`deployments/`](../deployments/README.md), grouped into per-deployment **namespace** directories selected with `--deployments-dir` / `--deployment-network` (v1 references via `--v1-deployments-dir` / `--v1-deployment-network`). + +`phase deploy-v2` **deploys fresh by default** — it archives the current namespace to `deployments/--r` and deploys into a clean one. Since phase 1 sends many transactions and can be interrupted, re-run with `--resume` to continue into the existing namespace instead (rocketh is idempotent, sending only the not-yet-deployed contracts). See [`deployments/README.md`](../deployments/README.md) for the namespace layout, archiving, git-tracking, and idempotency rules. + +## CLI reference + +`bun run migration -- ` from `contracts/` (entrypoint [`script/migration.ts`](../script/migration.ts), wired through `package.json`). The CLI auto-loads `contracts/.env` (already-set environment variables win). Run `bun run migration -- --help` for full options. + +| Command | Purpose | +| --- | --- | +| `fetch-data` | Export ENS registrations from the TheGraph subgraph (mainnet or sepolia) into a pre-migration CSV | +| `premigration run` | Start pre-migration reservations from a fresh checkpoint (phases 2/4) | +| `premigration resume` | Resume pre-migration from the checkpoint | +| `premigration status` | Print the current pre-migration checkpoint JSON | +| `premigration verify` | Verify eligible CSV names were reserved or registered on v2 | +| `phase deploy-v2` | Phase 1: deploy the v2 migration contracts (incl. reverse-registrar adapters) with the registrar deferred; archives any existing namespace and deploys fresh by default (`--resume` continues an interrupted deploy instead) | +| `phase reclaim-v1-registrar-ownership` | Re-migration only: reclaim v1 `BaseRegistrar` ownership from a prior deployment's `ETHRenewerV1` back to the v1 owner (run before the Phase 1 deferred-tx replay on an already-migrated chain); signed by the prior renewer's owner / urManager | +| `phase disable-v1-registrars` | Phase 3: disable v1 registrar controllers | +| `phase set-v1-reverse-default-resolver` | Point the v1 `ReverseRegistrar` default resolver at the v1 `PublicResolver` (v1-owner write) | +| `phase verify-v1-registrars-disabled` | Verify v1 registrar controllers are disabled | +| `phase authorize-v1-renewer` | Phase 4: authorize `ETHRenewerV1` as a v1 controller so unmigrated names stay renewable | +| `phase execute-owner-txs` | Execute prepared owner transactions from a JSONL file (optionally filtered by `--role`) | +| `phase disable-batch-registrar` | Phase 6: revoke registrar/renew roles from `BatchRegistrar` | +| `phase verify-batch-registrar-disabled` | Verify `BatchRegistrar` no longer has registrar/renew roles | +| `phase batch-registrar-owner` | Print and optionally verify the `BatchRegistrar` owner | +| `phase activate-v1-handoff-controllers` | Phase 6: authorize `Graveyard` + testnet helper as v1 controllers | +| `phase activate-v1-graveyard` | Phase 6 (individual): authorize `Graveyard` only | +| `phase authorize-testnet-v1-premigration-registrar` | Phase 6 (individual, testnet): authorize the testnet premigration helper | +| `phase activate-v1-renewer` | Phase 6: transfer v1 `BaseRegistrar` ownership to `ETHRenewerV1` (final lock-down) | +| `phase enable-v2-registrar` | Phase 6: grant registrar/renew roles to `ETHRegistrar` | +| `phase verify-v2-registrar` | Verify `ETHRegistrar` has registrar/renew roles | +| `phase switch-urp-to-managed` | Phase 7: point the top URP at the managed URP | +| `phase upgrade-managed-urp` | Phase 7: upgrade the managed URP to `UniversalResolverV2` (resolution cutover) | +| `phase verify-urp` | Verify top and managed URP implementations | +| `fork full` | Run the full phased migration rehearsal against an Anvil fork | +| `clean-testnet` | Deploy fresh testnet v1 contracts and run the full phased migration (sepolia only) | + +## Hardhat plugin tasks + +Registered by [`plugins/migration/index.ts`](../plugins/migration/index.ts); invoke as: + +```bash +bunx hardhat --network migration [--options] +``` + +The tasks select the migration network with `--migration-network sepolia|mainnet` and use the Hardhat network's RPC and configured signer (so private keys can come from the Hardhat keystore instead of flags/env). See `bunx hardhat migration --help` for options. + +| Task | Purpose | +| --- | --- | +| `snapshot` | Create an RPC state snapshot (`evm_snapshot`), optionally writing the id to `--file` | +| `revert` | Revert to a snapshot id (from `--snapshot-id` or `--file`) | +| `verify-all` | Verify final migration wiring plus resolution smoke checks against `--names` | +| `batch-registrar-owner` | Print and optionally verify the `BatchRegistrar` owner | +| `fork-full` | Run the full phased migration rehearsal (Hardhat-signer variant of `fork full`) | +| `clean-testnet` | Deploy fresh testnet v1 and run the full phased migration | +| `smoke-v2-registrar` | Register a fresh `.eth` name through the enabled v2 registrar | +| `set-v1-reverse-default-resolver` | Point the v1 `ReverseRegistrar` default resolver at the v1 `PublicResolver` | +| `deploy-v2` | Deploy the v2 migration contracts (phase 1) | +| `premigration-run` | Run pre-migration reservations (phases 2/5) with the Hardhat signer as BatchRegistrar owner | + +## Environment variables + +Resolved by [`script/migration.ts`](../script/migration.ts) (the CLI also auto-loads `contracts/.env`): + +| Variable | Used for | +| --- | --- | +| `SEPOLIA_RPC_URL` / `MAINNET_RPC_URL` | Default RPC when `--rpc-url` is omitted | +| `DEPLOYER_KEY` | Deployer key (`phase deploy-v2`); fallback for owner/urManager keys | +| `OWNER_KEY` | Owner / registry root-role admin (`phase deploy-v2`, `disable-batch-registrar`, `enable-v2-registrar`; falls back to `DEPLOYER_KEY`) | +| `UR_MANAGER_KEY` | Intermediate URP admin (`phase upgrade-managed-urp`; falls back to `DEPLOYER_KEY`) | +| `SEPOLIA_V1_OWNER_KEY` / `V1_OWNER_KEY` | v1 owner (`disable-v1-registrars` †, `set-v1-reverse-default-resolver`, `authorize-v1-renewer`, `activate-v1-*`, `authorize-testnet-v1-premigration-registrar`) | +| `SEPOLIA_TOP_URP_OWNER_KEY` / `TOP_URP_OWNER_KEY` | Top URP admin (`phase switch-urp-to-managed`) | +| `OWNER_TX_KEY` | Generic signer for `phase execute-owner-txs` when no role-specific key matches | +| `_MNEMONIC`, `_MNEMONIC_PATH`, `_MNEMONIC_INDEX`, `_MNEMONIC_PASSPHRASE` | Mnemonic-backed signer alternatives for `phase execute-owner-txs`; prefixes `OWNER_TX`, `SEPOLIA_V1_OWNER` / `V1_OWNER`, `SEPOLIA_TOP_URP_OWNER` / `TOP_URP_OWNER` | +| `PREMIGRATION_PRIVATE_KEY`, `BATCH_REGISTRAR_OWNER_KEY`, `DEPLOYER_KEY` | BatchRegistrar owner key fallbacks for `premigration run` / `resume` | +| `THEGRAPH_API_KEY` / `GRAPH_API_KEY` | TheGraph Gateway key for `fetch-data` | +| `ETHERSCAN_API_KEY` | Etherscan v2 (multichain) API key for source-code verification (`bun run verify:`); not needed for Sourcify | + +† `phase disable-v1-registrars` takes the key via `--private-key`; the env fallbacks apply when it is executed through `phase execute-owner-txs` with `--role v1Owner`. + +For `phase execute-owner-txs`, the key is selected by the `--role` filter: `v1Owner` → the v1-owner variables, `sepolia-top-urp-owner` → the top-URP-owner variables, `deployer` → `DEPLOYER_KEY`; with no role, `OWNER_TX_KEY` and then the role-specific variables are tried in order. + +## Live deployment (Sepolia) + +End-to-end runbook for a real, fresh Sepolia deployment that replaces the live v2 set and re-runs every phase. Rehearse first (see [Rehearsals](#rehearsals)) — `fork full` exercises this exact sequence against forked state. + +### Signer keys + +Three keys cover every signature in the sepolia reuse flow. The deployer fills the `owner`/registry-root-admin role, the v1 owner is a separate account, and the intermediate URP admin is the wallet that controls the long-lived intermediate URP. The top URP owner key is **not** needed here — the top URP already fronts the intermediate URP, so the cutover never touches it: + +- **`DEPLOYER_KEY`** — the deployer EOA that signs phase-1 contract deployments. On Sepolia it also resolves as `owner` (registry root-role admin: `disable-batch-registrar`, `enable-v2-registrar`). It is also the `BatchRegistrar` owner that drives pre-migration. Must be a freshly funded account with enough Sepolia ETH for the many transactions in phase 1. +- **`SEPOLIA_V1_OWNER_KEY`** — the v1 owner (`0x0f32b753afc8abad9ca6fe589f707755f4df2353`), which controls the v1 `BaseRegistrar` / `RegistrarSecurityController`. Signs the deferred phase-1 v1-owner transactions (pointing the v1 `.eth` resolver at the new `ENSV2Resolver` and authorizing the reverse-registrar adapters), plus `disable-v1-registrars` (phase 3), `authorize-v1-renewer` (phase 4), and `activate-v1-handoff-controllers` / `activate-v1-renewer` (phase 6). +- **`UR_MANAGER_KEY`** — the admin of the long-lived intermediate `ManagedUniversalResolverProxy` (`0x6d80F2172CFdEc5730fE683860C33d26fC42e6F1`, admin `0xffFffFFfFF52D316B7Bd028358089bc8066b8f80`). Signs `upgrade-managed-urp` (phase 7), the v2 resolution cutover. Configured as `securityCouncil`/`urManager` for sepolia in the account config. + +> **`SEPOLIA_TOP_URP_OWNER_KEY`** is only needed on bootstrap networks (mainnet, fresh chains) where the top URP does not yet front an intermediate URP and the top URP admin (`0x69420f05A11f617B4B74fFe2E04B2D300dFA556F` on sepolia, the DAO on mainnet) must first run `switch-urp-to-managed`. On sepolia that switch is a no-op. + +> **`phase deploy-v2` cannot sign v1-owner transactions itself** — it only wires the deployer/owner keys. So phase 1 must record its v1-owner transactions with `--defer-v1-owner-transactions` and you replay them with `phase execute-owner-txs --role v1Owner`, which reads `SEPOLIA_V1_OWNER_KEY`. Every later v1-owner / top-URP command reads its key from env directly, except `disable-v1-registrars`, which takes `--private-key` explicitly. + +### Setup + +```bash +cd contracts +bun run compile # forge + hardhat → generated/artifacts + +export SEPOLIA_RPC_URL= # phase 1 sends many txs +export DEPLOYER_KEY=0x # also owner / urManager / securityCouncil / BatchRegistrar owner +export SEPOLIA_V1_OWNER_KEY=0x +export SEPOLIA_TOP_URP_OWNER_KEY=0x + +mkdir -p .dev/sepolia-live +``` + +Also prepare a **current** Sepolia registration CSV for the pre-migration phases (Dune export — see [premigration.md](./premigration.md)). The repo's `csv-data/ens-registrations-sepolia.csv` is a small sample, not a real export. + +### Phase 1 — deploy fresh v2 + +```bash +# deployer-signed deploy into deployments/sepolia/; v1-owner txs recorded, not broadcast +bun run migration -- phase deploy-v2 --network sepolia \ + --defer-v1-owner-transactions \ + --deferred-v1-owner-transactions-file .dev/sepolia-live/phase1-v1owner.jsonl + +# Re-deploying onto an ALREADY-MIGRATED chain only: the v1 BaseRegistrar is still +# owned by the prior deployment's ETHRenewerV1, so reclaim it to the v1 owner before +# replaying the deferred txs — one of them is a v1 BaseRegistrar setResolver, which is +# owner-gated. Signed by the prior renewer's owner (urManager). No-op on a pristine chain. +bun run migration -- phase reclaim-v1-registrar-ownership --network sepolia \ + --private-key $UR_MANAGER_KEY + +# v1 owner replays the deferred setResolver + reverse-adapter grants +bun run migration -- phase execute-owner-txs --network sepolia \ + --role v1Owner --file .dev/sepolia-live/phase1-v1owner.jsonl +``` + +`phase deploy-v2` archives any existing `sepolia` namespace (to `sepolia--r`) and deploys fresh into the default `sepolia` namespace; every later phase auto-resolves addresses from `deployments/sepolia/`. If phase 1 is interrupted, re-run the same command with `--resume` to continue. + +> **Deployer and `.env` hygiene.** `DEPLOYER_KEY` should be a freshly funded EOA. If it +> happens to be the same address as the v1 owner, `phase deploy-v2` now wires that address +> with the v1-owner key (from `SEPOLIA_V1_OWNER_KEY`/`V1_OWNER_KEY`, falling back to +> `DEPLOYER_KEY`) so it keeps a local signer; previously a keyless same-address v1 owner +> would shadow the deployer's signer and every deploy tx would fail node-side signing. +> Keep `.env` values free of inline `#` comments — the loader trims a whitespace-introduced +> inline comment, but quote the value if it must contain a literal `#`. + +### Phases 2–7 — wire up and cut over + +```bash +# Phase 2 — initial pre-migration (BatchRegistrar owner = deployer). See premigration.md. +bun run migration -- premigration run --network sepolia \ + --csv-file --work-dir .dev/sepolia-live/premig-1 +bun run migration -- premigration verify --network sepolia --csv-file + +# Phase 3 — freeze v1 registrations (v1 owner; this command needs --private-key) +bun run migration -- phase disable-v1-registrars --network sepolia \ + --private-key $SEPOLIA_V1_OWNER_KEY +bun run migration -- phase verify-v1-registrars-disabled --network sepolia + +# Phase 4 — keep unmigrated names renewable (v1 owner via env) +bun run migration -- phase authorize-v1-renewer --network sepolia + +# Phase 5 — final sync from a fresh post-freeze CSV export +bun run migration -- premigration run --network sepolia \ + --csv-file --work-dir .dev/sepolia-live/premig-2 +bun run migration -- premigration verify --network sepolia --csv-file + +# Phase 6 — enable v2 controller (registry root admin = deployer/owner; + v1 owner) +bun run migration -- phase disable-batch-registrar --network sepolia +bun run migration -- phase activate-v1-handoff-controllers --network sepolia +bun run migration -- phase activate-v1-renewer --network sepolia +bun run migration -- phase enable-v2-registrar --network sepolia +bun run migration -- phase verify-v2-registrar --network sepolia + +# Phase 7 — resolution cutover (intermediate URP admin = UR_MANAGER_KEY). +# The top URP already fronts the intermediate URP, so only the upgrade is needed. +bun run migration -- phase upgrade-managed-urp --network sepolia +bun run migration -- phase verify-urp --network sepolia +``` + +### After + +The new `deployments/sepolia/` namespace (and any dated archive) is committed automatically — `.gitignore` tracks real namespaces by default and ignores only the `-fork` / `-clean-` runtime sets (see [deployments/README.md](../deployments/README.md)). + +Two things to plan for: + +- **Renewal gap (phases 3→5).** Between the freeze and the end of the long final sync renewals are paused until `authorize-v1-renewer` (phase 4) reopens them. With an EOA v1 owner on Sepolia you can run phases 3 and 4 back-to-back, so the window is small. (The atomic-batch guidance under [phase 4](#phase-4-authorize-ethrenewerv1) is a mainnet/multisig concern.) +- **Pre-migration is the heavy, stateful part.** Phases 2 and 5 are checkpointed (`premigration resume`) and have their own flags (`--registry`, `--batch-registrar`, `--batch-size`, the v1-expiry RPC). Read [premigration.md](./premigration.md) and confirm the CSV export before the live run. + +> **Mainnet differs.** There the owner, top URP admin, and v1 owner are all the DAO/multisig, so the owner-signed and URP-admin phases are run with `--calldata-only` (or deferred) and executed through the Safe rather than with local keys. + +### Verify source code + +Once the deployment is live, submit the deployed contracts for source-code verification on Etherscan and Sourcify. This reads the deployment artifacts under `deployments//` (each carries the solc metadata and constructor args needed) — no recompilation or redeploy is required. + +```bash +cd contracts +export ETHERSCAN_API_KEY= # one key covers all chains; not needed for Sourcify +bun run verify:sepolia # → verify:mainnet for the mainnet set +``` + +`verify:` runs [`script/verify.ts`](../script/verify.ts), which submits every contract to both Etherscan and Sourcify via [`@rocketh/verifier`](https://www.npmjs.com/package/@rocketh/verifier). It is idempotent and re-runnable: contracts already verified on a backend are detected and skipped, so it is safe to re-run after a partial deploy or to pick up newly added contracts. Proxy entries are verified from their `*_Proxy` / `*_Implementation` artifacts. + +The verifier rebuilds the solc standard-JSON input from each artifact's recorded metadata, which needs the literal content of every source file. Hardhat-compiled artifacts embed that content, but forge-compiled ones record only each source's hash and URLs; for those, `verify.ts` backfills the missing content from disk (keyed by the metadata source paths and checked against the recorded hash) before submitting, so a contract verifies regardless of which compiler produced its artifact. Flags after `--` pass through to the underlying CLI (e.g. `bun run verify -- --network sepolia --etherscan-only`). + +## Rehearsals + +### `fork full` + +```bash +bun run migration -- fork full --network sepolia --csv-file ./csv-data/ens-registrations-sepolia.csv \ + [--work-dir ] [--save-deployments] [--snapshot-file ] +``` + +Spawns a local Anvil fork of the network RPC (default port 8547 sepolia / 8548 mainnet), impersonates the deployer, owner, v1 owner, URP admins, and BatchRegistrar owner, and runs phases 1–7 in order with smoke checks interleaved: + +- v1 registration succeeds before phase 3 and is rejected after; +- `ETHRenewerV1` is confirmed as an authorized v1 renewal controller after phase 4; +- a pre-migrated name is migrated to v2 via `UnlockedMigrationController` after phase 5; +- the v2 registrar rejects registrations before phase 6's grant, rejects pre-migrated reserved names after it, and accepts a fresh name after enablement. + +When the target chain has already completed the v1 hand-off — re-running against an already-migrated Sepolia, or a repeat mainnet run after a redeploy — `fork full` detects this from the v1 registrar-controller state and skips the smoke checks that require live v1 registration (the v1-registration bullet and the pre-migrated-reserved-name rejection in the last bullet), while still running the deploy, pre-migration, renewer authorization, the pre-enablement rejection, the fresh-name registration, and the URP cut-over. A pristine chain runs all of them. There is no flag for this; it is detected automatically. + +`--direct` skips Anvil and targets `--rpc-url` directly (e.g. a Tenderly virtual testnet) — it requires explicit `--deployer` and `--ur-manager` addresses, plus `--owner` on sepolia (the Hardhat `migration fork-full` task derives them from the keystore). `--resume-from-phase 2` (requires `--work-dir`) skips phase 1 and reloads saved deployments. `--snapshot-file` records a pre-rehearsal `evm_snapshot` id, which the Hardhat `migration revert` task can restore. + +### `clean-testnet` + +```bash +bun run migration -- clean-testnet --network sepolia --rpc-url --deployer
+``` + +Sepolia only. Runs phase 0 — a fresh v1 stack deployed into `deployments/v1/` — then phases 1–7 directly against the RPC, always including `TestnetV1PremigrationRegistrar`. The v2 namespace defaults to `sepolia-clean-`; the command refuses to reuse the canonical `sepolia` namespace or any namespace that already contains deployment files. Without `--csv-file`, only the generated smoke labels are seeded. Against an RPC without state controls (anything other than a local node or a Tenderly virtual testnet), a configured deployer key is required — prefer the Hardhat `migration clean-testnet` task, which signs with the configured Hardhat account. + +## Related docs + +- [deployments/README.md](../deployments/README.md) — deployment artifact layout, namespace naming, and the idempotency rule for fresh re-deploys. +- [premigration.md](./premigration.md) — the `BatchRegistrar` seeding step in detail (phases 2 and 5): CSV format, continuity expiry, checkpoints, verification. +- [universalResolver.md](./universalResolver.md) — the URP proxy chain behind phase 7, and the post-cutover step. +- [prepareMigration.md](./prepareMigration.md) — the non-phased, all-at-once role hand-off script that phase 6 supersedes. diff --git a/contracts/docs/premigration.md b/contracts/docs/premigration.md new file mode 100644 index 000000000..f8e055829 --- /dev/null +++ b/contracts/docs/premigration.md @@ -0,0 +1,153 @@ +# ENS Pre-Migration Script + +## Overview + +The pre-migration script (`contracts/script/preMigration.ts`) seeds ENS v1 `.eth` second-level (2LD) registrations into the v2 registry. It reads a CSV export of v1 registrations, verifies each name on-chain against the v1 `BaseRegistrar`, and reserves or renews it on v2 via the `BatchRegistrar` contract. + +Names are written to v2 in a **reserved** state (owner `address(0)`) with the v1 expiry preserved (plus a configurable bonus period) and `ENSV1Resolver` set as the fallback resolver. Ownership transfer happens in a later migration phase. + +In the phased migration this script is driven through the operator CLI (`bun run migration -- premigration run` / `resume`, then `verify`); see [migration.md](./migration.md). The reference below documents the underlying script directly. + +## Prerequisites + +- **Bun** runtime, and forge artifacts compiled (`forge build` in `contracts/`). +- **Deployed contracts:** the v2 `PermissionedRegistry`, `BatchRegistrar` (owned by the signer), and `ENSV1Resolver`. +- **Signer key** for the `BatchRegistrar` owner — `--private-key` or the `PREMIGRATION_PRIVATE_KEY` env var. +- **RPC endpoint** where both v1 and v2 contracts live (chain ID auto-detected). Optionally a separate `--mainnet-rpc-url` for v1 reads (e.g. when v2 runs on a devnet with its own v1 set). +- **CSV file** of v1 registrations (see [CSV input](#csv-input)). + +## CLI Reference + +Run from `contracts/`: + +```bash +bun run script/preMigration.ts [options] +``` + +### Required + +| Option | Description | +|---|---| +| `--rpc-url ` | RPC endpoint (where v1 + v2 live) | +| `--registry
` | v2 `PermissionedRegistry` address | +| `--batch-registrar
` | `BatchRegistrar` address | +| `--csv-file ` | CSV of v1 registrations | +| `--v1-resolver
` | `ENSV1Resolver` address (set as fallback resolver) | + +### Optional + +| Option | Default | Description | +|---|---|---| +| `--private-key ` | `PREMIGRATION_PRIVATE_KEY` | `BatchRegistrar` owner key. Exits if neither is set. | +| `--account
` | — | Impersonated/unlocked `BatchRegistrar` owner (forks/devnets). | +| `--mainnet-rpc-url ` | `https://eth.drpc.org` | RPC for v1 `BaseRegistrar` expiry reads; point at a devnet when v2 runs locally. | +| `--batch-size ` | `50` | Names per on-chain batch. | +| `--start-index ` | `-1` | CSV line to start from (set automatically by `--continue`). | +| `--limit ` | none | Max names to process. | +| `--dry-run` | `false` | Simulate without sending transactions. | +| `--continue` | `false` | Resume from the last checkpoint. | +| `--bonus-period-days ` | `62` | Days added to each name's v1 expiry to compute its v2 expiry. `0` preserves v1 expiries exactly. | +| `--v1-base-registrar
` | mainnet `BaseRegistrar` | v1 `BaseRegistrar` for expiry lookups (override for testing). | + +> Eligibility is independently gated by v1's hard-coded 90-day grace: a name expired more than 90 days ago is past grace and skipped, regardless of `--bonus-period-days`. Choose a bonus period large enough that the deepest in-grace name you want migrated does not compute a past v2 expiry (which would fail registration). + +## CSV input + +Parsing is **header-driven**: the first line is the header, the label column is located by name, everything else is ignored. Two column names are accepted (case-insensitive, trimmed): **`labelName`** (v1 subgraph schema, preferred) or **`label`** (the `exportTheGraphRegistrations.ts` exporter). Both work with no flag: + +```csv +node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate +,,,,,,vitalik,, +``` + +```csv +name,label,labelhash,registrant,expiryDate,registrationDate +vitalik.eth,vitalik,0x...,0x...,...,... +``` + +Quoted fields and `""`-escaped quotes are handled; a UTF-8 BOM, a single trailing blank line, and CRLF endings are tolerated. + +**Strict structural parsing.** Any structural problem aborts the run with the CSV path and 1-based line number (header = line 1); fix the file and re-run. Aborts on: missing both `labelName` and `label` columns; unbalanced quotes (header or row); a data row whose column count differs from the header; an empty/whitespace-only label cell; a blank line anywhere but a single trailing one; an empty file. + +**Application-level filtering** happens *after* structural parsing and does **not** abort: labels longer than 255 bytes and the bracketed-labelhash form (`[0x…]`) are skipped and counted as `invalidLabelCount`. + +> **Limitation:** `readline` splits on `\n`, so a field containing a literal newline inside quotes is misread. No exporter we control produces these; pre-process the file if you have one. + +## How it works + +Names stream from the CSV in batches of `--batch-size`. Each batch is verified with a single multicall (two RPC calls regardless of size) reading v2 state (`PermissionedRegistry.getState()`) and v1 expiry (`BaseRegistrar.nameExpires()`), then submitted as one `BatchRegistrar.batchRegister()` transaction. Per-name action: + +| v2 status | v1 status | Action | +|---|---|---| +| Available (0) | Registered, or expired but within v1's 90-day grace | **Reserve** with expiry `v1Expiry + bonusPeriodDays` | +| Reserved (1) | Registered, different expiry | **Renew** (sync expiry) | +| Reserved (1) | Registered, same expiry | **Skip** (up to date) | +| Registered (2) | Any | **Fail** (already fully owned on v2) | +| Any | Never registered, or past v1's 90-day grace | **Skip** (v1 owner lost the claim) | + +Reserved names are written with owner/registry `address(0)`, resolver = `ENSV1Resolver`, roleBitmap `0`, and the computed expiry. + +**Gas safety.** Before submitting, the script estimates gas; if it exceeds 80% of the block limit the batch is split in half and re-estimated (recursively). If a batch reverts at execution, it is recursively halved and retried (binary search) until failing names are isolated — preserving partial progress. A checkpoint is saved after each batch. + +## Checkpoint & resume + +A checkpoint (`preMigration-checkpoint.json`) is written after each batch, tracking the last processed line and accumulated counters (reserved, renewed, skipped, invalid, failed). `--continue` loads it, sets `--start-index` to the last processed line, and resumes; counters accumulate across runs. + +```bash +bun run script/preMigration.ts --continue [same options as before] +``` + +## Dry run + +`--dry-run` runs the full pipeline — CSV parse, v1/v2 verification, expiry computation, checkpointing — and logs what would happen, but sends no transactions. + +## Output + +Informational output goes to `preMigration.log` and errors to `preMigration-errors.log`; the console mirrors progress with a final summary table (processed / reserved / renewed / skipped / invalid / failed / success rate). Non-CSV failures (individual name reverts, RPC timeouts at a 30s per-call limit, checkpoint write errors) are counted and logged without aborting the run. + +## Examples + +```bash +export PREMIGRATION_PRIVATE_KEY=0x... + +# Dry run first +bun run script/preMigration.ts \ + --rpc-url --registry --batch-registrar \ + --v1-resolver --csv-file ./data/v1-registrations.csv --dry-run + +# Execute (drop --dry-run); resume after an interruption with --continue +bun run script/preMigration.ts \ + --rpc-url --registry --batch-registrar \ + --v1-resolver --csv-file ./data/v1-registrations.csv +``` + +## Testing on a Sepolia fork + +To rehearse pre-migration against real Sepolia v1 state without a full `fork full` run, deploy the v2 stack onto a local Anvil fork (v2 is not on real Sepolia) and run pre-migration against it. + +> **Account requirement:** the deployer/owner must be an address with **no code** on Sepolia. The standard Anvil test accounts carry an EIP-7702 delegation there, so their `onERC1155Received` does not return the ERC-1155 acceptance value and the `eth` 2LD mint during deploy reverts. Use a fresh throwaway key funded via `anvil_setBalance`. + +```bash +# 1. Fork Sepolia +anvil --fork-url "$SEPOLIA_RPC_URL" --port 8547 --chain-id 11155111 & + +# 2. Fresh deployer with no Sepolia code, funded on the fork +KEY=; ADDR=$(cast wallet address --private-key "$KEY") +cast rpc anvil_setBalance "$ADDR" 0x21e19e0c9bab2400000 --rpc-url http://127.0.0.1:8547 + +# 3. Deploy v2 onto the fork (impersonate the v1 owner for the .eth resolver write) +DEPLOYER_KEY=$KEY OWNER_KEY=$KEY UR_MANAGER_KEY=$KEY \ + bun run migration -- phase deploy-v2 --network sepolia --rpc-url http://127.0.0.1:8547 \ + --deployer "$ADDR" --owner "$ADDR" --ur-manager "$ADDR" --impersonate-v1-owner \ + --save-deployments --deployments-dir /tmp/fork-deployments --deployment-network sepolia + +# 4. Run + verify (addresses read from the deployment JSON; v1 reads use the same fork RPC) +bun run migration -- premigration run --network sepolia --rpc-url http://127.0.0.1:8547 \ + --deployments-dir /tmp/fork-deployments --deployment-network sepolia \ + --csv-file ./csv-data/ens-registrations-sepolia.csv --private-key "$KEY" +bun run migration -- premigration verify --network sepolia --rpc-url http://127.0.0.1:8547 \ + --deployments-dir /tmp/fork-deployments --deployment-network sepolia \ + --csv-file ./csv-data/ens-registrations-sepolia.csv +``` + +For the full phased rehearsal instead, see the `fork full` command in [migration.md](./migration.md#rehearsals). diff --git a/contracts/docs/prepareMigration.md b/contracts/docs/prepareMigration.md new file mode 100644 index 000000000..fef119b20 --- /dev/null +++ b/contracts/docs/prepareMigration.md @@ -0,0 +1,58 @@ +# ENS Prepare-Migration Script + +## Overview + +The prepare-migration script (`contracts/script/prepareMigration.ts`) flips the `.eth` `PermissionedRegistry` from its **seeding** configuration (only `BatchRegistrar` can register) to its **live** configuration (`ETHRegistrar` handles new registrations and renewals; the two migration controllers promote reserved names to registered as ENSv1 owners migrate in). `BatchRegistrar` is fully decommissioned. Run it once, after all pre-migration seeding via [`preMigration.ts`](./premigration.md) has completed and before opening registration to users. It is idempotent: re-running against an already-live registry simply re-issues the same grants/revokes. + +> **The phased flow supersedes this.** In the phased v1 → v2 migration ([migration.md](./migration.md)) the same hand-off happens in [phase 6](./migration.md#phase-6-enable-the-v2-controller) — `phase disable-batch-registrar` revokes the `BatchRegistrar` roles and `phase enable-v2-registrar` grants `REGISTRAR | RENEW` to `ETHRegistrar`, while the migration controllers receive `ROLE_REGISTER_RESERVED` already at deploy time. This script remains the path for non-phased, all-at-once deployments (e.g. devnets deployed outside the phased flow). + +## Role changes + +Four root-level role operations on the target registry. For the roles themselves and the EAC admin/base pairing, see the [EAC section of the contracts README](../README.md#access-control). + +| Target | Op | Roles | Expected prior state | +|---|---|---|---| +| `BatchRegistrar` | **REVOKE** | `ROLE_REGISTRAR` · `ROLE_REGISTER_RESERVED` · `ROLE_RENEW` (+ their admin bits) | Holds `ROLE_REGISTRAR \| ROLE_RENEW`. The admin bits and `ROLE_REGISTER_RESERVED` are revoked defensively so the post-state is unambiguously "no roles"; they are no-ops on a canonical deploy. | +| `ETHRegistrar` | **GRANT** | `ROLE_REGISTRAR` · `ROLE_RENEW` | None of the granted bits. | +| `UnlockedMigrationController` | **GRANT** | `ROLE_REGISTER_RESERVED` | None of the granted bit. | +| `LockedMigrationController` | **GRANT** | `ROLE_REGISTER_RESERVED` | None of the granted bit. | + +> **Devnet note.** The canonical deploy scripts (`deploy/03_ETHRegistrar.ts`, `deploy/02_UnlockedMigrationController.ts`, `deploy/04_LockedMigrationController.ts`) pre-grant these roles for local convenience — except `deploy/03_ETHRegistrar.ts` skips the `ETHRegistrar` grant when the `deferV2Registrar` tag is set (the phased deploy always sets it; the grant is deferred to phase 6). So against a fresh devnet deployed *without* `deferV2Registrar`, every GRANT is already satisfied and only the `BatchRegistrar` revoke changes state. The fixture `revertPrePrepareMigrationRoles` in `test/utils/mockPrepareMigration.ts` undoes the pre-grants so the grant paths can be exercised in e2e tests. + +## CLI Reference + +Run from `contracts/`: + +```bash +bun run script/prepareMigration.ts [options] +``` + +| Option | Required | Description | +|---|---|---| +| `--rpc-url ` | yes | JSON-RPC endpoint for the target chain (chain ID auto-detected) | +| `--registry
` | yes | `.eth` `PermissionedRegistry` address | +| `--batch-registrar
` | yes | `BatchRegistrar` (roles revoked) | +| `--eth-registrar
` | yes | `ETHRegistrar` (receives `ROLE_REGISTRAR \| ROLE_RENEW`) | +| `--unlocked-migration-controller
` | yes | receives `ROLE_REGISTER_RESERVED` | +| `--locked-migration-controller
` | yes | receives `ROLE_REGISTER_RESERVED` | +| `--private-key ` | for `--execute` | Signer key. When supplied in dry-run, enables the admin-role pre-flight check. | +| `--execute` | — | Broadcast transactions. Without it the script is a dry run and sends nothing. | + +The signer must hold the admin counterparts of every role being moved (`ROLE_REGISTRAR_ADMIN`, `ROLE_REGISTER_RESERVED_ADMIN`, `ROLE_RENEW_ADMIN`) at the registry root. Forge artifacts must be compiled (`forge build`) — the script loads the `PermissionedRegistry` ABI from `contracts/out/`. + +## Dry run vs. execute + +Dry run is the default: it previews each planned op next to the current on-chain role bitmap for every target, and (when a signer is supplied) runs the admin-role pre-flight and aborts if any admin bit is missing — no transactions are sent. + +`--execute` (with `--private-key`) broadcasts the grants/revokes sequentially, one per op, then re-reads and prints the final role state. An interruption leaves a partially-applied state; re-running is safe. + +```bash +# Dry run (add --private-key to also run the admin pre-flight) +bun run script/prepareMigration.ts \ + --rpc-url --registry --batch-registrar \ + --eth-registrar --unlocked-migration-controller \ + --locked-migration-controller + +# Execute +bun run script/prepareMigration.ts --private-key --execute +``` diff --git a/contracts/docs/universalResolver.md b/contracts/docs/universalResolver.md new file mode 100644 index 000000000..28e65d154 --- /dev/null +++ b/contracts/docs/universalResolver.md @@ -0,0 +1,97 @@ +# Universal Resolver Deployment Structure + +## Overview + +During the v1 → v2 migration, universal resolution runs through a chain of two upgradable proxies in front of the implementation: + +``` +ENS clients + └─ UpgradableUniversalResolverProxy "top URP" + │ admin: DAO on mainnet, top URP owner on sepolia (`owner` account) + └─ ManagedUniversalResolverProxy "managed URP" + │ admin: security council (`urManager` account) + └─ UniversalResolverV2 implementation +``` + +- **Top URP** — the long-lived address clients resolve through: `0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe` on mainnet, sepolia, and holesky (`DEPLOYED_UNIVERSAL_RESOLVER_PROXY` in [`script/deploy-constants.ts`](../script/deploy-constants.ts)). Its admin is the slow-moving owner: the DAO on mainnet, the top URP owner account on sepolia. **The top URP is never (re)deployed by these scripts** — it is always adopted by address. Deploying a fresh top URP on a new network is not currently supported (the create3 path was removed; it can be re-added later). +- **Managed (intermediate) URP** — a second instance of the same proxy contract, admin'd by an account we control (the security council, or a designated intermediate URP admin). It exists so that implementation upgrades during the migration require only a transaction from its admin, never a top-URP-owner transaction. +- **UniversalResolverV2** — the stateless implementation ([`src/universalResolver/UniversalResolverV2.sol`](../src/universalResolver/UniversalResolverV2.sol)). + +### Reuse vs. bootstrap + +There are two flows depending on whether the top URP already fronts an intermediate URP we administer: + +- **Reuse** (networks listed in `KNOWN_INTERMEDIATE_URP`, e.g. sepolia → `0x6d80F2172CFdEc5730fE683860C33d26fC42e6F1`): the top URP already points at the intermediate URP, so a fresh v2 deployment **adopts the existing intermediate URP** and the *only* on-chain mutation is `intermediateUrp.upgradeTo(newImplementation)`, signed by the intermediate URP admin. The externally-administered top URP is never touched, so no top-URP-owner (or DAO) signature is needed. +- **Bootstrap** (mainnet and fresh chains, where the top URP still points directly at v1): a fresh intermediate URP is deployed and the top URP owner points the top URP at it once, before the v2 upgrade. After the migration stabilizes, the top URP owner could point the top URP directly at the final implementation, retiring the managed hop. + +## Lifecycle + +**Reuse flow** (intermediate URP already in place): + +1. **Adopt the top URP and the existing intermediate URP** by address. +2. **Deploy the `UniversalResolverV2` implementation.** +3. **Upgrade intermediate URP → `UniversalResolverV2`** (intermediate URP admin transaction). This is the v2 resolution cutover. The top URP is untouched. + +**Bootstrap flow** (no intermediate URP yet): + +1. **Adopt the top URP** (pointing at the v1 `UniversalResolver`). +2. **Deploy the intermediate URP**, seeded to whatever the top URP currently serves. +3. **Switch top URP → intermediate URP** (one top-URP-owner transaction). Resolution behavior is unchanged. +4. **Deploy the `UniversalResolverV2` implementation.** +5. **Upgrade intermediate URP → `UniversalResolverV2`** (admin transaction). This is the v2 resolution cutover. +6. **Post-cutover:** optionally point the top URP directly at the implementation, removing the managed hop. + +## Deploy scripts + +The phases map to [`deploy/universalResolver/`](../deploy/universalResolver/): + +| Script | Action | Signer | Migration tag | +| --- | --- | --- | --- | +| `00_deploy_UniversalResolver.ts` | Adopt the known `0xeEeE…EeEe` top URP (clean-testnet runs deploy their own) | `deployer` | `migration:phase1:deploy-v2` | +| `01_setup_UniversalResolverToV1.ts` | Initialize a freshly bootstrapped top URP → v1 `UniversalResolver` (skips once the top URP already serves an implementation) | `owner` † | `migration:phase1:deploy-v2` | +| `02_deploy_ManagedUniversalResolverProxy.ts` | Adopt the known intermediate URP (reuse), else deploy a fresh one | `deployer` | `migration:phase1:deploy-v2` | +| `03_setup_UniversalResolverToManaged.ts` | Point top URP → intermediate URP (skips when it already does) | `owner` † | `migration:phase5:switch-urp-to-managed` | +| `04_deploy_UniversalResolverImplementation.ts` | Deploy `UniversalResolverV2` | `deployer` | `migration:phase1:deploy-v2` | +| `05_setup_ManagedUniversalResolverProxyToUniversalResolverImplementation.ts` | Upgrade intermediate URP → `UniversalResolverV2` | `urManager` † | `migration:phase6:upgrade-managed-urp` | +| `06_setup_UniversalResolverToUniversalResolverImplementation.ts` | Point top URP → `UniversalResolverV2` directly (bootstrap post-cutover only) | `owner` † | `migration:post-cutover:direct-urp-to-v2` | + +In the reuse flow only scripts `00`, `02`, `04`, and `05` do anything — `01` and `03` short-circuit because the top URP already fronts the intermediate URP, and `06` is a bootstrap-only post-cutover step. + +† When a setup script's proxy admin is external, the script does not execute the upgrade. It prints the target address and `upgradeTo` calldata for the admin to execute out-of-band (see `logUpgradeCalldata` in [`script/universalResolverDeployUtils.ts`](../script/universalResolverDeployUtils.ts)). The top-URP scripts (`01`, `03`, `06`) defer on mainnet (DAO) and sepolia (top URP owner); the intermediate-URP script (`05`) defers only on mainnet (DAO / security council) and executes directly on sepolia, where the intermediate URP admin is the `securityCouncil`/`urManager` account. + +Setup scripts are idempotent — they read the proxy's current `implementation()` and skip when it already matches. + +**Local environments:** every script except `04` skips when the environment has the `local` tag. Local devnets and tests deploy only the bare `UniversalResolverV2` and resolve against it directly, with no proxies. + +## Accounts + +Named accounts in [`rocketh/config.ts`](../rocketh/config.ts): + +| Account | Role | Value | +| --- | --- | --- | +| `owner` | Top URP admin | DAO on mainnet; deployer elsewhere | +| `securityCouncil` | Intermediate URP admin | Intermediate URP admin wallet on sepolia; defaults to `deployer` elsewhere until a council multisig is configured per network | +| `urManager` | Account used by deploy scripts for intermediate-URP operations | Resolves to `securityCouncil` | + +## CLI + +The bootstrap-only switch (top-URP-owner-signed) and the intermediate-URP upgrade (admin-signed), plus verification, are exposed as `script/migration.ts` phase commands, for use against live networks and fork rehearsals. In the reuse flow the upgrade is the only step you run. The post-cutover step 6 has no phase command — it runs only as the `migration:post-cutover:direct-urp-to-v2` deploy script: + +```bash +# Bootstrap only: top URP → intermediate URP (top URP owner signature). +# No-ops with "top URP already fronts managed URP" when reuse is already in place. +bun run migration -- phase switch-urp-to-managed --network sepolia --rpc-url \ + [--calldata-only] [--private-key ] [--impersonate-account
] + +# Resolution cutover: intermediate URP → UniversalResolverV2 (intermediate URP admin signature) +bun run migration -- phase upgrade-managed-urp --network sepolia --rpc-url \ + [--calldata-only] [--private-key ] [--impersonate-account
] + +# Verify both proxies' current implementations +bun run migration -- phase verify-urp --network sepolia --rpc-url \ + [--expected-top-implementation
] [--expected-managed-implementation
] +``` + +- Signing keys come from `--private-key` or environment variables: `SEPOLIA_TOP_URP_OWNER_KEY` / `TOP_URP_OWNER_KEY` for the top URP owner, `UR_MANAGER_KEY` / `DEPLOYER_KEY` for the intermediate URP admin. +- `--calldata-only` prints the transaction target and calldata instead of sending (for multisig execution); `--impersonate-account` sends as the admin on a fork. +- Proxy addresses default to the canonical top URP and the `ManagedUniversalResolverProxy` deployment under `--deployments-dir` / `--deployment-network`; override with `--top-urp` / `--managed-urp` / `--implementation`. diff --git a/contracts/foundry.lock b/contracts/foundry.lock index bda54c9b9..af4bb44e8 100644 --- a/contracts/foundry.lock +++ b/contracts/foundry.lock @@ -1,30 +1,9 @@ { - "contracts/lib/buffer": { - "rev": "82cc81935de1d1a82e021cf1030d902c5248982b" - }, - "contracts/lib/forge-std": { - "rev": "77041d2ce690e692d6e03cc812b57d1ddaa4d505" - }, - "contracts/lib/openzeppelin-contracts": { - "rev": "e4f70216d759d8e6a64144a9e1f7bbeed78e7079" - }, - "contracts/lib/openzeppelin-contracts-upgradeable": { - "rev": "5fc3fee14043035097ae718387200f4f4daaa982" - }, - "contracts/lib/openzeppelin-contracts-v4": { - "rev": "54b3f14346da01ba0d159114b399197fea8b7cda" - }, - "contracts/lib/solsha1": { - "rev": "c4fbe97cf5e8c1b8d607001588fd23abb5bfb923" - }, - "contracts/lib/verifiable-factory": { - "rev": "c47c0e61ce03b3ab5891a3b743287b54aee9f021" - }, "lib/buffer": { "rev": "82cc81935de1d1a82e021cf1030d902c5248982b" }, "lib/ens-contracts": { - "rev": "6d877523e11f647ed62e8ee159f48f288c9cd9e9" + "rev": "3b1cc225ccdf64581d5fdc81db574f51ba5c8c09" }, "lib/forge-std": { "rev": "77041d2ce690e692d6e03cc812b57d1ddaa4d505" @@ -38,16 +17,16 @@ "lib/openzeppelin-contracts-v4": { "rev": "54b3f14346da01ba0d159114b399197fea8b7cda" }, + "lib/solady": { + "rev": "90db92ce173856605d24a554969f2c67cadbc7e9" + }, "lib/solsha1": { "rev": "c4fbe97cf5e8c1b8d607001588fd23abb5bfb923" }, "lib/unruggable-gateways": { - "tag": { - "name": "v1.3.5", - "rev": "7426ac57509e2023a673956439eed29998d2e371" - } + "rev": "7426ac57509e2023a673956439eed29998d2e371" }, "lib/verifiable-factory": { - "rev": "c47c0e61ce03b3ab5891a3b743287b54aee9f021" + "rev": "5ef7b1a88fd9062bae580ed4048ca369f18450c4" } } \ No newline at end of file diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 3b3b71d48..7bbe47d53 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -9,15 +9,14 @@ gas_reports = ["*"] evm_version = "cancun" optimizer = true optimizer_runs = 200 - -ignored_warnings_from = [ - "lib/ens-contracts/contracts/registry/ENSRegistry.sol", - "lib/ens-contracts/contracts/ethregistrar/BaseRegistrarImplementation.sol", - "lib/ens-contracts/contracts/wrapper/NameWrapper.sol", -] +skip = ["HCAProxyInitCode.yul", "HCAProxyNoInitCode.yul"] +ignored_warnings_from = ["lib/", "src/hca/HCAProxyInitCode.yul"] [fuzz] -runs = 256 +runs = 4096 + +[profile.yul] +skip = [] [lint] lint_on_build = false diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 0d8e4a150..b02a9f411 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -1,32 +1,100 @@ -import type { HardhatUserConfig } from "hardhat/config"; +import { configVariable, type HardhatUserConfig } from "hardhat/config"; import HardhatChaiMatchersViemPlugin from "@ensdomains/hardhat-chai-matchers-viem"; +import HardhatKeystore from "@nomicfoundation/hardhat-keystore"; import HardhatNetworkHelpersPlugin from "@nomicfoundation/hardhat-network-helpers"; import HardhatViem from "@nomicfoundation/hardhat-viem"; import HardhatDeploy from "hardhat-deploy"; -import HardhatStorageLayoutPlugin from "./plugins/storage-layout/index.ts"; import HardhatIgnoreWarningsPlugin from "./plugins/ignore-warnings/index.ts"; +import HardhatClearRemappingsPlugin from "./plugins/clear-remappings/index.ts"; +import HardhatMigrationPlugin from "./plugins/migration/index.ts"; +import HardhatStorageLayoutPlugin from "./plugins/storage-layout/index.ts"; +const version = "0.8.25"; +const outputSelection = { + "*": { + "*": ["storageLayout"], + }, +}; +const tenderlySepoliaRpcUrl = + process.env.TENDERLY_SEPOLIA_RPC_URL ?? + configVariable('TENDERLY_SEPOLIA_RPC_URL'); +const plugins = [ + HardhatNetworkHelpersPlugin, + ...(process.env.HARDHAT_DISABLE_VIEM === '1' + ? [] + : [HardhatChaiMatchersViemPlugin, HardhatViem]), + HardhatStorageLayoutPlugin, + HardhatIgnoreWarningsPlugin, + HardhatDeploy, + HardhatKeystore, + HardhatClearRemappingsPlugin, + HardhatMigrationPlugin, +]; const config = { solidity: { compilers: [ { - version: "0.8.25", + version, settings: { optimizer: { enabled: true, runs: 1000, }, evmVersion: "cancun", - outputSelection: { - "*": { - "*": ["storageLayout"], - }, - }, + outputSelection, }, }, ], + overrides: { + "lib/ens-contracts/contracts/wrapper/NameWrapper.sol": { + version: "0.8.17", + settings: { + optimizer: { + enabled: true, + runs: 1200, + }, + }, + }, + // 23k at 1 + // 25k at 1000 + "src/registry/WrapperRegistry.sol": { + version, + settings: { + optimizer: { + enabled: true, + runs: 100, + }, + evmVersion: "cancun", + outputSelection, + }, + }, + "src/L2/reverse-registrar/L2ReverseRegistrar.sol": { + version, + settings: { + optimizer: { + enabled: true, + runs: 1_000_000, + }, + evmVersion: "paris", + outputSelection, + }, + }, + }, + }, + networks: { + 'sepolia-dev': { + type: 'http', + url: configVariable('SEPOLIA_RPC_URL'), + accounts: [configVariable('DEV_DEPLOYER_KEY')], + chainId: 11155111, + }, + 'tenderly-sepolia': { + type: 'http', + url: tenderlySepoliaRpcUrl, + accounts: [configVariable('DEPLOYER_KEY')], + }, }, paths: { sources: { @@ -36,27 +104,25 @@ const config = { "./lib/verifiable-factory/src/", "./lib/ens-contracts/contracts/", "./lib/openzeppelin-contracts/contracts/utils/introspection/", - "./lib/openzeppelin-contracts/contracts/token/ERC721", + "./lib/openzeppelin-contracts/contracts/token/ERC721/", "./lib/openzeppelin-contracts/contracts/token/ERC1155/", + "./lib/openzeppelin-contracts/contracts/proxy/ERC1967/", // note: this increases artifact size by 25MB+ for 1 interface // "./lib/unruggable-gateways/contracts/", ], }, }, + generateTypedArtifacts: { + destinations: [ + { + mode: "typescript", + }, + ], + }, shouldIgnoreWarnings: (path) => { - return ( - path.startsWith("./lib/ens-contracts/") || - path.startsWith("./lib/solsha1/") - ); + return path.startsWith("./lib/"); }, - plugins: [ - HardhatNetworkHelpersPlugin, - HardhatChaiMatchersViemPlugin, - HardhatViem, - HardhatStorageLayoutPlugin, - HardhatIgnoreWarningsPlugin, - HardhatDeploy, - ], + plugins, } satisfies HardhatUserConfig; export default config; diff --git a/contracts/lib/ens-contracts b/contracts/lib/ens-contracts index 6d877523e..3b1cc225c 160000 --- a/contracts/lib/ens-contracts +++ b/contracts/lib/ens-contracts @@ -1 +1 @@ -Subproject commit 6d877523e11f647ed62e8ee159f48f288c9cd9e9 +Subproject commit 3b1cc225ccdf64581d5fdc81db574f51ba5c8c09 diff --git a/contracts/lib/solady b/contracts/lib/solady new file mode 160000 index 000000000..90db92ce1 --- /dev/null +++ b/contracts/lib/solady @@ -0,0 +1 @@ +Subproject commit 90db92ce173856605d24a554969f2c67cadbc7e9 diff --git a/contracts/lib/unruggable-gateways b/contracts/lib/unruggable-gateways index 3d6874283..7426ac575 160000 --- a/contracts/lib/unruggable-gateways +++ b/contracts/lib/unruggable-gateways @@ -1 +1 @@ -Subproject commit 3d68742832c68bf9a158c7bcd1aa47fad511b213 +Subproject commit 7426ac57509e2023a673956439eed29998d2e371 diff --git a/contracts/lib/verifiable-factory b/contracts/lib/verifiable-factory index c47c0e61c..5ef7b1a88 160000 --- a/contracts/lib/verifiable-factory +++ b/contracts/lib/verifiable-factory @@ -1 +1 @@ -Subproject commit c47c0e61ce03b3ab5891a3b743287b54aee9f021 +Subproject commit 5ef7b1a88fd9062bae580ed4048ca369f18450c4 diff --git a/contracts/package.json b/contracts/package.json index 09542bd77..c5c4c95da 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,18 +1,20 @@ { "name": "contracts", "dependencies": { - "@ensdomains/hardhat-chai-matchers-viem": "^0.1.14", + "@ensdomains/hardhat-chai-matchers-viem": "^0.1.16", "@nomicfoundation/hardhat-network-helpers": "3.0.0", "@nomicfoundation/hardhat-viem": "3.0.0", - "@rocketh/deploy": "0.14.0", - "@rocketh/read-execute": "0.14.0", - "@rocketh/viem": "0.14.0", + "@nomicfoundation/hardhat-keystore": "3.0.5", + "@rocketh/deploy": "0.19.1", + "@rocketh/node": "0.19.3", + "@rocketh/read-execute": "0.19.0", + "@rocketh/viem": "0.19.0", "commander": "^14.0.1", "dns-packet": "^5.6.1", - "hardhat": "3.0.1", - "hardhat-deploy": "2.0.0-next.41", + "hardhat": "3.1.12", + "hardhat-deploy": "2.0.3", "prool": "^0.0.24", - "rocketh": "0.14.5", + "rocketh": "0.19.3", "viem": "^2.31.6", "yoctocolors": "^2.1.2" }, @@ -20,16 +22,13 @@ "@ensdomains/address-encoder": "^1.1.3", "@nomicfoundation/edr": "0.12.0-next.4", "@nomicfoundation/hardhat-foundry": "^1.2.0", - "@rocketh/proxy": "0.14.0", - "@rocketh/verifier": "0.14.4", + "@rocketh/proxy": "0.19.3", + "@rocketh/verifier": "0.19.3", "@types/bun": "^1.3.2", + "abitype": "^1.2.3", "chai": "^5.1.1", "ethers": "^6.15.0", - "prettier": "^3.5.3", - "prettier-plugin-solidity": "2.0.0", - "solhint": "6.0.0", - "solhint-plugin-contracts-v2": "workspace:*", - "solhint-plugin-prettier": "^0.1.0", + "solgrid": "0.0.16", "ts-node": "^10.9.2", "vite-tsconfig-paths": "^5.1.4", "vitest": "3.1.3" @@ -42,13 +41,17 @@ "node": ">=24" }, "scripts": { - "lint": "NODE_PATH=./node_modules solhint --noPoster 'src/**/*.sol'", + "lint": "solgrid check 'src/**/*.sol' && solgrid check --config solgrid.test.toml 'test/**/*.sol' 'script/**/*.sol'", + "lint:fix": "solgrid fix 'src/**/*.sol' && solgrid fix --config solgrid.test.toml 'test/**/*.sol' 'script/**/*.sol'", + "format": "solgrid fmt 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol'", + "format:check": "solgrid fmt --diff 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol'", + "check:types": "NODE_OPTIONS=--max-old-space-size=8192 tsc --noEmit", "compile:forge": "forge build", "compile:hardhat": "hardhat compile", "compile": "bun run compile:forge && bun run compile:hardhat", "test:forge": "forge test", "test:hardhat": "bun run compile:hardhat && vitest run", - "test:e2e": "bun run compile:hardhat --quiet && bun test ./test/e2e/", + "test:e2e": "bun run compile --quiet && bun test --max-concurrency=1 ./test/e2e/", "test": "bun run test:forge && bun run test:hardhat", "interfaces": "bun run compile:hardhat --quiet && bun ./lib/ens-contracts/scripts/interfaces.ts", "coverage:forge": "mkdir -p coverage/ && forge coverage --report lcov --report-file coverage/forge.lcov", @@ -58,8 +61,12 @@ "coverage": "bun run coverage:forge && bun run coverage:hardhat && bun run coverage:reports", "clean": "forge clean && hardhat clean && rm -rf coverage/", "devnet": "bun run compile && bun ./script/runDevnet.ts", + "migration": "bun ./script/migration.ts", + "docs:addresses": "bun ./script/generateAddressDocs.ts", "aakit": "bun ./script/deployAAkit.ts", - "check:types": "tsc --noEmit" + "verify": "bun ./script/verify.ts", + "verify:sepolia": "bun ./script/verify.ts --network sepolia", + "verify:mainnet": "bun ./script/verify.ts --network mainnet" }, "type": "module" } diff --git a/contracts/plugins/clear-remappings/index.ts b/contracts/plugins/clear-remappings/index.ts new file mode 100644 index 000000000..e054d37e0 --- /dev/null +++ b/contracts/plugins/clear-remappings/index.ts @@ -0,0 +1,13 @@ +import { overrideTask } from "hardhat/config"; +import type { HardhatPlugin } from "hardhat/types/plugins"; + +const plugin: HardhatPlugin = { + id: "hardhat-clear-remappings", + tasks: ["build", "compile"].map((action) => + overrideTask(action) + .setAction(() => import("./task.ts")) + .build(), + ), +}; + +export default plugin; diff --git a/contracts/plugins/clear-remappings/task.ts b/contracts/plugins/clear-remappings/task.ts new file mode 100644 index 000000000..e27072832 --- /dev/null +++ b/contracts/plugins/clear-remappings/task.ts @@ -0,0 +1,29 @@ +import type { TaskOverrideActionFunction } from "hardhat/types/tasks"; +import { readFile, writeFile } from "node:fs/promises"; +import { resolve } from "node:path"; + +const REMAPPINGS_PATH = resolve( + import.meta.dirname, + "../../lib/ens-contracts/remappings.txt", +); + +// This is for emptying out the remappings.txt in ens-contracts +// so that it doesn't break the build. We already have the remappings for ens-contracts +// in our own local file, but the build process still doesn't like that +// the folders referenced in the ens-contracts remappings don't exist. + +const action: TaskOverrideActionFunction = async ( + taskArguments, + _hre, + runSuper, +) => { + const original = await readFile(REMAPPINGS_PATH, "utf8"); + await writeFile(REMAPPINGS_PATH, ""); + try { + return await runSuper(taskArguments); + } finally { + await writeFile(REMAPPINGS_PATH, original); + } +}; + +export default action; diff --git a/contracts/plugins/migration/index.ts b/contracts/plugins/migration/index.ts new file mode 100644 index 000000000..03169de82 --- /dev/null +++ b/contracts/plugins/migration/index.ts @@ -0,0 +1,554 @@ +import { emptyTask, task } from "hardhat/config"; +import type { HardhatPlugin } from "hardhat/types/plugins"; + +// Intentionally real, long-lived .eth names: the resolution smoke checks should +// exercise names that actually exist on the target network with stable records. +const DEFAULT_VERIFY_SMOKE_NAMES = "raffy.eth,vitalik.eth,nick.eth"; + +const plugin: HardhatPlugin = { + id: "ens-migration", + tasks: [ + emptyTask("migration", "Run ENS migration operations").build(), + task(["migration", "snapshot"], "Create an RPC state snapshot") + .addOption({ + name: "file", + description: "Optional file to write the snapshot id", + defaultValue: "", + }) + .setAction(() => import("./tasks/snapshot.ts")) + .build(), + task(["migration", "revert"], "Revert an RPC state snapshot") + .addOption({ + name: "snapshotId", + description: "Snapshot id returned by evm_snapshot", + defaultValue: "", + }) + .addOption({ + name: "file", + description: "File containing the snapshot id", + defaultValue: "", + }) + .setAction(() => import("./tasks/revert.ts")) + .build(), + task( + ["migration", "verify-all"], + "Verify final migration wiring and resolution", + ) + .addOption({ + name: "migrationNetwork", + description: "Migration network: sepolia or mainnet", + defaultValue: "sepolia", + }) + .addOption({ + name: "deploymentNetwork", + description: "Deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "deploymentsDir", + description: "Root directory for v2 deployments", + defaultValue: "./deployments", + }) + .addOption({ + name: "names", + description: "Comma-separated .eth names for resolution smoke checks", + defaultValue: DEFAULT_VERIFY_SMOKE_NAMES, + }) + .addOption({ + name: "topUrp", + description: "Top UniversalResolverProxy address", + defaultValue: "", + }) + .setAction(() => import("./tasks/verify-all.ts")) + .build(), + task( + ["migration", "batch-registrar-owner"], + "Print and optionally verify the BatchRegistrar owner", + ) + .addOption({ + name: "migrationNetwork", + description: "Migration network: sepolia or mainnet", + defaultValue: "sepolia", + }) + .addOption({ + name: "deploymentNetwork", + description: "Deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "deploymentsDir", + description: "Root directory for v2 deployments", + defaultValue: "./deployments", + }) + .addOption({ + name: "batchRegistrar", + description: "BatchRegistrar address", + defaultValue: "", + }) + .addOption({ + name: "expectedOwner", + description: "Expected BatchRegistrar owner", + defaultValue: "", + }) + .addOption({ + name: "chainId", + description: "Chain id override", + defaultValue: "", + }) + .setAction(() => import("./tasks/batch-registrar-owner.ts")) + .build(), + task(["migration", "fork-full"], "Run the full phased migration rehearsal") + .addOption({ + name: "migrationNetwork", + description: "Migration network: sepolia or mainnet", + defaultValue: "sepolia", + }) + .addOption({ + name: "csvFile", + description: "Registration CSV", + defaultValue: "", + }) + .addOption({ + name: "batchSize", + description: "Names per pre-migration batch", + defaultValue: "", + }) + .addOption({ + name: "initialLimit", + description: "Optional cap before disabling v1 registrars", + defaultValue: "", + }) + .addOption({ + name: "finishLimit", + description: "Optional cap after disabling v1 registrars", + defaultValue: "", + }) + .addOption({ + name: "workDir", + description: "Directory for fork logs, checkpoints, and generated CSV", + defaultValue: "", + }) + .addOption({ + name: "resumeFromPhase", + description: "Resume the full rehearsal from phase 2", + defaultValue: "", + }) + .addOption({ + name: "deploymentsDir", + description: "Root directory for deployment files", + defaultValue: "./deployments", + }) + .addOption({ + name: "deploymentNetwork", + description: "Deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "v1DeploymentsDir", + description: "Root directory for v1 deployment files", + defaultValue: "", + }) + .addOption({ + name: "v1DeploymentNetwork", + description: "V1 deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "snapshotFile", + description: "Optional file to write a pre-rehearsal snapshot id", + defaultValue: "", + }) + .addOption({ + name: "deployer", + description: + "Migration deployer address; defaults to the configured Hardhat account", + defaultValue: "", + }) + .addOption({ + name: "owner", + description: + "Migration owner/admin address; defaults to the configured Hardhat account", + defaultValue: "", + }) + .addOption({ + name: "v1Owner", + description: + "V1 owner address; defaults to the network-configured v1 owner", + defaultValue: "", + }) + .addOption({ + name: "urManager", + description: + "Managed URP admin address; defaults to the configured Hardhat account", + defaultValue: "", + }) + .addOption({ + name: "chainId", + description: "Chain id override", + defaultValue: "", + }) + .addOption({ + name: "port", + description: "Local Anvil port", + defaultValue: "", + }) + .addFlag({ + name: "direct", + description: + "Use the configured Hardhat network directly instead of starting Anvil", + }) + .addFlag({ + name: "saveDeployments", + description: "Persist deployment files", + }) + .addFlag({ + name: "includeTestnetPremigrationRegistrar", + description: "Deploy the testnet v1 premigration registrar helper", + }) + .addFlag({ + name: "debugRpc", + description: "Log JSON-RPC error responses", + }) + .addFlag({ + name: "keepAnvil", + description: "Leave the local Anvil process running", + }) + .setAction(() => import("./tasks/fork-full.ts")) + .build(), + task( + ["migration", "clean-testnet"], + "Deploy fresh testnet v1 and run the full phased migration", + ) + .addOption({ + name: "migrationNetwork", + description: "Migration network: sepolia", + defaultValue: "sepolia", + }) + .addOption({ + name: "csvFile", + description: + "Optional registration CSV to seed in addition to generated smoke labels", + defaultValue: "", + }) + .addOption({ + name: "batchSize", + description: "Names per pre-migration batch", + defaultValue: "", + }) + .addOption({ + name: "initialLimit", + description: "Optional cap before disabling v1 registrars", + defaultValue: "", + }) + .addOption({ + name: "finishLimit", + description: "Optional cap after disabling v1 registrars", + defaultValue: "", + }) + .addOption({ + name: "workDir", + description: + "Directory for clean deploy logs, checkpoints, and generated CSV", + defaultValue: "", + }) + .addOption({ + name: "deploymentsDir", + description: "Root directory for v2 deployment files", + defaultValue: "./deployments", + }) + .addOption({ + name: "deploymentNetwork", + description: + "Deployment namespace for v2 files; defaults to sepolia-clean-", + defaultValue: "", + }) + .addOption({ + name: "v1DeploymentsDir", + description: "Root directory for v1 deployment files", + defaultValue: "./deployments/v1", + }) + .addOption({ + name: "v1DeploymentNetwork", + description: + "Deployment namespace for v1 files; defaults to the v2 namespace", + defaultValue: "", + }) + .addOption({ + name: "snapshotFile", + description: + "Optional file to write a pre-phase snapshot id after v1 deployment", + defaultValue: "", + }) + .addOption({ + name: "deployer", + description: + "Migration deployer address; defaults to the configured Hardhat account", + defaultValue: "", + }) + .addOption({ + name: "owner", + description: "Migration owner/admin address; defaults to the deployer", + defaultValue: "", + }) + .addOption({ + name: "v1Owner", + description: + "V1 owner address; defaults to the network-configured v1 owner", + defaultValue: "", + }) + .addOption({ + name: "urManager", + description: "Managed URP admin address; defaults to the deployer", + defaultValue: "", + }) + .addOption({ + name: "chainId", + description: "Chain id override", + defaultValue: "", + }) + .addFlag({ + name: "resumeExistingDeployments", + description: + "Resume a clean testnet namespace that already has deployment files", + }) + .addFlag({ + name: "debugRpc", + description: "Log JSON-RPC error responses", + }) + .setAction(() => import("./tasks/clean-testnet.ts")) + .build(), + task( + ["migration", "smoke-v2-registrar"], + "Register a fresh .eth name through the enabled v2 registrar", + ) + .addOption({ + name: "migrationNetwork", + description: "Migration network: sepolia or mainnet", + defaultValue: "sepolia", + }) + .addOption({ + name: "deploymentNetwork", + description: "Deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "deploymentsDir", + description: "Root directory for v2 deployment files", + defaultValue: "./deployments", + }) + .addOption({ + name: "label", + description: "Optional label to register without .eth", + defaultValue: "", + }) + .addOption({ + name: "owner", + description: "Name owner; defaults to the configured Hardhat account", + defaultValue: "", + }) + .addOption({ + name: "chainId", + description: "Chain id override", + defaultValue: "", + }) + .addFlag({ + name: "rpcStateControls", + description: "Use fork RPC time controls for the commitment wait", + }) + .setAction(() => import("./tasks/smoke-v2-registrar.ts")) + .build(), + task( + ["migration", "set-v1-reverse-default-resolver"], + "Point the v1 ReverseRegistrar default resolver at v1 PublicResolver", + ) + .addOption({ + name: "migrationNetwork", + description: "Migration network: sepolia or mainnet", + defaultValue: "sepolia", + }) + .addOption({ + name: "v1DeploymentsDir", + description: "Root directory for v1 deployment files", + defaultValue: "./deployments/v1", + }) + .addOption({ + name: "v1DeploymentNetwork", + description: "V1 deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "chainId", + description: "Chain id override", + defaultValue: "", + }) + .addOption({ + name: "privateKey", + description: + "V1 owner private key (defaults to SEPOLIA_V1_OWNER_KEY/V1_OWNER_KEY, then the Hardhat account)", + defaultValue: "", + }) + .setAction(() => import("./tasks/set-v1-reverse-default-resolver.ts")) + .build(), + task(["migration", "deploy-v2"], "Deploy the v2 migration contracts") + .addOption({ + name: "migrationNetwork", + description: "Migration network: sepolia or mainnet", + defaultValue: "sepolia", + }) + .addOption({ + name: "deploymentsDir", + description: "Root directory for v2 deployments", + defaultValue: "./deployments", + }) + .addOption({ + name: "deploymentNetwork", + description: "Deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "v1DeploymentsDir", + description: "Root directory for v1 deployment files", + defaultValue: "", + }) + .addOption({ + name: "v1DeploymentNetwork", + description: "V1 deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "snapshotFile", + description: "Optional file to write a pre-deploy snapshot id", + defaultValue: "", + }) + .addFlag({ + name: "saveDeployments", + description: "Persist deployment files", + }) + .addFlag({ + name: "includeTestnetPremigrationRegistrar", + description: "Deploy the testnet v1 premigration registrar helper", + }) + .addFlag({ + name: "deferV1OwnerTransactions", + description: + "Record v1-owner transactions instead of broadcasting them (requires --deferred-v1-owner-transactions-file)", + }) + .addOption({ + name: "deferredV1OwnerTransactionsFile", + description: + "JSONL file for deferred v1-owner transactions (required when deferring)", + defaultValue: "", + }) + .addOption({ + name: "tags", + description: + "Comma-separated deploy tags to run instead of the default v2 migration tags", + defaultValue: "", + }) + .addFlag({ + name: "impersonateLegacyOwner", + description: "Impersonate the v1 owner on a fork", + }) + .addFlag({ + name: "debugRpc", + description: "Log JSON-RPC error responses", + }) + .addOption({ + name: "chainId", + description: "Chain id override", + defaultValue: "", + }) + .addOption({ + name: "deployer", + description: "Deployer account address", + defaultValue: "", + }) + .addOption({ + name: "owner", + description: "Owner/admin address", + defaultValue: "", + }) + .addOption({ + name: "urManager", + description: "Managed URP admin address", + defaultValue: "", + }) + .addOption({ + name: "v1Owner", + description: + "v1 owner address for v1 writes; defaults to the network-configured v1 owner", + defaultValue: "", + }) + .setAction(() => import("./tasks/deploy-v2.ts")) + .build(), + task(["migration", "premigration-run"], "Run pre-migration reservations") + .addOption({ + name: "migrationNetwork", + description: "Migration network: sepolia or mainnet", + defaultValue: "sepolia", + }) + .addOption({ + name: "deploymentsDir", + description: "Root directory for v2 deployments", + defaultValue: "./deployments", + }) + .addOption({ + name: "deploymentNetwork", + description: "Deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "v1DeploymentsDir", + description: "Root directory for v1 deployment files", + defaultValue: "", + }) + .addOption({ + name: "v1DeploymentNetwork", + description: "V1 deployment directory network name", + defaultValue: "", + }) + .addOption({ + name: "csvFile", + description: "Pre-migration CSV", + defaultValue: "", + }) + .addOption({ + name: "mainnetRpcUrl", + description: "RPC URL for v1 expiry reads", + defaultValue: "", + }) + .addOption({ + name: "batchSize", + description: "Names per batch", + defaultValue: "50", + }) + .addOption({ + name: "limit", + description: "Maximum names to process", + defaultValue: "", + }) + .addOption({ + name: "bonusPeriodDays", + description: + "Days added to each name's v1 expiry to compute its v2 expiry", + defaultValue: "", + }) + .addOption({ + name: "workDir", + description: "Directory for checkpoints and logs", + defaultValue: "", + }) + .addFlag({ + name: "dryRun", + description: "Simulate without transactions", + }) + .addFlag({ + name: "resume", + description: "Resume from checkpoint", + }) + .setAction(() => import("./tasks/premigration-run.ts")) + .build(), + ], +}; + +export default plugin; diff --git a/contracts/plugins/migration/tasks/batch-registrar-owner.ts b/contracts/plugins/migration/tasks/batch-registrar-owner.ts new file mode 100644 index 000000000..dd34f4882 --- /dev/null +++ b/contracts/plugins/migration/tasks/batch-registrar-owner.ts @@ -0,0 +1,48 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { + checkBatchRegistrarOwner, + parseMigrationNetwork, +} from "../../../script/migration.js"; +import { + optionalAddress, + nonEmptyString, + requireHttpNetwork, +} from "./utils.js"; + +type BatchRegistrarOwnerTaskArgs = { + migrationNetwork: string; + deploymentNetwork: string; + deploymentsDir: string; + batchRegistrar: string; + expectedOwner: string; + chainId: string; +}; + +const action: NewTaskActionFunction = async ( + args, + hre, +) => { + const connection = await hre.network.connect(); + try { + const networkConfig = requireHttpNetwork( + connection.networkConfig, + "migration batch-registrar-owner", + connection.networkName, + ); + + await checkBatchRegistrarOwner({ + network: parseMigrationNetwork(args.migrationNetwork), + rpcUrl: await networkConfig.url.getUrl(), + chainId: nonEmptyString(args.chainId), + deploymentNetwork: nonEmptyString(args.deploymentNetwork), + deploymentsDir: args.deploymentsDir, + batchRegistrar: optionalAddress(args.batchRegistrar), + expectedOwner: optionalAddress(args.expectedOwner), + }); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/clean-testnet.ts b/contracts/plugins/migration/tasks/clean-testnet.ts new file mode 100644 index 000000000..1d6aa29da --- /dev/null +++ b/contracts/plugins/migration/tasks/clean-testnet.ts @@ -0,0 +1,82 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { + parseMigrationNetwork, + runCleanTestnetFull, +} from "../../../script/migration.js"; +import { + isTenderlyVirtualRpc, + logMigrationSigners, + nonEmptyString, + requireHttpNetwork, + resolveMigrationSigners, +} from "./utils.js"; + +type CleanTestnetTaskArgs = { + migrationNetwork: string; + chainId: string; + csvFile: string; + batchSize: string; + initialLimit: string; + finishLimit: string; + workDir: string; + deploymentsDir: string; + deploymentNetwork: string; + v1DeploymentsDir: string; + v1DeploymentNetwork: string; + snapshotFile: string; + deployer: string; + owner: string; + v1Owner: string; + urManager: string; + resumeExistingDeployments: boolean; + debugRpc: boolean; +}; + +const action: NewTaskActionFunction = async ( + args, + hre, +) => { + const connection = await hre.network.connect(); + try { + const networkConfig = requireHttpNetwork( + connection.networkConfig, + "migration clean-testnet", + connection.networkName, + ); + const rpcUrl = await networkConfig.url.getUrl(); + const signers = await resolveMigrationSigners({ + args, + networkConfig, + provider: connection.provider, + ownerFallback: "deployer", + taskName: "migration clean-testnet", + }); + logMigrationSigners(signers); + + await runCleanTestnetFull({ + network: parseMigrationNetwork(args.migrationNetwork), + rpcUrl, + provider: connection.provider, + chainId: nonEmptyString(args.chainId), + csvFile: nonEmptyString(args.csvFile), + batchSize: nonEmptyString(args.batchSize), + initialLimit: nonEmptyString(args.initialLimit), + finishLimit: nonEmptyString(args.finishLimit), + workDir: nonEmptyString(args.workDir), + deploymentsDir: args.deploymentsDir, + deploymentNetwork: nonEmptyString(args.deploymentNetwork), + v1DeploymentsDir: nonEmptyString(args.v1DeploymentsDir), + v1DeploymentNetwork: nonEmptyString(args.v1DeploymentNetwork), + tenderly: isTenderlyVirtualRpc(rpcUrl), + snapshotFile: nonEmptyString(args.snapshotFile), + ...signers, + resumeExistingDeployments: args.resumeExistingDeployments, + debugRpc: args.debugRpc, + }); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/deploy-v2.ts b/contracts/plugins/migration/tasks/deploy-v2.ts new file mode 100644 index 000000000..4a3974009 --- /dev/null +++ b/contracts/plugins/migration/tasks/deploy-v2.ts @@ -0,0 +1,90 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { deployV2, parseMigrationNetwork } from "../../../script/migration.js"; +import { createSnapshot, saveSnapshotFile } from "./snapshot-utils.js"; +import { + isTenderlyVirtualRpc, + requireHttpNetwork, + resolveMigrationSigners, +} from "./utils.js"; + +type DeployV2TaskArgs = { + migrationNetwork: string; + deploymentsDir: string; + deploymentNetwork: string; + v1DeploymentsDir: string; + v1DeploymentNetwork: string; + snapshotFile: string; + saveDeployments: boolean; + tags: string; + includeTestnetPremigrationRegistrar: boolean; + deferV1OwnerTransactions: boolean; + deferredV1OwnerTransactionsFile: string; + impersonateLegacyOwner: boolean; + debugRpc: boolean; + chainId: string; + deployer: string; + owner: string; + urManager: string; + v1Owner: string; +}; + +const action: NewTaskActionFunction = async (args, hre) => { + const connection = await hre.network.connect(); + try { + const networkConfig = requireHttpNetwork( + connection.networkConfig, + "migration deploy-v2", + connection.networkName, + ); + const rpcUrl = await networkConfig.url.getUrl(); + const migrationNetwork = parseMigrationNetwork(args.migrationNetwork); + const signers = await resolveMigrationSigners({ + args, + networkConfig, + ownerFallback: "deployer", + taskName: "migration deploy-v2", + }); + + // On mainnet the owner is the DAO, not the deployer. When no --owner is + // supplied, leave owner/ownerPrivateKey unset so deployV2 uses the + // network-configured owner default rather than acting as the deployer. + const ownerOverride = + args.owner === "" && migrationNetwork === "mainnet" + ? { owner: undefined, ownerPrivateKey: undefined } + : {}; + + if (args.snapshotFile !== "") { + const snapshotId = await createSnapshot(connection.provider); + await saveSnapshotFile(args.snapshotFile, snapshotId, connection.networkName); + console.log(`pre-deploy snapshot: ${snapshotId}`); + console.log(`snapshot file: ${args.snapshotFile}`); + } + + await deployV2({ + network: migrationNetwork, + rpcUrl, + provider: connection.provider, + chainId: args.chainId || undefined, + deploymentsDir: args.deploymentsDir, + deploymentNetwork: args.deploymentNetwork || undefined, + v1DeploymentsDir: args.v1DeploymentsDir || undefined, + v1DeploymentNetwork: args.v1DeploymentNetwork || undefined, + saveDeployments: args.saveDeployments, + tags: args.tags === "" ? undefined : args.tags.split(",").filter(Boolean), + tenderly: isTenderlyVirtualRpc(rpcUrl), + includeTestnetPremigrationRegistrar: args.includeTestnetPremigrationRegistrar, + deferV1OwnerTransactions: args.deferV1OwnerTransactions, + deferredV1OwnerTransactionsFile: args.deferredV1OwnerTransactionsFile || undefined, + impersonateV1Owner: args.impersonateLegacyOwner, + rpcCompatibility: true, + debugRpc: args.debugRpc, + ...signers, + ...ownerOverride, + }); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/fork-full.ts b/contracts/plugins/migration/tasks/fork-full.ts new file mode 100644 index 000000000..b7694d3f0 --- /dev/null +++ b/contracts/plugins/migration/tasks/fork-full.ts @@ -0,0 +1,93 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { + parseMigrationNetwork, + runForkFull, +} from "../../../script/migration.js"; +import { + isTenderlyVirtualRpc, + logMigrationSigners, + nonEmptyString, + requireHttpNetwork, + resolveMigrationSigners, +} from "./utils.js"; + +type ForkFullTaskArgs = { + migrationNetwork: string; + direct: boolean; + chainId: string; + port: string; + csvFile: string; + batchSize: string; + initialLimit: string; + finishLimit: string; + workDir: string; + resumeFromPhase: string; + saveDeployments: boolean; + deploymentsDir: string; + deploymentNetwork: string; + v1DeploymentsDir: string; + v1DeploymentNetwork: string; + snapshotFile: string; + deployer: string; + owner: string; + v1Owner: string; + urManager: string; + includeTestnetPremigrationRegistrar: boolean; + debugRpc: boolean; + keepAnvil: boolean; +}; + +const action: NewTaskActionFunction = async (args, hre) => { + if (args.csvFile === "") { + throw new Error("migration fork-full requires --csv-file"); + } + + const connection = await hre.network.connect(); + try { + const networkConfig = requireHttpNetwork( + connection.networkConfig, + "migration fork-full", + connection.networkName, + ); + const rpcUrl = await networkConfig.url.getUrl(); + const signers = await resolveMigrationSigners({ + args, + networkConfig, + provider: connection.provider, + ownerFallback: "hardhat", + taskName: "migration fork-full", + }); + logMigrationSigners(signers); + + await runForkFull({ + network: parseMigrationNetwork(args.migrationNetwork), + rpcUrl, + direct: args.direct, + chainId: nonEmptyString(args.chainId), + port: nonEmptyString(args.port), + csvFile: args.csvFile, + batchSize: nonEmptyString(args.batchSize), + initialLimit: nonEmptyString(args.initialLimit), + finishLimit: nonEmptyString(args.finishLimit), + workDir: nonEmptyString(args.workDir), + resumeFromPhase: nonEmptyString(args.resumeFromPhase), + saveDeployments: args.saveDeployments, + deploymentsDir: args.deploymentsDir, + deploymentNetwork: nonEmptyString(args.deploymentNetwork), + v1DeploymentsDir: nonEmptyString(args.v1DeploymentsDir), + v1DeploymentNetwork: nonEmptyString(args.v1DeploymentNetwork), + tenderly: isTenderlyVirtualRpc(rpcUrl), + includeTestnetPremigrationRegistrar: + args.includeTestnetPremigrationRegistrar, + snapshotFile: nonEmptyString(args.snapshotFile), + ...signers, + debugRpc: args.debugRpc, + keepAnvil: args.keepAnvil, + }); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/premigration-run.ts b/contracts/plugins/migration/tasks/premigration-run.ts new file mode 100644 index 000000000..e9933e7ed --- /dev/null +++ b/contracts/plugins/migration/tasks/premigration-run.ts @@ -0,0 +1,78 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { + parseMigrationNetwork, + runPreMigrationCommand, +} from "../../../script/migration.js"; +import { + defaultHardhatSigner, + nonEmptyString, + requireHttpNetwork, +} from "./utils.js"; + +type PremigrationRunTaskArgs = { + migrationNetwork: string; + deploymentsDir: string; + deploymentNetwork: string; + v1DeploymentsDir: string; + v1DeploymentNetwork: string; + csvFile: string; + mainnetRpcUrl: string; + batchSize: string; + limit: string; + bonusPeriodDays: string; + workDir: string; + dryRun: boolean; + resume: boolean; +}; + +const action: NewTaskActionFunction = async ( + args, + hre, +) => { + const connection = await hre.network.connect(); + try { + const networkConfig = requireHttpNetwork( + connection.networkConfig, + "migration premigration-run", + connection.networkName, + ); + const rpcUrl = await networkConfig.url.getUrl(); + const signer = await defaultHardhatSigner( + networkConfig, + connection.provider, + ); + if (!signer.privateKey) { + throw new Error( + "migration premigration-run could not resolve a Hardhat private key; configure DEPLOYER_KEY", + ); + } + if (args.csvFile === "") { + throw new Error("migration premigration-run requires --csv-file"); + } + + await runPreMigrationCommand( + { + network: parseMigrationNetwork(args.migrationNetwork), + rpcUrl, + mainnetRpcUrl: nonEmptyString(args.mainnetRpcUrl), + deploymentsDir: args.deploymentsDir, + deploymentNetwork: nonEmptyString(args.deploymentNetwork), + v1DeploymentsDir: nonEmptyString(args.v1DeploymentsDir), + v1DeploymentNetwork: nonEmptyString(args.v1DeploymentNetwork), + privateKey: signer.privateKey, + csvFile: args.csvFile, + batchSize: nonEmptyString(args.batchSize), + limit: nonEmptyString(args.limit), + bonusPeriodDays: nonEmptyString(args.bonusPeriodDays), + workDir: nonEmptyString(args.workDir), + dryRun: args.dryRun, + }, + args.resume, + ); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/revert.ts b/contracts/plugins/migration/tasks/revert.ts new file mode 100644 index 000000000..be632fe86 --- /dev/null +++ b/contracts/plugins/migration/tasks/revert.ts @@ -0,0 +1,30 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { readSnapshotFile } from "./snapshot-utils.js"; + +type RevertTaskArgs = { + snapshotId: string; + file: string; +}; + +const action: NewTaskActionFunction = async (args, hre) => { + if (args.snapshotId === "" && args.file === "") { + throw new Error("Provide --snapshot-id or --file"); + } + const snapshotId = args.snapshotId || await readSnapshotFile(args.file); + const connection = await hre.network.connect(); + try { + const result = await connection.provider.request({ + method: "evm_revert", + params: [snapshotId], + }); + if (result !== true) { + throw new Error(`evm_revert failed for snapshot ${snapshotId}: ${String(result)}`); + } + console.log(`reverted snapshot: ${snapshotId}`); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/set-v1-reverse-default-resolver.ts b/contracts/plugins/migration/tasks/set-v1-reverse-default-resolver.ts new file mode 100644 index 000000000..9e7f3e5f5 --- /dev/null +++ b/contracts/plugins/migration/tasks/set-v1-reverse-default-resolver.ts @@ -0,0 +1,58 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { + parseMigrationNetwork, + setV1ReverseDefaultResolver, +} from "../../../script/migration.js"; +import { + defaultHardhatPrivateKey, + nonEmptyString, + requireHttpNetwork, +} from "./utils.js"; + +type SetV1ReverseDefaultResolverTaskArgs = { + migrationNetwork: string; + chainId: string; + v1DeploymentsDir: string; + v1DeploymentNetwork: string; + privateKey: string; +}; + +const action: NewTaskActionFunction< + SetV1ReverseDefaultResolverTaskArgs +> = async (args, hre) => { + const connection = await hre.network.connect(); + try { + const networkConfig = requireHttpNetwork( + connection.networkConfig, + "migration set-v1-reverse-default-resolver", + connection.networkName, + ); + // setDefaultResolver is owner-gated on the v1 ReverseRegistrar, whose owner is + // the v1 owner rather than the deployer. Prefer an explicitly supplied v1-owner + // key, then the configured v1-owner env key, and only fall back to the Hardhat + // account for the clean-testnet case where the deployer owns the fresh v1. + const privateKey = + (nonEmptyString(args.privateKey) as `0x${string}` | undefined) ?? + (process.env.SEPOLIA_V1_OWNER_KEY as `0x${string}` | undefined) ?? + (process.env.V1_OWNER_KEY as `0x${string}` | undefined) ?? + (await defaultHardhatPrivateKey(networkConfig)); + if (privateKey === undefined) { + throw new Error( + "migration set-v1-reverse-default-resolver could not resolve a signer; pass --private-key, configure SEPOLIA_V1_OWNER_KEY/V1_OWNER_KEY, or DEPLOYER_KEY", + ); + } + await setV1ReverseDefaultResolver({ + network: parseMigrationNetwork(args.migrationNetwork), + rpcUrl: await networkConfig.url.getUrl(), + chainId: nonEmptyString(args.chainId), + v1DeploymentsDir: nonEmptyString(args.v1DeploymentsDir), + v1DeploymentNetwork: nonEmptyString(args.v1DeploymentNetwork), + privateKey, + }); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/smoke-v2-registrar.ts b/contracts/plugins/migration/tasks/smoke-v2-registrar.ts new file mode 100644 index 000000000..042d59ff6 --- /dev/null +++ b/contracts/plugins/migration/tasks/smoke-v2-registrar.ts @@ -0,0 +1,63 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { + parseMigrationNetwork, + runV2RegistrarSmoke, +} from "../../../script/migration.js"; +import { + addressForPrivateKey, + defaultHardhatPrivateKey, + optionalAddress, + nonEmptyString, + requireHttpNetwork, +} from "./utils.js"; + +type SmokeV2RegistrarTaskArgs = { + migrationNetwork: string; + chainId: string; + deploymentsDir: string; + deploymentNetwork: string; + label: string; + owner: string; + rpcStateControls: boolean; +}; + +const action: NewTaskActionFunction = async ( + args, + hre, +) => { + const connection = await hre.network.connect(); + try { + const networkConfig = requireHttpNetwork( + connection.networkConfig, + "migration smoke-v2-registrar", + connection.networkName, + ); + const privateKey = await defaultHardhatPrivateKey(networkConfig); + if (privateKey === undefined) { + throw new Error( + "migration smoke-v2-registrar could not resolve a Hardhat private key; configure DEPLOYER_KEY", + ); + } + const signer = addressForPrivateKey(privateKey); + const owner = optionalAddress(args.owner) ?? signer; + console.log(`migration signer: ${signer}`); + console.log(`name owner: ${owner}`); + + await runV2RegistrarSmoke({ + network: parseMigrationNetwork(args.migrationNetwork), + rpcUrl: await networkConfig.url.getUrl(), + chainId: nonEmptyString(args.chainId), + deploymentsDir: args.deploymentsDir, + deploymentNetwork: nonEmptyString(args.deploymentNetwork), + label: nonEmptyString(args.label), + owner, + privateKey, + rpcStateControls: args.rpcStateControls, + }); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/snapshot-utils.ts b/contracts/plugins/migration/tasks/snapshot-utils.ts new file mode 100644 index 000000000..98203d302 --- /dev/null +++ b/contracts/plugins/migration/tasks/snapshot-utils.ts @@ -0,0 +1,32 @@ +import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; +import { + createRpcSnapshot, + saveRpcSnapshotFile, +} from "../../../script/migration.js"; + +// The canonical snapshot create/save implementations (and the JSON payload shape of +// the snapshot file) live in script/migration.ts; these are thin re-exports so the +// Hardhat tasks and the standalone CLI cannot drift apart. +export const createSnapshot = createRpcSnapshot; + +export async function saveSnapshotFile( + path: string, + snapshotId: string, + network: string, +): Promise { + saveRpcSnapshotFile(path, snapshotId, network); +} + +export async function readSnapshotFile(path: string): Promise { + const contents = await readFile(resolve(path), "utf8"); + try { + const parsed = JSON.parse(contents); + if (typeof parsed.snapshotId === "string") return parsed.snapshotId; + } catch { + // Plain snapshot id files are also accepted. + } + const snapshotId = contents.trim(); + if (!snapshotId) throw new Error(`snapshot file is empty: ${path}`); + return snapshotId; +} diff --git a/contracts/plugins/migration/tasks/snapshot.ts b/contracts/plugins/migration/tasks/snapshot.ts new file mode 100644 index 000000000..8e08c50b7 --- /dev/null +++ b/contracts/plugins/migration/tasks/snapshot.ts @@ -0,0 +1,23 @@ +import type { NewTaskActionFunction } from "hardhat/types/tasks"; + +import { createSnapshot, saveSnapshotFile } from "./snapshot-utils.js"; + +type SnapshotTaskArgs = { + file: string; +}; + +const action: NewTaskActionFunction = async (args, hre) => { + const connection = await hre.network.connect(); + try { + const snapshotId = await createSnapshot(connection.provider); + console.log(snapshotId); + if (args.file !== "") { + await saveSnapshotFile(args.file, snapshotId, connection.networkName); + console.log(`snapshot file: ${args.file}`); + } + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/plugins/migration/tasks/utils.ts b/contracts/plugins/migration/tasks/utils.ts new file mode 100644 index 000000000..566955743 --- /dev/null +++ b/contracts/plugins/migration/tasks/utils.ts @@ -0,0 +1,202 @@ +import { getAddress, type Address } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; + +import { isTenderlyVirtualRpc } from "../../../script/migration.js"; + +export { isTenderlyVirtualRpc }; + +type HttpNetworkConfig = { + type: "http"; + url: { getUrl(): Promise }; + accounts?: unknown; +}; + +type RpcAccountProvider = { + request(args: { method: string; params?: unknown[] }): Promise; +}; + +type MigrationSignerArgs = { + deployer: string; + owner: string; + v1Owner: string; + urManager: string; +}; + +export type MigrationSigners = { + deployer: Address; + owner: Address; + v1Owner?: Address; + urManager: Address; + deployerPrivateKey?: `0x${string}`; + ownerPrivateKey?: `0x${string}`; + v1OwnerPrivateKey?: `0x${string}`; + urManagerPrivateKey?: `0x${string}`; +}; + +/** Returns the value unless it is the empty string (Hardhat's "unset" default). */ +export function nonEmptyString(value: string): string | undefined { + return value === "" ? undefined : value; +} + +export function optionalAddress(value: string): Address | undefined { + return value === "" ? undefined : (getAddress(value) as Address); +} + +export function requireHttpNetwork( + networkConfig: { type: string }, + taskName: string, + networkName: string, +): HttpNetworkConfig { + if (networkConfig.type !== "http") { + throw new Error(`${taskName} requires an HTTP network; got ${networkName}`); + } + return networkConfig as HttpNetworkConfig; +} + + +export async function defaultHardhatAccount( + provider: RpcAccountProvider, +): Promise
{ + const accounts = await provider.request({ + method: "eth_accounts", + params: [], + }); + if (!Array.isArray(accounts) || typeof accounts[0] !== "string") + return undefined; + return getAddress(accounts[0]) as Address; +} + +export async function defaultHardhatPrivateKey(networkConfig: { + accounts?: unknown; +}): Promise<`0x${string}` | undefined> { + const accounts = networkConfig.accounts; + if (!Array.isArray(accounts) || accounts.length === 0) return undefined; + const first = accounts[0] as { getHexString?: () => Promise }; + const value = await first.getHexString?.(); + return value === undefined ? undefined : (value as `0x${string}`); +} + +export function addressForPrivateKey(privateKey: `0x${string}`): Address { + return privateKeyToAccount(privateKey).address as Address; +} + +export function maybeAddressForPrivateKey( + privateKey: `0x${string}` | undefined, +): Address | undefined { + return privateKey === undefined + ? undefined + : addressForPrivateKey(privateKey); +} + +/** Returns `privateKey` only when `address` is the same account as `signerAddress`. */ +export function privateKeyIfAddressMatches( + address: Address | undefined, + signerAddress: Address | undefined, + privateKey: `0x${string}` | undefined, +): `0x${string}` | undefined { + if (address === undefined || signerAddress === undefined) return undefined; + return getAddress(address) === getAddress(signerAddress) + ? privateKey + : undefined; +} + +export async function defaultHardhatSigner( + networkConfig: { accounts?: unknown }, + provider?: RpcAccountProvider, +): Promise<{ address?: Address; privateKey?: `0x${string}` }> { + const privateKey = await defaultHardhatPrivateKey(networkConfig); + if (privateKey !== undefined) { + return { + address: addressForPrivateKey(privateKey), + privateKey, + }; + } + return { + address: provider ? await defaultHardhatAccount(provider) : undefined, + privateKey: undefined, + }; +} + +export async function resolveMigrationSigners({ + args, + networkConfig, + provider, + ownerFallback, + taskName, +}: { + args: MigrationSignerArgs; + networkConfig: { accounts?: unknown }; + provider?: RpcAccountProvider; + ownerFallback: "deployer" | "hardhat"; + taskName: string; +}): Promise { + const hardhatSigner = await defaultHardhatSigner(networkConfig, provider); + const deployer = optionalAddress(args.deployer) ?? hardhatSigner.address; + if (deployer === undefined) { + throw new Error( + `${taskName} could not resolve a Hardhat deployer account; configure DEPLOYER_KEY or pass --deployer`, + ); + } + + const defaultOwner = + ownerFallback === "deployer" ? deployer : hardhatSigner.address; + const owner = optionalAddress(args.owner) ?? defaultOwner; + if (owner === undefined) { + throw new Error( + `${taskName} could not resolve a Hardhat owner account; configure DEPLOYER_KEY or pass --owner`, + ); + } + + const urManager = + optionalAddress(args.urManager) ?? + (ownerFallback === "deployer" ? deployer : hardhatSigner.address); + if (urManager === undefined) { + throw new Error( + `${taskName} could not resolve a Hardhat account; configure DEPLOYER_KEY or pass --ur-manager`, + ); + } + + // Leave unset when no override is supplied so downstream deploy logic uses the + // network-configured v1 owner rather than overriding it with the migration owner. + const v1Owner = optionalAddress(args.v1Owner); + const hardhatPrivateKey = hardhatSigner.privateKey; + const hardhatAddress = hardhatSigner.address; + return { + deployer, + deployerPrivateKey: privateKeyIfAddressMatches( + deployer, + hardhatAddress, + hardhatPrivateKey, + ), + owner, + ownerPrivateKey: privateKeyIfAddressMatches( + owner, + hardhatAddress, + hardhatPrivateKey, + ), + v1Owner, + v1OwnerPrivateKey: privateKeyIfAddressMatches( + v1Owner, + hardhatAddress, + hardhatPrivateKey, + ), + urManager, + urManagerPrivateKey: privateKeyIfAddressMatches( + urManager, + hardhatAddress, + hardhatPrivateKey, + ), + }; +} + +export function logMigrationSigners( + signers: Pick< + MigrationSigners, + "deployer" | "owner" | "v1Owner" | "urManager" + >, +) { + console.log(`migration deployer: ${signers.deployer}`); + console.log(`migration owner: ${signers.owner}`); + console.log(`v1 owner: ${signers.v1Owner ?? "(network default)"}`); + console.log(`managed URP admin: ${signers.urManager}`); +} diff --git a/contracts/plugins/migration/tasks/verify-all.ts b/contracts/plugins/migration/tasks/verify-all.ts new file mode 100644 index 000000000..3f1207ce9 --- /dev/null +++ b/contracts/plugins/migration/tasks/verify-all.ts @@ -0,0 +1,197 @@ +import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; + +import type { NewTaskActionFunction } from "hardhat/types/tasks"; +import { + createPublicClient, + custom, + decodeFunctionResult, + defineChain, + encodeFunctionData, + getAddress, + namehash, + parseAbi, + zeroAddress, + type Address, + type Hex, +} from "viem"; + +import { Artifact_PermissionedRegistry } from "generated/artifacts/PermissionedRegistry.js"; +import { Artifact_UniversalResolverV2 } from "generated/artifacts/UniversalResolverV2.js"; +import { Artifact_UpgradableUniversalResolverProxy } from "generated/artifacts/UpgradableUniversalResolverProxy.js"; +import { DEPLOYED_UNIVERSAL_RESOLVER_PROXY, ROLES } from "../../../script/deploy-constants.js"; + +type VerifyAllTaskArgs = { + migrationNetwork: string; + deploymentNetwork: string; + deploymentsDir: string; + names: string; + topUrp: string; +}; + +type Deployment = { + address: Address; +}; + +const REGISTRAR_ROLES = ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW; +const addrAbi = parseAbi(["function addr(bytes32 node) view returns (address)"]); + +function dnsEncodeName(name: string): Hex { + const bytes: number[] = []; + for (const label of name.split(".")) { + const labelBytes = Buffer.from(label, "utf8"); + if (labelBytes.length > 255) { + throw new Error(`label is too long: ${label}`); + } + bytes.push(labelBytes.length, ...labelBytes); + } + bytes.push(0); + return `0x${Buffer.from(bytes).toString("hex")}`; +} + +async function loadDeployment( + deploymentsDir: string, + deploymentNetwork: string, + name: string, +): Promise { + const path = resolve(deploymentsDir, deploymentNetwork, `${name}.json`); + const deployment = JSON.parse(await readFile(path, "utf8")) as Deployment; + if (!deployment.address) throw new Error(`deployment missing address: ${path}`); + return deployment; +} + +function expectAddress(label: string, actual: Address, expected: Address) { + if (getAddress(actual) !== getAddress(expected)) { + throw new Error(`${label}: expected ${expected}, got ${actual}`); + } + console.log(`ok: ${label} = ${actual}`); +} + +function expectAddressOneOf( + label: string, + actual: Address, + expected: Array<{ label: string; address: Address }>, +) { + const actualAddress = getAddress(actual); + const match = expected.find(({ address }) => actualAddress === getAddress(address)); + if (!match) { + const expectedLabels = expected + .map(({ label, address }) => `${label} ${address}`) + .join(", "); + throw new Error(`${label}: expected one of ${expectedLabels}, got ${actual}`); + } + console.log(`ok: ${label} = ${actual} (${match.label})`); + return match.label; +} + +function expectBoolean(label: string, actual: boolean, expected: boolean) { + if (actual !== expected) { + throw new Error(`${label}: expected ${expected}, got ${actual}`); + } + console.log(`ok: ${label} = ${actual}`); +} + +const action: NewTaskActionFunction = async (args, hre) => { + const deploymentNetwork = args.deploymentNetwork || args.migrationNetwork; + const connection = await hre.network.connect(); + try { + const chainId = Number(await connection.provider.request({ method: "eth_chainId" })); + const client = createPublicClient({ + chain: defineChain({ + id: chainId, + name: connection.networkName, + nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" }, + rpcUrls: { default: { http: [] } }, + }), + transport: custom(connection.provider), + }); + + const rootRegistry = await loadDeployment(args.deploymentsDir, deploymentNetwork, "RootRegistry"); + const ethRegistry = await loadDeployment(args.deploymentsDir, deploymentNetwork, "ETHRegistry"); + const ethRegistrar = await loadDeployment(args.deploymentsDir, deploymentNetwork, "ETHRegistrar"); + const batchRegistrar = await loadDeployment(args.deploymentsDir, deploymentNetwork, "BatchRegistrar"); + const universalResolverV2 = await loadDeployment(args.deploymentsDir, deploymentNetwork, "UniversalResolverV2"); + const topUrp = (args.topUrp || DEPLOYED_UNIVERSAL_RESOLVER_PROXY) as Address; + const managedUrp = await loadDeployment(args.deploymentsDir, deploymentNetwork, "ManagedUniversalResolverProxy"); + + const rootEthSubregistry = await client.readContract({ + address: rootRegistry.address, + abi: Artifact_PermissionedRegistry.abi, + functionName: "getSubregistry", + args: ["eth"], + }) as Address; + expectAddress("RootRegistry .eth subregistry", rootEthSubregistry, ethRegistry.address); + + const [parent, label] = await client.readContract({ + address: ethRegistry.address, + abi: Artifact_PermissionedRegistry.abi, + functionName: "getParent", + }) as [Address, string]; + expectAddress("ETHRegistry parent", parent, rootRegistry.address); + if (label !== "eth") throw new Error(`ETHRegistry parent label: expected eth, got ${label}`); + console.log(`ok: ETHRegistry parent label = ${label}`); + + const topImplementation = await client.readContract({ + address: topUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + functionName: "implementation", + }) as Address; + + const managedImplementation = await client.readContract({ + address: managedUrp.address, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + functionName: "implementation", + }) as Address; + expectAddress("managed URP implementation", managedImplementation, universalResolverV2.address); + expectAddressOneOf("deployed URP implementation", topImplementation, [ + { label: "managed-hop state", address: managedUrp.address }, + { label: "direct implementation state", address: universalResolverV2.address }, + ]); + + const batchRegistrarEnabled = await client.readContract({ + address: ethRegistry.address, + abi: Artifact_PermissionedRegistry.abi, + functionName: "hasRootRoles", + args: [REGISTRAR_ROLES, batchRegistrar.address], + }) as boolean; + expectBoolean("BatchRegistrar registrar roles", batchRegistrarEnabled, false); + + const ethRegistrarEnabled = await client.readContract({ + address: ethRegistry.address, + abi: Artifact_PermissionedRegistry.abi, + functionName: "hasRootRoles", + args: [REGISTRAR_ROLES, ethRegistrar.address], + }) as boolean; + expectBoolean("ETHRegistrar registrar roles", ethRegistrarEnabled, true); + + const names = args.names.split(",").map((name) => name.trim()).filter(Boolean); + for (const name of names) { + const call = encodeFunctionData({ + abi: addrAbi, + functionName: "addr", + args: [namehash(name)], + }); + const [result, resolver] = await client.readContract({ + address: topUrp, + abi: Artifact_UniversalResolverV2.abi, + functionName: "resolve", + args: [dnsEncodeName(name), call], + }) as [Hex, Address]; + const address = decodeFunctionResult({ + abi: addrAbi, + functionName: "addr", + data: result, + }) as Address; + if (getAddress(address) === getAddress(zeroAddress)) { + throw new Error(`${name} resolved to zero address via resolver ${resolver}`); + } + console.log(`ok: ${name} resolves to ${address} via ${resolver}`); + } + + console.log("verify-all passed"); + } finally { + await connection.close(); + } +}; + +export default action; diff --git a/contracts/remappings.txt b/contracts/remappings.txt index 25346ee06..16553d6eb 100644 --- a/contracts/remappings.txt +++ b/contracts/remappings.txt @@ -7,6 +7,7 @@ @unruggable/gateways/=lib/unruggable-gateways/ @ensdomains/verifiable-factory/=lib/verifiable-factory/src/ forge-std/=lib/forge-std/src/ +solady/=lib/solady/src/ lib/ens-contracts/contracts/utils/LibMem/=src/utils/ lib/ens-contracts/:@openzeppelin/contracts=lib/openzeppelin-contracts-v4/contracts lib/ens-contracts/:@openzeppelin/contracts-v5=lib/openzeppelin-contracts/contracts diff --git a/contracts/rocketh.ts b/contracts/rocketh.ts deleted file mode 100644 index 11dd19e1b..000000000 --- a/contracts/rocketh.ts +++ /dev/null @@ -1,79 +0,0 @@ -// rocketh.ts -// ------------------------------------------------------------------------------------------------ -// Typed Config -// ------------------------------------------------------------------------------------------------ -import type { UserConfig } from "rocketh"; -export const config = { - accounts: { - deployer: { - default: 0, - }, - owner: { - default: 0, - // admin is DAO on mainnet - 1: "0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7", - }, - }, - networks: { - // "l1-local": { - // scripts: ["deploy/l1", "deploy/shared"], - // tags: ["l1", "local"], - // rpcUrl: "http://127.0.0.1:8545", - // }, - // "l2-local": { - // scripts: ["deploy/l2", "deploy/shared"], - // tags: ["l2", "local"], - // rpcUrl: "http://127.0.0.1:8546", - // }, - mainnet: { - scripts: ["deploy/l1/universalResolver"], - tags: ["hasDao"], - }, - sepolia: { - scripts: ["deploy/l1/universalResolver"], - tags: [], - }, - holesky: { - scripts: ["deploy/l1/universalResolver"], - tags: [], - }, - }, -} as const satisfies UserConfig; - -// ------------------------------------------------------------------------------------------------ -// Imports and Re-exports -// ------------------------------------------------------------------------------------------------ -// We regroup all what is needed for the deploy scripts -// so that they just need to import this file -import * as deployFunctions from "@rocketh/deploy"; -import * as readExecuteFunctions from "@rocketh/read-execute"; -import * as viemFunctions from "@rocketh/viem"; - -// ------------------------------------------------------------------------------------------------ -// we re-export the artifacts, so they are easily available from the alias -import artifacts from "./generated/artifacts.ts"; -export { artifacts }; -// ------------------------------------------------------------------------------------------------ - -import { - setup, - type CurriedFunctions, - type Environment as Environment_, -} from "rocketh"; - -const functions = { - ...deployFunctions, - ...readExecuteFunctions, - ...viemFunctions, -}; - -export type Environment = Environment_ & - CurriedFunctions; - -const enhanced = setup(functions); - -// import type { RockethArguments } from "./script/types.ts"; - -export const execute = enhanced.deployScript; //; - -export const loadAndExecuteDeployments = enhanced.loadAndExecuteDeployments; //; diff --git a/contracts/rocketh/config.ts b/contracts/rocketh/config.ts new file mode 100644 index 000000000..746f2877a --- /dev/null +++ b/contracts/rocketh/config.ts @@ -0,0 +1,274 @@ +import * as deployExtension from "@rocketh/deploy"; +import { loadDeploymentsFromFiles } from "@rocketh/node"; +import type { Environment } from "@rocketh/node"; +import * as proxyExtension from "@rocketh/proxy"; +import * as readExecuteExtension from "@rocketh/read-execute"; +import * as viemExtension from "@rocketh/viem"; +import { appendFileSync, mkdirSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import type { + Deployment, + EIP1193TransactionReceipt, + PendingDeployment, + UserConfig, +} from "rocketh/types"; +import { encodeFunctionData, getAddress, type Address } from "viem"; + +export const config = { + accounts: { + deployer: { + default: 0, + }, + owner: { + default: 0, + // admin is DAO on mainnet + mainnet: "0xfe89cc7abb2c4183683ab71653c4cdc9b02d44b7", + 1: "0xfe89cc7abb2c4183683ab71653c4cdc9b02d44b7", + }, + securityCouncil: { + // admin of ManagedUniversalResolverProxy; set per-network to the + // security council multisig once one is designated + default: "deployer", + // admin of the long-lived intermediate URP that the top URP already fronts + sepolia: "0xffFffFFfFF52D316B7Bd028358089bc8066b8f80", + 11155111: "0xffFffFFfFF52D316B7Bd028358089bc8066b8f80", + }, + urManager: { + default: "securityCouncil", + }, + v1Owner: { + default: "owner", + sepolia: "0x0f32b753afc8abad9ca6fe589f707755f4df2353", + 11155111: "0x0f32b753afc8abad9ca6fe589f707755f4df2353", + }, + }, + environments: { + mainnet: { + chain: 1, + scripts: ["deploy"], + overrides: { + tags: ["hasDao"], + }, + }, + sepolia: { + chain: 11155111, + scripts: ["deploy"], + }, + "sepolia-dev": { + chain: 11155111, + scripts: ["deploy"], + overrides: { + // Treat this Sepolia-derived environment as sepolia for the known top URP + // and other sepolia-gated setup; getV1 applies the matching v1 normalization. + tags: ["sepolia", "dev"], + }, + }, + "sepolia-v1-dev": { + chain: 11155111, + scripts: ["lib/ens-contracts/deploy"], + }, + }, + data: {}, +} as const satisfies UserConfig; + +type LoadedDeployments = Awaited>; + +const rockethDir = dirname(fileURLToPath(import.meta.url)); +const deploymentsCache = new Map>(); + +type V1DeploymentOverrides = { + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + deferV1OwnerTransactions?: boolean; + deferredV1OwnerTransactionsFile?: string; +}; + +const extensions = { + ...deployExtension, + ...proxyExtension, + ...readExecuteExtension, + ...viemExtension, + execute: (env: Environment) => { + const execute = readExecuteExtension.execute(env); + return async (deployment: any, args: any) => { + const extra = (env.extra ?? {}) as V1DeploymentOverrides; + if (!extra.deferV1OwnerTransactions) return execute(deployment, args); + + const from = getAddress(env.resolveAccount(args.account)); + const v1Owner = env.namedAccounts?.v1Owner; + const owner = env.namedAccounts?.owner; + const deployer = env.namedAccounts?.deployer; + // Defer writes whose signer cannot sign during a live phase-1 deploy and + // must instead be replayed via execute-owner-txs (or a Safe): the v1 owner, + // and the admin owner when it is a distinct account (the DAO on mainnet) + // rather than the deployer itself. + const role = + v1Owner && from === getAddress(v1Owner) + ? "v1Owner" + : owner && + deployer && + getAddress(owner) !== getAddress(deployer) && + from === getAddress(owner) + ? "owner" + : undefined; + if (!role) { + return execute(deployment, args); + } + + const data = encodeFunctionData({ + abi: deployment.abi, + functionName: args.functionName, + args: args.args, + } as any); + const deferred = { + account: role, + from, + to: getAddress(deployment.address), + value: args.value?.toString() ?? "0", + data, + functionName: String(args.functionName), + args: args.args ?? [], + message: args.message, + deployment: deploymentNameFor(env, deployment), + }; + + env.showMessage( + ` - Deferred ${role} tx: ${deferred.functionName} -> ${deferred.to}`, + ); + if (extra.deferredV1OwnerTransactionsFile) { + const file = resolve(extra.deferredV1OwnerTransactionsFile); + mkdirSync(dirname(file), { recursive: true }); + appendFileSync(file, `${JSON.stringify(deferred, jsonReplacer)}\n`); + } + + return deferredReceipt(deferred.from as Address, deferred.to as Address); + }; + }, + getV1: (env: Environment) => { + const extra = (env.extra ?? {}) as V1DeploymentOverrides; + // Sepolia-derived environments (e.g. sepolia-dev) share the canonical sepolia v1 + // deployment set rather than one keyed by the literal environment name. + const environment = + extra.v1DeploymentNetwork ?? + (env.name.startsWith("sepolia") ? "sepolia" : env.name); + const paths = extra.v1DeploymentsDir + ? [resolve(extra.v1DeploymentsDir)] + : [ + resolve(rockethDir, "..", "deployments", "v1"), + resolve(rockethDir, "..", "lib", "ens-contracts", "deployments"), + ]; + const load = (path: string) => { + const key = `${path}:${environment}`; + if (deploymentsCache.has(key)) return deploymentsCache.get(key)!; + const result = loadDeploymentsFromFiles(path, environment, false); + deploymentsCache.set(key, result); + return result; + }; + return async ( + name: string, + ): Promise> => { + for (const path of paths) { + const { deployments } = await load(path); + const deployment = deployments[name]; + if (deployment) return deployment as Deployment; + } + const current = env.deployments[name]; + if (current) return current as Deployment; + throw new Error(`V1 deployment ${name} not found`); + }; + }, + savePendingDeployment: + (env: Environment) => async (pendingDeployment: PendingDeployment) => { + const receipt = await waitForReceipt( + env, + pendingDeployment.transaction.hash, + ); + const contractAddress = + pendingDeployment.expectedAddress ?? receipt.contractAddress; + if (!contractAddress) { + throw new Error(`no contract address found for ${pendingDeployment.name}`); + } + + const { abi, ...artifactObjectWithoutABI } = + pendingDeployment.partialDeployment; + return env.save(pendingDeployment.name, { + address: contractAddress, + abi, + ...artifactObjectWithoutABI, + transaction: pendingDeployment.transaction, + receipt: { + blockHash: receipt.blockHash, + blockNumber: receipt.blockNumber, + transactionIndex: receipt.transactionIndex, + }, + }); + }, +}; +export { extensions }; + +function deploymentNameFor(env: Environment, deployment: { address: Address }) { + const found = Object.entries(env.deployments).find(([, candidate]) => + getAddress(candidate.address) === getAddress(deployment.address) + ); + return found?.[0]; +} + +function jsonReplacer(_key: string, value: unknown) { + return typeof value === "bigint" ? value.toString() : value; +} + +function deferredReceipt(from: Address, to: Address): EIP1193TransactionReceipt { + return { + blockHash: `0x${"0".repeat(64)}`, + blockNumber: "0x0", + contractAddress: null, + cumulativeGasUsed: "0x0", + effectiveGasPrice: "0x0", + from, + gasUsed: "0x0", + logs: [], + logsBloom: `0x${"0".repeat(512)}`, + root: `0x${"0".repeat(64)}`, + status: "0x1", + to, + transactionHash: `0x${"0".repeat(64)}`, + transactionIndex: "0x0", + type: "0x2", + } as unknown as EIP1193TransactionReceipt; +} + +async function waitForReceipt( + env: Environment, + hash: `0x${string}`, +): Promise { + for (;;) { + let receipt: EIP1193TransactionReceipt | null = null; + try { + receipt = (await env.network.provider.request({ + method: "eth_getTransactionReceipt", + params: [hash], + })) as EIP1193TransactionReceipt | null; + } catch {} + if (receipt?.blockHash) return receipt; + await new Promise((resolve) => setTimeout(resolve, 50)); + } +} + +type HookFunctions = { + createLegacyRegistryNames?: (env: Environment) => () => Promise; + registerLegacyNames?: (env: Environment) => () => Promise; + registerWrappedNames?: (env: Environment) => () => Promise; + registerUnwrappedNames?: (env: Environment) => () => Promise; + savePendingDeployment?: ( + env: Environment, + ) => ( + pendingDeployment: PendingDeployment, + ) => Promise>; +}; + +type Extensions = typeof extensions & HookFunctions; +type Accounts = typeof config.accounts; +type Data = typeof config.data; + +export type { Accounts, Data, Extensions }; diff --git a/contracts/rocketh/deploy.ts b/contracts/rocketh/deploy.ts new file mode 100644 index 000000000..753e4a2df --- /dev/null +++ b/contracts/rocketh/deploy.ts @@ -0,0 +1,14 @@ +import { setupDeployScripts } from "rocketh"; +import artifacts from "../script/artifacts.js"; +import { + type Accounts, + type Data, + type Extensions, + extensions, +} from "./config.js"; + +const { deployScript } = setupDeployScripts( + extensions, +); + +export { artifacts, deployScript, deployScript as execute }; diff --git a/contracts/rocketh/environment.ts b/contracts/rocketh/environment.ts new file mode 100644 index 000000000..ee4aea20a --- /dev/null +++ b/contracts/rocketh/environment.ts @@ -0,0 +1,28 @@ +import { setupEnvironmentFromFiles } from "@rocketh/node"; +import { setupHardhatDeploy } from "hardhat-deploy/helpers"; +import { + type Accounts, + type Data, + type Extensions, + extensions, +} from "./config.js"; + +const { + loadAndExecuteDeploymentsFromFiles, + loadAndExecuteDeploymentsFromFilesWithConfig, +} = setupEnvironmentFromFiles(extensions); +const { loadEnvironmentFromHardhat } = setupHardhatDeploy< + Extensions, + Accounts, + Data +>(extensions); + +export type Environment = Awaited< + ReturnType +>; + +export { + loadAndExecuteDeploymentsFromFiles, + loadAndExecuteDeploymentsFromFilesWithConfig, + loadEnvironmentFromHardhat, +}; diff --git a/contracts/script/addressDocs.ts b/contracts/script/addressDocs.ts new file mode 100644 index 000000000..266ff77ae --- /dev/null +++ b/contracts/script/addressDocs.ts @@ -0,0 +1,154 @@ +import { loadDeploymentsFromFiles } from "@rocketh/node"; +import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { join, resolve } from "node:path"; + +const DEFAULT_DOCS_DIR = resolve( + new URL(import.meta.url).pathname, + "../..", + "docs", + "addresses", +); + +/// Block explorer base URLs keyed by chain id. Chains absent from this map +/// render plain (unlinked) addresses. +const EXPLORER_BASE: Record = { + 1: "https://etherscan.io", + 11155111: "https://sepolia.etherscan.io", +}; + +export interface ContractEntry { + name: string; + address: string; +} + +/// True for `_Implementation` / `_Proxy` artifacts whose `` +/// deployment also exists, so the proxy chain collapses to its canonical entry. +export function isProxyArtifact(name: string, names: Set): boolean { + for (const suffix of ["_Implementation", "_Proxy"]) { + if (name.endsWith(suffix) && names.has(name.slice(0, -suffix.length))) { + return true; + } + } + return false; +} + +/// Build the canonical, sorted list of contracts for a deployment namespace: +/// proxy implementation/proxy artifacts and entries without an address are +/// dropped, the remainder sorted alphabetically by name. +export function loadContractEntries( + deployments: Record, +): ContractEntry[] { + const names = new Set(Object.keys(deployments)); + return Object.entries(deployments) + .map(([name, deployment]) => ({ + name, + address: (deployment as { address?: string }).address ?? "", + })) + .filter(({ name, address }) => address && !isProxyArtifact(name, names)) + .sort((a, b) => a.name.localeCompare(b.name)); +} + +/// Etherscan address URL for a chain, or `null` when the chain is unknown. +export function explorerUrl(chainId: number, address: string): string | null { + const base = EXPLORER_BASE[chainId]; + return base ? `${base}/address/${address}` : null; +} + +/// Markdown address cell: an explorer link when the chain is known, otherwise +/// the plain address. +function addressCell(chainId: number | undefined, address: string): string { + const url = chainId === undefined ? null : explorerUrl(chainId, address); + return url ? `[${address}](${url})` : address; +} + +function formatTable( + contracts: ContractEntry[], + chainId: number | undefined, +): string { + const rows = [ + ["Contract", "Address"], + ["---", "---"], + ...contracts.map(({ name, address }) => [ + name, + addressCell(chainId, address), + ]), + ]; + return rows.map((row) => `| ${row.join(" | ")} |`).join("\n"); +} + +function readJson(path: string): T | null { + try { + return JSON.parse(readFileSync(path, "utf-8")) as T; + } catch { + return null; + } +} + +export interface GenerateAddressMarkdownOptions { + /// Root deployments directory containing the namespace subdirectory. + deploymentsDir: string; + /// Namespace subdirectory to read artifacts from (e.g. `sepolia`). + namespace: string; + /// Canonical network name used for the output filename and heading (e.g. + /// `sepolia`). Defaults to `namespace`. + docName?: string; + /// Output directory for the generated markdown. Defaults to + /// `contracts/docs/addresses`. + outDir?: string; +} + +/// Generate a markdown address table for a deployment namespace and write it to +/// `/.md`. Returns the written file path. +export async function generateAddressMarkdown( + opts: GenerateAddressMarkdownOptions, +): Promise { + const deploymentsDir = resolve(opts.deploymentsDir); + const docName = opts.docName ?? opts.namespace; + const outDir = resolve(opts.outDir ?? DEFAULT_DOCS_DIR); + + const { deployments } = await loadDeploymentsFromFiles( + deploymentsDir, + opts.namespace, + false, + ); + const contracts = loadContractEntries(deployments); + + const namespaceDir = join(deploymentsDir, opts.namespace); + const chain = readJson<{ chainId?: string | number }>( + join(namespaceDir, ".chain"), + ); + const deployment = readJson<{ deployedAt?: string }>( + join(namespaceDir, ".deployment.json"), + ); + const chainId = + chain?.chainId !== undefined ? Number(chain.chainId) : undefined; + + const title = `# ENSv2 ${capitalize(docName)} Deployment Addresses`; + const meta = [ + `- **Network:** ${docName}`, + chainId !== undefined ? `- **Chain ID:** ${chainId}` : null, + deployment?.deployedAt + ? `- **Deployed at:** ${deployment.deployedAt}` + : null, + ].filter(Boolean) as string[]; + + const body = [ + title, + "", + "> Auto-generated by `bun run docs:addresses`. Do not edit by hand.", + "", + ...meta, + "", + formatTable(contracts, chainId), + "", + ].join("\n"); + + mkdirSync(outDir, { recursive: true }); + const outPath = join(outDir, `${docName}.md`); + writeFileSync(outPath, body); + return outPath; +} + +function capitalize(s: string): string { + return s.length === 0 ? s : s[0].toUpperCase() + s.slice(1); +} diff --git a/contracts/script/artifacts.ts b/contracts/script/artifacts.ts new file mode 100644 index 000000000..2d7eca729 --- /dev/null +++ b/contracts/script/artifacts.ts @@ -0,0 +1,40 @@ +import * as generatedAbis from "generated/abis/index.ts"; +import * as generatedArtifacts from "generated/artifacts/index.ts"; + +type Artifact = { + abi: TAbi; + bytecode: `0x${string}`; + deployedBytecode?: `0x${string}`; + metadata?: string; + contractName?: string; + sourceName?: string; +}; + +const interfaceArtifact = ( + abi: TAbi, +): Artifact => ({ + abi, + bytecode: "0x", + metadata: "", +}); + +const artifacts = { + ...generatedArtifacts, + IAddressSet: interfaceArtifact(generatedAbis.IAddressSet), + IContractNamer: interfaceArtifact(generatedAbis.IContractNamer), + IETHRegistrarController: interfaceArtifact( + generatedAbis.IETHRegistrarController, + ), + ILabelStore: interfaceArtifact(generatedAbis.ILabelStore), + INameWrapper: interfaceArtifact(generatedAbis.INameWrapper), + IRentPriceOracle: interfaceArtifact(generatedAbis.IRentPriceOracle), + IWrappedETHRegistrarController: interfaceArtifact( + generatedAbis.IWrappedETHRegistrarController, + ), + MigrationHelper: + generatedArtifacts.src_migration_MigrationHelper_sol_MigrationHelper, + "test/mocks/MockERC20.sol/MockERC20": + generatedArtifacts.test_mocks_MockERC20_sol_MockERC20, +}; + +export default artifacts; diff --git a/contracts/script/deploy-constants.ts b/contracts/script/deploy-constants.ts index 90a541b9a..3a7f52310 100644 --- a/contracts/script/deploy-constants.ts +++ b/contracts/script/deploy-constants.ts @@ -1,6 +1,74 @@ export const MAX_EXPIRY = (1n << 64n) - 1n; // see: DatastoreUtils.sol export const LOCAL_BATCH_GATEWAY_URL = "x-batch-gateway:true"; +export const DEPLOYED_UNIVERSAL_RESOLVER_PROXY = + "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe" as const; + +// Networks whose top URP already fronts a long-lived intermediate (managed) URP +// whose admin we control, keyed by network name. On these networks a fresh v2 +// deployment reuses the existing intermediate URP instead of deploying a new one. +export const KNOWN_INTERMEDIATE_URP: Record = { + sepolia: "0x6d80F2172CFdEc5730fE683860C33d26fC42e6F1", +}; + +export const SEPOLIA_USDC = + "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238" as const; + +// Real mainnet payment tokens used by the rent price oracle in place of the +// free-mint test mocks (which must never ship to mainnet). Confirm/adjust the +// accepted set before a mainnet deploy. +export const MAINNET_USDC = + "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" as const; +export const MAINNET_DAI = + "0x6B175474E89094C44Da98b954EedeAC495271d0F" as const; + +export const STANDARD_RENT_PRICE_ORACLE_PRICE_DECIMALS = 12n; +export const STANDARD_RENT_PRICE_ORACLE_PRICE_SCALE = + 10n ** STANDARD_RENT_PRICE_ORACLE_PRICE_DECIMALS; + +export const STANDARD_RENT_PRICE_ORACLE_BASE_RATE_SPECS = [ + { codepointCount: 1, yearlyPrice: 0n }, + { codepointCount: 2, yearlyPrice: 0n }, + { codepointCount: 3, yearlyPrice: 640n }, + { codepointCount: 4, yearlyPrice: 160n }, + { codepointCount: 5, yearlyPrice: 8n }, +] as const; + +export const STANDARD_RENT_PRICE_ORACLE_DISCOUNT_SCALE = (1n << 128n) - 1n; + +export const STANDARD_RENT_PRICE_ORACLE_DISCOUNT_POINT_SPECS = [ + { t: 31_557_600n, numer: 0n, denom: 1n }, + { t: 31_557_600n, numer: 1n, denom: 4n }, + { t: 31_557_600n, numer: 11n, denom: 16n }, + { t: 31_557_600n, numer: 5n, denom: 16n }, + { t: 31_557_600n, numer: 3n, denom: 8n }, + { t: 31_557_600n, numer: 1n, denom: 1n }, +] as const; + +export function standardRentPriceOracleDiscountRatio( + numer: bigint, + denom: bigint, +) { + return ( + (STANDARD_RENT_PRICE_ORACLE_DISCOUNT_SCALE * numer + denom - 1n) / denom + ); +} + +export function standardRentPriceOracleDiscountPoints() { + return STANDARD_RENT_PRICE_ORACLE_DISCOUNT_POINT_SPECS.map( + ({ t, numer, denom }) => ({ + t, + value: standardRentPriceOracleDiscountRatio(numer, denom), + }), + ); +} + +export function standardRentPriceOracleBaseRates(secPerYear: bigint) { + return STANDARD_RENT_PRICE_ORACLE_BASE_RATE_SPECS.map(({ yearlyPrice }) => { + const yearlyUnits = STANDARD_RENT_PRICE_ORACLE_PRICE_SCALE * yearlyPrice; + return (yearlyUnits + secPerYear - 1n) / secPerYear; + }); +} interface Flags { [key: string]: bigint | Flags; @@ -19,12 +87,11 @@ const FLAGS = { SET_SUBREGISTRY: 1n << 20n, SET_RESOLVER: 1n << 24n, CAN_TRANSFER: 1n << 28n, + WAS_RESERVED: 1n << 32n, + SET_URI: 1n << 36n, + CAN_NAME: 1n << 120n, UPGRADE: 1n << 124n, }, - // see: ETHRegistrar.sol - REGISTRAR: { - SET_ORACLE: 1n << 0n, - }, // see: PermissionedResolver.sol / PermissionedResolverLib.sol RESOLVER: { SET_ADDR: 1n << 0n, @@ -38,6 +105,17 @@ const FLAGS = { CLEAR: 1n << 32n, UPGRADE: 1n << 124n, }, + // see: StandardRentPriceOracle.sol + ORACLE: { + UPDATE_TOKEN: 1n << 0n, + DISABLE_TOKEN: 1n << 4n, + CAN_NAME: 1n << 8n, + }, + // see: PermissionedAddressSet.sol + ADDRESS_SET: { + APPROVE: 1n << 0n, + CAN_NAME: 1n << 4n, + }, } as const satisfies Flags; function adminify(flags: Flags): Flags { @@ -49,10 +127,56 @@ function adminify(flags: Flags): Flags { ); } +const ADMIN = adminify(FLAGS) as typeof FLAGS; + export const ROLES = { ...FLAGS, - ADMIN: adminify(FLAGS), -} as const satisfies Flags; + ADMIN, +} as const; + +// Role bitmaps for static deployment per README Static Deployment Permissions. +export const DEPLOYMENT_ROLES = { + // RootRegistry root: REGISTRAR✓✓, REGISTER_RESERVED✓✓, SET_PARENT✓✓, RENEW✓✓ + ROOT_REGISTRY_ROOT: + ROLES.REGISTRY.REGISTRAR | + ROLES.ADMIN.REGISTRY.REGISTRAR | + ROLES.REGISTRY.REGISTER_RESERVED | + ROLES.ADMIN.REGISTRY.REGISTER_RESERVED | + ROLES.REGISTRY.SET_PARENT | + ROLES.ADMIN.REGISTRY.SET_PARENT | + ROLES.REGISTRY.RENEW | + ROLES.ADMIN.REGISTRY.RENEW | + ROLES.REGISTRY.CAN_NAME | + ROLES.ADMIN.REGISTRY.CAN_NAME | + ROLES.REGISTRY.SET_URI | + ROLES.ADMIN.REGISTRY.SET_URI, + // .eth token: SET_SUBREGISTRY AR, SET_RESOLVER AR + ETH_TOKEN: + ROLES.REGISTRY.SET_SUBREGISTRY | + ROLES.ADMIN.REGISTRY.SET_SUBREGISTRY | + ROLES.REGISTRY.SET_RESOLVER | + ROLES.ADMIN.REGISTRY.SET_RESOLVER, + // .reverse token: full role bitmap. + // Granting all roles is harmless; some (e.g. REGISTRAR) are root-only and don't apply to tokens. + REVERSE_REGISTRY_ROOT: FLAGS.ALL, + // ETHRegistry root deployer: REGISTRAR✓, REGISTER_RESERVED✓, SET_PARENT✓✓, RENEW✓ + ETH_REGISTRY_ROOT: + ROLES.ADMIN.REGISTRY.REGISTRAR | + ROLES.ADMIN.REGISTRY.REGISTER_RESERVED | + ROLES.REGISTRY.SET_PARENT | + ROLES.ADMIN.REGISTRY.SET_PARENT | + ROLES.ADMIN.REGISTRY.RENEW | + ROLES.REGISTRY.CAN_NAME | + ROLES.ADMIN.REGISTRY.CAN_NAME | + ROLES.REGISTRY.SET_URI | + ROLES.ADMIN.REGISTRY.SET_URI, + // ETHRegistrar and BatchRegistrar are granted REGISTRAR and RENEW on ETHRegistry root at static deploy. + ETH_REGISTRAR_ROOT: ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW, + ETH_RENEWER_V1_ROOT: ROLES.REGISTRY.RENEW, + // UnlockedMigrationController and LockedMigrationController + // only need to register() pre-migrated reservations on ETHRegistry (see: "ENSv2 Migration Case Study") + MIGRATION_CONTROLLER_ROOT: ROLES.REGISTRY.REGISTER_RESERVED, +} as const; // see: IPermissionedRegistry.sol export const STATUS = { @@ -60,3 +184,64 @@ export const STATUS = { RESERVED: 1, REGISTERED: 2, }; + +// see: INameWrapper.sol +export const FUSES = { + CANNOT_UNWRAP: 1 << 0, + CANNOT_BURN_FUSES: 1 << 1, + CANNOT_TRANSFER: 1 << 2, + CANNOT_SET_RESOLVER: 1 << 3, + CANNOT_SET_TTL: 1 << 4, + CANNOT_CREATE_SUBDOMAIN: 1 << 5, + CANNOT_APPROVE: 1 << 6, + PARENT_CANNOT_CONTROL: 1 << 16, + IS_DOT_ETH: 1 << 17, + CAN_EXTEND_EXPIRY: 1 << 18, + CAN_DO_EVERYTHING: 0, +} as const; + +export const FUSE_MASKS = { + PARENT_CONTROLLED: 0xffff0000, + PARENT_RESERVED: 0x0000ff80, // bits 7-15 (docs say 17-32) + USER_SETTABLE: 0xfffdffff, // ~IS_DOT_ETH +} as const; + +// see: StandardRegistrar.sol +export const SEC_PER_DAY = 86400n; +export const SEC_PER_YEAR = 365n * SEC_PER_DAY; + +export const MIN_COMMITMENT_AGE = 60n; // 1 minute +export const MAX_COMMITMENT_AGE = SEC_PER_DAY; + +export const GRACE_PERIOD_V1 = 90n * SEC_PER_DAY; +export const GRACE_PERIOD_V2 = 28n * SEC_PER_DAY; +export const PREMIGRATION_BONUS_PERIOD = + 1n + (GRACE_PERIOD_V1 - GRACE_PERIOD_V2); + +export const PRICE_DECIMALS = 12; +export const PRICE_SCALE = 10n ** BigInt(PRICE_DECIMALS); + +export const MIN_REGISTER_DURATION = 28n * SEC_PER_DAY; +export const MIN_RENEW_DURATION = 1n; + +export const PREMIUM_PRICE_INITIAL = PRICE_SCALE * 100_000_000n; +export const PREMIUM_HALVING_PERIOD = SEC_PER_DAY; +export const PREMIUM_PERIOD = SEC_PER_DAY * 21n; + +export const BASE_RATE_PER_CP = [ + 0n, + 0n, + PRICE_SCALE * 640n, + PRICE_SCALE * 160n, + PRICE_SCALE * 8n, +].map((x) => (x + SEC_PER_YEAR - 1n) / SEC_PER_YEAR); + +export const DISCOUNT_DENOMINATOR = 10n ** 38n; +function discountNumer(numer: bigint, denom: bigint) { + return (DISCOUNT_DENOMINATOR * numer) / denom; +} +export const DISCOUNT_POINTS: { duration: bigint; numer: bigint }[] = [ + { duration: SEC_PER_YEAR * 2n, numer: discountNumer(7n, 8n) }, //// 1 - 14/16 = 12.50% + { duration: SEC_PER_YEAR * 3n, numer: discountNumer(11n, 16n) }, // 1 - 11/16 = 31.25% + { duration: SEC_PER_YEAR * 6n, numer: discountNumer(9n, 16n) }, /// 1 - 9/16 = 43.75% +]; diff --git a/contracts/script/exportTheGraphRegistrations.ts b/contracts/script/exportTheGraphRegistrations.ts index af375efab..d91875846 100644 --- a/contracts/script/exportTheGraphRegistrations.ts +++ b/contracts/script/exportTheGraphRegistrations.ts @@ -1,31 +1,26 @@ #!/usr/bin/env bun import { Command } from "commander"; -import { writeFileSync, appendFileSync } from "node:fs"; -import { - Logger, - green, - cyan, - bold, - dim, -} from "./logger.js"; +import { appendFileSync, writeFileSync } from "node:fs"; +import { bold, cyan, dim, Logger } from "./logger.js"; // Types interface ENSRegistration { id: string; - labelName: string; + labelName: string | null; registrant: { - id: string; - }; - expiryDate: string; - registrationDate: string; + id: string | null; + } | null; + expiryDate: string | null; + registrationDate: string | null; domain: { - name: string; - labelhash: string; + id: string | null; + name: string | null; + labelhash: string | null; parent: { - id: string; - }; - }; + id: string | null; + } | null; + } | null; } interface GraphQLResponse { @@ -35,8 +30,11 @@ interface GraphQLResponse { errors?: Array<{ message: string }>; } +export type ENSRegistrationNetwork = "mainnet" | "sepolia"; + interface ExportConfig { thegraphApiKey: string; + network: ENSRegistrationNetwork; batchSize: number; startIndex: number; limit: number | null; @@ -44,19 +42,58 @@ interface ExportConfig { } // Constants -const SUBGRAPH_ID = "5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH"; -const GATEWAY_ENDPOINT = `https://gateway.thegraph.com/api/{API_KEY}/subgraphs/id/${SUBGRAPH_ID}`; +const SUBGRAPH_IDS: Record = { + mainnet: "5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH", + sepolia: "G1SxZs317YUb9nQX3CC98hDyvxfMJNZH5pPRGpNrtvwN", +}; +const GATEWAY_ENDPOINT_TEMPLATE = + "https://gateway.thegraph.com/api/{API_KEY}/subgraphs/id/{SUBGRAPH_ID}"; const RATE_LIMIT_DELAY_MS = 200; const logger = new Logger(); +function envValue(...names: string[]): string | undefined { + for (const name of names) { + const value = process.env[name]; + if (value) return value; + } + return undefined; +} + +function requireTheGraphApiKey(value: string | undefined): string { + const apiKey = value ?? envValue("THEGRAPH_API_KEY", "GRAPH_API_KEY"); + if (!apiKey) { + throw new Error( + "Missing --thegraph-api-key or THEGRAPH_API_KEY/GRAPH_API_KEY", + ); + } + return apiKey; +} + +export function parseENSRegistrationNetwork( + value: string, +): ENSRegistrationNetwork { + if (value === "mainnet" || value === "sepolia") return value; + throw new Error(`Unsupported ENS registrations network: ${value}`); +} + +export function getGatewayEndpoint(config: { + thegraphApiKey: string; + network: ENSRegistrationNetwork; +}): string { + return GATEWAY_ENDPOINT_TEMPLATE.replace( + "{API_KEY}", + config.thegraphApiKey, + ).replace("{SUBGRAPH_ID}", SUBGRAPH_IDS[config.network]); +} + async function fetchRegistrations( config: ExportConfig, skip: number, first: number, - fetchFn: typeof fetch = fetch + fetchFn: typeof fetch = fetch, ): Promise { - const endpoint = GATEWAY_ENDPOINT.replace("{API_KEY}", config.thegraphApiKey); + const endpoint = getGatewayEndpoint(config); const query = ` query GetEthRegistrations($first: Int!, $skip: Int!) { @@ -74,6 +111,7 @@ async function fetchRegistrations( expiryDate registrationDate domain { + id name labelhash parent { @@ -97,49 +135,59 @@ async function fetchRegistrations( if (!response.ok) { const errorText = await response.text(); - throw new Error(`HTTP error! status: ${response.status}, body: ${errorText}`); + throw new Error( + `HTTP error! status: ${response.status}, body: ${errorText}`, + ); } const result: GraphQLResponse = await response.json(); if (result.errors) { throw new Error( - `GraphQL error: ${result.errors.map((e) => e.message).join(", ")}` + `GraphQL error: ${result.errors.map((e) => e.message).join(", ")}`, ); } if (!result.data || !result.data.registrations) { - throw new Error(`Invalid response structure from TheGraph: missing data.registrations`); + throw new Error( + `Invalid response structure from TheGraph: missing data.registrations`, + ); } return result.data.registrations; } -function escapeCSV(value: string): string { - if (value.includes(',') || value.includes('"') || value.includes('\n')) { - return `"${value.replace(/"/g, '""')}"`; +function escapeCSV(value: string | null | undefined): string { + const text = value ?? ""; + if (text.includes(",") || text.includes('"') || text.includes("\n")) { + return `"${text.replace(/"/g, '""')}"`; } - return value; + return text; } function registrationToCSVRow(reg: ENSRegistration): string { return [ - escapeCSV(reg.domain.name), + escapeCSV(reg.domain?.id), + escapeCSV(reg.domain?.name), + escapeCSV(reg.domain?.labelhash), + escapeCSV(reg.registrant?.id), + "", + "", escapeCSV(reg.labelName), - escapeCSV(reg.domain.labelhash), - escapeCSV(reg.registrant.id), - escapeCSV(reg.expiryDate), escapeCSV(reg.registrationDate), - ].join(','); + escapeCSV(reg.expiryDate), + ].join(","); } async function exportRegistrations(config: ExportConfig): Promise { let skip = config.startIndex; let hasMore = true; let totalCount = 0; + let skippedNoLabel = 0; - const csvHeader = 'name,label,labelhash,registrant,expiryDate,registrationDate\n'; - writeFileSync(config.outputFile, csvHeader, 'utf-8'); + const csvHeader = + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate\n"; + writeFileSync(config.outputFile, csvHeader, "utf-8"); logger.info(`CSV file created: ${cyan(config.outputFile)}`); logger.info(`Fetching registrations from TheGraph Gateway...\n`); @@ -149,7 +197,7 @@ async function exportRegistrations(config: ExportConfig): Promise { let registrations = await fetchRegistrations( config, skip, - config.batchSize + config.batchSize, ); if (registrations.length === 0) { @@ -162,15 +210,26 @@ async function exportRegistrations(config: ExportConfig): Promise { hasMore = false; } - const csvRows = registrations.map(registrationToCSVRow).join('\n') + '\n'; - appendFileSync(config.outputFile, csvRows, 'utf-8'); + // Drop rows without a decodable label: the premigration reader treats an + // empty labelName cell as a fatal CSVFormatError, so a single unknown-label + // registration would otherwise abort the entire downstream run. + const labelledRegistrations = registrations.filter( + (reg) => (reg.labelName ?? "").trim() !== "", + ); + skippedNoLabel += registrations.length - labelledRegistrations.length; + + if (labelledRegistrations.length > 0) { + const csvRows = + labelledRegistrations.map(registrationToCSVRow).join("\n") + "\n"; + appendFileSync(config.outputFile, csvRows, "utf-8"); + } totalCount += registrations.length; skip += registrations.length; logger.info( cyan(`Fetched and wrote ${registrations.length} registrations`) + - dim(` (total: ${totalCount})`) + dim(` (total: ${totalCount})`), ); if (config.limit && totalCount >= config.limit) { @@ -185,7 +244,14 @@ async function exportRegistrations(config: ExportConfig): Promise { } } - logger.info(`\nTotal registrations exported: ${bold(totalCount.toString())}`); + logger.info( + `\nTotal registrations exported: ${bold((totalCount - skippedNoLabel).toString())}`, + ); + if (skippedNoLabel > 0) { + logger.info( + `Skipped ${bold(skippedNoLabel.toString())} registration(s) with no decodable labelName`, + ); + } logger.success(`Successfully exported to ${config.outputFile}`); } @@ -193,17 +259,34 @@ export async function main(argv = process.argv): Promise { const program = new Command() .name("export-registrations") .description("Export ENS .eth 2LD registrations from TheGraph to CSV") - .requiredOption("--thegraph-api-key ", "TheGraph Gateway API key (get from https://thegraph.com/studio/apikeys/)") - .option("--batch-size ", "Number of names to fetch per TheGraph API request", "1000") + .option( + "--thegraph-api-key ", + "TheGraph Gateway API key; falls back to THEGRAPH_API_KEY or GRAPH_API_KEY", + ) + .option( + "--network ", + "ENS registrations network: mainnet or sepolia", + "mainnet", + ) + .option( + "--batch-size ", + "Number of names to fetch per TheGraph API request", + "1000", + ) .option("--start-index ", "Starting index for pagination", "0") .option("--limit ", "Maximum total number of names to fetch") - .option("--output ", "Output CSV file path", `csv-data/ens-registrations-${new Date().toISOString().split('T')[0]}.csv`); + .option( + "--output ", + "Output CSV file path", + `csv-data/ens-registrations-${new Date().toISOString().split("T")[0]}.csv`, + ); program.parse(argv); const opts = program.opts(); const config: ExportConfig = { - thegraphApiKey: opts.thegraphApiKey, + thegraphApiKey: requireTheGraphApiKey(opts.thegraphApiKey), + network: parseENSRegistrationNetwork(opts.network), batchSize: parseInt(opts.batchSize) || 1000, startIndex: parseInt(opts.startIndex) || 0, limit: opts.limit ? parseInt(opts.limit) : null, @@ -215,11 +298,15 @@ export async function main(argv = process.argv): Promise { logger.divider(); logger.info(`Configuration:`); - logger.config('TheGraph API Key', `${config.thegraphApiKey.substring(0, 8)}...`); - logger.config('Batch Size', config.batchSize); - logger.config('Start Index', config.startIndex); - logger.config('Limit', config.limit ?? "none"); - logger.config('Output File', config.outputFile); + logger.config( + "TheGraph API Key", + `${config.thegraphApiKey.substring(0, 8)}...`, + ); + logger.config("Network", config.network); + logger.config("Batch Size", config.batchSize); + logger.config("Start Index", config.startIndex); + logger.config("Limit", config.limit ?? "none"); + logger.config("Output File", config.outputFile); logger.info(""); await exportRegistrations(config); diff --git a/contracts/script/forkBootstrap.ts b/contracts/script/forkBootstrap.ts new file mode 100644 index 000000000..ee0cc3e24 --- /dev/null +++ b/contracts/script/forkBootstrap.ts @@ -0,0 +1,162 @@ +import { readFile, writeFile, mkdir, copyFile } from "node:fs/promises"; +import { join } from "node:path"; +import { type Address, parseEther } from "viem"; + +// v1 contracts on canonical mainnet that v2 deploys and `setup.ts` reference +// by name through rocketh's `get()`. Pre-populated into the devnet deployments +// dir so `get(name)` resolves to the canonical address without redeploying. +const V1_DEPLOYMENT_NAMES = [ + "ENSRegistry", + "Root", + "BaseRegistrarImplementation", + "NameWrapper", + "RegistrarSecurityController", + "ETHRegistrarController", + "WrappedETHRegistrarController", + "PublicResolver", + "UniversalResolver", + "OffchainDNSResolver", + "SimplePublicSuffixList", + "DNSSECImpl", + "ReverseRegistrar", + "DefaultReverseRegistrar", + "DefaultReverseResolver", + "BatchGatewayProvider", +] as const; + +// Canonical contracts whose `.owner()` issues writes during the v2 deploy or +// activation flow. Read live so that future ownership changes on mainnet are +// picked up without code changes. +const V1_OWNABLE_NAMES = [ + "BaseRegistrarImplementation", + "NameWrapper", + "ReverseRegistrar", + "DefaultReverseRegistrar", + "RegistrarSecurityController", +] as const; + +// ENS DAO multisig — mapped to the `owner` named account on chainId 1 via +// Rocketh config. Included unconditionally so that even if a future ownership +// transfer hasn't fully propagated, the DAO address is still funded. +export const ENS_DAO_MULTISIG: Address = + "0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7"; + +// Original ETHRegistrarController deployed at mainnet block 9380471. Still +// authorised on `BaseRegistrarImplementation.controllers` on canonical +// mainnet, so `activateV2` must explicitly revoke it. The address is +// hard-coded because `lib/ens-contracts/deployments/mainnet/` does not ship +// a rocketh artifact for it (the canonical deploy scripts wire it in only +// for the synthetic devnet); the ABI is recovered from the archive sibling. +const LEGACY_ETH_REGISTRAR_CONTROLLER_ADDRESS: Address = + "0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5"; +const LEGACY_ETH_REGISTRAR_CONTROLLER_ARCHIVE = join( + "..", + "archive", + "ETHRegistrarController_mainnet_9380471.sol", + "ETHRegistrarController_mainnet_9380471.json", +); + +const OWNER_ABI = [ + { + type: "function", + name: "owner", + stateMutability: "view", + inputs: [], + outputs: [{ type: "address" }], + }, +] as const; + +type ClientLike = { + readContract: (args: { + address: Address; + abi: typeof OWNER_ABI; + functionName: "owner"; + }) => Promise; + setBalance: (args: { address: Address; value: bigint }) => Promise; +}; + +export async function bootstrapForkDeployments({ + client, + deploymentsDir, + canonicalDir, + chainId, +}: { + client: ClientLike; + deploymentsDir: string; + canonicalDir: string; + chainId: number; +}) { + await mkdir(deploymentsDir, { recursive: true }); + + for (const name of V1_DEPLOYMENT_NAMES) { + const src = JSON.parse( + await readFile(join(canonicalDir, `${name}.json`), "utf8"), + ); + const dst = { address: src.address, abi: src.abi }; + await writeFile( + join(deploymentsDir, `${name}.json`), + JSON.stringify(dst, null, 2), + ); + } + + // Synthesise the LegacyETHRegistrarController rocketh artifact from the + // hard-coded mainnet address + the archive ABI, so `rocketh.get(...)` in + // `setup.ts` resolves to the live contract during fork-mode activateV2. + const legacyArchive = JSON.parse( + await readFile( + join(canonicalDir, LEGACY_ETH_REGISTRAR_CONTROLLER_ARCHIVE), + "utf8", + ), + ); + await writeFile( + join(deploymentsDir, "LegacyETHRegistrarController.json"), + JSON.stringify( + { + address: LEGACY_ETH_REGISTRAR_CONTROLLER_ADDRESS, + abi: legacyArchive.abi, + }, + null, + 2, + ), + ); + + // Mirror the canonical `.chain` so rocketh's chainId/genesisHash checks pass + // against the live forked node (which exposes the upstream genesis at block + // 0). rocketh stores chainId as a string and compares it strictly. + await copyFile( + join(canonicalDir, ".chain"), + join(deploymentsDir, ".chain"), + ); + + // sanity: bail loudly if the canonical chainId disagrees with the live one + const liveChainHeader = JSON.parse( + await readFile(join(deploymentsDir, ".chain"), "utf8"), + ); + if (String(liveChainHeader.chainId) !== String(chainId)) { + throw new Error( + `canonical .chain chainId=${liveChainHeader.chainId} does not match live chainId=${chainId}`, + ); + } + + const ownerAddrs = new Set
([ENS_DAO_MULTISIG]); + for (const name of V1_OWNABLE_NAMES) { + const src = JSON.parse( + await readFile(join(canonicalDir, `${name}.json`), "utf8"), + ); + try { + const addr = (await client.readContract({ + address: src.address as Address, + abi: OWNER_ABI, + functionName: "owner", + })) as Address; + ownerAddrs.add(addr); + } catch { + // contract doesn't expose owner(); skip + } + } + + const fundWei = parseEther("10000"); + for (const addr of ownerAddrs) { + await client.setBalance({ address: addr, value: fundWei }); + } +} diff --git a/contracts/script/foundry/DeployDOS.s.sol b/contracts/script/foundry/DeployDOS.s.sol index 8ed2bef6c..d2d0ec403 100644 --- a/contracts/script/foundry/DeployDOS.s.sol +++ b/contracts/script/foundry/DeployDOS.s.sol @@ -1,160 +1,243 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; -import "forge-std/Script.sol"; +import {Script} from "forge-std/Script.sol"; +import {GatewayProvider} from "@ens/contracts/ccipRead/GatewayProvider.sol"; +import {HexUtils} from "@ens/contracts/utils/HexUtils.sol"; +import {VerifiableFactory} from "@ensdomains/verifiable-factory/VerifiableFactory.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; +import {DOSRegistrar} from "~src/registrar/DOSRegistrar.sol"; +import { + DiscountPoint, + PaymentRatio, + StandardRentPriceOracle +} from "~src/registrar/StandardRentPriceOracle.sol"; import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; -import {IRegistryMetadata} from "~src/registry/interfaces/IRegistryMetadata.sol"; -import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; - -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; -import {SimpleRegistryMetadata} from "~src/registry/SimpleRegistryMetadata.sol"; import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; -import {UserRegistry} from "~src/registry/UserRegistry.sol"; - -import {StandardRentPriceOracle, DiscountPoint, PaymentRatio} from "~src/registrar/StandardRentPriceOracle.sol"; -import {DOSRegistrar} from "~src/registrar/DOSRegistrar.sol"; -import {IRentPriceOracle} from "~src/registrar/interfaces/IRentPriceOracle.sol"; - +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {L2ReverseRegistrar} from "~src/reverse-registrar/L2ReverseRegistrar.sol"; import {PermissionedResolver} from "~src/resolver/PermissionedResolver.sol"; +import {UserRegistry} from "~src/registry/UserRegistry.sol"; +import {ContractNamer} from "~src/utils/ContractNamer.sol"; +import {LabelStore} from "~src/utils/LabelStore.sol"; import {UniversalResolverV2} from "~src/universalResolver/UniversalResolverV2.sol"; -import {IGatewayProvider} from "@ens/contracts/universalResolver/AbstractUniversalResolver.sol"; - -import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; -import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; - -contract DeployDOS is Script { - /// @dev WDOS (Wrapped Native Token) on DOS Chain - address constant WDOS = 0x1111111111111111111111111111111111111111; - - /// @dev Maximum expiry - uint64 constant MAX_EXPIRY = type(uint64).max; - - // ---- Stored between phases so we stay under the stack limit ---- - IHCAFactoryBasic internal _hcaFactory; - IRegistryMetadata internal _metadata; - PermissionedRegistry internal _root; - PermissionedRegistry internal _dosTLD; - PermissionedRegistry internal _reverseReg; - - function run() external { - uint256 deployerPk = vm.envUint("PRIVATE_KEY"); - address deployer = vm.addr(deployerPk); - vm.startBroadcast(deployerPk); - - _deployCore(deployer); - _deployRegistrar(deployer); - _deployImplementations(); +/// @title Deploy DOS Name Service +/// @notice Deploys a greenfield ENSv2 stack configured for the `.dos` namespace. +contract DeployDOS is Script, ERC1155Holder { + address internal constant DEFAULT_WDOS = 0x1111111111111111111111111111111111111111; + uint64 internal constant MAX_EXPIRY = type(uint64).max; + uint64 internal constant GRACE_PERIOD = 28 days; + uint64 internal constant MIN_COMMITMENT_AGE = 60; + uint64 internal constant MAX_COMMITMENT_AGE = 1 days; + uint64 internal constant MIN_REGISTER_DURATION = 28 days; + uint256 internal constant PRICE_SCALE = 1e12; + uint256 internal constant SEC_PER_YEAR = 365 days; + + /// @notice Payment token decimals cannot represent the oracle price scale. + /// @param decimals Token decimals reported by the ERC20 contract. + error PaymentTokenDecimalsTooLow(uint8 decimals); + + /// @notice Payment token decimals exceed the oracle ratio capacity. + /// @param decimals Token decimals reported by the ERC20 contract. + error PaymentTokenDecimalsTooHigh(uint8 decimals); + + /// @notice Contracts produced by the DOS deployment profile. + struct Deployment { + ContractNamer contractNamer; + VerifiableFactory verifiableFactory; + LabelStore labelStore; + PermissionedRegistry rootRegistry; + PermissionedRegistry dosRegistry; + PermissionedRegistry reverseRegistry; + StandardRentPriceOracle priceOracle; + DOSRegistrar dosRegistrar; + PermissionedResolver permissionedResolverImplementation; + UserRegistry userRegistryImplementation; + GatewayProvider gatewayProvider; + UniversalResolverV2 universalResolver; + L2ReverseRegistrar reverseRegistrar; + } + /// @notice Broadcasts a DOS Name Service deployment using environment configuration. + /// @dev Required env: `PRIVATE_KEY`. Optional env: `BENEFICIARY`, `PAYMENT_TOKEN`. + /// @return deployment The deployed contract set. + function run() external returns (Deployment memory deployment) { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address deployer = vm.addr(privateKey); + address beneficiary = vm.envOr("BENEFICIARY", deployer); + address paymentToken = vm.envOr("PAYMENT_TOKEN", DEFAULT_WDOS); + + vm.startBroadcast(privateKey); + deployment = deploy(deployer, beneficiary, IERC20(paymentToken), block.chainid); vm.stopBroadcast(); - - console.log("--- Deployment Complete ---"); - console.log("Deployer:", deployer); } - /// @dev Phase 1: HCAFactory, Metadata, Root, DOS TLD, Reverse registries + TLD registrations. - function _deployCore(address deployer) internal { - // 1. HCAFactory (mock for testnet) - MockHCAFactoryBasic hcaFactory = new MockHCAFactoryBasic(); - _hcaFactory = IHCAFactoryBasic(address(hcaFactory)); - console.log("HCAFactory:", address(hcaFactory)); - - // 2. SimpleRegistryMetadata - SimpleRegistryMetadata metadata = new SimpleRegistryMetadata(_hcaFactory); - _metadata = IRegistryMetadata(address(metadata)); - console.log("SimpleRegistryMetadata:", address(metadata)); - - // 3. RootRegistry - PermissionedRegistry root = new PermissionedRegistry( - _hcaFactory, _metadata, deployer, EACBaseRolesLib.ALL_ROLES + /// @notice Deploys and wires the complete `.dos` contract set. + /// @param owner Account that controls registry, registrar and pricing administration. + /// @param beneficiary Account that receives registration and renewal payments. + /// @param paymentToken ERC20 token accepted by the fixed-price oracle. + /// @param chainId DOS Chain ID used to derive the ENSIP-19 reverse namespace. + /// @return deployment The deployed contract set. + function deploy(address owner, address beneficiary, IERC20 paymentToken, uint256 chainId) + public + returns (Deployment memory deployment) + { + ContractNamer namerImplementation = new ContractNamer(); + deployment.contractNamer = ContractNamer( + address( + new ERC1967Proxy( + address(namerImplementation), + abi.encodeCall(ContractNamer.initialize, (owner)) + ) + ) ); - _root = root; - console.log("RootRegistry:", address(root)); + deployment.verifiableFactory = new VerifiableFactory(); + deployment.labelStore = new LabelStore(deployment.contractNamer); - // 4. DOSTLDRegistry - PermissionedRegistry dosTLD = new PermissionedRegistry( - _hcaFactory, _metadata, deployer, EACBaseRolesLib.ALL_ROLES + deployment.rootRegistry = new PermissionedRegistry( + deployment.labelStore, + owner, + _rootRegistryRoles() + ); + deployment.dosRegistry = new PermissionedRegistry( + deployment.labelStore, + owner, + _dosRegistryRoles() + ); + deployment.reverseRegistry = new PermissionedRegistry( + deployment.labelStore, + owner, + _rootRegistryRoles() ); - _dosTLD = dosTLD; - console.log("DOSTLDRegistry:", address(dosTLD)); - // Register "dos" TLD in root - root.register("dos", deployer, IRegistry(address(dosTLD)), address(0), 0, MAX_EXPIRY); + deployment.rootRegistry.register( + "dos", + owner, + deployment.dosRegistry, + address(0), + _tldTokenRoles(), + MAX_EXPIRY + ); + deployment.dosRegistry.setParent(deployment.rootRegistry, "dos"); + + deployment.rootRegistry.register( + "reverse", + owner, + deployment.reverseRegistry, + address(0), + _tldTokenRoles(), + MAX_EXPIRY + ); + deployment.reverseRegistry.setParent(deployment.rootRegistry, "reverse"); + + deployment.priceOracle = _deployPriceOracle(owner, paymentToken); + deployment.dosRegistrar = new DOSRegistrar( + owner, + deployment.dosRegistry, + beneficiary, + deployment.priceOracle, + GRACE_PERIOD, + MIN_COMMITMENT_AGE, + MAX_COMMITMENT_AGE, + MIN_REGISTER_DURATION + ); + deployment.dosRegistry.grantRootRoles( + RegistryRolesLib.ROLE_REGISTRAR | RegistryRolesLib.ROLE_RENEW, + address(deployment.dosRegistrar) + ); + + deployment.permissionedResolverImplementation = new PermissionedResolver(owner); + deployment.userRegistryImplementation = new UserRegistry(deployment.labelStore, owner); - // 5. ReverseRegistry - PermissionedRegistry reverseReg = new PermissionedRegistry( - _hcaFactory, _metadata, deployer, EACBaseRolesLib.ALL_ROLES + string[] memory gateways = new string[](0); + deployment.gatewayProvider = new GatewayProvider(owner, gateways); + deployment.universalResolver = new UniversalResolverV2( + deployment.rootRegistry, + deployment.gatewayProvider, + deployment.contractNamer ); - _reverseReg = reverseReg; - console.log("ReverseRegistry:", address(reverseReg)); - // Register "reverse" in root - root.register("reverse", deployer, IRegistry(address(reverseReg)), address(0), 0, MAX_EXPIRY); + uint256 coinType = (1 << 31) | chainId; + string memory reverseLabel = HexUtils.unpaddedUintToHex(coinType, true); + deployment.reverseRegistrar = new L2ReverseRegistrar(chainId, reverseLabel); + deployment.reverseRegistry.register( + reverseLabel, + owner, + IRegistry(address(0)), + address(deployment.reverseRegistrar), + 0, + MAX_EXPIRY + ); } - /// @dev Phase 2: PriceOracle + DOSRegistrar + role grants. - function _deployRegistrar(address deployer) internal { - // 6. StandardRentPriceOracle - uint256[] memory baseRatePerCp = new uint256[](3); - baseRatePerCp[0] = 3_170_979_198; // 1-char: ~100 DOS/year - baseRatePerCp[1] = 1_585_489_599; // 2-char: ~50 DOS/year - baseRatePerCp[2] = 317_097_919; // 3+ char: ~10 DOS/year - - DiscountPoint[] memory discountPoints = new DiscountPoint[](0); + function _deployPriceOracle(address owner, IERC20 paymentToken) + internal + returns (StandardRentPriceOracle oracle) + { + uint256[] memory baseRates = new uint256[](3); + baseRates[0] = _yearlyRate(100); + baseRates[1] = _yearlyRate(50); + baseRates[2] = _yearlyRate(10); + DiscountPoint[] memory discounts = new DiscountPoint[](0); PaymentRatio[] memory paymentRatios = new PaymentRatio[](1); - paymentRatios[0] = PaymentRatio({token: IERC20(WDOS), numer: 1, denom: 1}); - - StandardRentPriceOracle priceOracle = new StandardRentPriceOracle( - deployer, - IPermissionedRegistry(address(_dosTLD)), - baseRatePerCp, - discountPoints, - 0, // premiumPriceInitial - 0, // premiumHalvingPeriod - 0, // premiumPeriod - paymentRatios - ); - console.log("StandardRentPriceOracle:", address(priceOracle)); - - // 7. DOSRegistrar - DOSRegistrar registrar = new DOSRegistrar( - IPermissionedRegistry(address(_dosTLD)), - _hcaFactory, - deployer, // beneficiary - 60, // minCommitmentAge (seconds) - 86400, // maxCommitmentAge (1 day) - 2419200, // minRegisterDuration (28 days) - IRentPriceOracle(address(priceOracle)) - ); - console.log("DOSRegistrar:", address(registrar)); + uint8 decimals = IERC20Metadata(address(paymentToken)).decimals(); + if (decimals < 12) { + revert PaymentTokenDecimalsTooLow(decimals); + } + if (decimals > 50) { + revert PaymentTokenDecimalsTooHigh(decimals); + } + uint256 scale = 10 ** (decimals - 12); + paymentRatios[0] = PaymentRatio({paymentToken: paymentToken, numer: uint128(scale), denom: 1}); + + oracle = new StandardRentPriceOracle(owner, baseRates, discounts, 0, 0, 0, 0, paymentRatios); + } - // Grant ROLE_REGISTRAR | ROLE_RENEW to DOSRegistrar on dosTLD - _dosTLD.grantRootRoles( - RegistryRolesLib.ROLE_REGISTRAR | RegistryRolesLib.ROLE_RENEW, - address(registrar) - ); + function _yearlyRate(uint256 yearlyPrice) internal pure returns (uint256) { + return (PRICE_SCALE * yearlyPrice + SEC_PER_YEAR - 1) / SEC_PER_YEAR; } - /// @dev Phase 3: Implementation contracts (UUPS) + UniversalResolver. - function _deployImplementations() internal { - // 8. PermissionedResolver implementation - PermissionedResolver resolverImpl = new PermissionedResolver(_hcaFactory); - console.log("PermissionedResolver (impl):", address(resolverImpl)); + function _rootRegistryRoles() internal pure returns (uint256) { + return + RegistryRolesLib.ROLE_REGISTRAR | + RegistryRolesLib.ROLE_REGISTRAR_ADMIN | + RegistryRolesLib.ROLE_REGISTER_RESERVED | + RegistryRolesLib.ROLE_REGISTER_RESERVED_ADMIN | + RegistryRolesLib.ROLE_SET_PARENT | + RegistryRolesLib.ROLE_SET_PARENT_ADMIN | + RegistryRolesLib.ROLE_RENEW | + RegistryRolesLib.ROLE_RENEW_ADMIN | + RegistryRolesLib.ROLE_CAN_NAME | + RegistryRolesLib.ROLE_CAN_NAME_ADMIN | + RegistryRolesLib.ROLE_SET_URI | + RegistryRolesLib.ROLE_SET_URI_ADMIN; + } - // 9. UserRegistry implementation - UserRegistry userRegistryImpl = new UserRegistry(_hcaFactory, _metadata); - console.log("UserRegistry (impl):", address(userRegistryImpl)); + function _dosRegistryRoles() internal pure returns (uint256) { + return + RegistryRolesLib.ROLE_REGISTRAR_ADMIN | + RegistryRolesLib.ROLE_REGISTER_RESERVED_ADMIN | + RegistryRolesLib.ROLE_SET_PARENT | + RegistryRolesLib.ROLE_SET_PARENT_ADMIN | + RegistryRolesLib.ROLE_RENEW_ADMIN | + RegistryRolesLib.ROLE_CAN_NAME | + RegistryRolesLib.ROLE_CAN_NAME_ADMIN | + RegistryRolesLib.ROLE_SET_URI | + RegistryRolesLib.ROLE_SET_URI_ADMIN; + } - // 10. UniversalResolverV2 - UniversalResolverV2 universalResolver = new UniversalResolverV2( - IRegistry(address(_root)), - IGatewayProvider(address(0)) // no batch gateway for testnet - ); - console.log("UniversalResolverV2:", address(universalResolver)); + function _tldTokenRoles() internal pure returns (uint256) { + return + RegistryRolesLib.ROLE_SET_SUBREGISTRY | + RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN | + RegistryRolesLib.ROLE_SET_RESOLVER | + RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN; } } diff --git a/contracts/script/foundry/SetupResolver.s.sol b/contracts/script/foundry/SetupResolver.s.sol deleted file mode 100644 index 45db5ba47..000000000 --- a/contracts/script/foundry/SetupResolver.s.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import "forge-std/Script.sol"; - -import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; - -import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; -import {PermissionedResolver} from "~src/resolver/PermissionedResolver.sol"; -import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; -import {PermissionedResolverLib} from "~src/resolver/libraries/PermissionedResolverLib.sol"; -import {LibLabel} from "~src/utils/LibLabel.sol"; -import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; -import {COIN_TYPE_ETH} from "@ens/contracts/utils/ENSIP19.sol"; - -contract SetupResolver is Script { - // Testnet 3939 addresses - PermissionedRegistry constant DOS_TLD = PermissionedRegistry(0x62BE2a74E9f477A4e044ecA917c594fb11D01Bf4); - PermissionedResolver constant RESOLVER_IMPL = PermissionedResolver(0xB132A5447077ad10Acd4244F96dFA92A1Cd5d6dE); - - function run() external { - uint256 deployerPk = vm.envUint("PRIVATE_KEY"); - address deployer = vm.addr(deployerPk); - - vm.startBroadcast(deployerPk); - - // 1. Deploy ERC1967 proxy for PermissionedResolver - bytes memory initData = abi.encodeCall( - PermissionedResolver.initialize, - (deployer, EACBaseRolesLib.ALL_ROLES) - ); - ERC1967Proxy proxy = new ERC1967Proxy(address(RESOLVER_IMPL), initData); - PermissionedResolver resolver = PermissionedResolver(address(proxy)); - console.log("Resolver proxy:", address(resolver)); - - // 2. Set resolver on DOSTLDRegistry for "doschain" - uint256 tokenId = LibLabel.id("doschain"); - DOS_TLD.setResolver(tokenId, address(resolver)); - console.log("Resolver set for doschain.dos"); - - // 3. Set address record: addr(doschain.dos) = deployer - // node = namehash("doschain.dos") - bytes32 node = NameCoder.namehash( - abi.encodePacked(uint8(8), "doschain", uint8(3), "dos", uint8(0)), - 0 - ); - resolver.setAddr(node, deployer); - console.log("addr(doschain.dos) =", deployer); - - vm.stopBroadcast(); - } -} diff --git a/contracts/script/generateAddressDocs.ts b/contracts/script/generateAddressDocs.ts new file mode 100644 index 000000000..e4ee34c42 --- /dev/null +++ b/contracts/script/generateAddressDocs.ts @@ -0,0 +1,44 @@ +#!/usr/bin/env bun +import { Command } from "commander"; +import { resolve } from "node:path"; +import { generateAddressMarkdown } from "./addressDocs.js"; + +const currentPath = new URL(import.meta.url).pathname; +const defaultDeploymentsDir = resolve(currentPath, "../..", "deployments"); + +const program = new Command() + .option( + "--network ", + "Canonical network name used for the output filename and heading", + "sepolia", + ) + .option( + "--namespace ", + "Deployment namespace subdirectory to read (defaults to the network name)", + ) + .option( + "--deployments-dir ", + "Root directory for v2 deployment files", + defaultDeploymentsDir, + ) + .option( + "--out-dir ", + "Output directory for the generated markdown (defaults to docs/addresses)", + ); + +program.parse(process.argv); +const opts = program.opts<{ + network: string; + namespace?: string; + deploymentsDir: string; + outDir?: string; +}>(); + +const outPath = await generateAddressMarkdown({ + deploymentsDir: opts.deploymentsDir, + namespace: opts.namespace ?? opts.network, + docName: opts.network, + outDir: opts.outDir, +}); + +console.log(`Wrote ${outPath}`); diff --git a/contracts/script/list-contracts.ts b/contracts/script/list-contracts.ts new file mode 100644 index 000000000..a6c687c69 --- /dev/null +++ b/contracts/script/list-contracts.ts @@ -0,0 +1,61 @@ +import { loadDeploymentsFromFiles } from "@rocketh/node"; +import { Command } from "commander"; +import { resolve } from "path"; +import { isProxyArtifact } from "./addressDocs.js"; + +const currentPath = new URL(import.meta.url).pathname; +const defaultDeploymentsDir = resolve(currentPath, "../..", "deployments"); + +const program = new Command() + .option("--chain-name ", "Deployment network name", "sepolia-dev") + .option("--deployments-dir ", "Root directory for v2 deployment files", defaultDeploymentsDir) + .option("--v1-deployments-dir ", "Root directory for v1 deployment files") + .option("--v2-only", "Only list v2 deployment files", false) + .option("--raw", "Include proxy implementation/proxy deployment artifacts", false); + +program.parse(process.argv); +const opts = program.opts<{ + chainName: string; + deploymentsDir: string; + v1DeploymentsDir?: string; + v2Only: boolean; + raw: boolean; +}>(); + +const deploymentsDir = resolve(opts.deploymentsDir); +const v1DeploymentsDir = opts.v1DeploymentsDir + ? resolve(opts.v1DeploymentsDir) + : resolve(deploymentsDir, "v1"); + +const deploymentRoots = opts.v2Only + ? { v2: deploymentsDir } + : { v1: v1DeploymentsDir, v2: deploymentsDir }; + +for (const [chain, root] of Object.entries(deploymentRoots)) { + const deployments = await loadDeploymentsFromFiles(root, opts.chainName, false).then((d) => d.deployments); + const names = new Set(Object.keys(deployments)); + const contracts = Object.entries(deployments) + .filter(([name]) => opts.raw || !isProxyArtifact(name, names)) + .map(([name, deployment]) => ({ + name, + address: (deployment as { address: string }).address, + })) + .sort((a, b) => a.name.localeCompare(b.name)); + + if (contracts.length === 0) { + console.log(`${chain}: no deployments found in ${root}/${opts.chainName}`); + continue; + } + + console.log(chain); + console.log(formatMarkdownTable(contracts)); +} + +function formatMarkdownTable(contracts: Array<{ name: string; address: string }>): string { + const rows = [ + ["Name", "Address"], + ["---", "---"], + ...contracts.map(({ name, address }) => [name, address]), + ]; + return rows.map((row) => `| ${row.join(" | ")} |`).join("\n"); +} diff --git a/contracts/script/logger.ts b/contracts/script/logger.ts index 86bdee0d2..7ec31fee0 100644 --- a/contracts/script/logger.ts +++ b/contracts/script/logger.ts @@ -24,6 +24,7 @@ export interface LoggerOptions { */ export class Logger { protected options: LoggerOptions; + private fileLoggingDisabledReason?: string; constructor(options: LoggerOptions = {}) { this.options = { enableFileLogging: false, ...options }; @@ -48,7 +49,17 @@ export class Logger { if (!file) return; const timestamp = new Date().toISOString(); - writeFileSync(file, `[${timestamp}]${prefix} ${message}\n`, { flag: "a" }); + if (this.fileLoggingDisabledReason) return; + + try { + writeFileSync(file, `[${timestamp}]${prefix} ${message}\n`, { flag: "a" }); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + this.fileLoggingDisabledReason = errorMessage; + console.warn( + yellow(`WARNING: file logging disabled after write failure: ${errorMessage}`), + ); + } } /** diff --git a/contracts/script/migration.ts b/contracts/script/migration.ts new file mode 100644 index 000000000..7d6337d4a --- /dev/null +++ b/contracts/script/migration.ts @@ -0,0 +1,5948 @@ +#!/usr/bin/env bun + +import { Command } from "commander"; +import { + existsSync, + mkdirSync, + readdirSync, + readFileSync, + renameSync, + writeFileSync, +} from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join, resolve } from "node:path"; +import { + createPublicClient, + createWalletClient, + custom, + defineChain, + encodeAbiParameters, + encodeFunctionData, + getAddress, + getContract, + http, + keccak256, + namehash, + parseEther, + stringToHex, + zeroAddress, + zeroHash, + type Address, + type Chain, +} from "viem"; +import { + generatePrivateKey, + mnemonicToAccount, + privateKeyToAccount, +} from "viem/accounts"; +import { mainnet, sepolia } from "viem/chains"; +import type { AccountDefinition, AccountType, UserConfig } from "rocketh/types"; +import { Artifact_BaseRegistrarImplementation } from "generated/artifacts/BaseRegistrarImplementation.js"; +import { Artifact_BatchRegistrar } from "generated/artifacts/BatchRegistrar.js"; +import { Artifact_PermissionedRegistry } from "generated/artifacts/PermissionedRegistry.js"; +import { Artifact_UpgradableUniversalResolverProxy } from "generated/artifacts/UpgradableUniversalResolverProxy.js"; +import { config as rockethConfig } from "../rocketh/config.js"; +import { loadAndExecuteDeploymentsFromFilesWithConfig } from "../rocketh/environment.js"; +import { generateAddressMarkdown } from "./addressDocs.js"; +import { + DEPLOYED_UNIVERSAL_RESOLVER_PROXY, + ROLES, + SEC_PER_DAY, + STATUS, +} from "./deploy-constants.js"; +import { main as exportRegistrationsMain } from "./exportTheGraphRegistrations.js"; +import { + createFreshCheckpoint, + isValidLabel, + loadCheckpoint, + main as preMigrationMain, + parseCSVLine, + V1_GRACE_PERIOD_SECONDS, +} from "./preMigration.js"; + +const DEFAULT_ANVIL_KEY = + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" as const; +const DEFAULT_ANVIL_DEPLOYER = + "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" as const; +const DEFAULT_ANVIL_OWNER = + "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" as const; +const MAINNET_DAO = "0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7" as const; +// The Sepolia ENS v1 BaseRegistrar owner EOA; derived from the `v1Owner` named +// account in rocketh/config.ts so the two values cannot drift apart. +const SEPOLIA_V1_OWNER = getAddress(rockethConfig.accounts.v1Owner.sepolia); + +const V1_REGISTRATION_DURATION = 365n * SEC_PER_DAY; +const V2_REGISTRATION_DURATION = 28n * SEC_PER_DAY; +const REGISTRAR_ROLES = ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW; +const RPC_RETRY_COUNT = 3; +const PREMIGRATION_VERIFY_BATCH_SIZE = 250; + +const DEFAULT_DEPLOYMENTS_DIR = resolve(import.meta.dirname, "../deployments"); +const BUNDLED_V1_DEPLOYMENTS_DIR = resolve( + import.meta.dirname, + "../lib/ens-contracts/deployments", +); +const LOCAL_V1_DEPLOYMENTS_DIR = resolve( + import.meta.dirname, + "../deployments/v1", +); + +const MIGRATION_DEPLOY_TAGS = ["migration:phase1:deploy-v2"] as const; + +export const migrationDataComponents = [ + { name: "label", type: "string" }, + { name: "owner", type: "address" }, + { name: "subregistry", type: "address" }, + { name: "resolver", type: "address" }, +] as const; + +export type MigrationNetwork = "sepolia" | "mainnet"; + +type RpcProvider = { + request(args: { + method: string; + params?: readonly unknown[] | object; + }): Promise; +}; + +type JsonDeployment = { + address: Address; + abi: readonly any[]; +}; + +type V1DeploymentOptions = { + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; +}; + +type PrivateKeyOptions = { + deployerPrivateKey?: `0x${string}`; + ownerPrivateKey?: `0x${string}`; + v1OwnerPrivateKey?: `0x${string}`; + urManagerPrivateKey?: `0x${string}`; +}; + +type NetworkConfig = { + chain: Chain; + environment: MigrationNetwork; + rpcEnv: string; + defaultForkPort: number; + defaultOwner: Address; + defaultV1Owner: Address; + chainTags: string[]; +}; + +type PreparedOwnerTransaction = { + account?: string; + role?: string; + from?: Address; + to: Address; + value?: string; + data: `0x${string}`; + phase?: string; + label?: string; + functionName?: string; + deployment?: string; +}; + +const NETWORKS: Record = { + sepolia: { + chain: sepolia, + environment: "sepolia", + rpcEnv: "SEPOLIA_RPC_URL", + defaultForkPort: 8547, + defaultOwner: DEFAULT_ANVIL_OWNER, + defaultV1Owner: SEPOLIA_V1_OWNER, + chainTags: [], + }, + mainnet: { + chain: mainnet, + environment: "mainnet", + rpcEnv: "MAINNET_RPC_URL", + defaultForkPort: 8548, + defaultOwner: MAINNET_DAO, + defaultV1Owner: MAINNET_DAO, + chainTags: ["hasDao"], + }, +}; + +export function parseMigrationNetwork( + value: string | undefined, +): MigrationNetwork { + if (value === "mainnet" || value === "sepolia") return value; + throw new Error(`Unsupported network: ${value ?? ""}`); +} + +function loadDotEnv(filePath: string): void { + if (!existsSync(filePath)) return; + for (const line of readFileSync(filePath, "utf-8").split(/\r?\n/)) { + const match = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)=(.*)$/); + if (!match) continue; + const [, key] = match; + if (process.env[key]) continue; + let value = match[2].trim(); + const quoted = + (value.startsWith('"') && value.endsWith('"')) || + (value.startsWith("'") && value.endsWith("'")); + if (quoted) { + value = value.slice(1, -1); + } else { + // An unquoted value ends where an inline comment begins (whitespace + // followed by '#'); surrounding whitespace is not part of the value. + value = value.replace(/\s+#.*$/, "").trim(); + } + process.env[key] = value; + } +} + +function requireRpcUrl( + opts: { rpcUrl?: string }, + network: MigrationNetwork, +): string { + const config = NETWORKS[network]; + const rpcUrl = opts.rpcUrl ?? process.env[config.rpcEnv]; + if (!rpcUrl) { + throw new Error(`Missing --rpc-url or ${config.rpcEnv}`); + } + return rpcUrl; +} + +function forkChain( + network: MigrationNetwork, + chainId: number, + rpcUrl: string, +): Chain { + const base = NETWORKS[network].chain; + return defineChain({ + ...base, + id: chainId, + name: chainId === base.id ? base.name : `${base.name} Fork ${chainId}`, + rpcUrls: { default: { http: [rpcUrl] } }, + }); +} + +function migrationChain(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; +}): Chain { + return forkChain( + opts.network, + parseNumber(opts.chainId, NETWORKS[opts.network].chain.id), + opts.rpcUrl, + ); +} + +function publicClient(rpcUrl: string, chain: Chain, provider?: RpcProvider) { + return createPublicClient({ + chain, + transport: provider + ? custom(provider as any) + : http(rpcUrl, { retryCount: RPC_RETRY_COUNT }), + }); +} + +async function getProviderChainId(provider: RpcProvider): Promise { + const value = await provider.request({ method: "eth_chainId" }); + if (typeof value === "number") return value; + if (typeof value === "bigint") return Number(value); + if (typeof value === "string") return Number(BigInt(value)); + throw new Error(`Unsupported eth_chainId response: ${String(value)}`); +} + +type WalletAccount = + | ReturnType + | ReturnType; + +function walletClient({ + rpcUrl, + chain, + privateKey, + account, + provider, +}: { + rpcUrl: string; + chain: Chain; + privateKey?: `0x${string}`; + account?: Address | WalletAccount; + provider?: RpcProvider; +}) { + const walletAccount = privateKey ? privateKeyToAccount(privateKey) : account; + if (!walletAccount) { + throw new Error("A private key or impersonated account is required"); + } + return createWalletClient({ + account: walletAccount, + chain, + transport: provider + ? custom(provider as any) + : http(rpcUrl, { retryCount: RPC_RETRY_COUNT }), + }); +} + +function loadDeploymentFromRoot( + root: string, + environment: string, + name: string, +): JsonDeployment | null { + const path = join(root, environment, `${name}.json`); + if (!existsSync(path)) return null; + return JSON.parse(readFileSync(path, "utf-8")) as JsonDeployment; +} + +function loadV1Deployment( + network: MigrationNetwork, + name: string, + opts: V1DeploymentOptions = {}, +): JsonDeployment | null { + const roots = opts.v1DeploymentsDir + ? [resolve(opts.v1DeploymentsDir)] + : [LOCAL_V1_DEPLOYMENTS_DIR, BUNDLED_V1_DEPLOYMENTS_DIR]; + const environment = opts.v1DeploymentNetwork ?? NETWORKS[network].environment; + for (const root of roots) { + const deployment = loadDeploymentFromRoot(root, environment, name); + if (deployment) return deployment; + } + return null; +} + +function requireV1Deployment( + network: MigrationNetwork, + name: string, + opts: V1DeploymentOptions = {}, +): JsonDeployment { + const deployment = loadV1Deployment(network, name, opts); + if (!deployment) { + const environment = + opts.v1DeploymentNetwork ?? NETWORKS[network].environment; + throw new Error(`Missing ${environment} v1 deployment: ${name}`); + } + return deployment; +} + +function loadV2Deployment( + root: string, + environment: string, + name: string, +): JsonDeployment { + const deployment = loadDeploymentFromRoot(resolve(root), environment, name); + if (!deployment) { + throw new Error( + `Missing v2 deployment: ${resolve(root)}/${environment}/${name}.json`, + ); + } + return deployment; +} + +function maybeLoadV2Deployment( + root: string, + environment: string, + name: string, +): JsonDeployment | null { + return loadDeploymentFromRoot(resolve(root), environment, name); +} + +function resolveDeploymentAddress( + explicitAddress: Address | undefined, + deploymentsDir: string, + environment: string, + name: string, +): Address { + if (explicitAddress) return explicitAddress; + return loadV2Deployment(deploymentsDir, environment, name).address; +} + +function parseNumber( + value: string | number | undefined, + fallback: number, +): number { + if (value === undefined || value === "") return fallback; + const parsed = Number(value); + if (!Number.isFinite(parsed)) { + throw new Error(`Expected a numeric value, got: ${JSON.stringify(value)}`); + } + return parsed; +} + +function envValue(...names: string[]): string | undefined { + for (const name of names) { + const value = process.env[name]; + if (value) return value; + } + return undefined; +} + +function envPrivateKey(...names: string[]): `0x${string}` | undefined { + return envValue(...names) as `0x${string}` | undefined; +} + +function parseResumeFromPhase(value: string | undefined): 2 | undefined { + if (value === undefined || value === "") return undefined; + const normalized = value.toLowerCase().replace(/^phase-?/, ""); + if (normalized === "2") return 2; + throw new Error(`Unsupported --resume-from-phase value: ${value}`); +} + +// Locate the label column case-insensitively (matching the premigration run +// parser), accepting either a `labelName` or `label` header. Returns -1 when +// neither is present so callers can fail loudly instead of guessing a column. +function csvLabelColumnIndex(header: string[]): number { + const normalized = header.map((field) => field.trim().toLowerCase()); + const labelNameIndex = normalized.indexOf("labelname"); + if (labelNameIndex >= 0) return labelNameIndex; + return normalized.indexOf("label"); +} + +// Quote a CSV field when it contains a delimiter, quote, or newline so labels +// with such characters survive a round-trip through the premigration reader. +function escapeCsvField(value: string): string { + return /[",\n\r]/.test(value) + ? `"${value.replace(/"/g, '""')}"` + : value; +} + +function readLabelsFromCsv(csvFile: string, limit?: number): string[] { + const lines = readFileSync(csvFile, "utf-8").trim().split(/\r?\n/); + if (lines.length === 0 || !lines[0]) return []; + const header = parseCSVLine(lines[0]); + const labelIndex = csvLabelColumnIndex(header); + if (labelIndex < 0) { + throw new Error( + `CSV must contain a labelName or label column: ${csvFile}`, + ); + } + const labels: string[] = []; + for (const line of lines.slice(1)) { + if (limit !== undefined && labels.length >= limit) break; + const label = parseCSVLine(line)[labelIndex]?.trim(); + if (label) labels.push(label); + } + return labels; +} + +function transformCsvForPreMigration( + sourcePath: string, + targetPath: string, +): number { + const lines = readFileSync(sourcePath, "utf-8").trim().split(/\r?\n/); + if (lines.length === 0) throw new Error(`CSV is empty: ${sourcePath}`); + + const sourceHeader = parseCSVLine(lines[0]); + const labelIndex = csvLabelColumnIndex(sourceHeader); + if (labelIndex < 0) { + throw new Error( + `CSV must contain either a labelName or label column: ${sourcePath}`, + ); + } + + const output = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + ]; + for (const line of lines.slice(1)) { + const columns = parseCSVLine(line); + const label = columns[labelIndex]?.trim(); + if (label) output.push(`,,,,,,${escapeCsvField(label)},,`); + } + writeFileSync(targetPath, `${output.join("\n")}\n`); + return output.length - 1; +} + +function prependCsvLabels(csvFile: string, labels: string[]): void { + const lines = readFileSync(csvFile, "utf-8").trimEnd().split(/\r?\n/); + const [header, ...rows] = lines; + const smokeRows = labels.map((label) => `,,,,,,${label},,`); + writeFileSync(csvFile, `${[header, ...smokeRows, ...rows].join("\n")}\n`); +} + +function readPremigrationLabels(csvFile: string, count: number): string[] { + const lines = readFileSync(csvFile, "utf-8").trimEnd().split(/\r?\n/); + const [header, ...rows] = lines; + const labelIndex = parseCSVLine(header).indexOf("labelName"); + if (labelIndex < 0) { + throw new Error(`CSV must contain a labelName column: ${csvFile}`); + } + const labels = rows + .map((row) => parseCSVLine(row)[labelIndex]?.trim()) + .filter((label): label is string => Boolean(label)); + if (labels.length < count) { + throw new Error(`CSV must contain at least ${count} labels: ${csvFile}`); + } + return labels.slice(0, count); +} + +function labelId(label: string): bigint { + return BigInt(keccak256(stringToHex(label))); +} + +async function requestAny( + client: RpcProvider, + requests: Array<{ method: string; params: unknown[] }>, +) { + let lastError: unknown; + for (const request of requests) { + try { + return await client.request({ + method: request.method as any, + params: request.params as any, + }); + } catch (error) { + lastError = error; + } + } + throw lastError; +} + +async function increaseTime( + client: ReturnType, + seconds: bigint, +) { + await requestAny(client, [ + { method: "anvil_increaseTime", params: [Number(seconds)] }, + { method: "evm_increaseTime", params: [Number(seconds)] }, + ]); + await requestAny(client, [ + { method: "anvil_mine", params: [1] }, + { method: "evm_mine", params: [] }, + ]); +} + +async function waitForCommitmentAge( + client: ReturnType, + seconds: bigint, + useRpcStateControls: boolean, +) { + if (useRpcStateControls) { + await increaseTime(client, seconds); + return; + } + const startTimestamp = (await client.getBlock()).timestamp; + const targetTimestamp = startTimestamp + seconds + 15n; + console.log( + `waiting for commitment age until block timestamp ${targetTimestamp}`, + ); + for (;;) { + const currentTimestamp = (await client.getBlock()).timestamp; + if (currentTimestamp >= targetTimestamp) return; + const remainingSeconds = targetTimestamp - currentTimestamp; + const delaySeconds = remainingSeconds < 12n ? remainingSeconds : 12n; + await new Promise((resolvePromise) => + setTimeout(resolvePromise, Number(delaySeconds) * 1000), + ); + } +} + +async function setBalance(client: RpcProvider, address: Address) { + const balance = `0x${parseEther("100").toString(16)}`; + await requestAny(client, [ + { method: "anvil_setBalance", params: [address, balance] }, + { method: "hardhat_setBalance", params: [address, balance] }, + { method: "tenderly_setBalance", params: [address, balance] }, + { method: "tenderly_setBalance", params: [[address], balance] }, + ]); +} + +async function impersonate(client: RpcProvider, address: Address) { + await requestAny(client, [ + { method: "anvil_impersonateAccount", params: [address] }, + { method: "hardhat_impersonateAccount", params: [address] }, + { method: "tenderly_impersonateAccount", params: [address] }, + { method: "tenderly_impersonateAccount", params: [[address]] }, + ]); + await setBalance(client, address); +} + +async function waitForRpc(rpcUrl: string, chain: Chain): Promise { + const client = publicClient(rpcUrl, chain); + const started = Date.now(); + while (Date.now() - started < 30_000) { + try { + await client.getChainId(); + return; + } catch { + try { + const response = await fetch(rpcUrl, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: 1, + method: "eth_chainId", + params: [], + }), + }); + const payload = await response.json(); + if (typeof payload?.result === "string") return; + } catch {} + await new Promise((resolve) => setTimeout(resolve, 500)); + } + } + throw new Error(`Timed out waiting for RPC at ${rpcUrl}`); +} + +function buildFeeHistoryResult(params: any) { + const blockCount = Number(BigInt(params?.[0] ?? "0x1")); + const percentiles = params?.[2] ?? []; + return { + oldestBlock: "0x1", + baseFeePerGas: Array.from({ length: blockCount + 1 }, () => "0x1"), + gasUsedRatio: Array.from({ length: blockCount }, () => 0), + reward: Array.from({ length: blockCount }, () => + Array.from({ length: percentiles.length }, () => "0x1"), + ), + }; +} + +function buildFeeHistoryResponse(request: any) { + return { + jsonrpc: "2.0", + id: request.id, + result: buildFeeHistoryResult(request.params), + }; +} + +function isMissingFeeHistory(error: any): boolean { + const message = String(error?.details ?? error?.message ?? ""); + return ( + error?.code === -32601 || + error?.code === -32001 || + message.includes("eth_feeHistory") || + message.includes("Method not found") || + message.includes("method not found") || + message === "not found" + ); +} + +function withRpcCompatibility( + provider: RpcProvider, + debugRpc = false, +): RpcProvider { + return { + async request(args) { + try { + return await provider.request(args); + } catch (error) { + if (args.method === "eth_feeHistory" && isMissingFeeHistory(error)) { + return buildFeeHistoryResult( + Array.isArray(args.params) ? args.params : [], + ); + } + if (debugRpc) { + console.error(`rpc error from ${args.method}:`, error); + } + throw error; + } + }, + }; +} + +function httpRpcProvider(rpcUrl: string): RpcProvider { + let id = 0; + return { + async request(args) { + const response = await fetch(rpcUrl, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ + jsonrpc: "2.0", + id: ++id, + method: args.method, + params: args.params ?? [], + }), + }); + const payload = (await response.json()) as { + result?: unknown; + error?: { code?: number; message?: string; data?: unknown }; + }; + if (payload.error) { + const error = new Error( + payload.error.message ?? "JSON-RPC error", + ) as Error & { + code?: number; + data?: unknown; + }; + error.code = payload.error.code; + error.data = payload.error.data; + throw error; + } + return payload.result; + }, + }; +} + +function privateKeyRpcProvider({ + rpcUrl, + chain, + privateKey, +}: { + rpcUrl: string; + chain: Chain; + privateKey: `0x${string}`; +}): RpcProvider { + const account = privateKeyToAccount(privateKey); + const client = createWalletClient({ + account, + chain, + transport: http(rpcUrl, { retryCount: RPC_RETRY_COUNT }), + }); + const fallback = httpRpcProvider(rpcUrl); + const normalizeTransaction = (transaction: any) => { + if (transaction.type === "0x2") { + return { ...transaction, type: "eip1559" }; + } + if (transaction.maxFeePerGas || transaction.maxPriorityFeePerGas) { + const { gasPrice: _gasPrice, type: _type, ...rest } = transaction; + return { ...rest, type: "eip1559" }; + } + return transaction; + }; + return { + async request(args) { + if (args.method === "eth_accounts") + return [account.address.toLowerCase()]; + if (args.method === "eth_sendTransaction") { + const [transaction] = (args.params ?? []) as [any]; + return await client.sendTransaction(normalizeTransaction(transaction)); + } + if (args.method === "eth_signTransaction") { + const [transaction] = (args.params ?? []) as [any]; + return await client.signTransaction(normalizeTransaction(transaction)); + } + return fallback.request(args); + }, + }; +} + +function privateKeySignerProtocol(rpcUrl: string, chain: Chain) { + return async (protocolString: string) => { + const privateKey = protocolString.slice( + "privateKey:".length, + ) as `0x${string}`; + return { + type: "remote" as const, + signer: privateKeyRpcProvider({ rpcUrl, chain, privateKey }) as any, + } as any; + }; +} + +function impersonatedAccountProvider( + provider: RpcProvider, + address: Address, +): RpcProvider { + return { + async request(args) { + if (args.method === "eth_accounts") return [address]; + return provider.request(args); + }, + }; +} + +function impersonationProvider(opts: DeployV2Options): RpcProvider | undefined { + if (opts.rpcUrl) { + return withRpcCompatibility( + httpRpcProvider(opts.rpcUrl), + Boolean(opts.debugRpc), + ); + } + if (!opts.provider) return undefined; + return opts.rpcCompatibility + ? withRpcCompatibility(opts.provider, Boolean(opts.debugRpc)) + : opts.provider; +} + +export async function createRpcSnapshot( + provider: RpcProvider, +): Promise { + const snapshotId = await provider.request({ + method: "evm_snapshot", + params: [], + }); + if (typeof snapshotId !== "string") { + throw new Error(`unexpected evm_snapshot response: ${String(snapshotId)}`); + } + return snapshotId; +} + +export function saveRpcSnapshotFile( + path: string, + snapshotId: string, + network: string, +) { + const filePath = resolve(path); + mkdirSync(dirname(filePath), { recursive: true }); + writeFileSync( + filePath, + `${JSON.stringify( + { + network, + snapshotId, + createdAt: new Date().toISOString(), + }, + null, + 2, + )}\n`, + ); +} + +/** + * Permanently monkey-patches `globalThis.fetch` to add JSON-RPC compatibility + * fallbacks for HTTP traffic issued by libraries we do not control (rocketh/viem + * internals): when an RPC lacks `eth_feeHistory` and returns an error, a synthetic + * fee-history response is fabricated so EIP-1559 fee estimation can proceed. With + * `debugRpc` enabled, JSON-RPC error payloads are also logged. The patch is + * process-wide, never uninstalled, and otherwise passes responses through untouched. + */ +function installRpcCompatibility(debugRpc: boolean): void { + const originalFetch = globalThis.fetch.bind(globalThis); + (globalThis as any).fetch = async (input: any, init?: any) => { + const request = (() => { + if (typeof init?.body !== "string") return null; + try { + return JSON.parse(init.body); + } catch { + return null; + } + })(); + const response = await originalFetch(input, init); + try { + const payload = await response.clone().json(); + if (payload?.error && request?.method === "eth_feeHistory") { + return new Response(JSON.stringify(buildFeeHistoryResponse(request)), { + headers: { "content-type": "application/json" }, + status: 200, + }); + } + if (debugRpc && payload?.error) { + console.error( + `rpc error from ${request?.method ?? "unknown"}:`, + payload.error, + ); + } + } catch { + // Non-JSON responses are unrelated to JSON-RPC compatibility handling. + } + return response; + }; +} + +function isLocalRpcUrl(rpcUrl: string): boolean { + return /^https?:\/\/(127\.0\.0\.1|localhost)(?::|\/|$)/i.test(rpcUrl); +} + +// Tenderly virtual testnets expose state-control RPC methods (impersonation, time +// travel, setBalance) just like a local node, so they can run the rehearsal +// without configured signer keys. +export function isTenderlyVirtualRpc(rpcUrl: string): boolean { + try { + const hostname = new URL(rpcUrl).hostname.toLowerCase(); + return ( + hostname.startsWith("virtual.") && hostname.endsWith(".rpc.tenderly.co") + ); + } catch { + return false; + } +} + +function printPreparedCall( + label: string, + target: Address, + data: `0x${string}`, +): void { + console.log(`${label}`); + console.log(` to: ${target}`); + console.log(` data: ${data}`); +} + +function optionalString(value: unknown): string | undefined { + return typeof value === "string" ? value : undefined; +} + +function parsePreparedOwnerTransaction( + value: unknown, + lineNumber: number, +): PreparedOwnerTransaction { + if (typeof value !== "object" || value === null) { + throw new Error(`Invalid owner tx on line ${lineNumber}: expected object`); + } + const input = value as Record; + const to = optionalString(input.to); + const data = optionalString(input.data); + if (!to) + throw new Error(`Invalid owner tx on line ${lineNumber}: missing to`); + if (!data?.startsWith("0x")) { + throw new Error(`Invalid owner tx on line ${lineNumber}: missing calldata`); + } + + const rawValue = input.value; + return { + account: optionalString(input.account), + role: optionalString(input.role), + from: input.from ? getAddress(String(input.from)) : undefined, + to: getAddress(to), + value: rawValue === undefined ? undefined : String(rawValue), + data: data as `0x${string}`, + phase: optionalString(input.phase), + label: optionalString(input.label), + functionName: optionalString(input.functionName), + deployment: optionalString(input.deployment), + }; +} + +function readPreparedOwnerTransactions( + file: string, + role?: string, +): PreparedOwnerTransaction[] { + const roleFilter = role?.toLowerCase(); + return readFileSync(resolve(file), "utf-8") + .split(/\r?\n/) + .map((line, index) => ({ line: line.trim(), lineNumber: index + 1 })) + .filter(({ line }) => line.length > 0) + .map(({ line, lineNumber }) => + parsePreparedOwnerTransaction(JSON.parse(line), lineNumber), + ) + .filter((tx) => { + if (!roleFilter) return true; + return [tx.role, tx.account] + .filter((value): value is string => Boolean(value)) + .some((value) => value.toLowerCase() === roleFilter); + }); +} + +function preparedOwnerTransactionRole(tx: PreparedOwnerTransaction): string { + return tx.role ?? tx.account ?? "owner"; +} + +function preparedOwnerTransactionLabel(tx: PreparedOwnerTransaction): string { + const action = tx.label ?? tx.functionName ?? tx.deployment ?? "transaction"; + return [tx.phase, action].filter(Boolean).join(": "); +} + +// Role-specific env-var prefixes for prepared owner transactions. Roles not listed +// here fall back to OWNER_TX_ENV_DEFAULT_PREFIXES. Role names are matched after +// lowercasing and stripping dashes (e.g. "v1-owner" -> "v1owner"). +const OWNER_TX_ENV_PREFIXES: Record = { + v1owner: ["SEPOLIA_V1_OWNER", "V1_OWNER"], + sepoliatopurpowner: ["SEPOLIA_TOP_URP_OWNER", "TOP_URP_OWNER"], +}; + +const OWNER_TX_ENV_DEFAULT_PREFIXES = [ + "OWNER_TX", + "SEPOLIA_V1_OWNER", + "V1_OWNER", + "SEPOLIA_TOP_URP_OWNER", + "TOP_URP_OWNER", +] as const; + +function normalizeOwnerTransactionRole(role: string | undefined): string { + return role?.toLowerCase().replace(/-/g, "") ?? ""; +} + +function ownerTransactionEnv( + role: string | undefined, + suffix: string, +): string | undefined { + const prefixes = + OWNER_TX_ENV_PREFIXES[normalizeOwnerTransactionRole(role)] ?? + OWNER_TX_ENV_DEFAULT_PREFIXES; + return envValue(...prefixes.map((prefix) => `${prefix}${suffix}`)); +} + +function ownerTransactionPrivateKey( + role: string | undefined, + privateKey: `0x${string}` | undefined, +): `0x${string}` | undefined { + if (privateKey) return privateKey; + if (normalizeOwnerTransactionRole(role) === "deployer") { + return envPrivateKey("DEPLOYER_KEY"); + } + return ownerTransactionEnv(role, "_KEY") as `0x${string}` | undefined; +} + +function ownerTransactionMnemonic( + role: string | undefined, +): string | undefined { + return ownerTransactionEnv(role, "_MNEMONIC"); +} + +function ownerTransactionMnemonicPath( + role: string | undefined, +): string | undefined { + return ownerTransactionEnv(role, "_MNEMONIC_PATH"); +} + +function ownerTransactionMnemonicPassphrase( + role: string | undefined, +): string | undefined { + return ownerTransactionEnv(role, "_MNEMONIC_PASSPHRASE"); +} + +function ownerTransactionMnemonicIndex(role: string | undefined): number { + return parseNumber(ownerTransactionEnv(role, "_MNEMONIC_INDEX"), 0); +} + +function ownerTransactionSigner( + role: string | undefined, + privateKey: `0x${string}` | undefined, +): WalletAccount | undefined { + const resolvedPrivateKey = ownerTransactionPrivateKey(role, privateKey); + if (resolvedPrivateKey) return privateKeyToAccount(resolvedPrivateKey); + + const mnemonic = ownerTransactionMnemonic(role); + if (!mnemonic) return undefined; + + const path = ownerTransactionMnemonicPath(role); + const passphrase = ownerTransactionMnemonicPassphrase(role); + return mnemonicToAccount( + mnemonic, + (path + ? { path, passphrase } + : { + addressIndex: ownerTransactionMnemonicIndex(role), + passphrase, + }) as never, + ); +} + +async function executePreparedOwnerTransactions(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + file: string; + role?: string; + privateKey?: `0x${string}`; + dryRun?: boolean; +}) { + const transactions = readPreparedOwnerTransactions(opts.file, opts.role); + if (transactions.length === 0) { + throw new Error(`No prepared owner transactions found in ${opts.file}`); + } + + const account = ownerTransactionSigner(opts.role, opts.privateKey); + if (!account && !opts.dryRun) { + throw new Error( + "Missing --private-key, owner key env var, or owner mnemonic env var for prepared owner transactions", + ); + } + + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + const wallet = account + ? walletClient({ rpcUrl: opts.rpcUrl, chain, account }) + : null; + + for (const tx of transactions) { + const label = preparedOwnerTransactionLabel(tx); + const role = preparedOwnerTransactionRole(tx); + console.log(`${opts.dryRun ? "prepared" : "executing"} ${role}: ${label}`); + console.log(` to: ${tx.to}`); + console.log(` data: ${tx.data}`); + + if ( + account && + tx.from && + getAddress(account.address) !== getAddress(tx.from) + ) { + throw new Error( + `Signer ${account.address} does not match prepared tx sender ${tx.from} for ${label}`, + ); + } + if (opts.dryRun) continue; + + const hash = await wallet!.sendTransaction({ + to: tx.to, + data: tx.data, + value: BigInt(tx.value ?? "0"), + }); + await waitForSuccessfulReceipt(client, hash, label); + console.log(` tx: ${hash}`); + } +} + +async function runFetchData(opts: { + thegraphApiKey?: string; + network?: string; + batchSize?: string; + startIndex?: string; + limit?: string; + output: string; +}) { + const thegraphApiKey = + opts.thegraphApiKey ?? envValue("THEGRAPH_API_KEY", "GRAPH_API_KEY"); + if (!thegraphApiKey) { + throw new Error( + "Missing --thegraph-api-key or THEGRAPH_API_KEY/GRAPH_API_KEY", + ); + } + const args = [ + "bun", + "script/exportTheGraphRegistrations.ts", + "--thegraph-api-key", + thegraphApiKey, + "--network", + opts.network ?? "mainnet", + "--batch-size", + String(parseNumber(opts.batchSize, 1000)), + "--start-index", + String(parseNumber(opts.startIndex, 0)), + "--output", + opts.output, + ]; + if (opts.limit) args.push("--limit", opts.limit); + await exportRegistrationsMain(args); +} + +export async function runPreMigrationCommand( + opts: { + rpcUrl: string; + mainnetRpcUrl?: string; + network?: MigrationNetwork; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + deploymentNetwork?: string; + deploymentsDir?: string; + registry?: Address; + batchRegistrar?: Address; + privateKey?: `0x${string}`; + account?: Address; + csvFile: string; + batchSize?: string; + limit?: string; + bonusPeriodDays?: string; + v1Resolver?: Address; + v1BaseRegistrar?: Address; + workDir?: string; + dryRun?: boolean; + }, + resume: boolean, + runMain: (argv: string[]) => Promise = preMigrationMain, +) { + const network = opts.network ?? "mainnet"; + const deploymentNetwork = opts.deploymentNetwork ?? network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const registry = resolveDeploymentAddress( + opts.registry, + deploymentsDir, + deploymentNetwork, + "ETHRegistry", + ); + const batchRegistrar = resolveDeploymentAddress( + opts.batchRegistrar, + deploymentsDir, + deploymentNetwork, + "BatchRegistrar", + ); + const v1Resolver = resolveDeploymentAddress( + opts.v1Resolver, + deploymentsDir, + deploymentNetwork, + "ENSV1Resolver", + ); + const v1BaseRegistrar = + opts.v1BaseRegistrar ?? + requireV1Deployment(network, "BaseRegistrarImplementation", opts).address; + const envFallbackKey = envPrivateKey( + "PREMIGRATION_PRIVATE_KEY", + "BATCH_REGISTRAR_OWNER_KEY", + "DEPLOYER_KEY", + ); + // When the caller supplies an impersonated account, only consult the env + // fallback key if it actually controls that account; otherwise the batch run + // would sign as the wrong address and BatchRegistrar.onlyOwner would revert. + const fallbackKey = + opts.account && envFallbackKey + ? getAddress(privateKeyToAccount(envFallbackKey).address) === + getAddress(opts.account) + ? envFallbackKey + : undefined + : envFallbackKey; + const privateKey = opts.privateKey ?? fallbackKey; + const previousCwd = process.cwd(); + + if (opts.workDir) { + mkdirSync(resolve(opts.workDir), { recursive: true }); + process.chdir(resolve(opts.workDir)); + } + + try { + const args = [ + "bun", + "script/preMigration.ts", + "--rpc-url", + opts.rpcUrl, + "--registry", + registry, + "--batch-registrar", + batchRegistrar, + "--csv-file", + resolve(previousCwd, opts.csvFile), + "--v1-resolver", + v1Resolver, + "--mainnet-rpc-url", + opts.mainnetRpcUrl ?? opts.rpcUrl, + "--v1-base-registrar", + v1BaseRegistrar, + "--batch-size", + String(parseNumber(opts.batchSize, 50)), + ]; + if (privateKey) args.push("--private-key", privateKey); + if (opts.account) args.push("--account", opts.account); + if (opts.limit) args.push("--limit", opts.limit); + if (opts.dryRun) args.push("--dry-run"); + if (opts.bonusPeriodDays) + args.push("--bonus-period-days", opts.bonusPeriodDays); + if (resume) args.push("--continue"); + await runMain(args); + } finally { + process.chdir(previousCwd); + } +} + +async function printPreMigrationStatus(opts: { workDir?: string }) { + const previousCwd = process.cwd(); + if (opts.workDir) process.chdir(resolve(opts.workDir)); + try { + const checkpoint = loadCheckpoint() ?? createFreshCheckpoint(); + console.log(JSON.stringify(checkpoint, null, 2)); + } finally { + process.chdir(previousCwd); + } +} + +async function verifyPreMigration(opts: { + network: MigrationNetwork; + rpcUrl: string; + mainnetRpcUrl?: string; + chainId?: string; + csvFile: string; + registry?: Address; + v1Resolver?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + v1BaseRegistrar?: Address; + limit?: string; + expectedStatus?: "reserved" | "registered" | "reserved-or-registered"; + bonusPeriodDays?: string; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chainId = parseNumber(opts.chainId, NETWORKS[opts.network].chain.id); + const chain = forkChain(opts.network, chainId, opts.rpcUrl); + const client = publicClient(opts.rpcUrl, chain); + const v1Client = publicClient(opts.mainnetRpcUrl ?? opts.rpcUrl, chain); + const registry = getContract({ + address: resolveDeploymentAddress( + opts.registry, + deploymentsDir, + deploymentNetwork, + "ETHRegistry", + ), + abi: Artifact_PermissionedRegistry.abi, + client, + }); + const expectedResolver = + opts.v1Resolver ?? + maybeLoadV2Deployment(deploymentsDir, deploymentNetwork, "ENSV1Resolver") + ?.address; + const baseRegistrar = + opts.v1BaseRegistrar ?? + requireV1Deployment(opts.network, "BaseRegistrarImplementation", opts) + .address; + const expectedStatus = opts.expectedStatus ?? "reserved-or-registered"; + const labels = readLabelsFromCsv( + opts.csvFile, + opts.limit ? Number(opts.limit) : undefined, + ); + const v1Block = await v1Client.getBlock(); + const v2Block = await client.getBlock(); + const v1Now = BigInt(v1Block.timestamp); + const v2Now = BigInt(v2Block.timestamp); + const bonusPeriodDays = parseNumber(opts.bonusPeriodDays, 62); + const bonusPeriodSeconds = BigInt(bonusPeriodDays) * SEC_PER_DAY; + const errors: string[] = []; + let eligible = 0; + let skipped = 0; + let invalid = 0; + let verifiedActive = 0; + let verifiedExpiredBonus = 0; + + for ( + let start = 0; + start < labels.length; + start += PREMIGRATION_VERIFY_BATCH_SIZE + ) { + const batch = labels.slice(start, start + PREMIGRATION_VERIFY_BATCH_SIZE); + const validBatch = batch.filter((label) => { + if (isValidLabel(label)) return true; + invalid++; + return false; + }); + if (validBatch.length === 0) continue; + + const expiryResults = await v1Client.multicall({ + allowFailure: true, + contracts: validBatch.map((label) => ({ + address: baseRegistrar, + abi: Artifact_BaseRegistrarImplementation.abi, + functionName: "nameExpires", + args: [labelId(label)], + })), + }); + const stateResults = await client.multicall({ + allowFailure: true, + contracts: validBatch.map((label) => ({ + address: registry.address, + abi: Artifact_PermissionedRegistry.abi, + functionName: "getState", + args: [labelId(label)], + })), + }); + const resolverChecks: string[] = []; + + for (let index = 0; index < validBatch.length; index++) { + const label = validBatch[index]; + const expiryResult = expiryResults[index]; + const stateResult = stateResults[index]; + + if (expiryResult.status === "failure") { + errors.push( + `${label}.eth v1 expiry lookup failed: ${expiryResult.error}`, + ); + continue; + } + if (stateResult.status === "failure") { + errors.push( + `${label}.eth v2 state lookup failed: ${stateResult.error}`, + ); + continue; + } + + const expiry = expiryResult.result as bigint; + const v1IsClaimable = + expiry > 0n && expiry + V1_GRACE_PERIOD_SECONDS > v1Now; + if (!v1IsClaimable) { + skipped++; + continue; + } + + eligible++; + const expectedExpiry = expiry + bonusPeriodSeconds; + const state = stateResult.result as unknown as { + status: number; + expiry: bigint | number; + latestOwner: Address; + }; + if (BigInt(state.expiry) !== expectedExpiry) { + errors.push( + `${label}.eth expiry mismatch: v2=${state.expiry} expected=${expectedExpiry} v1=${expiry}`, + ); + continue; + } + + if (expectedExpiry <= v2Now) { + verifiedExpiredBonus++; + continue; + } + + const status = Number(state.status); + const statusOk = + expectedStatus === "reserved" + ? status === STATUS.RESERVED + : expectedStatus === "registered" + ? status === STATUS.REGISTERED + : status === STATUS.RESERVED || status === STATUS.REGISTERED; + if (!statusOk) { + errors.push(`${label}.eth has status ${status}`); + continue; + } + // The premigration fallback resolver is only asserted for names that remain + // RESERVED. A REGISTERED name has already been migrated and carries the + // resolver from its migration data (custom or zero), not the fallback, so + // asserting the fallback here would fail legitimate migrated names. + if (expectedResolver && status === STATUS.RESERVED) { + resolverChecks.push(label); + } else { + verifiedActive++; + } + } + + const resolverToCheck = expectedResolver; + if (resolverToCheck && resolverChecks.length > 0) { + const resolverResults = await client.multicall({ + allowFailure: true, + contracts: resolverChecks.map((label) => ({ + address: registry.address, + abi: Artifact_PermissionedRegistry.abi, + functionName: "getResolver", + args: [label], + })), + }); + for (let index = 0; index < resolverChecks.length; index++) { + const label = resolverChecks[index]; + const result = resolverResults[index]; + if (result.status === "failure") { + errors.push(`${label}.eth resolver lookup failed: ${result.error}`); + continue; + } + const actualResolver = result.result as Address; + if (getAddress(actualResolver) !== getAddress(resolverToCheck)) { + errors.push(`${label}.eth resolver mismatch: ${actualResolver}`); + continue; + } + verifiedActive++; + } + } + } + + console.log(`labels scanned: ${labels.length}`); + console.log(`invalid labels: ${invalid}`); + console.log(`eligible v1 names: ${eligible}`); + console.log(`skipped ineligible names: ${skipped}`); + console.log(`verified active names: ${verifiedActive}`); + console.log( + `verified expired-bonus names: ${verifiedExpiredBonus}`, + ); + console.log(`verified names: ${verifiedActive + verifiedExpiredBonus}`); + if (errors.length > 0) { + console.error(errors.slice(0, 20).join("\n")); + if (errors.length > 20) { + console.error(`...and ${errors.length - 20} more errors`); + } + throw new Error( + `pre-migration verification failed for ${errors.length} names`, + ); + } +} + +type ContractRef = { address: Address; abi: readonly any[] }; + +// Read owner() from the gating contract, reject a private key that does not +// control it, optionally impersonate it on a fork, and return a wallet able to +// sign as the owner. +async function resolveOwnerGatedWallet(opts: { + client: ReturnType; + chain: Chain; + rpcUrl: string; + provider?: RpcProvider; + gate: ContractRef; + ownerLabel: string; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; +}): Promise<{ owner: Address; wallet: ReturnType }> { + const owner = (await opts.client.readContract({ + address: opts.gate.address, + abi: opts.gate.abi, + functionName: "owner", + })) as Address; + if ( + opts.privateKey && + getAddress(privateKeyToAccount(opts.privateKey).address) !== + getAddress(owner) + ) { + throw new Error(`private key does not match ${opts.ownerLabel} ${owner}`); + } + if (opts.impersonateOwner) await impersonate(opts.client, owner); + const wallet = walletClient({ + rpcUrl: opts.rpcUrl, + chain: opts.chain, + privateKey: opts.privateKey, + account: opts.impersonateOwner ? owner : undefined, + provider: opts.provider, + }); + return { owner, wallet }; +} + +// Send a single owner-gated write: print calldata when only preparing a +// multisig transaction, otherwise resolve the owner-signing wallet, broadcast, +// and assert the receipt did not revert. +async function sendOwnerGatedWrite(opts: { + client: ReturnType; + chain: Chain; + rpcUrl: string; + provider?: RpcProvider; + target: ContractRef; + gate?: ContractRef; + functionName: string; + args: readonly unknown[]; + ownerLabel: string; + calldataLabel: string; + receiptLabel: string; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}): Promise { + const data = encodeFunctionData({ + abi: opts.target.abi, + functionName: opts.functionName, + args: opts.args, + }); + if (opts.calldataOnly) { + printPreparedCall(opts.calldataLabel, opts.target.address, data); + return; + } + const { wallet } = await resolveOwnerGatedWallet({ + client: opts.client, + chain: opts.chain, + rpcUrl: opts.rpcUrl, + provider: opts.provider, + gate: opts.gate ?? opts.target, + ownerLabel: opts.ownerLabel, + privateKey: opts.privateKey, + impersonateOwner: opts.impersonateOwner, + }); + const hash = await wallet.writeContract({ + address: opts.target.address, + abi: opts.target.abi, + functionName: opts.functionName, + args: opts.args, + }); + await waitForSuccessfulReceipt(opts.client, hash, opts.receiptLabel); +} + +// Send an admin-gated write where the authorized account is supplied directly +// rather than read from the contract's owner(). +async function sendAdminWrite(opts: { + client: ReturnType; + chain: Chain; + rpcUrl: string; + provider?: RpcProvider; + target: ContractRef; + functionName: string; + args: readonly unknown[]; + receiptLabel: string; + calldataLabel?: string; + privateKey?: `0x${string}`; + impersonateAccount?: Address; + calldataOnly?: boolean; +}): Promise { + const data = encodeFunctionData({ + abi: opts.target.abi, + functionName: opts.functionName, + args: opts.args, + }); + if (opts.calldataOnly) { + printPreparedCall( + opts.calldataLabel ?? opts.receiptLabel, + opts.target.address, + data, + ); + return; + } + if (opts.impersonateAccount) await impersonate(opts.client, opts.impersonateAccount); + const wallet = walletClient({ + rpcUrl: opts.rpcUrl, + chain: opts.chain, + privateKey: opts.privateKey, + account: opts.impersonateAccount, + provider: opts.provider, + }); + const hash = await wallet.writeContract({ + address: opts.target.address, + abi: opts.target.abi, + functionName: opts.functionName, + args: opts.args, + }); + await waitForSuccessfulReceipt(opts.client, hash, opts.receiptLabel); +} + +async function disableV1Registrars(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + extraControllers?: Array<{ name: string; address: Address }>; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}) { + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain, opts.provider); + const baseRegistrar = requireV1Deployment( + opts.network, + "BaseRegistrarImplementation", + opts, + ); + const registrarSecurityController = loadV1Deployment( + opts.network, + "RegistrarSecurityController", + opts, + ); + const controllerNames = [ + "LegacyETHRegistrarController", + "ETHRegistrarController", + "WrappedETHRegistrarController", + "NameWrapper", + ]; + + const target = registrarSecurityController ?? baseRegistrar; + const wallet = opts.calldataOnly + ? null + : ( + await resolveOwnerGatedWallet({ + client, + chain, + rpcUrl: opts.rpcUrl, + provider: opts.provider, + gate: target, + ownerLabel: "v1 registrar owner", + privateKey: opts.privateKey, + impersonateOwner: opts.impersonateOwner, + }) + ).wallet; + + const controllers = [ + ...controllerNames.flatMap((name) => { + const controller = loadV1Deployment(opts.network, name, opts); + return controller ? [{ name, address: controller.address }] : []; + }), + ...(opts.extraControllers ?? []), + ]; + + for (const { name, address } of controllers) { + const enabled = await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "controllers", + args: [address], + }); + if (!enabled) { + console.log(`already disabled: ${name} ${address}`); + continue; + } + + const functionName = registrarSecurityController + ? "removeRegistrarController" + : "removeController"; + const data = encodeFunctionData({ + abi: target.abi, + functionName, + args: [address], + }); + if (opts.calldataOnly) { + printPreparedCall(`disable ${name}`, target.address, data); + continue; + } + + const hash = await wallet!.writeContract({ + address: target.address, + abi: target.abi, + functionName, + args: [address], + }); + await client.waitForTransactionReceipt({ hash }); + console.log(`disabled v1 registrar controller ${name}: ${address}`); + } +} + +async function authorizeTestnetV1PremigrationRegistrar(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + deploymentsDir?: string; + deploymentNetwork?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + registrar?: Address; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const registrar = resolveDeploymentAddress( + opts.registrar, + deploymentsDir, + deploymentNetwork, + "TestnetV1PremigrationRegistrar", + ); + await setV1RegistrarController({ + ...opts, + controller: registrar, + label: "TestnetV1PremigrationRegistrar", + enabled: true, + }); +} + +async function setV1RegistrarController(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + controller: Address; + label: string; + enabled: boolean; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}) { + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain, opts.provider); + const baseRegistrar = requireV1Deployment( + opts.network, + "BaseRegistrarImplementation", + opts, + ); + const registrarSecurityController = loadV1Deployment( + opts.network, + "RegistrarSecurityController", + opts, + ); + const current = (await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "controllers", + args: [opts.controller], + })) as boolean; + console.log(`${opts.label} v1 registrar controller enabled: ${current}`); + if (current === opts.enabled) return; + + const target = registrarSecurityController ?? baseRegistrar; + const functionName = registrarSecurityController + ? opts.enabled + ? "addRegistrarController" + : "removeRegistrarController" + : opts.enabled + ? "addController" + : "removeController"; + await sendOwnerGatedWrite({ + client, + chain, + rpcUrl: opts.rpcUrl, + provider: opts.provider, + target, + functionName, + args: [opts.controller], + ownerLabel: "v1 registrar owner", + calldataLabel: `${opts.enabled ? "authorize" : "disable"} ${opts.label}`, + receiptLabel: `${functionName} ${opts.label}`, + privateKey: opts.privateKey, + impersonateOwner: opts.impersonateOwner, + calldataOnly: opts.calldataOnly, + }); + if (opts.calldataOnly) return; + + const updated = (await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "controllers", + args: [opts.controller], + })) as boolean; + console.log( + `${opts.label} v1 registrar controller enabled after phase: ${updated}`, + ); + if (updated !== opts.enabled) { + throw new Error( + `${opts.label} v1 registrar controller did not reach expected state`, + ); + } +} + +async function activateV1Graveyard(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + deploymentsDir?: string; + deploymentNetwork?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + graveyard?: Address; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const graveyard = resolveDeploymentAddress( + opts.graveyard, + deploymentsDir, + deploymentNetwork, + "Graveyard", + ); + await setV1RegistrarController({ + ...opts, + controller: graveyard, + label: "Graveyard", + enabled: true, + }); +} + +async function activateV1HandoffControllers(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + deploymentsDir?: string; + deploymentNetwork?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + graveyard?: Address; + testnetV1PremigrationRegistrar?: Address; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const testnetV1PremigrationRegistrar = + opts.testnetV1PremigrationRegistrar ?? + maybeLoadV2Deployment( + deploymentsDir, + deploymentNetwork, + "TestnetV1PremigrationRegistrar", + )?.address; + + if (testnetV1PremigrationRegistrar) { + await setV1RegistrarController({ + ...opts, + controller: testnetV1PremigrationRegistrar, + label: "TestnetV1PremigrationRegistrar", + enabled: true, + }); + } else { + console.log( + "no TestnetV1PremigrationRegistrar deployment found; skipping testnet helper authorization", + ); + } + + await activateV1Graveyard(opts); +} + +// Minimal interface of a prior migration's ETHRenewerV1, which holds v1 +// BaseRegistrar ownership once a migration has completed. +const PRIOR_RENEWER_ABI = [ + { + type: "function", + name: "owner", + inputs: [], + outputs: [{ type: "address" }], + stateMutability: "view", + }, + { + type: "function", + name: "transferRegistrarOwnership", + inputs: [{ name: "newOwner", type: "address" }], + outputs: [], + stateMutability: "nonpayable", + }, +] as const; + +// On a chain that has already completed a migration, the v1 BaseRegistrar is +// owned by the previous deployment's ETHRenewerV1 contract, so the EOA-signed +// v1-owner controller steps cannot run. Reclaim ownership back to the v1 owner +// by routing through the prior renewer's `transferRegistrarOwnership`, signed by +// the prior renewer's own owner. No-op on a pristine chain (BaseRegistrar still +// owned by the v1 owner EOA) or once ownership is already with the v1 owner. +async function reclaimV1RegistrarOwnership(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + v1Owner: Address; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; +}) { + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain, opts.provider); + const baseRegistrar = requireV1Deployment( + opts.network, + "BaseRegistrarImplementation", + opts, + ); + const currentOwner = (await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "owner", + })) as Address; + if (getAddress(currentOwner) === getAddress(opts.v1Owner)) return; + + const code = await client.getCode({ address: currentOwner }); + if (!code || code === "0x") { + console.log( + `v1 BaseRegistrar owner ${currentOwner} is an EOA other than the v1 owner; skipping reclaim`, + ); + return; + } + + // On a pristine chain the BaseRegistrar is owned by the live + // RegistrarSecurityController, not a prior deployment's ETHRenewerV1. Treating + // it as a prior renewer would move ownership to the v1 owner EOA and break the + // controller phases, which route addController through the security controller. + const registrarSecurityController = loadV1Deployment( + opts.network, + "RegistrarSecurityController", + opts, + ); + if ( + registrarSecurityController && + getAddress(currentOwner) === getAddress(registrarSecurityController.address) + ) { + console.log( + `v1 BaseRegistrar owner ${currentOwner} is the RegistrarSecurityController, not a prior renewer; skipping reclaim`, + ); + return; + } + + const gate: ContractRef = { address: currentOwner, abi: PRIOR_RENEWER_ABI }; + const { owner: priorRenewerOwner, wallet } = await resolveOwnerGatedWallet({ + client, + chain, + rpcUrl: opts.rpcUrl, + provider: opts.provider, + gate, + ownerLabel: "prior renewer owner", + privateKey: opts.privateKey, + impersonateOwner: opts.impersonateOwner, + }); + console.log( + `reclaiming v1 BaseRegistrar ownership from prior renewer ${currentOwner} (owner ${priorRenewerOwner}) to ${opts.v1Owner}`, + ); + const hash = await wallet.writeContract({ + address: currentOwner, + abi: PRIOR_RENEWER_ABI, + functionName: "transferRegistrarOwnership", + args: [opts.v1Owner], + }); + await waitForSuccessfulReceipt( + client, + hash, + "reclaim v1 BaseRegistrar ownership to v1 owner", + ); + + const updatedOwner = (await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "owner", + })) as Address; + if (getAddress(updatedOwner) !== getAddress(opts.v1Owner)) { + throw new Error( + `v1 BaseRegistrar ownership reclaim failed; owner is ${updatedOwner}`, + ); + } +} + +async function authorizeV1Renewer(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + deploymentsDir?: string; + deploymentNetwork?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + ethRenewerV1?: Address; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const ethRenewerV1 = resolveDeploymentAddress( + opts.ethRenewerV1, + deploymentsDir, + deploymentNetwork, + "ETHRenewerV1", + ); + + await setV1RegistrarController({ + ...opts, + controller: ethRenewerV1, + label: "ETHRenewerV1", + enabled: true, + }); + + return ethRenewerV1; +} + +async function activateV1RenewerAndTransferOwnership(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + deploymentsDir?: string; + deploymentNetwork?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + ethRenewerV1?: Address; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}) { + const ethRenewerV1 = await authorizeV1Renewer(opts); + + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain, opts.provider); + const baseRegistrar = requireV1Deployment( + opts.network, + "BaseRegistrarImplementation", + opts, + ); + const registrarSecurityController = loadV1Deployment( + opts.network, + "RegistrarSecurityController", + opts, + ); + const currentOwner = (await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "owner", + })) as Address; + console.log(`v1 BaseRegistrar owner: ${currentOwner}`); + if (getAddress(currentOwner) === getAddress(ethRenewerV1)) return; + + const target = registrarSecurityController ?? baseRegistrar; + const functionName = registrarSecurityController + ? "transferRegistrarOwnership" + : "transferOwnership"; + await sendOwnerGatedWrite({ + client, + chain, + rpcUrl: opts.rpcUrl, + provider: opts.provider, + target, + functionName, + args: [ethRenewerV1], + ownerLabel: "v1 registrar owner", + calldataLabel: "transfer v1 BaseRegistrar ownership to ETHRenewerV1", + receiptLabel: "transfer v1 BaseRegistrar ownership to ETHRenewerV1", + privateKey: opts.privateKey, + impersonateOwner: opts.impersonateOwner, + calldataOnly: opts.calldataOnly, + }); + if (opts.calldataOnly) return; + + const updatedOwner = (await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "owner", + })) as Address; + console.log(`v1 BaseRegistrar owner after phase: ${updatedOwner}`); + if (getAddress(updatedOwner) !== getAddress(ethRenewerV1)) { + throw new Error(`unexpected v1 BaseRegistrar owner: ${updatedOwner}`); + } +} + +async function verifyV1RegistrarsDisabled(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; +}) { + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + const baseRegistrar = requireV1Deployment( + opts.network, + "BaseRegistrarImplementation", + opts, + ); + const controllerNames = [ + "LegacyETHRegistrarController", + "ETHRegistrarController", + "WrappedETHRegistrarController", + "NameWrapper", + ]; + const enabledControllers: string[] = []; + + for (const name of controllerNames) { + const controller = loadV1Deployment(opts.network, name, opts); + if (!controller) continue; + const enabled = await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "controllers", + args: [controller.address], + }); + console.log( + `${name}: ${enabled ? "enabled" : "disabled"} (${controller.address})`, + ); + if (enabled) enabledControllers.push(name); + } + + if (enabledControllers.length > 0) { + throw new Error( + `v1 registrar controllers still enabled: ${enabledControllers.join(", ")}`, + ); + } +} + +export async function setV1ReverseDefaultResolver(opts: { + network: MigrationNetwork; + rpcUrl?: string; + chainId?: string; + provider?: RpcProvider; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}) { + const rpcUrl = requireRpcUrl(opts, opts.network); + const chain = forkChain( + opts.network, + parseNumber(opts.chainId, NETWORKS[opts.network].chain.id), + rpcUrl, + ); + const client = publicClient(rpcUrl, chain, opts.provider); + const reverseRegistrar = requireV1Deployment( + opts.network, + "ReverseRegistrar", + opts, + ); + const publicResolver = requireV1Deployment( + opts.network, + "PublicResolver", + opts, + ); + const currentResolver = (await client.readContract({ + address: reverseRegistrar.address, + abi: reverseRegistrar.abi, + functionName: "defaultResolver", + })) as Address; + console.log(`v1 reverse registrar default resolver: ${currentResolver}`); + if (getAddress(currentResolver) === getAddress(publicResolver.address)) { + return; + } + + // setDefaultResolver is owner-gated; the v1 ReverseRegistrar owner is the v1 + // owner, not the deployer, so a key controlling it (or impersonation) is + // required. + await sendOwnerGatedWrite({ + client, + chain, + rpcUrl, + provider: opts.provider, + target: reverseRegistrar, + functionName: "setDefaultResolver", + args: [publicResolver.address], + ownerLabel: "v1 reverse registrar owner", + calldataLabel: "set v1 reverse default resolver", + receiptLabel: "set v1 reverse default resolver", + privateKey: opts.privateKey, + impersonateOwner: opts.impersonateOwner, + calldataOnly: opts.calldataOnly, + }); + if (opts.calldataOnly) return; + + const updatedResolver = (await client.readContract({ + address: reverseRegistrar.address, + abi: reverseRegistrar.abi, + functionName: "defaultResolver", + })) as Address; + console.log( + `v1 reverse registrar default resolver after update: ${updatedResolver}`, + ); + if (getAddress(updatedResolver) !== getAddress(publicResolver.address)) { + throw new Error( + `unexpected v1 reverse default resolver: ${updatedResolver}`, + ); + } +} + +// Resolve the v2 ETHRegistry to write to: an explicit address (with the default +// PermissionedRegistry abi) or the deployment artifact (carrying its own abi). +function resolveRegistry(opts: { + registry?: Address; + deploymentsDir: string; + deploymentNetwork: string; +}): ContractRef { + const registry = opts.registry + ? null + : loadV2Deployment(opts.deploymentsDir, opts.deploymentNetwork, "ETHRegistry"); + return { + address: opts.registry ?? registry!.address, + abi: registry?.abi ?? Artifact_PermissionedRegistry.abi, + }; +} + +// Read whether an account holds the registrar/renew root roles on the registry. +async function readHasRegistrarRoles( + client: ReturnType, + registry: ContractRef, + account: Address, +): Promise { + return (await client.readContract({ + address: registry.address, + abi: registry.abi, + functionName: "hasRootRoles", + args: [REGISTRAR_ROLES, account], + })) as boolean; +} + +async function enableV2Registrar(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + registry?: Address; + ethRegistrar?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; + privateKey?: `0x${string}`; + impersonateAccount?: Address; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + const registry = resolveRegistry({ + registry: opts.registry, + deploymentsDir, + deploymentNetwork, + }); + const ethRegistrar = resolveDeploymentAddress( + opts.ethRegistrar, + deploymentsDir, + deploymentNetwork, + "ETHRegistrar", + ); + const beforeEnabled = await readHasRegistrarRoles(client, registry, ethRegistrar); + console.log(`v2 registrar already enabled: ${beforeEnabled}`); + if (beforeEnabled) return; + + await sendAdminWrite({ + client, + chain, + rpcUrl: opts.rpcUrl, + target: registry, + functionName: "grantRootRoles", + args: [REGISTRAR_ROLES, ethRegistrar], + receiptLabel: "enable v2 registrar", + privateKey: opts.privateKey, + impersonateAccount: opts.impersonateAccount, + }); + const afterEnabled = await readHasRegistrarRoles(client, registry, ethRegistrar); + console.log(`v2 registrar enabled after phase: ${afterEnabled}`); +} + +async function disableBatchRegistrar(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + registry?: Address; + batchRegistrar?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; + privateKey?: `0x${string}`; + impersonateAccount?: Address; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + const registry = resolveRegistry({ + registry: opts.registry, + deploymentsDir, + deploymentNetwork, + }); + const batchRegistrar = resolveDeploymentAddress( + opts.batchRegistrar, + deploymentsDir, + deploymentNetwork, + "BatchRegistrar", + ); + const beforeEnabled = await readHasRegistrarRoles( + client, + registry, + batchRegistrar, + ); + console.log(`batch registrar enabled before phase: ${beforeEnabled}`); + if (!beforeEnabled) return; + + await sendAdminWrite({ + client, + chain, + rpcUrl: opts.rpcUrl, + target: registry, + functionName: "revokeRootRoles", + args: [REGISTRAR_ROLES, batchRegistrar], + receiptLabel: `disable batch registrar ${batchRegistrar}`, + privateKey: opts.privateKey, + impersonateAccount: opts.impersonateAccount, + }); + const afterEnabled = await readHasRegistrarRoles( + client, + registry, + batchRegistrar, + ); + console.log(`batch registrar enabled after phase: ${afterEnabled}`); + if (afterEnabled) + throw new Error("batch registrar still has registrar/renew roles"); +} + +async function verifyBatchRegistrarDisabled(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + registry?: Address; + batchRegistrar?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + const registry = resolveRegistry({ + registry: opts.registry, + deploymentsDir, + deploymentNetwork, + }); + const batchRegistrar = resolveDeploymentAddress( + opts.batchRegistrar, + deploymentsDir, + deploymentNetwork, + "BatchRegistrar", + ); + const enabled = await readHasRegistrarRoles(client, registry, batchRegistrar); + console.log(`batch registrar enabled: ${enabled}`); + if (enabled) + throw new Error("batch registrar still has registrar/renew roles"); +} + +export async function checkBatchRegistrarOwner(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + batchRegistrar?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; + expectedOwner?: Address; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + const batchRegistrar = resolveDeploymentAddress( + opts.batchRegistrar, + deploymentsDir, + deploymentNetwork, + "BatchRegistrar", + ); + const owner = (await client.readContract({ + address: batchRegistrar, + abi: Artifact_BatchRegistrar.abi, + functionName: "owner", + })) as Address; + + console.log(`batch registrar: ${batchRegistrar}`); + console.log(`batch registrar owner: ${owner}`); + if ( + opts.expectedOwner !== undefined && + getAddress(owner) !== getAddress(opts.expectedOwner) + ) { + throw new Error( + `unexpected BatchRegistrar owner: expected ${opts.expectedOwner}, got ${owner}`, + ); + } +} + +async function readBatchRegistrarOwner(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + batchRegistrar: Address; +}) { + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + return (await client.readContract({ + address: opts.batchRegistrar, + abi: Artifact_BatchRegistrar.abi, + functionName: "owner", + })) as Address; +} + +function preMigrationSigner(account: Address): { + privateKey?: `0x${string}`; + account?: Address; +} { + return getAddress(account) === getAddress(DEFAULT_ANVIL_DEPLOYER) + ? { privateKey: DEFAULT_ANVIL_KEY } + : { account }; +} + +function adminSigner(account: Address): { + privateKey?: `0x${string}`; + impersonateAccount?: Address; +} { + return getAddress(account) === getAddress(DEFAULT_ANVIL_DEPLOYER) + ? { privateKey: DEFAULT_ANVIL_KEY } + : { impersonateAccount: account }; +} + +async function verifyV2Registrar(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + registry?: Address; + ethRegistrar?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + const registry = resolveRegistry({ + registry: opts.registry, + deploymentsDir, + deploymentNetwork, + }); + const ethRegistrar = resolveDeploymentAddress( + opts.ethRegistrar, + deploymentsDir, + deploymentNetwork, + "ETHRegistrar", + ); + const enabled = await readHasRegistrarRoles(client, registry, ethRegistrar); + console.log(`v2 registrar enabled: ${enabled}`); + if (!enabled) throw new Error("v2 registrar is not enabled"); +} + +async function verifyUrp(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + topUrp?: Address; + managedUrp?: Address; + expectedTopImplementation?: Address; + expectedManagedImplementation?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain); + const topUrp = opts.topUrp ?? DEPLOYED_UNIVERSAL_RESOLVER_PROXY; + const managedUrp = resolveDeploymentAddress( + opts.managedUrp, + deploymentsDir, + deploymentNetwork, + "ManagedUniversalResolverProxy", + ); + const top = getContract({ + address: topUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + client, + }); + const managed = getContract({ + address: managedUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + client, + }); + const topAdmin = (await top.read.admin()) as Address; + const topImplementation = (await top.read.implementation()) as Address; + const managedAdmin = (await managed.read.admin()) as Address; + const managedImplementation = + (await managed.read.implementation()) as Address; + + console.log(`top URP: ${topUrp}`); + console.log(`top URP admin: ${topAdmin}`); + console.log(`top URP implementation: ${topImplementation}`); + console.log(`managed URP: ${managedUrp}`); + console.log(`managed URP admin: ${managedAdmin}`); + console.log(`managed URP implementation: ${managedImplementation}`); + + if ( + opts.expectedTopImplementation && + getAddress(topImplementation) !== getAddress(opts.expectedTopImplementation) + ) { + throw new Error("top URP implementation does not match expected address"); + } + if ( + opts.expectedManagedImplementation && + getAddress(managedImplementation) !== + getAddress(opts.expectedManagedImplementation) + ) { + throw new Error( + "managed URP implementation does not match expected address", + ); + } +} + +async function switchTopUrpToManaged(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + topUrp?: Address; + managedUrp?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; + privateKey?: `0x${string}`; + impersonateAccount?: Address; + calldataOnly?: boolean; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain, opts.provider); + const topUrp = opts.topUrp ?? DEPLOYED_UNIVERSAL_RESOLVER_PROXY; + const managedUrp = resolveDeploymentAddress( + opts.managedUrp, + deploymentsDir, + deploymentNetwork, + "ManagedUniversalResolverProxy", + ); + // When the top URP already fronts the managed URP (the reuse flow), the switch + // is already done — never touch the externally-administered top URP. + const currentTopImplementation = (await client.readContract({ + address: topUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + functionName: "implementation", + })) as Address; + if (getAddress(currentTopImplementation) === getAddress(managedUrp)) { + console.log(`top URP already fronts managed URP: ${managedUrp}`); + return; + } + await sendAdminWrite({ + client, + chain, + rpcUrl: opts.rpcUrl, + provider: opts.provider, + target: { + address: topUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + }, + functionName: "upgradeTo", + args: [managedUrp], + calldataLabel: "switch UniversalResolverProxy to managed URP", + receiptLabel: "switch top URP to managed URP", + privateKey: opts.privateKey, + impersonateAccount: opts.impersonateAccount, + calldataOnly: opts.calldataOnly, + }); + if (opts.calldataOnly) return; + const top = getContract({ + address: topUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + client, + }); + const actualImplementation = (await top.read.implementation()) as Address; + if (getAddress(actualImplementation) !== getAddress(managedUrp)) { + throw new Error(`top URP implementation mismatch: ${actualImplementation}`); + } + console.log(`top URP implementation: ${actualImplementation}`); +} + +async function upgradeManagedUrp(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId?: string; + provider?: RpcProvider; + managedUrp?: Address; + implementation?: Address; + deploymentsDir?: string; + deploymentNetwork?: string; + privateKey?: `0x${string}`; + impersonateAccount?: Address; + calldataOnly?: boolean; +}) { + const deploymentNetwork = opts.deploymentNetwork ?? opts.network; + const deploymentsDir = opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR; + const chain = migrationChain(opts); + const client = publicClient(opts.rpcUrl, chain, opts.provider); + const managedUrp = resolveDeploymentAddress( + opts.managedUrp, + deploymentsDir, + deploymentNetwork, + "ManagedUniversalResolverProxy", + ); + const implementation = resolveDeploymentAddress( + opts.implementation, + deploymentsDir, + deploymentNetwork, + "UniversalResolverV2", + ); + // When reusing an existing managed URP that already fronts this implementation + // (e.g. a deterministic redeploy to the same address), the upgrade is a no-op + // and the proxy reverts with SameImplementation; treat it as already done. + const currentImplementation = (await client.readContract({ + address: managedUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + functionName: "implementation", + })) as Address; + if (getAddress(currentImplementation) === getAddress(implementation)) { + console.log(`managed URP already at implementation: ${implementation}`); + return; + } + await sendAdminWrite({ + client, + chain, + rpcUrl: opts.rpcUrl, + provider: opts.provider, + target: { + address: managedUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + }, + functionName: "upgradeTo", + args: [implementation], + calldataLabel: "upgrade managed URP", + receiptLabel: "upgrade managed URP", + privateKey: opts.privateKey, + impersonateAccount: opts.impersonateAccount, + calldataOnly: opts.calldataOnly, + }); + if (opts.calldataOnly) return; + const managed = getContract({ + address: managedUrp, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + client, + }); + const actualImplementation = (await managed.read.implementation()) as Address; + if (getAddress(actualImplementation) !== getAddress(implementation)) { + throw new Error( + `managed URP implementation mismatch: ${actualImplementation}`, + ); + } + console.log(`managed URP implementation: ${actualImplementation}`); +} + +type DeployV2Options = { + network: MigrationNetwork; + rpcUrl?: string; + chainId?: string; + deploymentsDir?: string; + deploymentNetwork?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + saveDeployments?: boolean; + fresh?: boolean; + tags?: readonly string[]; + tenderly?: boolean; + includeTestnetPremigrationRegistrar?: boolean; + deferV1OwnerTransactions?: boolean; + deferredV1OwnerTransactionsFile?: string; + cleanTestnet?: boolean; + deployer?: AccountDefinition; + deployerPrivateKey?: `0x${string}`; + owner?: AccountDefinition; + ownerPrivateKey?: `0x${string}`; + urManager?: AccountDefinition; + urManagerPrivateKey?: `0x${string}`; + v1Owner?: AccountDefinition; + v1OwnerPrivateKey?: `0x${string}`; + impersonateV1Owner?: boolean; + rpcCompatibility?: boolean; + debugRpc?: boolean; + provider?: RpcProvider; +}; + +type DeployV1Options = { + network: MigrationNetwork; + rpcUrl?: string; + chainId?: string; + deploymentsDir?: string; + deploymentNetwork?: string; + saveDeployments?: boolean; + tenderly?: boolean; + deployer?: AccountDefinition; + deployerPrivateKey?: `0x${string}`; + owner?: AccountDefinition; + ownerPrivateKey?: `0x${string}`; + rpcCompatibility?: boolean; + debugRpc?: boolean; + provider?: RpcProvider; +}; + +type RunForkFullOptions = { + network: MigrationNetwork; + rpcUrl?: string; + provider?: RpcProvider; + direct?: boolean; + chainId?: string; + port?: string; + csvFile: string; + batchSize?: string; + initialLimit?: string; + finishLimit?: string; + workDir?: string; + saveDeployments?: boolean; + deploymentsDir?: string; + deploymentNetwork?: string; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + tenderly?: boolean; + includeTestnetPremigrationRegistrar?: boolean; + cleanTestnet?: boolean; + rpcStateControls?: boolean; + debugRpc?: boolean; + keepAnvil?: boolean; + snapshotFile?: string; + deployer?: Address; + deployerPrivateKey?: `0x${string}`; + owner?: Address; + ownerPrivateKey?: `0x${string}`; + v1Owner?: Address; + v1OwnerPrivateKey?: `0x${string}`; + urManager?: Address; + urManagerPrivateKey?: `0x${string}`; + resumeFromPhase?: string; +}; + +type RunCleanTestnetFullOptions = Omit< + RunForkFullOptions, + "csvFile" | "resumeFromPhase" | "direct" | "keepAnvil" +> & { + csvFile?: string; + resumeExistingDeployments?: boolean; +}; + +function uniqueTags(tags: readonly (string | undefined)[]): string[] { + return [...new Set(tags.filter((tag): tag is string => Boolean(tag)))]; +} + +function normalizeAccountAddress(value: AccountDefinition): AccountDefinition { + if ( + typeof value === "string" && + value.startsWith("0x") && + value.length === 42 + ) { + return value.toLowerCase() as Address; + } + return value; +} + +function normalizeAccountType(value: AccountType): AccountType { + if (typeof value === "object" && value !== null && !Array.isArray(value)) { + return Object.fromEntries( + Object.entries(value).map(([key, account]) => [ + key, + normalizeAccountAddress(account as AccountDefinition), + ]), + ) as AccountType; + } + return normalizeAccountAddress(value as AccountDefinition); +} + +function signerAccountDefinition( + privateKey: `0x${string}` | undefined, + fallback: AccountDefinition | undefined, +): AccountDefinition | undefined { + return privateKey + ? (`privateKey:${privateKey}` as AccountDefinition) + : fallback; +} + +function keyAddress( + privateKey: `0x${string}` | undefined, +): Address | undefined { + return privateKey ? privateKeyToAccount(privateKey).address : undefined; +} + +function privateKeyForAddress( + address: Address, + keys: PrivateKeyOptions, +): `0x${string}` | undefined { + const expected = getAddress(address); + const entries = [ + keys.deployerPrivateKey, + keys.ownerPrivateKey, + keys.v1OwnerPrivateKey, + keys.urManagerPrivateKey, + ]; + return entries.find((privateKey) => { + const account = keyAddress(privateKey); + return account !== undefined && getAddress(account) === expected; + }); +} + +function requirePrivateKeyForAddress( + address: Address, + keys: PrivateKeyOptions, + label: string, +): `0x${string}` { + const privateKey = privateKeyForAddress(address, keys); + if (!privateKey) { + throw new Error( + `${label} ${address} is not backed by a configured private key`, + ); + } + return privateKey; +} + +function applyAccountOverride( + accounts: Record, + name: string, + value: AccountDefinition | undefined, +) { + if (value !== undefined) { + accounts[name] = { default: normalizeAccountAddress(value) }; + } +} + +// Returns the first candidate key that controls `target`, or — when no target +// address is known — the first available key. Used so an owner/admin private +// key is only applied when it actually signs for the resolved account, keeping +// an explicit or network-default owner (e.g. the mainnet DAO) from being +// silently replaced by a fallback deployer key. +function signerKeyForAccount( + target: Address | undefined, + candidates: Array<`0x${string}` | undefined>, +): `0x${string}` | undefined { + const keys = candidates.filter((key): key is `0x${string}` => Boolean(key)); + if (!target) return keys[0]; + return keys.find( + (key) => getAddress(privateKeyToAccount(key).address) === getAddress(target), + ); +} + +// Resolve env-configured signer keys for the standalone rehearsal CLIs, attaching +// each key only when it controls the requested account so an env key is never used +// to sign for a different address. Used by the direct/real-RPC paths that lack the +// impersonation a local node or Tenderly fork would provide. +function envMigrationSignerKeys(accounts: { + deployer?: Address; + owner?: Address; + v1Owner?: Address; + urManager?: Address; +}): PrivateKeyOptions { + const deployerKey = envPrivateKey("DEPLOYER_KEY"); + return { + deployerPrivateKey: signerKeyForAccount(accounts.deployer, [deployerKey]), + ownerPrivateKey: signerKeyForAccount(accounts.owner, [ + envPrivateKey("OWNER_KEY"), + deployerKey, + ]), + v1OwnerPrivateKey: signerKeyForAccount(accounts.v1Owner, [ + envPrivateKey("SEPOLIA_V1_OWNER_KEY", "V1_OWNER_KEY"), + deployerKey, + ]), + urManagerPrivateKey: signerKeyForAccount(accounts.urManager, [ + envPrivateKey("UR_MANAGER_KEY"), + deployerKey, + ]), + }; +} + +function addressForImpersonation( + account: AccountDefinition | undefined, + fallback: Address, + name: string, +): Address { + if (account === undefined) return fallback; + if ( + typeof account === "string" && + account.startsWith("0x") && + account.length === 42 + ) { + return getAddress(account) as Address; + } + throw new Error( + `${name} impersonation requires an address or omitted account override`, + ); +} + +function chainIdOverrideProvider( + provider: RpcProvider, + chainId: number, +): RpcProvider { + return { + async request(args) { + if (args.method === "eth_chainId") { + return `0x${chainId.toString(16)}`; + } + return provider.request(args); + }, + }; +} + +function buildDeployV2RockethConfig( + opts: DeployV2Options, + chainId: number, + chain: Chain, +): UserConfig { + const network = NETWORKS[opts.network]; + const deploymentNetwork = opts.deploymentNetwork ?? network.environment; + const baseConfig = rockethConfig as UserConfig; + const impersonatedV1Owner = opts.impersonateV1Owner + ? addressForImpersonation(opts.v1Owner, network.defaultV1Owner, "v1Owner") + : undefined; + const signerProvider = impersonatedV1Owner + ? impersonationProvider(opts) + : undefined; + const accounts = Object.fromEntries( + Object.entries(baseConfig.accounts ?? {}).map(([name, account]) => [ + name, + normalizeAccountType(account as AccountType), + ]), + ) as Record; + applyAccountOverride( + accounts, + "deployer", + signerAccountDefinition(opts.deployerPrivateKey, opts.deployer), + ); + applyAccountOverride( + accounts, + "owner", + signerAccountDefinition(opts.ownerPrivateKey, opts.owner), + ); + applyAccountOverride( + accounts, + "urManager", + signerAccountDefinition(opts.urManagerPrivateKey, opts.urManager), + ); + applyAccountOverride( + accounts, + "v1Owner", + signerAccountDefinition(opts.v1OwnerPrivateKey, opts.v1Owner), + ); + if (impersonatedV1Owner) { + accounts.v1Owner = { + default: `impersonate:${impersonatedV1Owner.toLowerCase()}`, + }; + } + + const baseEnvironments = baseConfig.environments ?? {}; + const baseEnvironment = baseEnvironments[network.environment] ?? {}; + const baseEnvironmentTags = baseEnvironment.overrides?.tags ?? []; + const baseChainTags = [ + ...(baseConfig.chains?.[network.chain.id]?.tags ?? []), + ...(baseConfig.chains?.[chainId]?.tags ?? []), + ]; + const tags = uniqueTags([ + opts.network === "sepolia" ? "sepolia" : undefined, + "deferV2Registrar", + opts.tenderly ? "tenderly" : undefined, + opts.includeTestnetPremigrationRegistrar + ? "testnet-premigration-registrar" + : undefined, + opts.cleanTestnet ? "clean-testnet" : undefined, + ...network.chainTags, + ...baseChainTags, + ...baseEnvironmentTags, + ]); + + return { + ...baseConfig, + deployments: resolve( + opts.deploymentsDir ?? baseConfig.deployments ?? DEFAULT_DEPLOYMENTS_DIR, + ), + accounts, + signerProtocols: { + ...(baseConfig.signerProtocols ?? {}), + ...(opts.rpcUrl + ? { privateKey: privateKeySignerProtocol(opts.rpcUrl, chain) } + : {}), + ...(impersonatedV1Owner && signerProvider + ? { + impersonate: async (protocolString: string) => { + const address = getAddress( + protocolString.slice("impersonate:".length), + ).toLowerCase() as Address; + return { + type: "remote", + signer: impersonatedAccountProvider(signerProvider, address), + }; + }, + } + : {}), + } as any, + chains: { + ...(baseConfig.chains ?? {}), + [chainId]: { + ...(baseConfig.chains?.[network.chain.id] ?? {}), + ...(baseConfig.chains?.[chainId] ?? {}), + info: chain, + ...(opts.rpcUrl ? { rpcUrl: opts.rpcUrl } : {}), + tags, + }, + }, + environments: { + ...baseEnvironments, + [deploymentNetwork]: { + ...baseEnvironment, + chain: chainId, + scripts: baseEnvironment.scripts ?? ["deploy"], + overrides: { + ...baseEnvironment.overrides, + tags, + }, + }, + }, + }; +} + +function buildDeployV1RockethConfig( + opts: DeployV1Options, + chainId: number, + chain: Chain, +): UserConfig { + const network = NETWORKS[opts.network]; + const deploymentNetwork = opts.deploymentNetwork ?? network.environment; + const baseConfig = rockethConfig as UserConfig; + const accounts = Object.fromEntries( + Object.entries(baseConfig.accounts ?? {}).map(([name, account]) => [ + name, + normalizeAccountType(account as AccountType), + ]), + ) as Record; + applyAccountOverride( + accounts, + "deployer", + signerAccountDefinition(opts.deployerPrivateKey, opts.deployer), + ); + applyAccountOverride( + accounts, + "owner", + signerAccountDefinition(opts.ownerPrivateKey, opts.owner), + ); + + const tags = uniqueTags([ + "test", + "legacy", + "use_root", + opts.tenderly ? "tenderly" : undefined, + opts.tenderly ? "allow_unsafe" : undefined, + ]); + + return { + ...baseConfig, + deployments: resolve(opts.deploymentsDir ?? LOCAL_V1_DEPLOYMENTS_DIR), + accounts, + signerProtocols: { + ...(baseConfig.signerProtocols ?? {}), + ...(opts.rpcUrl + ? { privateKey: privateKeySignerProtocol(opts.rpcUrl, chain) } + : {}), + }, + chains: { + ...(baseConfig.chains ?? {}), + [chainId]: { + ...(baseConfig.chains?.[network.chain.id] ?? {}), + ...(baseConfig.chains?.[chainId] ?? {}), + info: chain, + ...(opts.rpcUrl ? { rpcUrl: opts.rpcUrl } : {}), + tags, + }, + }, + environments: { + ...(baseConfig.environments ?? {}), + [deploymentNetwork]: { + chain: chainId, + scripts: ["lib/ens-contracts/deploy"], + overrides: { tags }, + }, + }, + }; +} + +async function waitForSuccessfulReceipt( + client: ReturnType, + hash: `0x${string}`, + label: string, +) { + const receipt = await client.waitForTransactionReceipt({ hash }); + if (receipt.status === "reverted") { + throw new Error(`${label} reverted: ${hash}`); + } + return receipt; +} + +// Normalize the provider (RPC-compatibility shim, chain-id override) and resolve +// the chain id and chain, shared by the v1 and v2 deploy entrypoints. +async function resolveDeployProviderAndChain(opts: { + network: MigrationNetwork; + rpcUrl?: string; + chainId?: string; + provider?: RpcProvider; + rpcCompatibility?: boolean; + debugRpc?: boolean; +}): Promise<{ provider?: RpcProvider; chainId: number; chain: Chain }> { + const network = NETWORKS[opts.network]; + if (!opts.rpcUrl && !opts.provider) { + throw new Error("Missing rpcUrl or provider"); + } + let provider = + opts.provider && opts.rpcCompatibility + ? withRpcCompatibility(opts.provider, Boolean(opts.debugRpc)) + : opts.provider; + const chainId = opts.chainId + ? parseNumber(opts.chainId, network.chain.id) + : provider + ? await getProviderChainId(provider) + : network.chain.id; + if (provider && opts.chainId) { + provider = chainIdOverrideProvider(provider, chainId); + } + const chain = forkChain( + opts.network, + chainId, + opts.rpcUrl ?? network.chain.rpcUrls.default.http[0], + ); + return { provider, chainId, chain }; +} + +// Print each deployed contract's address, or a placeholder when the artifact is +// absent from the namespace. +function logDeployedAddresses( + env: { get(name: string): { address: Address } }, + names: readonly string[], + prefix = "", +): void { + for (const name of names) { + try { + console.log(`${prefix}${name}: ${env.get(name).address}`); + } catch { + console.log(`${prefix}${name}: `); + } + } +} + +async function deployV1(opts: DeployV1Options) { + const network = NETWORKS[opts.network]; + const deploymentNetwork = opts.deploymentNetwork ?? network.environment; + const { provider, chainId, chain } = + await resolveDeployProviderAndChain(opts); + const env = await loadAndExecuteDeploymentsFromFilesWithConfig( + { + environment: deploymentNetwork, + askBeforeProceeding: false, + saveDeployments: Boolean(opts.saveDeployments), + provider: provider as any, + }, + buildDeployV1RockethConfig(opts, chainId, chain), + ); + + logDeployedAddresses( + env, + [ + "ENSRegistry", + "Root", + "BaseRegistrarImplementation", + "RegistrarSecurityController", + "ReverseRegistrar", + "DefaultReverseRegistrar", + "NameWrapper", + "PublicResolver", + "BatchGatewayProvider", + "UniversalResolver", + "MigrationHelper", + ], + "v1 ", + ); + + return env; +} + +export async function deployV2(opts: DeployV2Options) { + const network = NETWORKS[opts.network]; + const deploymentNetwork = opts.deploymentNetwork ?? network.environment; + const deploymentsDir = resolve(opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR); + // A fresh deployment archives any existing namespace and therefore must + // persist the new one, so it implies saving regardless of the flag. + const persist = Boolean(opts.saveDeployments) || Boolean(opts.fresh); + const { provider, chainId, chain } = + await resolveDeployProviderAndChain(opts); + if (opts.deferV1OwnerTransactions && !opts.deferredV1OwnerTransactionsFile) { + throw new Error( + "deferring v1 owner transactions requires an output file; pass --deferred-v1-owner-transactions-file so the deferred calldata is persisted for execute-owner-txs", + ); + } + if (opts.deferredV1OwnerTransactionsFile) { + const file = resolve(opts.deferredV1OwnerTransactionsFile); + mkdirSync(dirname(file), { recursive: true }); + writeFileSync(file, ""); + } + if (opts.impersonateV1Owner) { + const v1Owner = addressForImpersonation( + opts.v1Owner, + network.defaultV1Owner, + "v1Owner", + ); + await impersonate(impersonationProvider(opts) ?? provider!, v1Owner); + } + + if (opts.fresh) { + archiveExistingDeploymentNamespace(deploymentsDir, deploymentNetwork); + } + + const env = await loadAndExecuteDeploymentsFromFilesWithConfig( + { + environment: deploymentNetwork, + askBeforeProceeding: false, + saveDeployments: persist, + tags: opts.tags ? [...opts.tags] : [...MIGRATION_DEPLOY_TAGS], + provider: provider as any, + extra: { + v1DeploymentsDir: opts.v1DeploymentsDir, + v1DeploymentNetwork: + opts.v1DeploymentNetwork ?? + (opts.deploymentNetwork ? network.environment : undefined), + deferV1OwnerTransactions: opts.deferV1OwnerTransactions, + deferredV1OwnerTransactionsFile: opts.deferredV1OwnerTransactionsFile, + }, + }, + buildDeployV2RockethConfig(opts, chainId, chain), + ); + + if (persist) { + recordDeploymentMetadata(deploymentsDir, deploymentNetwork, chainId); + } + + logDeployedAddresses(env, [ + "ETHRegistry", + "UserRegistryImpl", + "PermissionedResolverImpl", + "BatchRegistrar", + "ENSV1Resolver", + "ETHRegistrar", + "ETHRenewerV1", + "UnlockedMigrationController", + "LockedMigrationController", + "UniversalResolverV2", + "ManagedUniversalResolverProxy", + "UpgradableUniversalResolverProxy", + "ReverseRegistrarAdapter", + "DefaultReverseRegistrarAdapter", + ]); + + // Refresh the generated address table for a persisted deploy so the docs + // track the namespace just written. Fork/non-persisted rehearsals are skipped. + if (persist) { + const docPath = await generateAddressMarkdown({ + deploymentsDir, + namespace: deploymentNetwork, + docName: opts.network, + }); + console.log(`address docs: ${docPath}`); + } + + return env; +} + +async function registerViaV1Controller({ + network, + rpcUrl, + chain, + provider, + v1DeploymentsDir, + v1DeploymentNetwork, + label, + owner, + privateKey, + account, + useRpcStateControls = true, +}: { + network: MigrationNetwork; + rpcUrl: string; + chain: Chain; + provider?: RpcProvider; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + label: string; + owner: Address; + privateKey?: `0x${string}`; + account?: Address; + useRpcStateControls?: boolean; +}) { + const client = publicClient(rpcUrl, chain, provider); + const wallet = walletClient({ rpcUrl, chain, privateKey, account, provider }); + const controller = requireV1Deployment(network, "ETHRegistrarController", { + v1DeploymentsDir, + v1DeploymentNetwork, + }); + const registration = { + label, + owner, + duration: V1_REGISTRATION_DURATION, + secret: zeroHash, + resolver: zeroAddress, + data: [], + reverseRecord: 0, + referrer: zeroHash, + }; + const commitment = (await client.readContract({ + address: controller.address, + abi: controller.abi, + functionName: "makeCommitment", + args: [registration], + })) as `0x${string}`; + let hash = await wallet.writeContract({ + address: controller.address, + abi: controller.abi, + functionName: "commit", + args: [commitment], + }); + await waitForSuccessfulReceipt(client, hash, `v1 commit ${label}.eth`); + const minCommitmentAge = (await client.readContract({ + address: controller.address, + abi: controller.abi, + functionName: "minCommitmentAge", + })) as bigint; + await waitForCommitmentAge( + client, + minCommitmentAge + 1n, + useRpcStateControls, + ); + const price = (await client.readContract({ + address: controller.address, + abi: controller.abi, + functionName: "rentPrice", + args: [label, V1_REGISTRATION_DURATION], + })) as { base: bigint; premium: bigint }; + hash = await wallet.writeContract({ + address: controller.address, + abi: controller.abi, + functionName: "register", + args: [registration], + value: price.base + price.premium, + }); + await waitForSuccessfulReceipt(client, hash, `v1 register ${label}.eth`); +} + +async function assertV1Owner({ + network, + rpcUrl, + chain, + provider, + v1DeploymentsDir, + v1DeploymentNetwork, + label, + owner, +}: { + network: MigrationNetwork; + rpcUrl: string; + chain: Chain; + provider?: RpcProvider; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + label: string; + owner: Address; +}) { + const actualOwner = await readV1Owner({ + network, + rpcUrl, + chain, + provider, + v1DeploymentsDir, + v1DeploymentNetwork, + label, + }); + if (getAddress(actualOwner) !== getAddress(owner)) { + throw new Error(`unexpected v1 owner for ${label}.eth: ${actualOwner}`); + } +} + +async function readV1Owner({ + network, + rpcUrl, + chain, + provider, + v1DeploymentsDir, + v1DeploymentNetwork, + label, +}: { + network: MigrationNetwork; + rpcUrl: string; + chain: Chain; + provider?: RpcProvider; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + label: string; +}) { + const client = publicClient(rpcUrl, chain, provider); + const baseRegistrar = requireV1Deployment( + network, + "BaseRegistrarImplementation", + { + v1DeploymentsDir, + v1DeploymentNetwork, + }, + ); + return (await client.readContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "ownerOf", + args: [labelId(label)], + })) as Address; +} + +function errorMessageChain(error: unknown): string[] { + const messages: string[] = []; + let current: unknown = error; + while (current !== undefined && current !== null && messages.length < 10) { + messages.push(current instanceof Error ? current.message : String(current)); + current = current instanceof Error ? current.cause : undefined; + } + return messages; +} + +/** + * Asserts that `promise` rejects. When `expectedError` is given, the rejection's + * message/cause chain must match it; otherwise unrelated failures (RPC outages, + * wrong signer, ...) would make a negative test "pass" for the wrong reason. + */ +async function assertRejected( + promise: Promise, + message: string, + expectedError?: string | RegExp, +) { + let rejection: unknown; + let rejected = false; + try { + await promise; + } catch (error) { + rejection = error; + rejected = true; + } + if (!rejected) { + throw new Error(message.replace("rejected", "did not reject")); + } + const chain = errorMessageChain(rejection); + if (expectedError !== undefined) { + const matches = chain.some((candidate) => + typeof expectedError === "string" + ? candidate.includes(expectedError) + : expectedError.test(candidate), + ); + if (!matches) { + console.error(`unexpected rejection: ${chain.join(" <- ")}`); + throw new Error( + `${message.replace("rejected", "rejected for an unexpected reason")}; expected ${expectedError}, got: ${chain[0] ?? String(rejection)}`, + ); + } + } + console.log(message); + console.log(` rejection: ${chain[0] ?? String(rejection)}`); +} + +async function assertV2State({ + rpcUrl, + chain, + ethRegistry, + label, + status, + owner, +}: { + rpcUrl: string; + chain: Chain; + ethRegistry: JsonDeployment; + label: string; + status: number; + owner?: Address; +}) { + const client = publicClient(rpcUrl, chain); + const state = (await client.readContract({ + address: ethRegistry.address, + abi: ethRegistry.abi, + functionName: "getState", + args: [labelId(label)], + })) as { status: number; latestOwner: Address }; + if (Number(state.status) !== status) { + throw new Error(`unexpected v2 status for ${label}.eth: ${state.status}`); + } + if (owner && getAddress(state.latestOwner) !== getAddress(owner)) { + throw new Error( + `unexpected v2 owner for ${label}.eth: ${state.latestOwner}`, + ); + } +} + +async function migrateUnwrappedV1Name({ + network, + rpcUrl, + chain, + provider, + v1DeploymentsDir, + v1DeploymentNetwork, + label, + owner, + privateKey, + account, + impersonateAccount, + migrationController, +}: { + network: MigrationNetwork; + rpcUrl: string; + chain: Chain; + provider?: RpcProvider; + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; + label: string; + owner: Address; + privateKey?: `0x${string}`; + account?: Address; + impersonateAccount?: Address; + migrationController: JsonDeployment; +}) { + const client = publicClient(rpcUrl, chain, provider); + if (impersonateAccount) await impersonate(client, impersonateAccount); + const wallet = walletClient({ + rpcUrl, + chain, + privateKey, + account: account ?? impersonateAccount, + provider, + }); + const v1Deployments = { v1DeploymentsDir, v1DeploymentNetwork }; + const registry = requireV1Deployment(network, "ENSRegistry", v1Deployments); + const baseRegistrar = requireV1Deployment( + network, + "BaseRegistrarImplementation", + v1Deployments, + ); + const resolver = (await client.readContract({ + address: registry.address, + abi: registry.abi, + functionName: "resolver", + args: [namehash(`${label}.eth`)], + })) as Address; + const data = encodeAbiParameters( + [{ type: "tuple", components: migrationDataComponents }], + [{ label, owner, subregistry: zeroAddress, resolver }], + ); + const hash = await wallet.writeContract({ + address: baseRegistrar.address, + abi: baseRegistrar.abi, + functionName: "safeTransferFrom", + args: [owner, migrationController.address, labelId(label), data], + }); + await waitForSuccessfulReceipt(client, hash, `v2 commit ${label}.eth`); +} + +async function registerViaV2Registrar({ + rpcUrl, + chain, + label, + owner, + privateKey, + ethRegistrar, + mockUsdc, + useRpcStateControls = true, +}: { + rpcUrl: string; + chain: Chain; + label: string; + owner: Address; + privateKey: `0x${string}`; + ethRegistrar: JsonDeployment; + mockUsdc: JsonDeployment; + useRpcStateControls?: boolean; +}) { + const client = publicClient(rpcUrl, chain); + const wallet = walletClient({ rpcUrl, chain, privateKey }); + const payer = privateKeyToAccount(privateKey).address; + const commitment = (await client.readContract({ + address: ethRegistrar.address, + abi: ethRegistrar.abi, + functionName: "makeCommitment", + args: [ + label, + owner, + zeroHash, + zeroAddress, + zeroAddress, + V2_REGISTRATION_DURATION, + zeroHash, + ], + })) as `0x${string}`; + let hash = await wallet.writeContract({ + address: ethRegistrar.address, + abi: ethRegistrar.abi, + functionName: "commit", + args: [commitment], + }); + await waitForSuccessfulReceipt(client, hash, `v2 commit ${label}.eth`); + const minCommitmentAge = (await client.readContract({ + address: ethRegistrar.address, + abi: ethRegistrar.abi, + functionName: "MIN_COMMITMENT_AGE", + })) as bigint; + await waitForCommitmentAge( + client, + minCommitmentAge + 1n, + useRpcStateControls, + ); + const [base, premium] = (await client.readContract({ + address: ethRegistrar.address, + abi: ethRegistrar.abi, + functionName: "getRegisterPrice", + args: [label, V2_REGISTRATION_DURATION, mockUsdc.address], + })) as [bigint, bigint]; + hash = await wallet.writeContract({ + address: mockUsdc.address, + abi: mockUsdc.abi, + functionName: "mint", + args: [payer, base + premium], + }); + await waitForSuccessfulReceipt( + client, + hash, + `mint payment token for ${label}.eth`, + ); + hash = await wallet.writeContract({ + address: mockUsdc.address, + abi: mockUsdc.abi, + functionName: "approve", + args: [ethRegistrar.address, base + premium], + }); + await waitForSuccessfulReceipt( + client, + hash, + `approve payment token for ${label}.eth`, + ); + hash = await wallet.writeContract({ + address: ethRegistrar.address, + abi: ethRegistrar.abi, + functionName: "register", + args: [ + label, + owner, + zeroHash, + zeroAddress, + zeroAddress, + V2_REGISTRATION_DURATION, + mockUsdc.address, + zeroHash, + ], + }); + await waitForSuccessfulReceipt(client, hash, `v2 register ${label}.eth`); +} + +type V2RegistrarSmokeOptions = { + network: MigrationNetwork; + rpcUrl?: string; + chainId?: string; + deploymentsDir?: string; + deploymentNetwork?: string; + label?: string; + owner?: Address; + privateKey: `0x${string}`; + rpcStateControls?: boolean; +}; + +export async function runV2RegistrarSmoke(opts: V2RegistrarSmokeOptions) { + const network = NETWORKS[opts.network]; + const rpcUrl = requireRpcUrl(opts, opts.network); + const chainId = parseNumber(opts.chainId, network.chain.id); + const chain = forkChain(opts.network, chainId, rpcUrl); + const deploymentsDir = resolve( + opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR, + ); + const deploymentNetwork = opts.deploymentNetwork ?? network.environment; + const client = publicClient(rpcUrl, chain); + const owner = opts.owner ?? privateKeyToAccount(opts.privateKey).address; + const label = + opts.label ?? + `${opts.network === "mainnet" ? "mf" : "sf"}${Date.now().toString(36)}v2ok`; + const ethRegistry = loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "ETHRegistry", + ); + const ethRegistrar = loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "ETHRegistrar", + ); + const mockUsdc = maybeLoadV2Deployment( + deploymentsDir, + deploymentNetwork, + "MockUSDC", + ); + if (!mockUsdc) { + throw new Error( + `v2 registrar smoke needs a mintable mock payment token, which is not deployed for ${deploymentNetwork}; on networks with real payment tokens, fund a whitelisted token and register directly`, + ); + } + + const enabled = (await client.readContract({ + address: ethRegistry.address, + abi: ethRegistry.abi, + functionName: "hasRootRoles", + args: [REGISTRAR_ROLES, ethRegistrar.address], + })) as boolean; + if (!enabled) { + throw new Error(`ETHRegistrar is not enabled for ${deploymentNetwork}`); + } + + const available = (await client.readContract({ + address: ethRegistrar.address, + abi: ethRegistrar.abi, + functionName: "isAvailable", + args: [label], + })) as boolean; + if (!available) { + throw new Error(`${label}.eth is not available for v2 registration smoke`); + } + + console.log( + `smoke: registering ${label}.eth via ETHRegistrar ${ethRegistrar.address}`, + ); + await registerViaV2Registrar({ + rpcUrl, + chain, + label, + owner, + privateKey: opts.privateKey, + ethRegistrar, + mockUsdc, + useRpcStateControls: opts.rpcStateControls ?? false, + }); + await assertV2State({ + rpcUrl, + chain, + ethRegistry, + label, + status: STATUS.REGISTERED, + owner, + }); + console.log(`v2 registrar registered ${label}.eth for ${owner}`); +} + +type V2MigrationDeployments = { + ethRegistry: JsonDeployment; + batchRegistrar: JsonDeployment; + ensV1Resolver: JsonDeployment; + ethRegistrar: JsonDeployment; + ethRenewerV1: JsonDeployment | null; + mockUsdc: JsonDeployment | null; + unlockedMigrationController: JsonDeployment; + universalResolverV2: JsonDeployment; + managedUrp: JsonDeployment; + topUrp: JsonDeployment; + graveyard: JsonDeployment; + testnetV1PremigrationRegistrar: JsonDeployment | null; +}; + +function loadV2MigrationDeployments( + deploymentsDir: string, + deploymentNetwork: string, +): V2MigrationDeployments { + return { + ethRegistry: loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "ETHRegistry", + ), + batchRegistrar: loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "BatchRegistrar", + ), + ensV1Resolver: loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "ENSV1Resolver", + ), + ethRegistrar: loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "ETHRegistrar", + ), + ethRenewerV1: maybeLoadV2Deployment( + deploymentsDir, + deploymentNetwork, + "ETHRenewerV1", + ), + mockUsdc: maybeLoadV2Deployment(deploymentsDir, deploymentNetwork, "MockUSDC"), + unlockedMigrationController: loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "UnlockedMigrationController", + ), + universalResolverV2: loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "UniversalResolverV2", + ), + managedUrp: loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "ManagedUniversalResolverProxy", + ), + topUrp: loadV2Deployment( + deploymentsDir, + deploymentNetwork, + "UpgradableUniversalResolverProxy", + ), + graveyard: loadV2Deployment(deploymentsDir, deploymentNetwork, "Graveyard"), + testnetV1PremigrationRegistrar: maybeLoadV2Deployment( + deploymentsDir, + deploymentNetwork, + "TestnetV1PremigrationRegistrar", + ), + }; +} + +function collectV2MigrationDeployments( + deployEnv: Awaited>, +): V2MigrationDeployments { + return { + ethRegistry: deployEnv.get("ETHRegistry"), + batchRegistrar: deployEnv.get("BatchRegistrar"), + ensV1Resolver: deployEnv.get("ENSV1Resolver"), + ethRegistrar: deployEnv.get("ETHRegistrar"), + ethRenewerV1: deployEnv.getOrNull("ETHRenewerV1"), + mockUsdc: deployEnv.getOrNull("MockUSDC"), + unlockedMigrationController: deployEnv.get("UnlockedMigrationController"), + universalResolverV2: deployEnv.get("UniversalResolverV2"), + managedUrp: deployEnv.get("ManagedUniversalResolverProxy"), + topUrp: deployEnv.get("UpgradableUniversalResolverProxy"), + graveyard: deployEnv.get("Graveyard"), + testnetV1PremigrationRegistrar: deployEnv.getOrNull( + "TestnetV1PremigrationRegistrar", + ), + }; +} + +async function disableAndVerifyBatchRegistrar(opts: { + network: MigrationNetwork; + rpcUrl: string; + chainId: string; + registry: Address; + batchRegistrar: Address; + deploymentsDir: string; + deploymentNetwork: string; + privateKey?: `0x${string}`; + impersonateAccount?: Address; +}) { + await disableBatchRegistrar(opts); + await verifyBatchRegistrarDisabled(opts); +} + +export async function runForkFull(opts: RunForkFullOptions) { + if (opts.direct || opts.debugRpc) + installRpcCompatibility(Boolean(opts.debugRpc)); + const resumeFromPhase = parseResumeFromPhase(opts.resumeFromPhase); + const network = NETWORKS[opts.network]; + const forkRpcUrl = requireRpcUrl(opts, opts.network); + const port = parseNumber(opts.port, network.defaultForkPort); + const chainId = parseNumber(opts.chainId, network.chain.id); + const rpcUrl = opts.direct ? forkRpcUrl : `http://127.0.0.1:${port}`; + const chain = forkChain(opts.network, chainId, rpcUrl); + const provider = opts.provider; + // State controls (impersonation, time travel, setBalance) are only available on + // simulated RPCs: the local Anvil fork, other local nodes, or Tenderly forks. + const useRpcStateControls = + opts.rpcStateControls ?? (Boolean(opts.tenderly) || isLocalRpcUrl(rpcUrl)); + const keys: PrivateKeyOptions = { + deployerPrivateKey: opts.deployerPrivateKey, + ownerPrivateKey: opts.ownerPrivateKey, + v1OwnerPrivateKey: opts.v1OwnerPrivateKey, + urManagerPrivateKey: opts.urManagerPrivateKey, + }; + const deploymentsDir = resolve( + opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR, + ); + const deploymentNetwork = opts.deploymentNetwork ?? network.environment; + const v1Deployments = { + v1DeploymentsDir: opts.v1DeploymentsDir, + v1DeploymentNetwork: opts.v1DeploymentNetwork, + }; + if (resumeFromPhase !== undefined && !opts.workDir) { + throw new Error("--resume-from-phase requires --work-dir"); + } + const workDir = resolve( + opts.workDir ?? + join(tmpdir(), `enschain-${opts.network}-migration-${Date.now()}`), + ); + mkdirSync(workDir, { recursive: true }); + + const transformedCsv = join(workDir, "premigration.csv"); + if (resumeFromPhase === 2) { + if (!existsSync(transformedCsv)) { + throw new Error( + `Cannot resume phase 2 without existing transformed CSV: ${transformedCsv}`, + ); + } + console.log( + `resuming from phase 2 with pre-migration CSV: ${transformedCsv}`, + ); + } else { + const totalRows = transformCsvForPreMigration( + resolve(opts.csvFile), + transformedCsv, + ); + console.log( + `prepared pre-migration CSV with ${totalRows} labels: ${transformedCsv}`, + ); + } + + const anvil = opts.direct + ? null + : Bun.spawn( + [ + "anvil", + "--fork-url", + forkRpcUrl, + "--host", + "127.0.0.1", + "--port", + String(port), + "--chain-id", + String(chainId), + ], + { stdout: "ignore", stderr: "inherit" }, + ); + + try { + await waitForRpc(rpcUrl, chain); + const client = publicClient(rpcUrl, chain, provider); + if (opts.snapshotFile !== undefined) { + const snapshotId = await createRpcSnapshot(client); + saveRpcSnapshotFile( + opts.snapshotFile, + snapshotId, + opts.direct ? network.environment : `${network.environment}-fork`, + ); + console.log(`pre-rehearsal snapshot: ${snapshotId}`); + console.log(`snapshot file: ${opts.snapshotFile}`); + } + const deployer = + opts.deployer ?? (opts.direct ? undefined : DEFAULT_ANVIL_DEPLOYER); + const owner = + opts.owner ?? + (opts.direct && opts.network === "sepolia" + ? undefined + : network.defaultOwner); + const urManager = + opts.urManager ?? (opts.direct ? undefined : DEFAULT_ANVIL_DEPLOYER); + if (deployer === undefined) { + throw new Error( + "--direct requires --deployer; use the Hardhat fork-full task to derive it from keystore", + ); + } + if (owner === undefined) { + throw new Error( + "--direct on sepolia requires --owner; use the Hardhat fork-full task to derive it from keystore", + ); + } + if (urManager === undefined) { + throw new Error( + "--direct requires --ur-manager; use the Hardhat fork-full task to derive it from keystore", + ); + } + if (!useRpcStateControls && !opts.deployerPrivateKey) { + throw new Error( + "direct migration without RPC state controls requires a deployer private key", + ); + } + const v1Owner = opts.v1Owner ?? network.defaultV1Owner; + if (useRpcStateControls) { + await setBalance(client, DEFAULT_ANVIL_DEPLOYER); + await setBalance(client, deployer); + await setBalance(client, owner); + await setBalance(client, v1Owner); + await setBalance(client, urManager); + } + const generatedSmokePrivateKey = useRpcStateControls + ? generatePrivateKey() + : undefined; + const smokeAccount = generatedSmokePrivateKey + ? privateKeyToAccount(generatedSmokePrivateKey) + : { address: deployer }; + const smokePrivateKey = + generatedSmokePrivateKey ?? + privateKeyForAddress(smokeAccount.address, keys); + const smokeSignerPrivateKey = + smokePrivateKey ?? + (() => { + throw new Error( + `smoke account ${smokeAccount.address} is not backed by a configured private key`, + ); + })(); + if (useRpcStateControls) { + await setBalance(client, smokeAccount.address); + } + if (opts.direct && useRpcStateControls) { + await impersonate(client, DEFAULT_ANVIL_DEPLOYER); + await impersonate(client, deployer); + await impersonate(client, owner); + await impersonate(client, v1Owner); + await impersonate(client, urManager); + } else if ( + useRpcStateControls && + getAddress(deployer) !== getAddress(DEFAULT_ANVIL_DEPLOYER) + ) { + await impersonate(client, deployer); + } + + const v1BaseRegistrar = requireV1Deployment( + opts.network, + "BaseRegistrarImplementation", + v1Deployments, + ); + const v1RegistrarOwner = (await client.readContract({ + address: v1BaseRegistrar.address, + abi: v1BaseRegistrar.abi, + functionName: "owner", + })) as Address; + if (useRpcStateControls) await impersonate(client, v1RegistrarOwner); + + // A chain that has already completed the v1 hand-off (phase 3 disabled the + // v1 registrar controllers) cannot perform a fresh v1 registration, so the + // live-v1 smokes must be skipped. Detect that from the controller state: a + // pristine chain (mainnet today) still exercises them while an + // already-migrated chain (sepolia, or a repeat mainnet run) does not. + const v1Controller = loadV1Deployment( + opts.network, + "ETHRegistrarController", + v1Deployments, + ); + const postMigration = v1Controller + ? !((await client.readContract({ + address: v1BaseRegistrar.address, + abi: v1BaseRegistrar.abi, + functionName: "controllers", + args: [v1Controller.address], + })) as boolean) + : false; + if (postMigration) { + console.log( + "post-migration mode: v1 hand-off already complete; skipping live v1 registration smokes", + ); + } + + let v2Deployments: V2MigrationDeployments; + + if (resumeFromPhase === 2) { + console.log("phase 1: skipped; loading saved v2 deployments"); + v2Deployments = loadV2MigrationDeployments( + deploymentsDir, + deploymentNetwork, + ); + } else { + console.log( + `phase 1: deploy v2 contracts against ${opts.v1DeploymentNetwork ?? network.environment} v1 references`, + ); + const deployEnv = await deployV2({ + network: opts.network, + rpcUrl, + provider, + rpcCompatibility: Boolean(provider), + chainId: String(chainId), + deploymentsDir, + deploymentNetwork, + ...v1Deployments, + saveDeployments: opts.saveDeployments, + tenderly: opts.tenderly, + includeTestnetPremigrationRegistrar: + opts.includeTestnetPremigrationRegistrar, + cleanTestnet: opts.cleanTestnet, + deployer, + deployerPrivateKey: opts.deployerPrivateKey, + owner, + ownerPrivateKey: opts.ownerPrivateKey, + v1Owner, + v1OwnerPrivateKey: opts.v1OwnerPrivateKey, + // When the v1 owner is not backed by a private key, the deploy must + // impersonate it so writes signed as the v1 owner (e.g. repointing the + // .eth resolver) have an unlocked signer on the fork. + impersonateV1Owner: useRpcStateControls && !opts.v1OwnerPrivateKey, + urManager, + urManagerPrivateKey: opts.urManagerPrivateKey, + }); + if (opts.saveDeployments) { + console.log( + `deployment files: ${join(deploymentsDir, deploymentNetwork)}`, + ); + } + + v2Deployments = collectV2MigrationDeployments(deployEnv); + } + const { + ethRegistry, + batchRegistrar, + ensV1Resolver, + ethRegistrar, + ethRenewerV1, + mockUsdc, + unlockedMigrationController, + universalResolverV2, + managedUrp, + topUrp, + graveyard, + testnetV1PremigrationRegistrar, + } = v2Deployments; + + const batchRegistrarOwner = await readBatchRegistrarOwner({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + batchRegistrar: batchRegistrar.address, + }); + console.log(`batch registrar owner: ${batchRegistrarOwner}`); + if ( + useRpcStateControls && + getAddress(batchRegistrarOwner) !== getAddress(DEFAULT_ANVIL_DEPLOYER) + ) { + await impersonate(client, batchRegistrarOwner); + } + const batchRegistrarSigner = useRpcStateControls + ? preMigrationSigner(batchRegistrarOwner) + : { + privateKey: requirePrivateKeyForAddress( + batchRegistrarOwner, + keys, + "BatchRegistrar owner", + ), + }; + const deploymentAdminSigner = useRpcStateControls + ? adminSigner(batchRegistrarOwner) + : { + privateKey: requirePrivateKeyForAddress( + batchRegistrarOwner, + keys, + "deployment admin", + ), + }; + // Signer for the v1-owner-gated controller changes (disable registrars, + // authorize the renewer, hand off ownership). On a fork we impersonate the + // owner; for a live run we require the key that controls it. + const v1OwnerSigner: { impersonateOwner: true } | { privateKey: `0x${string}` } = + useRpcStateControls + ? { impersonateOwner: true } + : { privateKey: requirePrivateKeyForAddress(v1Owner, keys, "v1 owner") }; + + // The migration wraps whatever the canonical top proxy currently serves. + // When reusing a long-lived intermediate URP, the top proxy already fronts + // it and the intermediate URP serves its own implementation (about to be + // upgraded). Otherwise the freshly deployed managed proxy is seeded to the + // top proxy's implementation, so both must report it before the switch. + const baselineImplementation = (await client.readContract({ + address: topUrp.address, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + functionName: "implementation", + })) as Address; + const topAlreadyFrontsManaged = + getAddress(baselineImplementation) === getAddress(managedUrp.address); + await verifyUrp({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + topUrp: topUrp.address, + managedUrp: managedUrp.address, + expectedTopImplementation: baselineImplementation, + ...(topAlreadyFrontsManaged + ? {} + : { expectedManagedImplementation: baselineImplementation }), + }); + + const smokePrefix = `${opts.network === "mainnet" ? "mf" : "sf"}${Date.now().toString(36)}`; + const smokeLabels = + resumeFromPhase === 2 + ? (() => { + const [migrate, reservedOnly] = readPremigrationLabels( + transformedCsv, + 2, + ); + console.log( + `resumed smoke labels: ${migrate}.eth, ${reservedOnly}.eth`, + ); + return { + v1BeforeDisable: `${smokePrefix}pre`, + migrate, + reservedOnly, + v1AfterDisable: `${smokePrefix}block`, + v2BeforeEnable: `${smokePrefix}v2block`, + v2AfterEnable: `${smokePrefix}v2ok`, + }; + })() + : { + v1BeforeDisable: `${smokePrefix}pre`, + migrate: `${smokePrefix}mig`, + reservedOnly: `${smokePrefix}res`, + v1AfterDisable: `${smokePrefix}block`, + v2BeforeEnable: `${smokePrefix}v2block`, + v2AfterEnable: `${smokePrefix}v2ok`, + }; + + let smokeMigrationOwner = smokeAccount.address; + let smokeMigrationPrivateKey: `0x${string}` | undefined = smokePrivateKey; + + const sharedSmokeV1 = { + network: opts.network, + rpcUrl, + chain, + provider, + ...v1Deployments, + }; + const registerSmokeV1 = (label: string) => + registerViaV1Controller({ + ...sharedSmokeV1, + label, + owner: smokeAccount.address, + privateKey: smokePrivateKey, + account: smokePrivateKey ? undefined : smokeAccount.address, + useRpcStateControls, + }); + const assertSmokeV1Owner = (label: string) => + assertV1Owner({ ...sharedSmokeV1, label, owner: smokeAccount.address }); + if (resumeFromPhase === 2) { + smokeMigrationOwner = await readV1Owner({ + network: opts.network, + rpcUrl, + chain, + provider, + ...v1Deployments, + label: smokeLabels.migrate, + }); + smokeMigrationPrivateKey = undefined; + if (useRpcStateControls) await impersonate(client, smokeMigrationOwner); + console.log(`resumed smoke migration owner: ${smokeMigrationOwner}`); + } else if (!postMigration) { + console.log( + "smoke: v1 registration succeeds before registrar disablement", + ); + await registerSmokeV1(smokeLabels.v1BeforeDisable); + await assertSmokeV1Owner(smokeLabels.v1BeforeDisable); + await registerSmokeV1(smokeLabels.migrate); + await assertSmokeV1Owner(smokeLabels.migrate); + await registerSmokeV1(smokeLabels.reservedOnly); + await assertSmokeV1Owner(smokeLabels.reservedOnly); + prependCsvLabels(transformedCsv, [ + smokeLabels.migrate, + smokeLabels.reservedOnly, + ]); + console.log( + `v1 registration succeeded before registrar disablement: ${smokeLabels.v1BeforeDisable}.eth`, + ); + } + + console.log("phase 2: initial pre-migration"); + await runPreMigrationCommand( + { + network: opts.network, + rpcUrl, + mainnetRpcUrl: rpcUrl, + ...v1Deployments, + deploymentNetwork, + registry: ethRegistry.address, + batchRegistrar: batchRegistrar.address, + ...batchRegistrarSigner, + csvFile: transformedCsv, + v1Resolver: ensV1Resolver.address, + v1BaseRegistrar: v1BaseRegistrar.address, + batchSize: opts.batchSize, + limit: opts.initialLimit, + workDir, + }, + resumeFromPhase === 2, + ); + if (!postMigration) { + await assertV2State({ + rpcUrl, + chain, + ethRegistry, + label: smokeLabels.migrate, + status: STATUS.RESERVED, + }); + console.log(`smoke pre-migration reserved ${smokeLabels.migrate}.eth`); + } + + console.log("phase 3: disable v1 registrars"); + await disableV1Registrars({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + provider, + ...v1Deployments, + ...v1OwnerSigner, + }); + if (!postMigration) { + await assertRejected( + registerSmokeV1(smokeLabels.v1AfterDisable), + `v1 registration rejected after registrar disablement: ${smokeLabels.v1AfterDisable}.eth`, + // The disabled controller can no longer mint on the BaseRegistrar, so the + // registration must fail with a revert (at simulation or in the receipt). + /revert/i, + ); + } + + // Re-running against an already-migrated chain leaves the v1 BaseRegistrar + // owned by the prior deployment's ETHRenewerV1; reclaim it to the v1 owner + // before any owner-signed controller change below. (No-op on a pristine + // chain. Live re-migrations use the standalone + // `phase reclaim-v1-registrar-ownership` command beforehand.) + if (useRpcStateControls) { + await reclaimV1RegistrarOwnership({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + provider, + ...v1Deployments, + v1Owner, + impersonateOwner: true, + }); + } + + console.log( + "phase 4: authorize ETHRenewerV1 so unmigrated names stay renewable", + ); + if (!ethRenewerV1) { + throw new Error("missing ETHRenewerV1 deployment for phase 4"); + } + await authorizeV1Renewer({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + provider, + ...v1Deployments, + deploymentsDir, + deploymentNetwork, + ethRenewerV1: ethRenewerV1.address, + ...v1OwnerSigner, + }); + { + const renewerAuthorized = (await client.readContract({ + address: v1BaseRegistrar.address, + abi: v1BaseRegistrar.abi, + functionName: "controllers", + args: [ethRenewerV1.address], + })) as boolean; + if (!renewerAuthorized) { + throw new Error( + "ETHRenewerV1 was not authorized as a v1 BaseRegistrar controller in phase 4", + ); + } + console.log( + "smoke ETHRenewerV1 authorized as a v1 renewal controller", + ); + } + + console.log("phase 5: sync remaining names and finish pre-migration"); + const finalSyncWorkDir = join(workDir, "final-sync"); + await runPreMigrationCommand( + { + network: opts.network, + rpcUrl, + mainnetRpcUrl: rpcUrl, + ...v1Deployments, + deploymentNetwork, + registry: ethRegistry.address, + batchRegistrar: batchRegistrar.address, + ...batchRegistrarSigner, + csvFile: transformedCsv, + v1Resolver: ensV1Resolver.address, + v1BaseRegistrar: v1BaseRegistrar.address, + batchSize: opts.batchSize, + limit: opts.finishLimit, + workDir: finalSyncWorkDir, + }, + existsSync(join(finalSyncWorkDir, "preMigration-checkpoint.json")), + ); + if (!postMigration) { + await assertV2State({ + rpcUrl, + chain, + ethRegistry, + label: smokeLabels.reservedOnly, + status: STATUS.RESERVED, + }); + console.log( + `smoke pre-migration reserved ${smokeLabels.reservedOnly}.eth for registrar rejection`, + ); + + console.log("smoke: migrate a pre-migrated v1 name to v2"); + await migrateUnwrappedV1Name({ + network: opts.network, + rpcUrl, + chain, + provider, + ...v1Deployments, + label: smokeLabels.migrate, + owner: smokeMigrationOwner, + privateKey: smokeMigrationPrivateKey, + ...(smokeMigrationPrivateKey === undefined + ? useRpcStateControls + ? { impersonateAccount: smokeMigrationOwner } + : { account: smokeMigrationOwner } + : {}), + migrationController: unlockedMigrationController, + }); + await assertV2State({ + rpcUrl, + chain, + ethRegistry, + label: smokeLabels.migrate, + status: STATUS.REGISTERED, + owner: smokeMigrationOwner, + }); + console.log(`smoke migration registered ${smokeLabels.migrate}.eth on v2`); + } + + console.log( + "phase 6: enable the v2 controller (disable batch registrar, hand off v1, enable v2 ETHRegistrar)", + ); + await disableAndVerifyBatchRegistrar({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + registry: ethRegistry.address, + batchRegistrar: batchRegistrar.address, + deploymentsDir, + deploymentNetwork, + ...deploymentAdminSigner, + }); + if (testnetV1PremigrationRegistrar) { + console.log( + `testnet premigration registrar remains enabled: ${testnetV1PremigrationRegistrar.address}`, + ); + } + + await activateV1HandoffControllers({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + provider, + ...v1Deployments, + deploymentsDir, + deploymentNetwork, + graveyard: graveyard.address, + testnetV1PremigrationRegistrar: testnetV1PremigrationRegistrar?.address, + ...v1OwnerSigner, + }); + + // Final lock-down of the v1 BaseRegistrar: hand its ownership to + // ETHRenewerV1. This must follow the owner-signed handoff-controller grants + // above, since the EOA can no longer manage controllers once ownership moves. + await activateV1RenewerAndTransferOwnership({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + provider, + ...v1Deployments, + deploymentsDir, + deploymentNetwork, + ethRenewerV1: ethRenewerV1.address, + ...v1OwnerSigner, + }); + const beforeEnabled = await client.readContract({ + address: ethRegistry.address, + abi: ethRegistry.abi, + functionName: "hasRootRoles", + args: [REGISTRAR_ROLES, ethRegistrar.address], + }); + if (beforeEnabled) { + throw new Error("v2 registrar was enabled before the final phase"); + } + // The paid-registration smokes need a mintable payment token, which only + // exists on networks that deploy the mock tokens (mainnet whitelists real + // USDC/DAI instead). Where there is no mock, still verify the role grant + // directly and skip the paid registrations. + if (mockUsdc) { + await assertRejected( + registerViaV2Registrar({ + rpcUrl, + chain, + label: smokeLabels.v2BeforeEnable, + owner: smokeAccount.address, + privateKey: smokeSignerPrivateKey, + ethRegistrar, + mockUsdc, + useRpcStateControls, + }), + `v2 registrar rejected registration before enablement: ${smokeLabels.v2BeforeEnable}.eth`, + // The registrar lacks REGISTRAR/RENEW root roles until they are granted. + /revert/i, + ); + } + await enableV2Registrar({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + registry: ethRegistry.address, + ethRegistrar: ethRegistrar.address, + deploymentsDir, + deploymentNetwork, + ...deploymentAdminSigner, + }); + if (mockUsdc) { + if (!postMigration) { + await assertRejected( + registerViaV2Registrar({ + rpcUrl, + chain, + label: smokeLabels.reservedOnly, + owner: smokeAccount.address, + privateKey: smokeSignerPrivateKey, + ethRegistrar, + mockUsdc, + useRpcStateControls, + }), + `v2 registrar rejected pre-migrated reserved name after enablement: ${smokeLabels.reservedOnly}.eth`, + // The name is RESERVED from pre-migration, so registration must revert. + /revert/i, + ); + } + await registerViaV2Registrar({ + rpcUrl, + chain, + label: smokeLabels.v2AfterEnable, + owner: smokeAccount.address, + privateKey: smokeSignerPrivateKey, + ethRegistrar, + mockUsdc, + useRpcStateControls, + }); + await assertV2State({ + rpcUrl, + chain, + ethRegistry, + label: smokeLabels.v2AfterEnable, + status: STATUS.REGISTERED, + owner: smokeAccount.address, + }); + console.log( + `v2 registrar registered ${smokeLabels.v2AfterEnable}.eth after enablement`, + ); + } else { + const afterEnabled = await client.readContract({ + address: ethRegistry.address, + abi: ethRegistry.abi, + functionName: "hasRootRoles", + args: [REGISTRAR_ROLES, ethRegistrar.address], + }); + if (!afterEnabled) { + throw new Error("v2 registrar was not enabled in phase 6"); + } + console.log( + "v2 registrar enabled (paid-registration smoke skipped: no mintable payment token on this network)", + ); + } + + console.log( + "phase 7: switch the Universal Resolver to v2 (resolution cutover)", + ); + // Reuse flow: the top URP already fronts the intermediate URP, so the switch + // is skipped and only the intermediate URP is upgraded below. Bootstrap flow: + // point the top URP at the freshly deployed managed URP first. + if (topAlreadyFrontsManaged) { + console.log( + `top URP already fronts managed URP: ${managedUrp.address}; skipping switch`, + ); + } else { + const topUrpAdmin = (await client.readContract({ + address: topUrp.address, + abi: Artifact_UpgradableUniversalResolverProxy.abi, + functionName: "admin", + })) as Address; + if (getAddress(topUrpAdmin) === getAddress(zeroAddress)) { + throw new Error( + "top URP admin is address(0); cannot impersonate admin for fork switch", + ); + } + console.log(`top URP admin: ${topUrpAdmin}`); + await switchTopUrpToManaged({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + provider, + topUrp: topUrp.address, + managedUrp: managedUrp.address, + ...(useRpcStateControls + ? { impersonateAccount: topUrpAdmin } + : { + privateKey: requirePrivateKeyForAddress( + topUrpAdmin, + keys, + "top URP admin", + ), + }), + }); + console.log(`top URP switched to managed URP: ${managedUrp.address}`); + } + + await upgradeManagedUrp({ + network: opts.network, + rpcUrl, + chainId: String(chainId), + provider, + managedUrp: managedUrp.address, + implementation: universalResolverV2.address, + ...(!useRpcStateControls + ? { + privateKey: requirePrivateKeyForAddress( + urManager, + keys, + "managed URP admin", + ), + } + : urManager === DEFAULT_ANVIL_DEPLOYER + ? { privateKey: DEFAULT_ANVIL_KEY } + : { impersonateAccount: urManager }), + }); + console.log(`managed URP upgraded to: ${universalResolverV2.address}`); + + if (opts.network === "mainnet") { + console.log( + `mainnet DAO simulation used owner/v1Owner impersonation: ${owner}`, + ); + } + console.log(`rehearsal work dir: ${workDir}`); + } finally { + if (anvil && !opts.keepAnvil) { + anvil.kill(); + } + } +} + +export async function runCleanTestnetFull(opts: RunCleanTestnetFullOptions) { + // Clean testnet deploys always run directly against the configured RPC; no local + // Anvil fork is ever spawned. + installRpcCompatibility(Boolean(opts.debugRpc)); + if (opts.network !== "sepolia") { + throw new Error( + "clean testnet full deploy currently supports sepolia only", + ); + } + + const network = NETWORKS[opts.network]; + const forkRpcUrl = requireRpcUrl(opts, opts.network); + const useRpcStateControls = + opts.tenderly || + isLocalRpcUrl(forkRpcUrl) || + isTenderlyVirtualRpc(forkRpcUrl); + if (!useRpcStateControls && !opts.deployerPrivateKey) { + throw new Error( + "clean testnet full deploy requires a configured deployer private key", + ); + } + const chainId = parseNumber(opts.chainId, network.chain.id); + const chain = forkChain(opts.network, chainId, forkRpcUrl); + const client = publicClient(forkRpcUrl, chain, opts.provider); + await waitForRpc(forkRpcUrl, chain); + + const deploymentNetwork = + opts.deploymentNetwork ?? + `${network.environment}-clean-${Date.now().toString(36)}`; + const v1DeploymentNetwork = opts.v1DeploymentNetwork ?? deploymentNetwork; + const v1DeploymentsDir = resolve( + opts.v1DeploymentsDir ?? LOCAL_V1_DEPLOYMENTS_DIR, + ); + const deploymentsDir = resolve( + opts.deploymentsDir ?? DEFAULT_DEPLOYMENTS_DIR, + ); + if (!opts.resumeExistingDeployments) { + assertCleanDeploymentNamespace( + deploymentsDir, + deploymentNetwork, + network.environment, + "v2", + ); + assertCleanDeploymentNamespace( + v1DeploymentsDir, + v1DeploymentNetwork, + network.environment, + "v1", + ); + } + const workDir = resolve( + opts.workDir ?? + join(tmpdir(), `enschain-${deploymentNetwork}-clean-${Date.now()}`), + ); + mkdirSync(workDir, { recursive: true }); + + const deployer = opts.deployer; + if (deployer === undefined) { + throw new Error("clean testnet full deploy requires --deployer"); + } + const owner = opts.owner ?? deployer; + const v1Owner = opts.v1Owner ?? owner; + const urManager = opts.urManager ?? deployer; + + if (useRpcStateControls) { + await setBalance(client, deployer); + await setBalance(client, owner); + await setBalance(client, v1Owner); + await setBalance(client, urManager); + await impersonate(client, deployer); + await impersonate(client, owner); + await impersonate(client, v1Owner); + await impersonate(client, urManager); + } + + console.log(`clean deployment namespace: ${deploymentNetwork}`); + console.log( + `v1 deployment files: ${join(v1DeploymentsDir, v1DeploymentNetwork)}`, + ); + console.log( + `v2 deployment files: ${join(deploymentsDir, deploymentNetwork)}`, + ); + + const v1DeploymentPath = join(v1DeploymentsDir, v1DeploymentNetwork); + const hasExistingV1Deployments = + existsSync(v1DeploymentPath) && + readdirSync(v1DeploymentPath).some((file) => file.endsWith(".json")); + if (opts.resumeExistingDeployments && hasExistingV1Deployments) { + console.log("clean phase 0: skipped; using existing fresh v1 deployments"); + } else { + console.log("clean phase 0: deploy fresh v1 contracts"); + await deployV1({ + network: opts.network, + rpcUrl: forkRpcUrl, + provider: opts.provider, + chainId: String(chainId), + deploymentsDir: v1DeploymentsDir, + deploymentNetwork: v1DeploymentNetwork, + saveDeployments: true, + tenderly: opts.tenderly, + deployer, + deployerPrivateKey: opts.deployerPrivateKey, + owner: v1Owner, + // Only attach a key that actually controls v1Owner; otherwise leave it unset + // so the fresh v1 stack is owned by the impersonated v1Owner rather than the + // deployer (whose key would otherwise be used as a blanket fallback and make + // later v1Owner-impersonated writes revert). + ownerPrivateKey: signerKeyForAccount(v1Owner, [ + opts.v1OwnerPrivateKey, + opts.ownerPrivateKey, + opts.deployerPrivateKey, + ]), + }); + } + + const csvFile = opts.csvFile + ? resolve(opts.csvFile) + : join(workDir, "clean-premigration-source.csv"); + if (!opts.csvFile) { + writeFileSync(csvFile, "labelName\n"); + } + + await runForkFull({ + ...opts, + direct: true, + rpcUrl: forkRpcUrl, + provider: opts.provider, + chainId: String(chainId), + csvFile, + workDir, + deploymentsDir: opts.deploymentsDir, + deploymentNetwork, + v1DeploymentsDir, + v1DeploymentNetwork, + saveDeployments: true, + tenderly: opts.tenderly, + rpcStateControls: useRpcStateControls, + includeTestnetPremigrationRegistrar: true, + cleanTestnet: true, + deployer, + deployerPrivateKey: opts.deployerPrivateKey, + owner, + // Only attach a key that controls the resolved account so an explicit + // --owner/--ur-manager/--v1-owner is not silently signed for by the + // deployer key; unmatched accounts fall back to fork impersonation. + ownerPrivateKey: signerKeyForAccount(owner, [ + opts.ownerPrivateKey, + opts.deployerPrivateKey, + ]), + v1Owner, + v1OwnerPrivateKey: signerKeyForAccount(v1Owner, [ + opts.v1OwnerPrivateKey, + opts.ownerPrivateKey, + opts.deployerPrivateKey, + ]), + urManager, + urManagerPrivateKey: signerKeyForAccount(urManager, [ + opts.urManagerPrivateKey, + opts.deployerPrivateKey, + ]), + resumeFromPhase: undefined, + }); +} + +function addNetworkOptions(command: Command): Command { + return command + .requiredOption("--network ", "Network: sepolia or mainnet") + .option("--rpc-url ", "Network RPC URL") + .option("--chain-id ", "Chain id override"); +} + +function addDeploymentOptions(command: Command): Command { + return command + .option("--deployment-network ", "Deployment directory network name") + .option( + "--deployments-dir ", + "Root directory for v2 deployments", + DEFAULT_DEPLOYMENTS_DIR, + ); +} + +function addV1DeploymentOptions(command: Command): Command { + return command + .option("--v1-deployments-dir ", "Root directory for v1 deployments") + .option( + "--v1-deployment-network ", + "V1 deployment directory network name", + ); +} + +// The signer options shared by every v1-owner-gated write command: a key, fork +// impersonation, or calldata-only preparation for a multisig. +function addV1OwnerWriteOptions(command: Command): Command { + return command + .option("--private-key ", "V1 owner private key") + .option("--impersonate-owner", "Impersonate owner on a fork", false) + .option( + "--calldata-only", + "Print transaction target and calldata", + false, + ); +} + +function assertCleanDeploymentNamespace( + root: string, + environment: string, + canonicalEnvironment: string, + label: string, +) { + if (environment === canonicalEnvironment) { + throw new Error( + `clean testnet deploy refuses to use canonical ${label} namespace: ${environment}`, + ); + } + const path = join(root, environment); + if (!existsSync(path)) return; + const deploymentFiles = readdirSync(path).filter((file) => + file.endsWith(".json"), + ); + if (deploymentFiles.length > 0) { + throw new Error( + `clean testnet deploy refuses to reuse populated ${label} namespace: ${path}`, + ); + } +} + +const DEPLOYMENT_METADATA_FILE = ".deployment.json"; + +// Records when a namespace was first deployed. rocketh ignores dotfiles other +// than `.migrations.json`, so this metadata never interferes with artifact +// loading. Written once so the timestamp reflects the original deployment and +// survives idempotent re-runs; the fresh-deploy archiver reads it back to name +// the archived folder. +function recordDeploymentMetadata( + root: string, + environment: string, + chainId: number, +) { + const dir = join(root, environment); + if (!existsSync(dir)) return; + const metadataPath = join(dir, DEPLOYMENT_METADATA_FILE); + if (existsSync(metadataPath)) return; + writeFileSync( + metadataPath, + `${JSON.stringify( + { environment, chainId, deployedAt: new Date().toISOString() }, + null, + 2, + )}\n`, + ); +} + +// Resolves a namespace's deploy time, preferring the recorded metadata and +// falling back to the latest `.migrations.json` entry (unix-epoch seconds). +function readDeploymentDeployedAt(path: string): string | undefined { + const metadataPath = join(path, DEPLOYMENT_METADATA_FILE); + if (existsSync(metadataPath)) { + try { + const { deployedAt } = JSON.parse(readFileSync(metadataPath, "utf-8")); + if (typeof deployedAt === "string") return deployedAt; + } catch {} + } + const migrationsPath = join(path, ".migrations.json"); + if (existsSync(migrationsPath)) { + try { + const migrations = JSON.parse(readFileSync(migrationsPath, "utf-8")) as + Record; + const timestamps = Object.values(migrations).filter( + (value) => typeof value === "number" && Number.isFinite(value), + ); + if (timestamps.length > 0) { + return new Date(Math.max(...timestamps) * 1000).toISOString(); + } + } catch {} + } + return undefined; +} + +// Moves an existing deployment namespace aside so a fresh deployment can take +// its place. The archive is suffixed with the archived deployment's date and an +// auto-incrementing revision, e.g. `sepolia-20260525-r1`. +function archiveExistingDeploymentNamespace(root: string, environment: string) { + const path = join(root, environment); + if (!existsSync(path)) return; + const hasArtifacts = readdirSync(path).some( + (file) => file.endsWith(".json") || file === ".chain", + ); + if (!hasArtifacts) return; + const deployedAt = + readDeploymentDeployedAt(path) ?? new Date().toISOString(); + const stamp = deployedAt.slice(0, 10).replace(/-/g, ""); + let revision = 1; + let archive = `${environment}-${stamp}-r${revision}`; + while (existsSync(join(root, archive))) { + revision += 1; + archive = `${environment}-${stamp}-r${revision}`; + } + renameSync(path, join(root, archive)); + console.log(`archived existing ${environment} deployment to ${archive}`); +} + +// Minimal CLI option shapes. Commander hands us plain strings; the address and +// private-key fields below are boundary assertions for downstream signatures. +type NetworkCliOptions = { + network: string; + rpcUrl?: string; + chainId?: string; +}; + +type DeploymentCliOptions = { + deploymentNetwork?: string; + deploymentsDir?: string; +}; + +type V1DeploymentCliOptions = { + v1DeploymentsDir?: string; + v1DeploymentNetwork?: string; +}; + +// Phase commands that broadcast (or print calldata) as the v1 owner. +type V1OwnerWriteCliOptions = { + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + calldataOnly?: boolean; +}; + +// Phase commands that broadcast as a registry/proxy admin account. +type AdminSignerCliOptions = { + privateKey?: `0x${string}`; + impersonateAccount?: Address; +}; + +type PremigrationRunCliOptions = NetworkCliOptions & + DeploymentCliOptions & + V1DeploymentCliOptions & { + privateKey?: `0x${string}`; + csvFile: string; + mainnetRpcUrl?: string; + registry?: Address; + batchRegistrar?: Address; + v1Resolver?: Address; + v1BaseRegistrar?: Address; + batchSize?: string; + limit?: string; + bonusPeriodDays?: string; + workDir?: string; + dryRun?: boolean; + }; + +type PremigrationVerifyCliOptions = NetworkCliOptions & + DeploymentCliOptions & + V1DeploymentCliOptions & { + csvFile: string; + mainnetRpcUrl?: string; + registry?: Address; + v1Resolver?: Address; + v1BaseRegistrar?: Address; + limit?: string; + expectedStatus?: "reserved" | "registered" | "reserved-or-registered"; + bonusPeriodDays?: string; + }; + +type DeployV2CliOptions = NetworkCliOptions & + DeploymentCliOptions & + V1DeploymentCliOptions & { + resume?: boolean; + includeTestnetPremigrationRegistrar?: boolean; + deferV1OwnerTransactions?: boolean; + deferredV1OwnerTransactionsFile?: string; + deployer?: Address; + owner?: Address; + urManager?: Address; + v1Owner?: Address; + impersonateV1Owner?: boolean; + rpcCompatibility?: boolean; + debugRpc?: boolean; + tags?: string; + }; + +type ForkFullCliOptions = Omit & + NetworkCliOptions; + +type CleanTestnetCliOptions = Omit & + NetworkCliOptions; + +function withNetwork( + opts: T, +): Omit & { network: MigrationNetwork } { + return { + ...opts, + network: parseMigrationNetwork(opts.network), + } as Omit & { network: MigrationNetwork }; +} + +// Parse the network and resolve the RPC URL (option or env) in one step, the +// pair every live/fork command needs before calling into the migration logic. +function withNetworkRpc( + input: T, +): Omit & { network: MigrationNetwork; rpcUrl: string } { + const networkOpts = withNetwork(input); + return { + ...networkOpts, + rpcUrl: requireRpcUrl(networkOpts, networkOpts.network), + }; +} + +// The v1-owner key for an owner-gated write: an explicit option, otherwise the +// conventional environment variables. +function v1OwnerKeyFromEnv(opts: { + privateKey?: `0x${string}`; +}): `0x${string}` | undefined { + return ( + opts.privateKey ?? envPrivateKey("SEPOLIA_V1_OWNER_KEY", "V1_OWNER_KEY") + ); +} + +export async function main(argv = process.argv): Promise { + loadDotEnv(resolve(import.meta.dirname, "../.env")); + + const program = new Command() + .name("migration") + .description( + "Operate and rehearse the ENS v1 to v2 migration in explicit phases.", + ); + + program.addCommand( + new Command("fetch-data") + .description("Fetch ENS registration data from TheGraph into a CSV") + .option( + "--thegraph-api-key ", + "TheGraph Gateway API key; falls back to THEGRAPH_API_KEY or GRAPH_API_KEY", + ) + .option( + "--network ", + "ENS registrations network: mainnet or sepolia", + "mainnet", + ) + .option("--batch-size ", "Rows per TheGraph request", "1000") + .option("--start-index ", "Pagination start index", "0") + .option("--limit ", "Maximum registrations to fetch") + .option( + "--output ", + "Output CSV file", + `csv-data/ens-registrations-${new Date().toISOString().split("T")[0]}.csv`, + ) + .action( + async (opts: { + thegraphApiKey?: string; + network?: string; + batchSize?: string; + startIndex?: string; + limit?: string; + output: string; + }) => { + await runFetchData(opts); + }, + ), + ); + + const premigration = new Command("premigration").description( + "Run, resume, inspect, and verify pre-migration reservations.", + ); + + const addPremigrationOptions = (command: Command) => + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions(command) + .option("--private-key ", "BatchRegistrar owner private key") + .requiredOption("--csv-file ", "Pre-migration CSV") + .option("--mainnet-rpc-url ", "RPC URL for v1 expiry reads") + .option("--registry
", "v2 ETHRegistry address") + .option("--batch-registrar
", "BatchRegistrar address") + .option("--v1-resolver
", "ENSV1Resolver address") + .option("--v1-base-registrar
", "v1 BaseRegistrar address") + .option("--batch-size ", "Names per batch", "50") + .option("--limit ", "Maximum names to process") + .option( + "--bonus-period-days ", + "Days added to each name's v1 expiry to compute its v2 expiry", + ) + .option("--work-dir ", "Directory for checkpoints and logs") + .option("--dry-run", "Simulate without transactions", false), + ), + ); + + premigration.addCommand( + addPremigrationOptions( + new Command("run").description( + "Start pre-migration from a fresh checkpoint", + ), + ).action(async (opts: PremigrationRunCliOptions) => { + const networkOpts = withNetworkRpc(opts); + await runPreMigrationCommand( + { + ...networkOpts, + }, + false, + ); + }), + ); + premigration.addCommand( + addPremigrationOptions( + new Command("resume").description("Resume pre-migration from checkpoint"), + ).action(async (opts: PremigrationRunCliOptions) => { + const networkOpts = withNetworkRpc(opts); + await runPreMigrationCommand( + { + ...networkOpts, + }, + true, + ); + }), + ); + premigration.addCommand( + new Command("status") + .description("Print the current pre-migration checkpoint") + .option( + "--work-dir ", + "Directory containing preMigration-checkpoint.json", + ) + .action(async (opts: { workDir?: string }) => { + await printPreMigrationStatus(opts); + }), + ); + premigration.addCommand( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("verify") + .description( + "Verify eligible CSV names were reserved or registered on v2", + ) + .requiredOption("--csv-file ", "Pre-migration CSV") + .option("--mainnet-rpc-url ", "RPC URL for v1 expiry reads") + .option("--registry
", "v2 ETHRegistry address") + .option("--v1-resolver
", "Expected ENSV1Resolver address") + .option("--v1-base-registrar
", "v1 BaseRegistrar address") + .option("--limit ", "Maximum labels to verify") + .option( + "--expected-status ", + "reserved, registered, or reserved-or-registered", + "reserved-or-registered", + ) + .option( + "--bonus-period-days ", + "Days added to each name's v1 expiry to compute its expected v2 expiry", + "62", + ), + ), + ), + ).action(async (opts: PremigrationVerifyCliOptions) => { + const networkOpts = withNetworkRpc(opts); + await verifyPreMigration({ + ...networkOpts, + }); + }), + ); + program.addCommand(premigration); + + const phase = new Command("phase").description( + "Run or verify individual live/fork migration phases.", + ); + + phase.addCommand( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("deploy-v2") + .description( + "Deploy the v2 migration contracts with the registrar deferred (archives any existing namespace and deploys fresh; use --resume to continue an interrupted deploy)", + ) + .option( + "--resume", + "Continue an interrupted deploy into the existing namespace instead of archiving and deploying fresh", + false, + ) + .option( + "--include-testnet-premigration-registrar", + "Deploy the testnet v1 premigration registrar helper", + false, + ) + .option( + "--defer-v1-owner-transactions", + "Record v1-owner transactions instead of broadcasting them", + false, + ) + .option( + "--deferred-v1-owner-transactions-file ", + "JSONL file for deferred v1-owner transactions", + ) + .option("--deployer
", "Deployer account address") + .option("--owner
", "Owner/admin address") + .option("--ur-manager
", "Managed URP admin address") + .option("--v1-owner
", "v1 owner address for v1 writes") + .option( + "--impersonate-v1-owner", + "Impersonate v1 owner on a fork", + false, + ) + .option( + "--rpc-compatibility", + "Enable compatibility fallbacks for fork RPCs", + false, + ) + .option("--debug-rpc", "Log JSON-RPC error responses", false) + .option( + "--tags ", + "Comma-separated deploy tags to run instead of the default v2 migration tags", + ), + ), + ), + ).action(async (opts: DeployV2CliOptions) => { + const networkOpts = withNetworkRpc(opts); + const network = networkOpts.network; + const deployerKey = envPrivateKey("DEPLOYER_KEY"); + const deployerAddress = deployerKey + ? privateKeyToAccount(deployerKey).address + : undefined; + // The owner defaults to the DAO on mainnet and to the deployer elsewhere; + // urManager defaults to the deployer (securityCouncil -> deployer). Only + // attach a key that controls the resolved account so the deployer key is + // never used to act as the mainnet DAO. + const ownerAddress = + opts.owner ?? (network === "mainnet" ? MAINNET_DAO : deployerAddress); + const urManagerAddress = opts.urManager ?? deployerAddress; + const v1OwnerAddress = opts.v1Owner ?? NETWORKS[network].defaultV1Owner; + // Respect an explicit --deployer override (e.g. an impersonated/unlocked + // account during a rehearsal or a key rotation): only attach the env key + // when it actually controls the requested deployer, so DEPLOYER_KEY never + // silently replaces the supplied sender. + const deployerAccount = opts.deployer ?? deployerAddress; + await deployV2({ + ...networkOpts, + deployer: opts.deployer, + deployerPrivateKey: signerKeyForAccount(deployerAccount, [deployerKey]), + ownerPrivateKey: signerKeyForAccount(ownerAddress, [ + envPrivateKey("OWNER_KEY"), + deployerKey, + ]), + urManagerPrivateKey: signerKeyForAccount(urManagerAddress, [ + envPrivateKey("UR_MANAGER_KEY"), + deployerKey, + ]), + v1Owner: v1OwnerAddress, + // Wire the v1-owner account to a local key when one controls it, so it + // is not left as a keyless node-signed address. Signers are keyed by + // address, so a keyless v1-owner sharing the deployer's address would + // otherwise overwrite the deployer's local signer and route every + // deploy transaction through node-side signing the RPC cannot perform. + v1OwnerPrivateKey: signerKeyForAccount(v1OwnerAddress, [ + envPrivateKey("SEPOLIA_V1_OWNER_KEY", "V1_OWNER_KEY"), + deployerKey, + ]), + fresh: !opts.resume, + saveDeployments: true, + tags: opts.tags ? opts.tags.split(",").filter(Boolean) : undefined, + }); + }), + ); + phase.addCommand( + addV1OwnerWriteOptions( + addV1DeploymentOptions( + addNetworkOptions( + new Command("disable-v1-registrars").description( + "Disable v1 registrar controllers", + ), + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + V1DeploymentCliOptions & + V1OwnerWriteCliOptions, + ) => { + const networkOpts = withNetworkRpc(opts); + await disableV1Registrars({ + ...networkOpts, + }); + }, + ), + ); + phase.addCommand( + addV1OwnerWriteOptions( + addV1DeploymentOptions( + addNetworkOptions( + new Command("set-v1-reverse-default-resolver").description( + "Point the v1 ReverseRegistrar default resolver at the v1 PublicResolver (v1-owner write)", + ), + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + V1DeploymentCliOptions & + V1OwnerWriteCliOptions, + ) => { + const networkOpts = withNetworkRpc(opts); + await setV1ReverseDefaultResolver({ + ...networkOpts, + privateKey: + v1OwnerKeyFromEnv(opts), + }); + }, + ), + ); + phase.addCommand( + addV1DeploymentOptions( + addNetworkOptions( + new Command("verify-v1-registrars-disabled").description( + "Verify v1 registrar controllers are disabled", + ), + ), + ).action(async (opts: NetworkCliOptions & V1DeploymentCliOptions) => { + const networkOpts = withNetworkRpc(opts); + await verifyV1RegistrarsDisabled({ + ...networkOpts, + }); + }), + ); + phase.addCommand( + addNetworkOptions( + new Command("execute-owner-txs") + .description("Execute prepared owner transactions from a JSONL file") + .requiredOption( + "--file ", + "JSONL file of prepared owner transactions", + ) + .option( + "--role ", + "Only execute transactions for this role/account", + ) + .option("--private-key ", "Owner private key") + .option( + "--dry-run", + "Print matching transactions without broadcasting", + false, + ), + ).action( + async ( + opts: NetworkCliOptions & { + file: string; + role?: string; + privateKey?: `0x${string}`; + dryRun?: boolean; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await executePreparedOwnerTransactions({ + ...networkOpts, + privateKey: opts.privateKey, + }); + }, + ), + ); + phase.addCommand( + addDeploymentOptions( + addNetworkOptions( + new Command("verify-urp") + .description("Verify top and managed UniversalResolverProxy status") + .option("--top-urp
", "Top-level URP address") + .option("--managed-urp
", "Managed URP address") + .option( + "--expected-top-implementation
", + "Expected top-level URP implementation", + ) + .option( + "--expected-managed-implementation
", + "Expected managed URP implementation", + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & { + topUrp?: Address; + managedUrp?: Address; + expectedTopImplementation?: Address; + expectedManagedImplementation?: Address; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await verifyUrp({ + ...networkOpts, + }); + }, + ), + ); + phase.addCommand( + addV1OwnerWriteOptions( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("authorize-testnet-v1-premigration-registrar") + .description( + "Authorize the testnet premigration helper as a v1 registrar controller", + ) + .option( + "--registrar
", + "TestnetV1PremigrationRegistrar address", + ), + ), + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + V1DeploymentCliOptions & + V1OwnerWriteCliOptions & { registrar?: Address }, + ) => { + const networkOpts = withNetworkRpc(opts); + await authorizeTestnetV1PremigrationRegistrar({ + ...networkOpts, + privateKey: + v1OwnerKeyFromEnv(opts), + }); + }, + ), + ); + phase.addCommand( + addV1OwnerWriteOptions( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("activate-v1-graveyard") + .description( + "Phase 6: authorize Graveyard as a v1 BaseRegistrar controller", + ) + .option("--graveyard
", "Graveyard address"), + ), + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + V1DeploymentCliOptions & + V1OwnerWriteCliOptions & { graveyard?: Address }, + ) => { + const networkOpts = withNetworkRpc(opts); + await activateV1Graveyard({ + ...networkOpts, + privateKey: + v1OwnerKeyFromEnv(opts), + }); + }, + ), + ); + phase.addCommand( + addV1OwnerWriteOptions( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("activate-v1-handoff-controllers") + .description( + "Phase 6: authorize Graveyard and the testnet premigration helper as v1 BaseRegistrar controllers", + ) + .option("--graveyard
", "Graveyard address") + .option( + "--testnet-v1-premigration-registrar
", + "TestnetV1PremigrationRegistrar address", + ), + ), + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + V1DeploymentCliOptions & + V1OwnerWriteCliOptions & { + graveyard?: Address; + testnetV1PremigrationRegistrar?: Address; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await activateV1HandoffControllers({ + ...networkOpts, + privateKey: + v1OwnerKeyFromEnv(opts), + }); + }, + ), + ); + phase.addCommand( + addV1OwnerWriteOptions( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("authorize-v1-renewer") + .description( + "Phase 4: authorize ETHRenewerV1 as a v1 BaseRegistrar controller so unmigrated names stay renewable during the migration", + ) + .option("--eth-renewer-v1
", "ETHRenewerV1 address"), + ), + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + V1DeploymentCliOptions & + V1OwnerWriteCliOptions & { ethRenewerV1?: Address }, + ) => { + const networkOpts = withNetworkRpc(opts); + await authorizeV1Renewer({ + ...networkOpts, + privateKey: + v1OwnerKeyFromEnv(opts), + }); + }, + ), + ); + phase.addCommand( + addV1OwnerWriteOptions( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("activate-v1-renewer") + .description( + "Phase 6: transfer v1 BaseRegistrar ownership to ETHRenewerV1 (re-authorizes it as a controller if needed)", + ) + .option("--eth-renewer-v1
", "ETHRenewerV1 address"), + ), + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + V1DeploymentCliOptions & + V1OwnerWriteCliOptions & { ethRenewerV1?: Address }, + ) => { + const networkOpts = withNetworkRpc(opts); + await activateV1RenewerAndTransferOwnership({ + ...networkOpts, + privateKey: + v1OwnerKeyFromEnv(opts), + }); + }, + ), + ); + phase.addCommand( + addV1DeploymentOptions( + addNetworkOptions( + new Command("reclaim-v1-registrar-ownership") + .description( + "Reclaim v1 BaseRegistrar ownership from a prior migration's ETHRenewerV1 back to the v1 owner (run before re-migrating an already-migrated chain)", + ) + .option("--v1-owner
", "v1 owner to reclaim ownership to") + .option( + "--private-key ", + "Prior renewer owner private key (defaults to OWNER_KEY/DEPLOYER_KEY)", + ) + .option( + "--impersonate-owner", + "Impersonate the prior renewer owner on a fork", + false, + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + V1DeploymentCliOptions & { + v1Owner?: Address; + privateKey?: `0x${string}`; + impersonateOwner?: boolean; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await reclaimV1RegistrarOwnership({ + ...networkOpts, + v1Owner: + opts.v1Owner ?? NETWORKS[networkOpts.network].defaultV1Owner, + privateKey: + opts.privateKey ?? envPrivateKey("OWNER_KEY", "DEPLOYER_KEY"), + }); + }, + ), + ); + phase.addCommand( + addDeploymentOptions( + addNetworkOptions( + new Command("switch-urp-to-managed") + .description( + "Switch the top UniversalResolverProxy to ManagedUniversalResolverProxy", + ) + .option("--top-urp
", "Top-level URP address") + .option("--managed-urp
", "Managed URP address") + .option("--private-key ", "Top URP admin private key") + .option( + "--impersonate-account
", + "Impersonate top URP admin on a fork", + ) + .option( + "--calldata-only", + "Print transaction target and calldata", + false, + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + AdminSignerCliOptions & { + topUrp?: Address; + managedUrp?: Address; + calldataOnly?: boolean; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await switchTopUrpToManaged({ + ...networkOpts, + privateKey: + opts.privateKey ?? + envPrivateKey("SEPOLIA_TOP_URP_OWNER_KEY", "TOP_URP_OWNER_KEY"), + }); + }, + ), + ); + phase.addCommand( + addDeploymentOptions( + addNetworkOptions( + new Command("upgrade-managed-urp") + .description("Upgrade the managed URP to UniversalResolverV2") + .option("--managed-urp
", "Managed URP address") + .option( + "--implementation
", + "UniversalResolverV2 implementation", + ) + .option("--private-key ", "Managed URP admin private key") + .option( + "--impersonate-account
", + "Impersonate admin on a fork", + ) + .option( + "--calldata-only", + "Print transaction target and calldata", + false, + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + AdminSignerCliOptions & { + managedUrp?: Address; + implementation?: Address; + calldataOnly?: boolean; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await upgradeManagedUrp({ + ...networkOpts, + privateKey: + opts.privateKey ?? envPrivateKey("UR_MANAGER_KEY", "DEPLOYER_KEY"), + }); + }, + ), + ); + phase.addCommand( + addDeploymentOptions( + addNetworkOptions( + new Command("disable-batch-registrar") + .description("Revoke registrar/renew roles from BatchRegistrar") + .option("--registry
", "v2 ETHRegistry address") + .option("--batch-registrar
", "BatchRegistrar address") + .option("--private-key ", "Registry role admin private key") + .option( + "--impersonate-account
", + "Impersonate registry role admin on a fork", + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + AdminSignerCliOptions & { + registry?: Address; + batchRegistrar?: Address; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await disableBatchRegistrar({ + ...networkOpts, + privateKey: + opts.privateKey ?? envPrivateKey("OWNER_KEY", "DEPLOYER_KEY"), + }); + }, + ), + ); + phase.addCommand( + addDeploymentOptions( + addNetworkOptions( + new Command("verify-batch-registrar-disabled") + .description( + "Verify BatchRegistrar no longer has registrar/renew roles", + ) + .option("--registry
", "v2 ETHRegistry address") + .option("--batch-registrar
", "BatchRegistrar address"), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & { + registry?: Address; + batchRegistrar?: Address; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await verifyBatchRegistrarDisabled({ + ...networkOpts, + }); + }, + ), + ); + phase.addCommand( + addDeploymentOptions( + addNetworkOptions( + new Command("batch-registrar-owner") + .description("Print and optionally verify the BatchRegistrar owner") + .option("--batch-registrar
", "BatchRegistrar address") + .option( + "--expected-owner
", + "Expected BatchRegistrar owner", + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & { + batchRegistrar?: Address; + expectedOwner?: Address; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await checkBatchRegistrarOwner({ + ...networkOpts, + }); + }, + ), + ); + phase.addCommand( + addDeploymentOptions( + addNetworkOptions( + new Command("enable-v2-registrar") + .description("Grant registrar/renew roles to ETHRegistrar") + .option("--registry
", "v2 ETHRegistry address") + .option("--eth-registrar
", "ETHRegistrar address") + .option("--private-key ", "Registry role admin private key") + .option( + "--impersonate-account
", + "Impersonate registry role admin on a fork", + ), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & + AdminSignerCliOptions & { + registry?: Address; + ethRegistrar?: Address; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await enableV2Registrar({ + ...networkOpts, + privateKey: + opts.privateKey ?? envPrivateKey("OWNER_KEY", "DEPLOYER_KEY"), + }); + }, + ), + ); + phase.addCommand( + addDeploymentOptions( + addNetworkOptions( + new Command("verify-v2-registrar") + .description("Verify ETHRegistrar has registrar/renew roles") + .option("--registry
", "v2 ETHRegistry address") + .option("--eth-registrar
", "ETHRegistrar address"), + ), + ).action( + async ( + opts: NetworkCliOptions & + DeploymentCliOptions & { + registry?: Address; + ethRegistrar?: Address; + }, + ) => { + const networkOpts = withNetworkRpc(opts); + await verifyV2Registrar({ + ...networkOpts, + }); + }, + ), + ); + program.addCommand(phase); + + const fork = new Command("fork").description("Run Anvil fork rehearsals."); + fork.addCommand( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("full") + .description( + "Run the full phased migration rehearsal against an Anvil fork", + ) + .option( + "--direct", + "Use --rpc-url directly instead of starting Anvil", + false, + ) + .option("--port ", "Local Anvil port") + .requiredOption("--csv-file ", "Registration CSV") + .option("--batch-size ", "Names per pre-migration batch") + .option( + "--initial-limit ", + "Optional cap before disabling v1 registrars", + ) + .option( + "--finish-limit ", + "Optional cap after disabling v1 registrars", + ) + .option( + "--work-dir ", + "Directory for fork logs, checkpoints, and generated CSV", + ) + .option( + "--resume-from-phase ", + "Resume the full rehearsal from phase 2", + ) + .option( + "--save-deployments", + "Persist deployment JSON files", + false, + ) + .option( + "--include-testnet-premigration-registrar", + "Deploy the testnet v1 premigration registrar helper", + false, + ) + .option( + "--snapshot-file ", + "Optional file to write a pre-rehearsal snapshot id", + ) + .option("--deployer
", "Migration deployer address") + .option("--owner
", "Migration owner/admin address") + .option("--v1-owner
", "V1 owner address") + .option("--ur-manager
", "Managed URP admin address") + .option("--debug-rpc", "Log JSON-RPC error responses", false) + .option( + "--keep-anvil", + "Leave the local Anvil process running", + false, + ), + ), + ), + ).action(async (opts: ForkFullCliOptions) => { + const networkOpts = withNetworkRpc(opts); + const forkRpcUrl = networkOpts.rpcUrl; + // Tenderly virtual testnets support state controls; the standalone CLI has + // no --tenderly flag, so detect it from the RPC like the Hardhat task does. + const tenderly = + networkOpts.tenderly ?? + (networkOpts.direct ? isTenderlyVirtualRpc(forkRpcUrl) : undefined); + // Only the direct path against a non-state-control RPC needs configured + // signer keys; Anvil forks and Tenderly/local RPCs provide impersonation. + const needsKeys = + Boolean(networkOpts.direct) && + !(Boolean(tenderly) || isLocalRpcUrl(forkRpcUrl)); + await runForkFull({ + ...networkOpts, + tenderly, + ...(needsKeys + ? envMigrationSignerKeys({ + deployer: networkOpts.deployer, + owner: networkOpts.owner, + v1Owner: + networkOpts.v1Owner ?? + NETWORKS[networkOpts.network].defaultV1Owner, + urManager: networkOpts.urManager, + }) + : {}), + }); + }), + ); + program.addCommand(fork); + + program.addCommand( + addV1DeploymentOptions( + addDeploymentOptions( + addNetworkOptions( + new Command("clean-testnet") + .description( + "Deploy fresh testnet v1 contracts and run the full phased migration", + ) + .option( + "--csv-file ", + "Optional registration CSV to seed in addition to generated smoke labels", + ) + .option("--batch-size ", "Names per pre-migration batch") + .option( + "--initial-limit ", + "Optional cap before disabling v1 registrars", + ) + .option( + "--finish-limit ", + "Optional cap after disabling v1 registrars", + ) + .option( + "--work-dir ", + "Directory for clean deploy logs, checkpoints, and generated CSV", + ) + .option( + "--snapshot-file ", + "Optional file to write a pre-phase snapshot id after v1 deployment", + ) + .option("--deployer
", "Migration deployer address") + .option("--owner
", "Migration owner/admin address") + .option("--v1-owner
", "V1 owner address") + .option("--ur-manager
", "Managed URP admin address") + .option("--debug-rpc", "Log JSON-RPC error responses", false), + ), + ), + ).action(async (opts: CleanTestnetCliOptions) => { + const networkOpts = withNetworkRpc(opts); + const forkRpcUrl = networkOpts.rpcUrl; + // Hydrate signer keys only when the RPC lacks state controls; a local node + // or Tenderly virtual testnet impersonates the configured accounts instead. + const needsKeys = !( + Boolean(networkOpts.tenderly) || + isLocalRpcUrl(forkRpcUrl) || + isTenderlyVirtualRpc(forkRpcUrl) + ); + await runCleanTestnetFull({ + ...networkOpts, + ...(needsKeys + ? envMigrationSignerKeys({ + deployer: networkOpts.deployer, + owner: networkOpts.owner ?? networkOpts.deployer, + v1Owner: + networkOpts.v1Owner ?? + networkOpts.owner ?? + networkOpts.deployer, + urManager: networkOpts.urManager ?? networkOpts.deployer, + }) + : {}), + }); + }), + ); + + program.parse(argv); +} + +if (import.meta.main) { + main().catch((error) => { + console.error(error); + process.exit(1); + }); +} diff --git a/contracts/script/patchArtifactsV1.ts b/contracts/script/patchArtifactsV1.ts index 916186aa6..daf3f4740 100644 --- a/contracts/script/patchArtifactsV1.ts +++ b/contracts/script/patchArtifactsV1.ts @@ -1,29 +1,102 @@ -import { readFile, writeFile, mkdir } from "node:fs/promises"; +import { readdir, writeFile, mkdir } from "node:fs/promises"; +import { basename, join, relative } from "node:path"; +const V1_PREFIX = "lib/ens-contracts/"; +const GENERATED_DIR = new URL("../generated/", import.meta.url).pathname; +const OUT_DIR = new URL( + "../lib/ens-contracts/generated/", + import.meta.url, +).pathname; + +/** + * Create re-export files in lib/ens-contracts/generated/ so that + * ens-contracts deploy scripts can resolve `generated/artifacts/X.js` + * and `generated/abis/X.js` via their own tsconfig paths. + * + * For contracts compiled from lib/ens-contracts/ sources, prefer the + * path-qualified version (which is guaranteed to be the ens-contracts + * build) over the short-named version (which may be a v2 contract + * with the same name). + */ export async function patchArtifactsV1() { - const code = await readFile( - new URL("../generated/artifacts.ts", import.meta.url), - { encoding: "utf8" }, - ); - - // extract the artifact data - const prefix = code.indexOf("{"); - if (prefix === -1) throw new Error("expected prefix"); - const suffix = code.lastIndexOf("}") + 1; - if (!suffix) throw new Error("expected suffix"); - - // replace any contract collision with the original version - const json = JSON.parse(code.slice(prefix, suffix)); - for (const [key, value] of Object.entries(json)) { - if (key.startsWith("lib/ens-contracts/")) { - json[(value as any).contractName] = value; - } + for (const subdir of ["artifacts", "abis"] as const) { + await patchDir(subdir); } + await writeArtifactIndexShim(); +} - // rebuild the artifact file - const newCode = - code.slice(0, prefix) + JSON.stringify(json) + code.slice(suffix); - const outDir = new URL("../lib/ens-contracts/generated/", import.meta.url); +async function patchDir(subdir: "artifacts" | "abis") { + const srcDir = join(GENERATED_DIR, subdir); + const outDir = join(OUT_DIR, subdir); await mkdir(outDir, { recursive: true }); - await writeFile(new URL("./artifacts.ts", outDir), newCode); + + // Collect all path-qualified ens-contracts files + // e.g. generated/artifacts/lib/ens-contracts/.../ContractName.ts + const v1Dir = join(srcDir, V1_PREFIX); + const v1Files = await collectFiles(v1Dir).catch(() => []); + + // Map short name -> path-qualified relative import path + const reexports = new Map(); + + for (const absPath of v1Files) { + if (!absPath.endsWith(".ts")) continue; + const name = basename(absPath, ".ts"); + // relative path from outDir to the path-qualified file + const relPath = relative(outDir, absPath); + reexports.set(name, relPath); + } + + // For any short-named file NOT already covered by a path-qualified + // ens-contracts file, check if it's an ens-contracts contract by + // looking at its sourceName. If so, re-export the short name version. + const topFiles = await readdir(srcDir).catch(() => []); + for (const file of topFiles) { + if (!file.endsWith(".ts") || file === "index.ts") continue; + const name = basename(file, ".ts"); + if (reexports.has(name)) continue; // path-qualified version takes priority + const relPath = relative(outDir, join(srcDir, file)); + reexports.set(name, relPath); + } + + // Write re-export files + for (const [name, relPath] of reexports) { + const exportName = subdir === "artifacts" ? `Artifact_${name}` : `Abi_${name}`; + const importPath = relPath.startsWith(".") ? relPath : `./${relPath}`; + const content = `export { ${exportName} } from "${importPath}";\n`; + await writeFile(join(outDir, `${name}.ts`), content); + } +} + +async function collectFiles(dir: string): Promise { + const entries = await readdir(dir, { withFileTypes: true }); + const files: string[] = []; + for (const entry of entries) { + const full = join(dir, entry.name); + if (entry.isDirectory()) { + files.push(...(await collectFiles(full))); + } else { + files.push(full); + } + } + return files; +} + +async function writeArtifactIndexShim() { + const content = `import artifacts from "../../../script/artifacts.js"; + +const v1Artifacts = new Proxy(artifacts, { + get(target, prop, receiver) { + if (typeof prop !== "string") return Reflect.get(target, prop, receiver); + const suffix = \`_\${prop}\`; + const key = Object.keys(target).find( + (name) => name.startsWith("lib_ens_contracts_") && name.endsWith(suffix), + ); + if (key) return target[key]; + return Reflect.get(target, prop, receiver); + }, +}); + +export default v1Artifacts; +`; + await writeFile(join(OUT_DIR, "artifacts.js"), content); } diff --git a/contracts/script/preMigration.ts b/contracts/script/preMigration.ts new file mode 100644 index 000000000..c92ff4e0c --- /dev/null +++ b/contracts/script/preMigration.ts @@ -0,0 +1,1284 @@ +#!/usr/bin/env bun + +import { Command } from "commander"; +import { + createReadStream, + existsSync, + readFileSync, + writeFileSync, +} from "node:fs"; +import { + createPublicClient, + createWalletClient, + getContract, + http, + keccak256, + publicActions, + toHex, + zeroAddress, + type Address, +} from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { mainnet } from "viem/chains"; +import { waitForSuccessfulTransactionReceipt } from "../test/utils/waitForSuccessfulTransactionReceipt.js"; +import { + blue, + bold, + cyan, + dim, + green, + Logger, + magenta, + red, + yellow, +} from "./logger.js"; + +import { loadArtifact, resolveChain } from "./scriptUtils.js"; + +// ABI fragments for v1 BaseRegistrar +const BASE_REGISTRAR_ABI = [ + { + inputs: [{ internalType: "uint256", name: "id", type: "uint256" }], + name: "nameExpires", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, +] as const; + +// Custom Errors +export class UnexpectedOwnerError extends Error { + constructor( + public readonly labelName: string, + public readonly actualOwner: Address, + public readonly expectedOwner: Address, + ) { + super( + `Name ${labelName}.eth is already registered but owned by unexpected address: ${actualOwner} (expected: ${expectedOwner})`, + ); + this.name = "UnexpectedOwnerError"; + } +} + +export class InvalidLabelNameError extends Error { + constructor(public readonly labelName: any) { + super(`Invalid label name: ${labelName}`); + this.name = "InvalidLabelNameError"; + } +} + +export class CSVFormatError extends Error { + constructor(message: string) { + super(message); + this.name = "CSVFormatError"; + } +} + +const ENCODED_LABELHASH_RE = /^\[[0-9a-fA-F]{64}\]$/; + +export function isValidLabel(label: any): label is string { + return ( + !!label && + typeof label === "string" && + label.trim() !== "" && + Buffer.from(label).length <= 255 && + !ENCODED_LABELHASH_RE.test(label) + ); +} + +// Types +export interface ENSRegistration { + labelName: string; + lineNumber: number; +} + +export interface PreMigrationConfig { + rpcUrl: string; + mainnetRpcUrl: string; + registryAddress: Address; + batchRegistrarAddress: Address; + privateKey?: `0x${string}`; + account?: Address; + csvFilePath: string; + batchSize: number; + startIndex: number; + limit: number | null; + dryRun: boolean; + continue?: boolean; + disableCheckpoint?: boolean; + bonusPeriodDays: number; + v1ResolverAddress: Address; + v1BaseRegistrarAddress: Address; +} + +export interface Checkpoint { + lastProcessedLineNumber: number; + totalProcessed: number; + totalExpected: number; + successCount: number; + renewedCount: number; + failureCount: number; + skippedCount: number; + invalidLabelCount: number; + timestamp: string; +} + +// Constants +const CHECKPOINT_FILE = "preMigration-checkpoint.json"; +const ERROR_LOG_FILE = "preMigration-errors.log"; +const INFO_LOG_FILE = "preMigration.log"; + +const RPC_TIMEOUT_MS = 30000; + +// ENS v1 BaseRegistrar on Ethereum mainnet +const BASE_REGISTRAR_ADDRESS = + "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85" as Address; + +/// Hard-coded ENSv1 grace period (in days). Defines the window after a name's +/// v1 expiry during which the original owner retains exclusive renewal rights +/// on v1. Sourced from `BaseRegistrarImplementation.GRACE_PERIOD = 90 days`. +/// Used as the v1-side eligibility gate for migration: a name is migratable +/// only while its v1 owner can still renew it. +export const V1_GRACE_PERIOD_DAYS = 90n; +export const V1_GRACE_PERIOD_SECONDS = V1_GRACE_PERIOD_DAYS * 86400n; + +export function createFreshCheckpoint(): Checkpoint { + return { + lastProcessedLineNumber: -1, + totalProcessed: 0, + totalExpected: 0, + successCount: 0, + renewedCount: 0, + failureCount: 0, + skippedCount: 0, + invalidLabelCount: 0, + timestamp: new Date().toISOString(), + }; +} + +// Pre-migration specific logger +class PreMigrationLogger extends Logger { + constructor() { + super({ + infoLogFile: INFO_LOG_FILE, + errorLogFile: ERROR_LOG_FILE, + enableFileLogging: true, + }); + } + + processingName(name: string, index: number, total: number): void { + this.raw( + cyan(`[${index}/${total}] Processing: ${bold(name)}.eth`), + `[${index}/${total}] Processing: ${name}.eth`, + ); + } + + finishedName( + name: string, + result: "reserved" | "renewed" | "skipped" | "failed", + ): void { + const icon = + result === "reserved" + ? "✓" + : result === "renewed" + ? "↻" + : result === "skipped" + ? "⊘" + : "✗"; + const color = + result === "reserved" + ? green + : result === "renewed" + ? cyan + : result === "skipped" + ? yellow + : red; + this.raw( + color(`${icon} Done: ${bold(name)}.eth`) + dim(` (${result})`), + `${icon} Done: ${name}.eth (${result})`, + ); + } + + reserving(name: string, expiry: string): void { + this.raw( + blue(` → Reserving on v2`) + dim(` (expires: ${expiry})`), + ` → Reserving on v2 (expires: ${expiry})`, + ); + } + + reserved(tx: string): void { + this.raw( + green(` → ✓ Reserved successfully`) + dim(` (tx: ${tx})`), + ` → ✓ Reserved successfully (tx: ${tx})`, + ); + } + + alreadyReserved(): void { + this.raw( + yellow(` → ⊘ Already reserved by this migration`), + ` → ⊘ Already reserved by this migration`, + ); + } + + renewing(name: string, currentExpiry: string, newExpiry: string): void { + this.raw( + blue(` → Renewing on v2`) + + dim(` (current: ${currentExpiry}, new: ${newExpiry})`), + ` → Renewing on v2 (current: ${currentExpiry}, new: ${newExpiry})`, + ); + } + + renewed(tx: string): void { + this.raw( + green(` → ✓ Renewed successfully`) + dim(` (tx: ${tx})`), + ` → ✓ Renewed successfully (tx: ${tx})`, + ); + } + + failed(name: string, error: string): void { + this.rawError( + red(` → ✗ Failed:`) + dim(` ${error}`), + ` → ✗ Failed: ${error}`, + ); + } + + dryRun(): void { + this.raw( + dim(` → [DRY RUN] Simulated registration (no transaction sent)`), + ` → [DRY RUN] Simulated registration (no transaction sent)`, + ); + } + + progress( + current: number, + total: number, + stats: { + reserved: number; + renewed: number; + skipped: number; + failed: number; + }, + ): void { + const percent = Math.round((current / total) * 100); + this.raw( + magenta( + `Progress: ${bold(`${current}/${total}`)} (${percent}%) - ` + + `${green("Reserved: " + stats.reserved)}, ` + + `${cyan("Renewed: " + stats.renewed)}, ` + + `${yellow("Skipped: " + stats.skipped)}, ` + + `${red("Failed: " + stats.failed)}`, + ), + `Progress: ${current}/${total} (${percent}%) - Reserved: ${stats.reserved}, Renewed: ${stats.renewed}, Skipped: ${stats.skipped}, Failed: ${stats.failed}`, + ); + } + + verifyingV1(name: string): void { + this.raw( + dim(` → Checking v1 status for ${name}.eth...`), + ` → Checking v1 status for ${name}.eth...`, + ); + } + + v1Verified(name: string, expiry: string): void { + this.raw( + green(` → ✓ Verified on v1`) + dim(` (expires: ${expiry})`), + ` → ✓ Verified on v1 (expires: ${expiry})`, + ); + } + + v1NotRegistered(name: string, reason: string): void { + this.raw( + yellow(` → ⊘ Not claimable on v1: ${reason}`), + ` → ⊘ Not claimable on v1: ${reason}`, + ); + } + + skippingInvalidName(domainName: string): void { + this.raw( + yellow(` → ⊘ Skipping: ${bold(domainName)}`) + + dim(` (invalid label name)`), + ` → ⊘ Skipping: ${domainName} (invalid label name)`, + ); + } + +} + +const logger = new PreMigrationLogger(); + +// Checkpoint management +export function loadCheckpoint(): Checkpoint | null { + if (!existsSync(CHECKPOINT_FILE)) { + return null; + } + + try { + const data = readFileSync(CHECKPOINT_FILE, "utf-8"); + return JSON.parse(data); + } catch (error) { + logger.error(`Failed to load checkpoint: ${error}`); + return null; + } +} + +export function saveCheckpoint(checkpoint: Checkpoint): void { + try { + writeFileSync(CHECKPOINT_FILE, JSON.stringify(checkpoint, null, 2)); + } catch (error) { + logger.error(`Failed to save checkpoint: ${error}`); + } +} + +// v1 verification +interface V1VerificationResult { + isRegistered: boolean; + expiry: bigint; +} + +export async function verifyNameOnV1( + labelName: string, + client: any, + baseRegistrarAddress: Address = BASE_REGISTRAR_ADDRESS, +): Promise { + if (!isValidLabel(labelName)) { + throw new InvalidLabelNameError(labelName); + } + + const tokenId = keccak256(toHex(labelName)); + + const expiry = await client.readContract({ + address: baseRegistrarAddress, + abi: BASE_REGISTRAR_ABI, + functionName: "nameExpires", + args: [tokenId], + }); + + const currentTimestamp = BigInt(Math.floor(Date.now() / 1000)); + const isRegistered = expiry > 0n && expiry > currentTimestamp; + + return { isRegistered, expiry }; +} + +async function validateBatchRegistrar( + client: any, + address: Address, +): Promise { + const code = await client.getCode({ address }); + if (!code || code === "0x") { + throw new Error( + `No contract deployed at BatchRegistrar address: ${address}`, + ); + } + logger.success(`Using BatchRegistrar at ${address}`); +} + +const CSV_ROW_PREVIEW_LIMIT = 200; +const UTF8_BOM = ""; + +function previewCSVLine(line: string): string { + return line.length <= CSV_ROW_PREVIEW_LIMIT + ? line + : `${line.slice(0, CSV_ROW_PREVIEW_LIMIT)}...`; +} + +async function* readCSVInBatches( + csvFilePath: string, + batchSize: number, + startLineNumber: number = -1, + limit: number | null = null, +): AsyncGenerator { + const readline = await import("node:readline"); + + const fileStream = createReadStream(csvFilePath); + const rl = readline.createInterface({ + input: fileStream, + crlfDelay: Infinity, + }); + + let dataLineNumber = 0; + let processedCount = 0; + let batch: ENSRegistration[] = []; + + let rawLineNumber = 0; + let headerParsed = false; + let labelColumnIndex = -1; + let expectedColumnCount = 0; + let pendingBlankLineNumber: number | null = null; + + for await (const rawLine of rl) { + rawLineNumber++; + + let line = rawLine; + if (rawLineNumber === 1 && line.startsWith(UTF8_BOM)) { + line = line.slice(UTF8_BOM.length); + } + + if (!headerParsed) { + let headerFields: string[]; + try { + headerFields = parseCSVLine(line); + } catch { + throw new CSVFormatError( + `CSV header at ${csvFilePath}:1 has unbalanced quotes. Row: ${previewCSVLine(line)}`, + ); + } + + const normalized = headerFields.map((f) => f.trim().toLowerCase()); + const labelNameIdx = normalized.indexOf("labelname"); + const labelIdx = normalized.indexOf("label"); + const resolvedIdx = labelNameIdx !== -1 ? labelNameIdx : labelIdx; + if (resolvedIdx === -1) { + const found = headerFields.map((f) => f.trim()).join(", "); + throw new CSVFormatError( + `CSV header at ${csvFilePath}:1 has no "labelName" or "label" column. ` + + `Found columns: [${found}]. ` + + `Expected one of "labelName" or "label" (case-insensitive).`, + ); + } + labelColumnIndex = resolvedIdx; + expectedColumnCount = headerFields.length; + headerParsed = true; + continue; + } + + if (dataLineNumber <= startLineNumber) { + if (line !== "") { + dataLineNumber++; + } + continue; + } + + if (limit !== null && processedCount >= limit) { + break; + } + + if (line === "") { + if (pendingBlankLineNumber === null) { + pendingBlankLineNumber = rawLineNumber; + } else { + throw new CSVFormatError( + `CSV row at ${csvFilePath}:${pendingBlankLineNumber} is blank. ` + + `Blank lines are only tolerated at end of file.`, + ); + } + continue; + } + + if (pendingBlankLineNumber !== null) { + throw new CSVFormatError( + `CSV row at ${csvFilePath}:${pendingBlankLineNumber} is blank. ` + + `Blank lines are only tolerated at end of file.`, + ); + } + + let parts: string[]; + try { + parts = parseCSVLine(line); + } catch { + throw new CSVFormatError( + `CSV row at ${csvFilePath}:${rawLineNumber} has unbalanced quotes. ` + + `Row: ${previewCSVLine(line)}`, + ); + } + + if (parts.length !== expectedColumnCount) { + throw new CSVFormatError( + `CSV row at ${csvFilePath}:${rawLineNumber} has ${parts.length} columns ` + + `but header declared ${expectedColumnCount}. ` + + `Row: ${previewCSVLine(line)}`, + ); + } + + const labelName = parts[labelColumnIndex].trim(); + if (labelName === "") { + throw new CSVFormatError( + `CSV row at ${csvFilePath}:${rawLineNumber} has empty "labelName". ` + + `Row: ${previewCSVLine(line)}`, + ); + } + + batch.push({ labelName, lineNumber: dataLineNumber }); + processedCount++; + + if (batch.length >= batchSize) { + yield batch; + batch = []; + } + + dataLineNumber++; + } + + if (!headerParsed) { + throw new CSVFormatError( + `CSV file at ${csvFilePath} is empty (no header row).`, + ); + } + + if (batch.length > 0) { + yield batch; + } +} + +export function parseCSVLine(line: string): string[] { + const result: string[] = []; + let current = ""; + let inQuotes = false; + + for (let i = 0; i < line.length; i++) { + const char = line[i]; + + if (char === '"') { + if (inQuotes && line[i + 1] === '"') { + current += '"'; + i++; + } else { + inQuotes = !inQuotes; + } + } else if (char === "," && !inQuotes) { + result.push(current); + current = ""; + } else { + current += char; + } + } + + if (inQuotes) { + throw new Error("unbalanced quotes"); + } + + result.push(current); + return result; +} + +interface MigrationClients { + client: any; + mainnetClient: any; + registry: any; + batchRegistrar: any; + registryAbi: any[]; +} + +async function createMigrationClients( + config: PreMigrationConfig, +): Promise { + const v2Chain = await resolveChain(config.rpcUrl, RPC_TIMEOUT_MS); + + const account = config.privateKey + ? privateKeyToAccount(config.privateKey) + : config.account; + if (!account) { + throw new Error( + "Missing signer: provide --private-key, PREMIGRATION_PRIVATE_KEY, or --account", + ); + } + + const client = createWalletClient({ + account, + chain: v2Chain, + transport: http(config.rpcUrl, { retryCount: 0, timeout: RPC_TIMEOUT_MS }), + }).extend(publicActions); + + const mainnetClient = createPublicClient({ + chain: mainnet, + transport: http(config.mainnetRpcUrl, { + retryCount: 0, + timeout: RPC_TIMEOUT_MS, + }), + }); + + const registryArtifact = loadArtifact("PermissionedRegistry"); + const registry = getContract({ + address: config.registryAddress, + abi: registryArtifact.abi, + client, + }); + + await validateBatchRegistrar(client, config.batchRegistrarAddress); + + const batchRegistrarArtifact = loadArtifact("BatchRegistrar"); + const batchRegistrar = getContract({ + address: config.batchRegistrarAddress, + abi: batchRegistrarArtifact.abi, + client, + }); + + return { + client, + mainnetClient, + registry, + batchRegistrar, + registryAbi: registryArtifact.abi, + }; +} + +async function fetchAndReserveInBatches( + config: PreMigrationConfig, + checkpoint: Checkpoint, +): Promise { + const { client, mainnetClient, registry, batchRegistrar, registryAbi } = + await createMigrationClients(config); + + const block = await client.getBlock(); + const maxGas = BigInt( + Math.floor(Number(block.gasLimit) * GAS_LIMIT_SAFETY_FACTOR), + ); + logger.config("Block Gas Limit", block.gasLimit.toString()); + logger.config("Max Gas Per Batch", maxGas.toString()); + + logger.info( + `\nReading CSV file and reserving in batches of ${config.batchSize}...`, + ); + logger.info(`CSV file: ${config.csvFilePath}`); + + const batchGenerator = readCSVInBatches( + config.csvFilePath, + config.batchSize, + config.startIndex, + config.limit, + ); + + for await (const batch of batchGenerator) { + try { + checkpoint.totalExpected += batch.length; + + let invalidLabelsInBatch = 0; + let lastInvalidLineNumber = checkpoint.lastProcessedLineNumber; + const validBatch = batch.filter((reg) => { + if (!isValidLabel(reg.labelName)) { + logger.skippingInvalidName(reg.labelName || "unknown"); + invalidLabelsInBatch++; + checkpoint!.invalidLabelCount++; + checkpoint!.totalProcessed++; + lastInvalidLineNumber = reg.lineNumber; + return false; + } + return true; + }); + + if (invalidLabelsInBatch > 0) { + checkpoint.lastProcessedLineNumber = lastInvalidLineNumber; + if (!config.disableCheckpoint) { + saveCheckpoint(checkpoint); + } + } + + logger.info( + `\nRead ${batch.length} names from CSV (${invalidLabelsInBatch} invalid labels filtered). ` + + `Starting reservation of ${validBatch.length} valid names...`, + ); + + if (validBatch.length > 0) { + checkpoint = await processBatch( + config, + validBatch, + client, + mainnetClient, + registry, + batchRegistrar, + checkpoint, + registryAbi, + maxGas, + ); + } + + logger.info( + `Batch complete. Total: ${checkpoint.totalProcessed} processed ` + + `(${checkpoint.successCount} reserved, ${checkpoint.renewedCount} renewed, ` + + `${checkpoint.skippedCount} skipped, ${checkpoint.invalidLabelCount} invalid, ` + + `${checkpoint.failureCount} failed)`, + ); + + if (config.limit && checkpoint.totalProcessed >= config.limit) { + logger.info(`\nReached limit of ${config.limit} names. Stopping.`); + break; + } + } catch (error) { + logger.error(`Failed to process batch: ${error}`); + throw error; + } + } + + printFinalSummary(checkpoint); +} + +export interface VerificationResult { + registration: ENSRegistration; + v2Status: number; + v2LatestOwner: string; + /// Whether the original v1 owner still has renewal rights — i.e., the name + /// is currently registered or within the v1 90-day grace period. Names that + /// pass this gate are candidates for migration; the v2 expiry is computed + /// separately by adding the configurable `--bonus-period-days`. + v1IsClaimable: boolean; + v1Expiry: bigint; + error?: string; +} + +export async function batchVerifyRegistrations( + registrations: ENSRegistration[], + client: any, + mainnetClient: any, + registryAddress: Address, + registryAbi: any[], + v1BaseRegistrarAddress: Address, +): Promise { + const v2Contracts = registrations.map((r) => ({ + address: registryAddress, + abi: registryAbi, + functionName: "getState" as const, + args: [BigInt(keccak256(toHex(r.labelName)))], + })); + + const v1Contracts = registrations.map((r) => ({ + address: v1BaseRegistrarAddress, + abi: BASE_REGISTRAR_ABI, + functionName: "nameExpires" as const, + args: [keccak256(toHex(r.labelName))], + })); + + const [v2Settled, v1Settled] = await Promise.allSettled([ + client.multicall({ contracts: v2Contracts }), + mainnetClient.multicall({ contracts: v1Contracts }), + ]); + + const buildFallback = (reason: unknown) => + registrations.map(() => ({ status: "failure" as const, error: reason })); + + if (v2Settled.status === "rejected") { + logger.warning( + `v2 multicall failed for batch of ${registrations.length}: ${v2Settled.reason}`, + ); + } + if (v1Settled.status === "rejected") { + logger.warning( + `v1 multicall failed for batch of ${registrations.length}: ${v1Settled.reason}`, + ); + } + + const v2Results = + v2Settled.status === "fulfilled" + ? v2Settled.value + : buildFallback(v2Settled.reason); + const v1Results = + v1Settled.status === "fulfilled" + ? v1Settled.value + : buildFallback(v1Settled.reason); + + const currentTimestamp = BigInt(Math.floor(Date.now() / 1000)); + + return registrations.map((reg, i) => { + const v2 = (v2Results as any[])[i]; + const v1 = (v1Results as any[])[i]; + + if (v2.status === "failure" || v1.status === "failure") { + return { + registration: reg, + v2Status: -1, + v2LatestOwner: zeroAddress, + v1IsClaimable: false, + v1Expiry: 0n, + error: v2.status === "failure" ? String(v2.error) : String(v1.error), + }; + } + + const expiry = v1.result as bigint; + return { + registration: reg, + v2Status: (v2.result as any).status, + v2LatestOwner: (v2.result as any).latestOwner, + v1IsClaimable: + expiry > 0n && expiry + V1_GRACE_PERIOD_SECONDS > currentTimestamp, + v1Expiry: expiry, + }; + }); +} + +interface BatchSubmitResult { + succeeded: { label: string; txHash: string }[]; + failed: { label: string; error: string }[]; +} + +async function submitBatchWithBinaryFallback( + batchRegistrar: any, + client: any, + resolver: Address, + labels: string[], + expires: bigint[], +): Promise { + try { + const hash = await batchRegistrar.write.batchRegister([ + zeroAddress, + resolver, + labels, + expires, + ]); + await waitForSuccessfulTransactionReceipt(client, { hash }); + return { + succeeded: labels.map((l) => ({ label: l, txHash: hash })), + failed: [], + }; + } catch (error) { + const errorMsg = error instanceof Error ? error.message : String(error); + if (labels.length <= 1) { + return { + succeeded: [], + failed: [{ label: labels[0], error: errorMsg }], + }; + } + + const mid = Math.ceil(labels.length / 2); + logger.warning( + `Batch of ${labels.length} failed: ${errorMsg}. Splitting into ${mid} + ${labels.length - mid}...`, + ); + + const leftResult = await submitBatchWithBinaryFallback( + batchRegistrar, + client, + resolver, + labels.slice(0, mid), + expires.slice(0, mid), + ); + const rightResult = await submitBatchWithBinaryFallback( + batchRegistrar, + client, + resolver, + labels.slice(mid), + expires.slice(mid), + ); + + return { + succeeded: [...leftResult.succeeded, ...rightResult.succeeded], + failed: [...leftResult.failed, ...rightResult.failed], + }; + } +} + +const GAS_LIMIT_SAFETY_FACTOR = 0.8; + +async function estimateAndSplitBatch( + batchRegistrar: any, + client: any, + resolver: Address, + labels: string[], + expires: bigint[], + maxGas: bigint, +): Promise { + try { + const estimatedGas = await batchRegistrar.estimateGas.batchRegister([ + zeroAddress, + resolver, + labels, + expires, + ]); + + if (estimatedGas <= maxGas) { + return await submitBatchWithBinaryFallback( + batchRegistrar, + client, + resolver, + labels, + expires, + ); + } + + if (labels.length <= 1) { + const msg = `single registration exceeds gas limit (${estimatedGas} > ${maxGas})`; + logger.warning(`Label ${labels[0]}: ${msg}`); + return { + succeeded: [], + failed: [{ label: labels[0], error: msg }], + }; + } + + logger.warning( + `Batch of ${labels.length} estimated at ${estimatedGas} gas (limit: ${maxGas}). Splitting...`, + ); + const mid = Math.ceil(labels.length / 2); + const leftResult = await estimateAndSplitBatch( + batchRegistrar, + client, + resolver, + labels.slice(0, mid), + expires.slice(0, mid), + maxGas, + ); + const rightResult = await estimateAndSplitBatch( + batchRegistrar, + client, + resolver, + labels.slice(mid), + expires.slice(mid), + maxGas, + ); + return { + succeeded: [...leftResult.succeeded, ...rightResult.succeeded], + failed: [...leftResult.failed, ...rightResult.failed], + }; + } catch (estimateError) { + logger.warning( + `Gas estimation failed for batch of ${labels.length}, using binary-search fallback`, + ); + return await submitBatchWithBinaryFallback( + batchRegistrar, + client, + resolver, + labels, + expires, + ); + } +} + +async function processBatch( + config: PreMigrationConfig, + registrations: ENSRegistration[], + client: any, + mainnetClient: any, + registry: any, + batchRegistrar: any, + checkpoint: Checkpoint, + registryAbi: any[], + maxGas: bigint, +): Promise { + const batchLabels: string[] = []; + const batchExpires: bigint[] = []; + const alreadyReservedNames = new Set(); + let lastLineNumber = checkpoint.lastProcessedLineNumber; + + const bonusPeriodSeconds = BigInt(config.bonusPeriodDays) * 86400n; + + const verificationResults = await batchVerifyRegistrations( + registrations, + client, + mainnetClient, + config.registryAddress, + registryAbi, + config.v1BaseRegistrarAddress, + ); + + const baseProcessed = checkpoint.totalProcessed; + for (let i = 0; i < verificationResults.length; i++) { + const result = verificationResults[i]; + const registration = result.registration; + const globalIndex = baseProcessed + i + 1; + lastLineNumber = registration.lineNumber; + + logger.processingName( + registration.labelName, + globalIndex, + checkpoint.totalExpected, + ); + + if (result.error) { + logger.failed(registration.labelName, result.error); + checkpoint.failureCount++; + checkpoint.totalProcessed++; + logger.finishedName(registration.labelName, "failed"); + continue; + } + + if (result.v2Status === 2) { + logger.error( + `Name ${registration.labelName}.eth is already registered with owner: ${result.v2LatestOwner}`, + ); + checkpoint.failureCount++; + checkpoint.totalProcessed++; + logger.finishedName(registration.labelName, "failed"); + continue; + } + if (result.v2Status === 1) { + alreadyReservedNames.add(registration.labelName); + } + + if (!result.v1IsClaimable) { + const reason = + result.v1Expiry === 0n + ? "never registered on v1" + : `past v1 ${V1_GRACE_PERIOD_DAYS}-day grace period`; + logger.v1NotRegistered(registration.labelName, reason); + checkpoint.skippedCount++; + checkpoint.totalProcessed++; + logger.finishedName(registration.labelName, "skipped"); + continue; + } + + const effectiveExpiry = result.v1Expiry + bonusPeriodSeconds; + + const expiryDateFormatted = new Date(Number(effectiveExpiry) * 1000) + .toISOString() + .split("T")[0]; + logger.v1Verified(registration.labelName, expiryDateFormatted); + + batchLabels.push(registration.labelName); + batchExpires.push(effectiveExpiry); + } + + if (batchLabels.length > 0 && !config.dryRun) { + logger.info(`\n → Batch reserving ${batchLabels.length} names...\n`); + + const result = await estimateAndSplitBatch( + batchRegistrar, + client, + config.v1ResolverAddress, + batchLabels, + batchExpires, + maxGas, + ); + + for (const { label, txHash } of result.succeeded) { + checkpoint.totalProcessed++; + if (alreadyReservedNames.has(label)) { + checkpoint.renewedCount++; + logger.renewed(txHash); + logger.finishedName(label, "renewed"); + } else { + checkpoint.successCount++; + logger.reserved(txHash); + logger.finishedName(label, "reserved"); + } + } + + for (const { label, error } of result.failed) { + logger.failed(label, error); + checkpoint.totalProcessed++; + checkpoint.failureCount++; + logger.finishedName(label, "failed"); + } + } else if (batchLabels.length > 0 && config.dryRun) { + logger.info(`\nDry run: Would batch reserve ${batchLabels.length} names`); + + for (const label of batchLabels) { + logger.dryRun(); + checkpoint.totalProcessed++; + if (alreadyReservedNames.has(label)) { + checkpoint.renewedCount++; + logger.finishedName(label, "renewed"); + } else { + checkpoint.successCount++; + logger.finishedName(label, "reserved"); + } + } + } + + checkpoint.lastProcessedLineNumber = lastLineNumber; + checkpoint.timestamp = new Date().toISOString(); + + if (!config.disableCheckpoint) { + saveCheckpoint(checkpoint); + } + + return checkpoint; +} + +function calculateSuccessRate( + successCount: number, + totalAttempts: number, +): number { + return totalAttempts > 0 + ? Math.round((successCount / totalAttempts) * 100) + : 0; +} + +function printFinalSummary(checkpoint: Checkpoint): void { + const actualRegistrations = + checkpoint.successCount + checkpoint.renewedCount + checkpoint.failureCount; + + logger.info(""); + logger.divider(); + logger.header("Pre-Migration Complete"); + logger.divider(); + + logger.config("Total names processed", checkpoint.totalProcessed); + logger.config( + "Successfully reserved", + green(checkpoint.successCount.toString()), + ); + logger.config( + "Successfully renewed", + cyan(checkpoint.renewedCount.toString()), + ); + logger.config( + "Skipped (already up-to-date/expired)", + yellow(checkpoint.skippedCount.toString()), + ); + logger.config( + "Invalid labels", + yellow(checkpoint.invalidLabelCount.toString()), + ); + logger.config( + "Failed (other errors)", + checkpoint.failureCount > 0 + ? red(checkpoint.failureCount.toString()) + : checkpoint.failureCount, + ); + logger.config("Actual reservations/renewals attempted", actualRegistrations); + + const rate = calculateSuccessRate( + checkpoint.successCount + checkpoint.renewedCount, + actualRegistrations, + ); + if (actualRegistrations > 0) { + logger.config("Success rate", `${rate}%`); + } + + logger.divider(); + + if (checkpoint.failureCount > 0) { + logger.warning( + `\nSome registrations failed. Check ${ERROR_LOG_FILE} for details.`, + ); + } +} + +export async function main(argv = process.argv): Promise { + const program = new Command() + .name("premigrate") + .description( + "Pre-migrate ENS .eth 2LDs from v1 to v2 on Ethereum mainnet. By default starts fresh. Use --continue to resume from checkpoint.", + ) + .requiredOption("--rpc-url ", "Ethereum mainnet RPC endpoint") + .requiredOption("--registry
", "v2 ETH Registry contract address") + .requiredOption( + "--batch-registrar
", + "Pre-deployed BatchRegistrar contract address", + ) + .option( + "--private-key ", + "Deployer private key (default: PREMIGRATION_PRIVATE_KEY env var)", + ) + .option( + "--account
", + "Impersonated or unlocked BatchRegistrar owner account", + ) + .requiredOption( + "--csv-file ", + "Path to CSV file containing ENS registrations", + ) + .option( + "--mainnet-rpc-url ", + "Mainnet RPC endpoint for v1 verification (default: public endpoint)", + "https://eth.drpc.org", + ) + .option( + "--batch-size ", + "Number of names to process per batch", + "50", + ) + .option( + "--start-index ", + "Starting index for resuming partial migrations", + "-1", + ) + .option( + "--limit ", + "Maximum total number of names to process and register", + ) + .option("--dry-run", "Simulate without executing transactions", false) + .option( + "--continue", + "Continue from previous checkpoint if it exists", + false, + ) + .option( + "--bonus-period-days ", + "Days added to each name's v1 expiry to compute its v2 expiry", + "62", + ) + .requiredOption( + "--v1-resolver
", + "ENSV1Resolver address deployed on v2 for fallback resolution", + ) + .option( + "--v1-base-registrar
", + "V1 BaseRegistrar address for expiry lookups", + BASE_REGISTRAR_ADDRESS, + ); + + program.parse(argv); + const opts = program.opts(); + + const privateKey = (opts.privateKey ?? + process.env.PREMIGRATION_PRIVATE_KEY) as `0x${string}` | undefined; + const account = opts.account as Address | undefined; + if (!privateKey && !account) { + console.error( + "Error: signer must be provided via --private-key, PREMIGRATION_PRIVATE_KEY, or --account", + ); + process.exit(1); + } + + const config: PreMigrationConfig = { + rpcUrl: opts.rpcUrl, + mainnetRpcUrl: opts.mainnetRpcUrl, + registryAddress: opts.registry as Address, + batchRegistrarAddress: opts.batchRegistrar as Address, + privateKey, + account, + csvFilePath: opts.csvFile, + batchSize: parseInt(opts.batchSize) || 100, + startIndex: parseInt(opts.startIndex) || 0, + limit: opts.limit ? parseInt(opts.limit) : null, + dryRun: opts.dryRun, + continue: opts.continue, + bonusPeriodDays: Number.isNaN(parseInt(opts.bonusPeriodDays)) + ? 62 + : parseInt(opts.bonusPeriodDays), + v1ResolverAddress: opts.v1Resolver as Address, + v1BaseRegistrarAddress: opts.v1BaseRegistrar as Address, + }; + + try { + logger.header("ENS Pre-Migration Script"); + logger.divider(); + + logger.info(`Configuration:`); + logger.config("RPC URL", config.rpcUrl); + logger.config("Registry", config.registryAddress); + logger.config("BatchRegistrar", config.batchRegistrarAddress); + logger.config( + "Signer Account", + config.account ?? + (opts.privateKey ? "private key (CLI)" : "private key (env)"), + ); + logger.config("Mainnet RPC (v1)", config.mainnetRpcUrl); + logger.config("CSV File", config.csvFilePath); + logger.config("Batch Size", config.batchSize); + logger.config("Bonus Period Days", config.bonusPeriodDays); + logger.config( + "V1 Grace Period Days (hard-coded)", + Number(V1_GRACE_PERIOD_DAYS), + ); + logger.config("V1 Resolver", config.v1ResolverAddress); + logger.config("Limit", config.limit ?? "none"); + logger.config("Dry Run", config.dryRun); + logger.config("Continue Mode", config.continue ?? false); + + let checkpoint = createFreshCheckpoint(); + if (config.continue) { + const cp = loadCheckpoint(); + if (cp) { + checkpoint = cp; + config.startIndex = cp.lastProcessedLineNumber; + logger.config( + "Checkpoint Found", + `${cp.totalProcessed} processed (${cp.successCount} reserved, ${cp.renewedCount} renewed, ${cp.skippedCount} skipped, ${cp.invalidLabelCount} invalid, ${cp.failureCount} failed) (last line: ${cp.lastProcessedLineNumber})`, + ); + logger.info(`Resuming from CSV line ${config.startIndex}`); + } + } + logger.info(""); + + await fetchAndReserveInBatches(config, checkpoint); + + logger.success("\nPre-migration script completed successfully!"); + } catch (error) { + logger.error(`Fatal error: ${error}`); + console.error(error); + process.exit(1); + } +} + +if (import.meta.main) { + main().catch((error) => { + console.error(error); + process.exit(1); + }); +} diff --git a/contracts/script/prepareMigration.ts b/contracts/script/prepareMigration.ts new file mode 100644 index 000000000..7ea9983c9 --- /dev/null +++ b/contracts/script/prepareMigration.ts @@ -0,0 +1,246 @@ +#!/usr/bin/env bun + +import { Command } from "commander"; +import { getContract, isAddress, type Address, type Hex } from "viem"; +import { waitForSuccessfulTransactionReceipt } from "../test/utils/waitForSuccessfulTransactionReceipt.js"; +import { DEPLOYMENT_ROLES, ROLES } from "./deploy-constants.js"; +import { bold, cyan, dim, green, Logger, red, yellow } from "./logger.js"; +import { createV2Clients, loadArtifact } from "./scriptUtils.js"; + +class PrepareLogger extends Logger { + line(msg: string): void { + this.raw(msg); + } +} + +const ROLE_NAMES: Array<[bigint, string]> = [ + [ROLES.REGISTRY.REGISTRAR, "ROLE_REGISTRAR"], + [ROLES.ADMIN.REGISTRY.REGISTRAR, "ROLE_REGISTRAR_ADMIN"], + [ROLES.REGISTRY.REGISTER_RESERVED, "ROLE_REGISTER_RESERVED"], + [ROLES.ADMIN.REGISTRY.REGISTER_RESERVED, "ROLE_REGISTER_RESERVED_ADMIN"], + [ROLES.REGISTRY.RENEW, "ROLE_RENEW"], + [ROLES.ADMIN.REGISTRY.RENEW, "ROLE_RENEW_ADMIN"], +]; + +function describeRoles(bitmap: bigint): string { + const matched = ROLE_NAMES.filter(([bit]) => (bitmap & bit) === bit).map( + ([, name]) => name, + ); + return matched.length ? matched.join(" | ") : "(none)"; +} + +type Op = + | { kind: "grant"; label: string; account: Address; roles: bigint } + | { kind: "revoke"; label: string; account: Address; roles: bigint }; + +interface Config { + rpcUrl: string; + registryAddress: Address; + batchRegistrarAddress: Address; + ethRegistrarAddress: Address; + unlockedMigrationControllerAddress: Address; + lockedMigrationControllerAddress: Address; + privateKey: Hex | null; + execute: boolean; +} + +function requireAddress(value: string | undefined, flag: string): Address { + if (!value || !isAddress(value)) { + throw new Error(`${flag} must be a valid 0x-prefixed address`); + } + return value as Address; +} + +function parseArgs(argv: string[]): Config { + const program = new Command() + .name("prepareMigration") + .description( + "Prepare .eth PermissionedRegistry for live migration: fully decommission BatchRegistrar (revoke all its roles) and grant registration and renewal roles to ETHRegistrar plus the reservation-promotion role to both migration controllers.", + ) + .requiredOption("--rpc-url ", "JSON-RPC endpoint") + .requiredOption("--registry
", ".eth PermissionedRegistry address") + .requiredOption("--batch-registrar
", "BatchRegistrar address") + .requiredOption("--eth-registrar
", "ETHRegistrar address") + .requiredOption( + "--unlocked-migration-controller
", + "UnlockedMigrationController address", + ) + .requiredOption( + "--locked-migration-controller
", + "LockedMigrationController address", + ) + .option("--private-key ", "signer private key (required with --execute)") + .option("--execute", "broadcast transactions (default: dry run)", false) + .parse(argv); + + const opts = program.opts(); + const privateKey = opts.privateKey + ? ((opts.privateKey.startsWith("0x") + ? opts.privateKey + : `0x${opts.privateKey}`) as Hex) + : null; + + if (opts.execute && !privateKey) { + throw new Error("--execute requires --private-key"); + } + + return { + rpcUrl: opts.rpcUrl, + registryAddress: requireAddress(opts.registry, "--registry"), + batchRegistrarAddress: requireAddress(opts.batchRegistrar, "--batch-registrar"), + ethRegistrarAddress: requireAddress(opts.ethRegistrar, "--eth-registrar"), + unlockedMigrationControllerAddress: requireAddress( + opts.unlockedMigrationController, + "--unlocked-migration-controller", + ), + lockedMigrationControllerAddress: requireAddress( + opts.lockedMigrationController, + "--locked-migration-controller", + ), + privateKey, + execute: !!opts.execute, + }; +} + +function buildOps(cfg: Config): Op[] { + return [ + { + kind: "revoke", + label: "BatchRegistrar", + account: cfg.batchRegistrarAddress, + // Revoke every bit granted at static deploy plus admin counterparts and + // REGISTER_RESERVED pair so the post-state is unambiguously empty. + roles: + DEPLOYMENT_ROLES.ETH_REGISTRAR_ROOT | + ROLES.ADMIN.REGISTRY.REGISTRAR | + ROLES.ADMIN.REGISTRY.RENEW | + DEPLOYMENT_ROLES.MIGRATION_CONTROLLER_ROOT | + ROLES.ADMIN.REGISTRY.REGISTER_RESERVED, + }, + { + kind: "grant", + label: "ETHRegistrar", + account: cfg.ethRegistrarAddress, + roles: DEPLOYMENT_ROLES.ETH_REGISTRAR_ROOT, + }, + { + kind: "grant", + label: "UnlockedMigrationController", + account: cfg.unlockedMigrationControllerAddress, + roles: DEPLOYMENT_ROLES.MIGRATION_CONTROLLER_ROOT, + }, + { + kind: "grant", + label: "LockedMigrationController", + account: cfg.lockedMigrationControllerAddress, + roles: DEPLOYMENT_ROLES.MIGRATION_CONTROLLER_ROOT, + }, + ]; +} + +// Admin bits needed to grant/revoke a given role bitmap: each low-128 role bit +// requires its paired admin bit at (bit << 128); admin bits are self-admin. +function requiredAdminBits(roles: bigint): bigint { + const LOW_MASK = (1n << 128n) - 1n; + const low = roles & LOW_MASK; + const high = roles & ~LOW_MASK; + return (low << 128n) | high; +} + +export async function main(argv: string[] = process.argv): Promise { + const cfg = parseArgs(argv); + const logger = new PrepareLogger(); + + const { abi: registryAbi } = loadArtifact("PermissionedRegistry"); + const { publicClient, walletClient, account } = await createV2Clients({ + rpcUrl: cfg.rpcUrl, + privateKey: cfg.privateKey, + }); + + const registryRead = getContract({ + abi: registryAbi, + address: cfg.registryAddress, + client: publicClient, + }); + const registryWrite = walletClient + ? getContract({ + abi: registryAbi, + address: cfg.registryAddress, + client: walletClient, + }) + : null; + + const ops = buildOps(cfg); + + logger.header("Prepare-Migration"); + logger.config("RPC", cfg.rpcUrl); + logger.config("Registry", cfg.registryAddress); + logger.config("Signer", account?.address ?? "(none — dry run)"); + logger.config("Mode", cfg.execute ? "EXECUTE" : "DRY RUN"); + + logger.header("Planned operations"); + for (const op of ops) { + const current = (await registryRead.read.roles([0n, op.account])) as bigint; + logger.line( + `${op.kind === "grant" ? green("+ GRANT ") : red("- REVOKE")} ${bold(op.label)} ${dim(op.account)}`, + ); + logger.line(` roles: ${describeRoles(op.roles)}`); + logger.line(dim(` current on-chain: ${describeRoles(current)}`)); + } + + if (account) { + logger.header("Signer admin-role pre-flight"); + const signerRoles = (await registryRead.read.roles([ + 0n, + account.address, + ])) as bigint; + logger.line(dim(` signer root roles: ${describeRoles(signerRoles)}`)); + let missing = 0n; + for (const op of ops) { + const lacks = requiredAdminBits(op.roles) & ~signerRoles; + if (lacks !== 0n) { + logger.error( + `signer missing admin bits for ${op.label} ${op.kind}: ${describeRoles(lacks)}`, + ); + missing |= lacks; + } + } + if (missing !== 0n) { + throw new Error("signer lacks required admin roles; aborting"); + } + logger.success("signer holds all required admin roles"); + } + + if (!cfg.execute || !registryWrite) { + logger.header("Dry run complete"); + logger.line(yellow("no transactions broadcast; pass --execute to proceed")); + return; + } + + logger.header("Executing"); + for (const op of ops) { + logger.line( + cyan(`→ ${op.kind.toUpperCase()} ${op.label} ${dim(op.account)}`), + ); + const fn = op.kind === "grant" ? "grantRootRoles" : "revokeRootRoles"; + const hash = await (registryWrite.write as any)[fn]([op.roles, op.account]); + logger.line(dim(` tx: ${hash}`)); + await waitForSuccessfulTransactionReceipt(publicClient, { hash }); + logger.success(`${op.label} ${op.kind} confirmed`); + } + + logger.header("Final state"); + for (const op of ops) { + const after = (await registryRead.read.roles([0n, op.account])) as bigint; + logger.line(`${bold(op.label)} ${dim(op.account)}`); + logger.line(dim(` roles: ${describeRoles(after)}`)); + } + logger.success("prepare-migration complete"); +} + +if (import.meta.main) { + main().catch((err) => { + console.error(err); + process.exit(1); + }); +} diff --git a/contracts/script/publicSuffixes.ts b/contracts/script/publicSuffixes.ts new file mode 100644 index 000000000..c03e6840d --- /dev/null +++ b/contracts/script/publicSuffixes.ts @@ -0,0 +1,114 @@ +import { labelhash, zeroAddress, type Abi, type Address } from "viem"; +import { dnsEncodeName } from "../test/utils/utils.js"; +import { MAX_EXPIRY, ROLES } from "./deploy-constants.js"; + +export const SUFFIX_BATCH_SIZE = 25; + +const BATCH_REGISTRAR_ROLE_BITMAP = + ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW; + +type DeploymentLike = { + address: Address; + abi: TAbi; +}; + +export async function fetchPublicSuffixes() { + const res = await fetch( + "https://publicsuffix.org/list/public_suffix_list.dat", + { headers: { Connection: "close" } }, + ); + if (!res.ok) throw new Error(`expected suffixes: ${res.status}`); + return (await res.text()) + .split("\n") + .map((x) => x.trim()) + .filter((x) => x && !x.startsWith("//")); +} + +// Filters candidates down to the suffixes that are on the v1 public suffix +// list and still available on the root registry, reading SUFFIX_BATCH_SIZE +// candidates at a time. +export async function filterAvailableSuffixes({ + read, + publicSuffixList, + rootRegistry, + candidates, +}: { + read: any; + publicSuffixList: DeploymentLike; + rootRegistry: DeploymentLike; + candidates: string[]; +}): Promise { + const suffixes: string[] = []; + for (let i = 0; i < candidates.length; i += SUFFIX_BATCH_SIZE) { + const batch = candidates.slice(i, i + SUFFIX_BATCH_SIZE); + const available = await Promise.all( + batch.map(async (suffix) => { + const isPublicSuffix = await read(publicSuffixList, { + functionName: "isPublicSuffix", + args: [dnsEncodeName(suffix)], + }); + if (!isPublicSuffix) return ""; + const status = await read(rootRegistry, { + functionName: "getStatus", + args: [BigInt(labelhash(suffix))], + }); + return status === 0 ? suffix : ""; + }), + ); + suffixes.push(...available.filter(Boolean)); + } + return suffixes; +} + +// Grants REGISTRAR|RENEW root roles to the batch registrar, registers the +// suffixes SUFFIX_BATCH_SIZE at a time against the given resolver, then +// revokes the roles again. +export async function registerSuffixesViaBatchRegistrar({ + write, + account, + rootRegistry, + batchRegistrar, + resolver, + suffixes, +}: { + write: any; + account: Address; + rootRegistry: DeploymentLike; + batchRegistrar: DeploymentLike; + resolver: Address; + suffixes: string[]; +}) { + await write(rootRegistry, { + account, + functionName: "grantRootRoles", + args: [BATCH_REGISTRAR_ROLE_BITMAP, batchRegistrar.address], + }); + + try { + for (let i = 0; i < suffixes.length; i += SUFFIX_BATCH_SIZE) { + const batch = suffixes.slice(i, i + SUFFIX_BATCH_SIZE); + const progress = Math.min(i + SUFFIX_BATCH_SIZE, suffixes.length); + console.log( + ` - Registering ${batch.length} suffixes (${progress}/${suffixes.length})`, + ); + await write(batchRegistrar, { + account, + functionName: "batchRegister", + args: [ + zeroAddress, + resolver, + batch, + new Array(batch.length).fill(MAX_EXPIRY), + ], + }); + } + } finally { + // Always revoke the temporary roles, even if a batch reverts partway, so the + // batch registrar is never left holding registrar permissions on the root. + await write(rootRegistry, { + account, + functionName: "revokeRootRoles", + args: [BATCH_REGISTRAR_ROLE_BITMAP, batchRegistrar.address], + }); + } +} diff --git a/contracts/script/runDevnet.ts b/contracts/script/runDevnet.ts index a74fb358e..309d4bfd5 100644 --- a/contracts/script/runDevnet.ts +++ b/contracts/script/runDevnet.ts @@ -1,8 +1,9 @@ import { createServer } from "node:http"; import { parseArgs } from "node:util"; -import { getAddress, toHex } from "viem"; +import { getAddress } from "viem"; import { setupDevnet } from "./setup.js"; import { testNames } from "./testNames.js"; +import { COIN_TYPE_ETH } from "../test/utils/utils.js"; const t0 = Date.now(); @@ -15,15 +16,42 @@ const args = parseArgs({ testNames: { type: "boolean", }, + chainId: { + type: "string", + }, + forkUrl: { + type: "string", + }, + forkBlock: { + type: "string", + }, + quiet: { + type: "boolean", + }, }, strict: true, }); +// Env-var fallbacks: CLI wins, then FORK_URL / FORK_BLOCK / DEVNET_QUIET. +// Lets callers (e.g. morticia's mainnet-fork e2e runner) configure once via +// env and avoid duplicating the same flags across every script invocation. +const forkUrl = args.values.forkUrl ?? process.env.FORK_URL; +const forkBlock = args.values.forkBlock ?? process.env.FORK_BLOCK; +const quiet = args.values.quiet ?? process.env.DEVNET_QUIET === "1"; + +if (forkUrl && args.values.testNames) { + console.error("--testNames is incompatible with --forkUrl"); + process.exit(2); +} + const env = await setupDevnet({ port: 8545, + chainId: forkUrl ? undefined : Number(args.values.chainId) || undefined, saveDeployments: true, procLog: args.values.procLog, - extraTime: args.values.testNames ? 86_401 : 60, + extraTime: forkUrl ? 0 : args.values.testNames ? 86_401 : 60, + forkUrl, + forkBlockNumber: forkBlock ? BigInt(forkBlock) : undefined, }); // handler for shell @@ -43,23 +71,44 @@ process.once("uncaughtException", async (err) => { throw err; }); -console.log(); -console.log("Available Named Accounts:"); -console.table(env.accounts.map((x) => ({ Name: x.name, Address: x.address }))); +if (!quiet) { + console.log(); + console.log("Available Named Accounts:"); + console.table( + Object.values(env.namedAccounts).map((x) => ({ + Name: x.name, + Address: x.address, + Resolver: x.resolver.address, + })), + ); -console.table({ - [env.deployment.client.chain.name]: { - Chain: `${env.deployment.client.chain.id} (${toHex(env.deployment.client.chain.id)})`, - Endpoint: `{http,ws}://${env.deployment.hostPort}`, - }, -}); + const tags = ["v2", "shared", "erc20"] as const; + console.table( + await Promise.all( + Object.entries(env.rocketh.deployments).map( + async ([name, { address }]) => { + const [primary] = await env.v2.UniversalResolver.read.reverse([ + address, + COIN_TYPE_ETH, + ]); + return { + "Contract Name": name, + "Contract Address": getAddress(address), + "Primary Name": + !primary && (name in env.v2 || name in env.shared) + ? undefined + : primary, + }; + }, + ), + ), + ); -console.table( - Object.entries(env.deployment.env.deployments).map(([name, { address }]) => ({ - [env.deployment.client.chain.name]: name, - "Contract Address": getAddress(address), - })), -); + console.log({ + Chain: env.client.chain.id, + Endpoint: `{http,ws}://${env.hostPort}`, + }); +} if (args.values.testNames) { await testNames(env); @@ -67,9 +116,33 @@ if (args.values.testNames) { await env.sync({ warpSec: "local" }); +// Fork-mode finalisation: activateV2 grants the v2 Graveyard + ETHRenewerV1 +// the RegistrarSecurityController controller role, retires the v1 ETH +// controllers, and transfers registrar ownership to ETHRenewerV1 — all via +// anvil autoImpersonate as the ENS DAO multisig. Without this every +// graveyard clear() reverts with ONLY_CONTROLLER on a fresh fork. +// Greenfield (non-fork) devnets retain the previous behaviour: callers are +// expected to grant controller roles themselves via test-side setup. +if (forkUrl) { + await env.activateV2(); +} + console.log(new Date(), `Ready! <${Date.now() - t0}ms>`); -const server = createServer((_req, res) => { +const server = createServer((req, res) => { + // Surface every rocketh-tracked deployment as JSON so consumers don't + // have to know about the deployments/devnet-{chainId}/*.json layout. + if (req.url === "/deployments") { + const body: Record = { + chainId: String(env.client.chain.id), + }; + for (const [name, dep] of Object.entries(env.rocketh.deployments)) { + body[name] = getAddress(dep.address); + } + res.writeHead(200, { "Content-Type": "application/json" }); + res.end(JSON.stringify(body)); + return; + } res.writeHead(200, { "Content-Type": "text/plain" }); res.end("healthy\n"); }); diff --git a/contracts/script/scriptUtils.ts b/contracts/script/scriptUtils.ts new file mode 100644 index 000000000..14b3c5761 --- /dev/null +++ b/contracts/script/scriptUtils.ts @@ -0,0 +1,86 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { + createPublicClient, + createWalletClient, + defineChain, + http, + publicActions, + type Chain, + type Hex, + type PublicClient, +} from "viem"; +import { privateKeyToAccount, type PrivateKeyAccount } from "viem/accounts"; +import { mainnet, sepolia } from "viem/chains"; + +export const DEFAULT_RPC_TIMEOUT_MS = 30_000; + +/// Canonical CREATE2 Multicall3 deployment address, identical across EVM chains. +const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11" as const; + +/// Load an ABI from the forge compilation artifact under `contracts/out/`. +export function loadArtifact(contractName: string): { abi: any[] } { + const artifactPath = join( + import.meta.dirname, + `../out/${contractName}.sol/${contractName}.json`, + ); + const artifact = JSON.parse(readFileSync(artifactPath, "utf-8")); + return { abi: artifact.abi }; +} + +/// Resolve the viem Chain for a given RPC endpoint: mainnet if chainId===1, +/// otherwise a synthesized custom chain wrapping the provided RPC URL. +export async function resolveChain( + rpcUrl: string, + timeoutMs = DEFAULT_RPC_TIMEOUT_MS, +): Promise { + const probe = createPublicClient({ + transport: http(rpcUrl, { retryCount: 0, timeout: timeoutMs }), + }); + const chainId = await probe.getChainId(); + if (chainId === 1) return mainnet; + if (chainId === sepolia.id) return sepolia; + return defineChain({ + id: chainId, + name: "Custom", + nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, + rpcUrls: { default: { http: [rpcUrl] } }, + contracts: { multicall3: { address: MULTICALL3_ADDRESS } }, + }); +} + +export interface V2ClientBundle { + chain: Chain; + account: PrivateKeyAccount | null; + publicClient: PublicClient; + // When `privateKey` is supplied this is a wallet client extended with + // public actions (so it can be used for reads as well as writes). + walletClient: ReturnType | null; +} + +/// Build viem clients for the target v2 chain. When `privateKey` is absent, +/// only a read-only `publicClient` is returned — suitable for dry-run flows. +export async function createV2Clients(opts: { + rpcUrl: string; + privateKey?: Hex | null; + timeoutMs?: number; +}): Promise { + const timeout = opts.timeoutMs ?? DEFAULT_RPC_TIMEOUT_MS; + const chain = await resolveChain(opts.rpcUrl, timeout); + const transport = http(opts.rpcUrl, { retryCount: 0, timeout }); + + const publicClient = createPublicClient({ chain, transport }); + + if (!opts.privateKey) { + return { chain, account: null, publicClient, walletClient: null }; + } + + const account = privateKeyToAccount(opts.privateKey); + const walletClient = createWalletClient({ + account, + chain, + transport, + }).extend(publicActions); + + return { chain, account, publicClient, walletClient }; +} diff --git a/contracts/script/setup.ts b/contracts/script/setup.ts index cd849b4ba..613c42e3e 100644 --- a/contracts/script/setup.ts +++ b/contracts/script/setup.ts @@ -1,269 +1,96 @@ -import { artifacts } from "@rocketh"; +import artifacts from "./artifacts.js"; import { rm } from "node:fs/promises"; +import { fileURLToPath } from "node:url"; import { anvil as createAnvil } from "prool/instances"; -import { type Environment, executeDeployScripts, resolveConfig } from "rocketh"; +import type { + UnresolvedNetworkSpecificData, + UnresolvedUnknownNamedAccounts, + UserConfig, +} from "rocketh/types"; import { - type Abi, type Account, type Address, - type Chain, + ContractFunctionExecutionError, + ContractFunctionRevertedError, + createPublicClient, createWalletClient, + decodeAbiParameters, + encodeAbiParameters, getContract, - type GetContractReturnType, - type Hash, type Hex, + hexToString, + keccak256, namehash, publicActions, + slice, + stringToHex, testActions, - type Transport, - webSocket, + http, zeroAddress, + defineChain, } from "viem"; import { mnemonicToAccount } from "viem/accounts"; +import { Artifact_DNSAliasResolver } from "generated/artifacts/DNSAliasResolver.js"; +import { Artifact_DNSTLDResolver } from "generated/artifacts/DNSTLDResolver.js"; +import { Artifact_DNSTXTResolver } from "generated/artifacts/DNSTXTResolver.js"; +import { Artifact_ENSV1Resolver } from "generated/artifacts/ENSV1Resolver.js"; +import { Artifact_ENSV2Resolver } from "generated/artifacts/ENSV2Resolver.js"; +import { Artifact_MockERC20 } from "generated/artifacts/test/mocks/MockERC20.sol/MockERC20.js"; +import { Artifact_UniversalResolverV2 } from "generated/artifacts/UniversalResolverV2.js"; + +import { loadAndExecuteDeploymentsFromFilesWithConfig } from "../rocketh/environment.js"; +import { + computeVerifiableProxyAddress as computeVerifiableProxyAddress_, + deployVerifiableProxy, +} from "../test/integration/fixtures/deployVerifiableProxy.js"; +import { + dnsEncodeName, + getReverseName, + splitName, +} from "../test/utils/utils.js"; +import { waitForSuccessfulTransactionReceipt } from "../test/utils/waitForSuccessfulTransactionReceipt.js"; import { LOCAL_BATCH_GATEWAY_URL, MAX_EXPIRY, ROLES, } from "./deploy-constants.js"; -import { deployArtifact } from "../test/integration/fixtures/deployArtifact.js"; -import { - computeVerifiableProxyAddress, - deployVerifiableProxy, -} from "../test/integration/fixtures/deployVerifiableProxy.js"; -import { waitForSuccessfulTransactionReceipt } from "../test/utils/waitForSuccessfulTransactionReceipt.ts"; import { patchArtifactsV1 } from "./patchArtifactsV1.js"; +import { bootstrapForkDeployments, ENS_DAO_MULTISIG } from "./forkBootstrap.js"; -/** - * Default chain ID for devnet environment - */ -export const DEFAULT_CHAIN_ID = 0xeeeeed; - -type DeployedArtifacts = Record; - -type Future = T | Promise; - -// typescript key (see below) mapped to rocketh deploy name -const renames: Record = { - ETHRegistrarV1: "BaseRegistrarImplementation", -}; - -const contracts = { - // v2 - SimpleRegistryMetadata: artifacts.SimpleRegistryMetadata.abi, - HCAFactory: artifacts.MockHCAFactoryBasic.abi, - VerifiableFactory: artifacts.VerifiableFactory.abi, - // core - RootRegistry: artifacts.PermissionedRegistry.abi, - ETHRegistry: artifacts.PermissionedRegistry.abi, - // eth registrar - ETHRegistrar: artifacts.ETHRegistrar.abi, - StandardRentPriceOracle: artifacts.StandardRentPriceOracle.abi, - MockUSDC: artifacts["test/mocks/MockERC20.sol/MockERC20"].abi, - MockDAI: artifacts["test/mocks/MockERC20.sol/MockERC20"].abi, - // VerifiableFactory implementations - PermissionedResolverImpl: artifacts.PermissionedResolver.abi, - UserRegistryImpl: artifacts.UserRegistry.abi, - WrapperRegistryImpl: artifacts.WrapperRegistry.abi, - // resolvers - UniversalResolverV2: artifacts.UniversalResolverV2.abi, - DNSTLDResolver: artifacts.DNSTLDResolver.abi, - DNSTXTResolver: artifacts.DNSTXTResolver.abi, - DNSAliasResolver: artifacts.DNSAliasResolver.abi, - // v1 - BatchGatewayProvider: artifacts.GatewayProvider.abi, - RootV1: artifacts.Root.abi, - ENSRegistryV1: artifacts.ENSRegistry.abi, - ETHRegistrarV1: artifacts.BaseRegistrarImplementation.abi, - ReverseRegistrarV1: artifacts.ReverseRegistrar.abi, - PublicResolverV1: artifacts.PublicResolver.abi, - NameWrapperV1: artifacts.NameWrapper.abi, - UniversalResolverV1: artifacts.UniversalResolver.abi, - // v1 compat - DefaultReverseRegistrar: artifacts.DefaultReverseRegistrar.abi, - DefaultReverseResolver: artifacts.DefaultReverseResolver.abi, - ETHReverseRegistrar: artifacts.L2ReverseRegistrar.abi, // TODO: change to using v1 - ETHReverseResolver: artifacts.ETHReverseResolver.abi, -} as const satisfies DeployedArtifacts; +const NAMED_ACCOUNTS = ["deployer", "owner", "user", "user2"] as const; export type StateSnapshot = () => Promise; -export type DevnetClient = ReturnType; export type DevnetEnvironment = Awaited>; +export type DevnetAccount = + DevnetEnvironment["namedAccounts"][(typeof NAMED_ACCOUNTS)[number]]; -export type Deployment = DeploymentInstance; - -function ansi(c: any, s: any) { +function ansi(c: unknown, s: unknown) { return `\x1b[${c}m${s}\x1b[0m`; } -function createClient(transport: Transport, chain: Chain, account: Account) { - return createWalletClient({ - transport, - chain, - account, - pollingInterval: 50, - cacheTime: 0, // must be 0 due to client caching - }) - .extend(publicActions) - .extend(testActions({ mode: "anvil" })); -} - -type ContractsOf = { - [K in keyof A]: A[K] extends Abi | readonly unknown[] - ? GetContractReturnType - : never; -}; - -export class DeploymentInstance< - const A extends DeployedArtifacts = typeof contracts, -> { - readonly contracts: ContractsOf; - constructor( - readonly anvil: ReturnType, - readonly client: DevnetClient, - readonly transport: Transport, - readonly hostPort: string, - readonly env: Environment, - namedArtifacts: A, - ) { - this.contracts = Object.fromEntries( - Object.entries(namedArtifacts).map(([name, abi]) => { - const deployment = env.get(renames[name] ?? name.replace(/V1$/, "")); - const contract = getContract({ - abi, - address: deployment.address, - client, - }) as { - write?: Record Promise>; - } & Record; - if ("write" in contract) { - const write = contract.write!; - // override to ensure successful transaction - // otherwise, success is being assumed based on an eth_estimateGas call - // but state could change, or eth_estimateGas could be wrong - contract.write = new Proxy( - {}, - { - get(_, functionName: string) { - return async (...parameters: unknown[]) => { - const hash = await write[functionName](...parameters); - await waitForSuccessfulTransactionReceipt(client, { hash }); - return hash; - }; - }, - }, - ); - } - return [name, contract]; - }), - ) as ContractsOf; - } - async computeVerifiableProxyAddress(args: { - deployer: Address; - salt: bigint; - }) { - return computeVerifiableProxyAddress({ - factoryAddress: this.contracts.VerifiableFactory.address, - bytecode: artifacts["UUPSProxy"].bytecode, - ...args, - }); - } - async deployPermissionedRegistry({ - account, - roles = ROLES.ALL, - }: { - account: Account; - roles?: bigint; - }) { - const walletClient = createClient( - this.transport, - this.client.chain, - account, - ); - const { abi, bytecode } = artifacts.PermissionedRegistry; - const hash = await walletClient.deployContract({ - abi, - bytecode, - args: [ - this.contracts.HCAFactory.address, - this.contracts.SimpleRegistryMetadata.address, - account.address, - roles, - ], - }); - const receipt = await waitForSuccessfulTransactionReceipt(walletClient, { - hash, - ensureDeployment: true, - }); - return getContract({ - abi, - address: receipt.contractAddress, - client: walletClient, - }); - } - async deployPermissionedResolver({ - account, - admin = account.address, - roles = ROLES.ALL, - salt, - }: { - account: Account; - admin?: Address; - roles?: bigint; - salt?: bigint; - }) { - return deployVerifiableProxy({ - walletClient: createClient(this.transport, this.client.chain, account), - factoryAddress: this.contracts.VerifiableFactory.address, - implAddress: this.contracts.PermissionedResolverImpl.address, - abi: this.contracts.PermissionedResolverImpl.abi, - functionName: "initialize", - args: [admin, roles], - salt, - }); - } - deployUserRegistry({ - account, - admin = account.address, - roles = ROLES.ALL, - salt, - }: { - account: Account; - admin?: Address; - roles?: bigint; - salt?: bigint; - }) { - return deployVerifiableProxy({ - walletClient: createClient(this.transport, this.client.chain, account), - factoryAddress: this.contracts.VerifiableFactory.address, - implAddress: this.contracts.UserRegistryImpl.address, - abi: this.contracts.UserRegistryImpl.abi, - functionName: "initialize", - args: [admin, roles], - salt, - }); - } -} - export async function setupDevnet({ - chainId = DEFAULT_CHAIN_ID, port = 0, - extraAccounts = 5, + chainId = 31337, mnemonic = "test test test test test test test test test test test junk", saveDeployments = false, quiet = !saveDeployments, procLog = false, extraTime = 0, + forkUrl, + forkBlockNumber, }: { - chainId?: number; port?: number; - extraAccounts?: number; + chainId?: number; mnemonic?: string; saveDeployments?: boolean; quiet?: boolean; procLog?: boolean; // show anvil process logs extraTime?: number; // extra time to subtract from genesis timestamp + forkUrl?: string; // when set, anvil forks from this RPC URL + forkBlockNumber?: bigint; // optional fork block; defaults to latest } = {}) { + const isFork = !!forkUrl; // shutdown functions for partial initialization const finalizers: (() => unknown | Promise)[] = []; async function shutdown() { @@ -283,44 +110,34 @@ export async function setupDevnet({ console.log("Deploying ENSv2..."); await patchArtifactsV1(); - // list of named wallets - const names = ["deployer", "owner", "bridger", "user", "user2"]; - extraAccounts += names.length; - - process.env["RUST_LOG"] = "info"; // required to capture console.log() - const baseArgs = { - accounts: extraAccounts, + process.env.RUST_LOG = "info"; // required to capture console.log() + const anvilInstance = createAnvil({ + accounts: NAMED_ACCOUNTS.length, mnemonic, - ...(extraTime + // when forking, anvil derives chainId from the upstream RPC; the bare + // `chainId` flag is omitted so anvil takes the upstream value + ...(isFork ? {} : { chainId }), + port, + // autoImpersonate lets the deploy flow sign as any address (e.g. the DAO + // multisig mapped to `owner` on chainId 1) without explicit unlocking. + // omitted in non-fork mode — prool encodes `false` as a positional arg + // rather than dropping the flag, which trips anvil's subcommand parser. + ...(isFork ? { autoImpersonate: true, forkUrl, forkBlockNumber } : {}), + ...(extraTime && !isFork ? { timestamp: Math.floor(Date.now() / 1000) - extraTime } : {}), - }; - const anvilInstance = createAnvil({ - ...baseArgs, - chainId, - port, }); - const accounts = Array.from({ length: extraAccounts }, (_, i) => + const accounts = NAMED_ACCOUNTS.map((name, i) => Object.assign(mnemonicToAccount(mnemonic, { addressIndex: i }), { - name: names[i] ?? `unnamed${i}`, + name, }), ); - const namedAccounts = Object.fromEntries(accounts.map((x) => [x.name, x])); - const { deployer } = namedAccounts; console.log("Launching devnet"); await anvilInstance.start(); finalizers.push(() => anvilInstance.stop()); - // parse `host:port` from the anvil boot message - const hostPort = (() => { - const message = anvilInstance.messages.get().join("\n").trim(); - const match = message.match(/Listening on (.*)$/); - if (!match) throw new Error(`expected host: ${message}`); - return match[1]; - })(); - let showConsole = true; const log = (chunk: string) => { // ref: https://github.com/adraffy/blocksmith.js/blob/main/src/Foundry.js#L991 @@ -332,7 +149,7 @@ export async function setupDevnet({ // "2025-10-09T16:31:48.449325Z INFO node::user:" // "2025-10-09T16:31:48.451639Z WARN backend: Skipping..." const match = line.match( - /^.{27} ([A-Z]+) (\w+(?:|::\w+)):(?:$| (.*)$)/, + /^.{27} {2}([A-Z]+) (\w+(?:|::\w+)):(?:$| (.*)$)/, ); if (match) { const [, , kind, action] = match; @@ -341,11 +158,11 @@ export async function setupDevnet({ showConsole = action !== "eth_estimateGas"; // detect if inside gas estimation } if (kind === "node::console") { - return showConsole ? `Devnet ${line}` : []; // ignore console during gas estimation + return showConsole ? line : []; // ignore console during gas estimation } } if (!procLog) return []; - return ansi(36, `Devnet ${line}`); + return ansi(36, line); }); if (!lines.length) return; console.log(lines.join("\n")); @@ -353,98 +170,458 @@ export async function setupDevnet({ anvilInstance.on("message", log); finalizers.push(() => anvilInstance.off("message", log)); - const transportOptions = { + // parse `host:port` from the anvil boot message + const hostPort = (() => { + const message = anvilInstance.messages.get().join("\n").trim(); + const match = message.match(/Listening on (.*)$/); + if (!match) throw new Error(`expected host: ${message}`); + return match[1]; + })(); + + const httpURL = `http://${hostPort}`; + + // when forking, anvil reports the upstream chainId — pull it from the live + // node so downstream chain definition + deployments dir name reflect reality + const activeChainId = isFork + ? await createPublicClient({ transport: http(httpURL) }).getChainId() + : chainId; + + const chain = defineChain({ + id: activeChainId, + name: "ENSv2", + nativeCurrency: { + decimals: 18, + name: "Ether", + symbol: "ETH", + }, + rpcUrls: { + default: { + http: [httpURL], + webSocket: [`ws://${hostPort}`], + }, + }, + }); + + const transport = http(httpURL, { retryCount: 1, - keepAlive: true, - reconnect: false, timeout: 10000, - } as const; - const transport = webSocket(`ws://${hostPort}`, transportOptions); - - const nativeCurrency = { - name: "Ether", - symbol: "ETH", - decimals: 18, - } as const; - const chain: Chain = { - id: chainId, - name: "Devnet", - nativeCurrency, - rpcUrls: { default: { http: [`http://${hostPort}`] } }, - }; + }); + + function createClient(account: Account) { + return createWalletClient({ + transport, + chain, + account, + pollingInterval: 50, + cacheTime: 0, // must be 0 due to client caching + }) + .extend(publicActions) + .extend(testActions({ mode: "anvil" })); + } - const client = createClient(transport, chain, deployer); + const client = createClient(accounts[0]); + + // Mock the EIP-7951 P-256 precompile at address 0x100. + // ens-contracts v1.7.0 replaced the pure-Solidity EllipticCurve library with + // a call to this precompile for DNSSEC P256SHA256 signature verification. + // Anvil does not yet support EIP-7951 (requires Osaka/Fusaka hardfork), so we + // deploy minimal bytecode that always returns 0x00...01 (valid signature). + // Bytecode: PUSH1 0x01, PUSH0, MSTORE, PUSH1 0x20, PUSH0, RETURN + await client.request({ + method: "anvil_setCode" as any, + params: [ + "0x0000000000000000000000000000000000000100", + "0x60015f5260205ff3", + ], + }); console.log("Deploying contracts"); - const name = "devnet-local"; + const deploymentName = `devnet-${activeChainId}`; + const deploymentsDirURL = new URL( + `../deployments/${deploymentName}`, + import.meta.url, + ); if (saveDeployments) { - await rm(new URL(`../deployments/${name}`, import.meta.url), { + await rm(deploymentsDirURL, { recursive: true, force: true, }); } + if (isFork) { + await bootstrapForkDeployments({ + client, + deploymentsDir: fileURLToPath(deploymentsDirURL), + canonicalDir: fileURLToPath( + new URL("../lib/ens-contracts/deployments/mainnet", import.meta.url), + ), + chainId: activeChainId, + }); + } process.env.BATCH_GATEWAY_URLS = JSON.stringify([LOCAL_BATCH_GATEWAY_URL]); - const deployResult = await executeDeployScripts( - resolveConfig({ - network: { - nodeUrl: chain.rpcUrls.default.http[0], - name, - tags: [ - "l1", - "local", - "use_root", // deploy root contracts - "allow_unsafe", // state hacks - "legacy", // legacy registry - ], - fork: false, - scripts: ["lib/ens-contracts/deploy", "deploy"], - publicInfo: { - name, - nativeCurrency: chain.nativeCurrency, - rpcUrls: { default: { http: [...chain.rpcUrls.default.http] } }, - }, - pollingInterval: 0.001, // cannot be zero - }, + const rocketh = await loadAndExecuteDeploymentsFromFilesWithConfig( + { + environment: deploymentName, askBeforeProceeding: false, saveDeployments, - accounts: Object.fromEntries(accounts.map((x) => [x.name, x.address])), - }), + defaultPollingInterval: 0.001, // cannot be zero + }, + { + accounts: Object.fromEntries( + accounts.map((x) => [x.name, x.address]), + ) as never, + chains: { + [activeChainId]: { + info: chain, + rpcUrl: httpURL, + pollingInterval: 0.001, + tags: [ + "v2", + "local", + "use_root", // deploy root contracts + "allow_unsafe", // state hacks + "legacy", // legacy registry + "tenderly", // let ENS deploy scripts run full setup on chain id 1 forks + ], + }, + }, + environments: { + [deploymentName]: { + chain: activeChainId, + // on fork, v1 contracts come from the live mainnet state we just + // pre-populated; only the v2 deploy scripts run on top + scripts: isFork + ? ["deploy"] + : ["lib/ens-contracts/deploy", "deploy"], + }, + }, + } satisfies UserConfig< + UnresolvedUnknownNamedAccounts, + UnresolvedNetworkSpecificData + >, ); + console.log("Deployed contracts"); + + // note: TypeScript is too slow when the following is generalized + const shared = { + BatchGatewayProvider: getContract({ + abi: artifacts.GatewayProvider.abi, + address: rocketh.get("BatchGatewayProvider").address, + client, + }), + DNSSECGatewayProvider: getContract({ + abi: artifacts.GatewayProvider.abi, + address: rocketh.get("DNSSECGatewayProvider").address, + client, + }), + DefaultReverseRegistrar: getContract({ + abi: artifacts.DefaultReverseRegistrar.abi, + address: rocketh.get("DefaultReverseRegistrar").address, + client, + }), + DefaultReverseResolver: getContract({ + abi: artifacts.DefaultReverseResolver.abi, + address: rocketh.get("DefaultReverseResolver").address, + client, + }), + ETHReverseRegistrar: getContract({ + abi: artifacts.ReverseRegistrar.abi, + address: rocketh.get("ReverseRegistrar").address, + client, + }), + ReverseRegistrarAdapter: getContract({ + abi: artifacts.ReverseRegistrarAdapter.abi, + address: rocketh.get("ReverseRegistrarAdapter").address, + client, + }), + DefaultReverseRegistrarAdapter: getContract({ + abi: artifacts.DefaultReverseRegistrarAdapter.abi, + address: rocketh.get("DefaultReverseRegistrarAdapter").address, + client, + }), + }; - const deployment = new DeploymentInstance( - anvilInstance, - client, - transport, - hostPort, - deployResult, - contracts, + const v1 = { + Root: getContract({ + abi: artifacts.Root.abi, + address: rocketh.get("Root").address, + client, + }), + ENSRegistry: getContract({ + abi: artifacts.ENSRegistry.abi, + address: rocketh.get("ENSRegistry").address, + client, + }), + BaseRegistrar: getContract({ + abi: artifacts.BaseRegistrarImplementation.abi, + address: rocketh.get("BaseRegistrarImplementation").address, + client, + }), + ReverseRegistrar: getContract({ + abi: artifacts.ReverseRegistrar.abi, + address: rocketh.get("ReverseRegistrar").address, + client, + }), + NameWrapper: getContract({ + abi: artifacts.NameWrapper.abi, + address: rocketh.get("NameWrapper").address, + client, + }), + // WrappedETHRegistrarController: getContract({ + // abi: artifacts.IWrappedETHRegistrarController.abi, + // address: rocketh.get("WrappedETHRegistrarController").address, + // client, + // }), + RegistrarSecurityController: getContract({ + abi: artifacts.RegistrarSecurityController.abi, + address: rocketh.get("RegistrarSecurityController").address, + client, + }), + // resolvers + PublicResolver: getContract({ + abi: artifacts.PublicResolver.abi, + address: rocketh.get("PublicResolver").address, + client, + }), + UniversalResolver: getContract({ + abi: artifacts.UniversalResolver.abi, + address: rocketh.get("UniversalResolver").address, + client, + }), + }; + + const NameCoderErrors = artifacts.NameCoder.abi.filter( + (x) => x.type === "error", ); + const v2 = { + ContractNamer: getContract({ + abi: artifacts.ContractNamer.abi, + address: rocketh.get("ContractNamer").address, + client, + }), + LabelStore: getContract({ + abi: artifacts.LabelStore.abi, + address: rocketh.get("LabelStore").address, + client, + }), + VerifiableFactory: getContract({ + abi: artifacts.VerifiableFactory.abi, + address: rocketh.get("VerifiableFactory").address, + client, + }), + RootRegistry: getContract({ + abi: [...artifacts.PermissionedRegistry.abi, ...NameCoderErrors], + address: rocketh.get("RootRegistry").address, + client, + }), + ETHRegistry: getContract({ + abi: [...artifacts.PermissionedRegistry.abi, ...NameCoderErrors], + address: rocketh.get("ETHRegistry").address, + client, + }), + // eth registrar + StandardRentPriceOracle: getContract({ + abi: artifacts.StandardRentPriceOracle.abi, + address: rocketh.get("StandardRentPriceOracle").address, + client, + }), + ETHRegistrar: getContract({ + abi: artifacts.ETHRegistrar.abi, + address: rocketh.get("ETHRegistrar").address, + client, + }), + ETHRenewerV1: getContract({ + abi: artifacts.ETHRenewerV1.abi, + address: rocketh.get("ETHRenewerV1").address, + client, + }), + // VerifiableFactory implementations + PermissionedResolverImpl: getContract({ + abi: artifacts.PermissionedResolver.abi, + address: rocketh.get("PermissionedResolverImpl").address, + client, + }), + UserRegistryImpl: getContract({ + abi: [...artifacts.UserRegistry.abi, ...NameCoderErrors], + address: rocketh.get("UserRegistryImpl").address, + client, + }), + WrapperRegistryImpl: getContract({ + abi: artifacts.WrapperRegistry.abi, + address: rocketh.get("WrapperRegistryImpl").address, + client, + }), + // migration + UnlockedMigrationController: getContract({ + abi: [...artifacts.UnlockedMigrationController.abi, ...NameCoderErrors], + address: rocketh.get("UnlockedMigrationController").address, + client, + }), + LockedMigrationController: getContract({ + abi: [...artifacts.LockedMigrationController.abi, ...NameCoderErrors], + address: rocketh.get("LockedMigrationController").address, + client, + }), + Graveyard: getContract({ + abi: artifacts.Graveyard.abi, + address: rocketh.get("Graveyard").address, + client, + }), + PublicResolverSet: getContract({ + abi: artifacts.PermissionedAddressSet.abi, + address: rocketh.get("PublicResolverSet").address, + client, + }), + ApprovedUpgradeGate: getContract({ + abi: artifacts.ApprovedUpgradeGate.abi, + address: rocketh.get("ApprovedUpgradeGate").address, + client, + }), + // resolvers + UniversalResolver: getContract({ + abi: Artifact_UniversalResolverV2.abi, + address: rocketh.deployments["UniversalResolverV2"].address, + client, + }), + DNSTLDResolver: getContract({ + abi: Artifact_DNSTLDResolver.abi, + address: rocketh.deployments["DNSTLDResolver"].address, + client, + }), + DNSTXTResolver: getContract({ + abi: Artifact_DNSTXTResolver.abi, + address: rocketh.deployments["DNSTXTResolver"].address, + client, + }), + DNSAliasResolver: getContract({ + abi: Artifact_DNSAliasResolver.abi, + address: rocketh.deployments["DNSAliasResolver"].address, + client, + }), + ENSV1Resolver: getContract({ + abi: Artifact_ENSV1Resolver.abi, + address: rocketh.deployments["ENSV1Resolver"].address, + client, + }), + ENSV2Resolver: getContract({ + abi: Artifact_ENSV2Resolver.abi, + address: rocketh.deployments["ENSV2Resolver"].address, + client, + }), + PublicResolver: getContract({ + abi: artifacts.PublicResolverV2.abi, + address: rocketh.get("PublicResolverV2").address, + client, + }), + }; + + const erc20 = { + MockUSDC: getContract({ + abi: Artifact_MockERC20.abi, + address: rocketh.deployments["MockUSDC"].address, + client, + }), + MockDAI: getContract({ + abi: Artifact_MockERC20.abi, + address: rocketh.deployments["MockDAI"].address, + client, + }), + }; - await setupEnsDotEth(deployment, deployer); - console.log("Setup ens.eth"); + const verifiableProxyLogic = await v2.VerifiableFactory.read.proxyLogic(); + + [shared, v1, v2, erc20] + .flatMap((x) => Object.values(x)) + .forEach(patchContractWrite); + console.log("Linked contracts"); + + const namedAccounts = Object.fromEntries( + await Promise.all( + accounts.map(async (account) => { + const resolver = await deployPermissionedResolver({ + account, + salt: { ownedVersion: 0n }, + }); + return [account.name, Object.assign(account, { resolver })]; + }), + ), + ) as Record< + (typeof NAMED_ACCOUNTS)[number], + (typeof accounts)[number] & { + resolver: Awaited>; + } + >; + console.log("Created PermissionedResolver for each account"); + + // on fork, ens.eth already exists on canonical v1 with real subdomains; + // skip the synthetic register-and-seed step to avoid colliding with state + if (!isFork) { + await setupEnsDotEth(); + console.log("Setup ens.eth"); + } console.log("Deployed ENSv2"); return { + client, + hostPort, accounts, namedAccounts, - deployment, + rocketh, + shared, + v1, + v2, + erc20, sync, waitFor, - getBlock, saveState, shutdown, + createClient, + computeVerifiableProxyAddress, + computeUserRegistrySalt, + computeOwnedResolverSalt, + castUserRegistry, + castPermissionedResolver, + deployUserRegistry, + deployPermissionedResolver, + findPermissionedRegistry, + findWrapperRegistry, + patchContractWrite, + activateV2, }; - async function waitFor(hash: Future) { - hash = await hash; - const receipt = await waitForSuccessfulTransactionReceipt(client, { - hash, + async function waitFor(hash: Hex | Promise) { + return waitForSuccessfulTransactionReceipt(client, { + hash: await hash, }); - return { receipt, deployment }; } - function getBlock() { - return client.getBlock(); + + // inject waitForSuccessfulTransactionReceipt into viem contract wrapper + function patchContractWrite(contract: T): T { + if ("write" in contract) { + const write0 = contract.write as Record< + string, + (...parameters: unknown[]) => Promise + >; + contract.write = new Proxy( + {}, + { + get(_, functionName: string) { + return async (...parameters: unknown[]) => { + const promise = write0[functionName](...parameters); + const receipt = await waitFor( + functionName === "safeTransferFrom" || + functionName === "safeBatchTransferFrom" + ? promise.catch(handleTransferError) // v1 abi lacks v2 errors + : promise, + ); + return receipt.transactionHash; + }; + }, + }, + ); + } + return contract; } + async function saveState(): Promise { let state = await client.request({ method: "evm_snapshot" } as any); let block0 = await client.getBlock(); @@ -461,11 +638,15 @@ export async function setupDevnet({ block0 = await client.getBlock(); }; } + async function sync({ blocks = 1, warpSec = "local", - }: { blocks?: number; warpSec?: number | "local" } = {}) { - const block = await getBlock(); + }: { + blocks?: number; + warpSec?: number | "local"; + } = {}) { + const block = await client.getBlock(); let timestamp = Number(block.timestamp); if (warpSec === "local") { timestamp = Math.max(timestamp, (Date.now() / 1000) | 0); @@ -478,6 +659,357 @@ export async function setupDevnet({ }); return BigInt(timestamp); } + + function computeVerifiableProxyAddress(deployer: Address, salt: bigint) { + return computeVerifiableProxyAddress_({ + factoryAddress: v2.VerifiableFactory.address, + proxyLogic: verifiableProxyLogic as Address, + deployer, + salt, + }); + } + + function computeOwnedResolverSalt(owner: Address, version = 0n) { + return BigInt( + keccak256( + encodeAbiParameters( + [ + { name: "id", type: "bytes32" }, + { name: "owner", type: "address" }, + { name: "version", type: "uint256" }, + ], + [keccak256(stringToHex("OwnedResolver")), owner, version], + ), + ), + ); + } + + function computeUserRegistrySalt(name: string, version = 0n) { + return BigInt( + keccak256( + encodeAbiParameters( + [ + { name: "id", type: "bytes32" }, + { name: "node", type: "bytes32" }, + { name: "version", type: "uint256" }, + ], + [keccak256(stringToHex("UserRegistry")), namehash(name), version], + ), + ), + ); + } + + async function deployPermissionedResolver({ + account, // deployer + admin = account.address, + roles = ROLES.ALL, + setters = [], + salt, + }: { + account: Account; + admin?: Address; + roles?: bigint; + setters?: Hex[]; + salt?: bigint | { ownedVersion: bigint }; + }) { + if (typeof salt === "object") { + salt = computeOwnedResolverSalt(admin, salt.ownedVersion); + } + return patchContractWrite( + await deployVerifiableProxy({ + walletClient: createClient(account), + factoryAddress: v2.VerifiableFactory.address, + implAddress: v2.PermissionedResolverImpl.address, + abi: v2.PermissionedResolverImpl.abi, + functionName: "initialize", + args: [admin, roles, setters], + salt, + }), + ); + } + + async function deployUserRegistry({ + account, + admin = account.address, + roles = ROLES.ALL, + salt, + }: { + account: Account; + admin?: Address; + roles?: bigint; + salt?: bigint | { name: string; version?: bigint }; + }) { + const implAddress = v2.UserRegistryImpl.address; + if (typeof salt === "object") { + salt = computeUserRegistrySalt(salt.name, salt.version); + } + return patchContractWrite( + await deployVerifiableProxy({ + walletClient: createClient(account), + factoryAddress: v2.VerifiableFactory.address, + implAddress, + abi: v2.UserRegistryImpl.abi, + functionName: "initialize", + args: [admin, roles], + salt, + }), + ); + } + + function castUserRegistry( + address: Address, + account: Account = namedAccounts.deployer, + ) { + return patchContractWrite( + getContract({ + abi: v2.UserRegistryImpl.abi, + address, + client: createClient(account), + }), + ); + } + + function castPermissionedResolver( + address: Address, + account: Account = namedAccounts.deployer, + ) { + return patchContractWrite( + getContract({ + abi: v2.PermissionedResolverImpl.abi, + address, + client: createClient(account), + }), + ); + } + + // note: casts to UserRegistry even if PermissionRegistry + // note: TypeScript is too slow when the following is generalized to any resolver type + async function findPermissionedRegistry(name: string, account?: Account) { + const address = await v2.UniversalResolver.read.findExactRegistry([ + dnsEncodeName(name), + ]); + if (address === zeroAddress) { + throw new Error(`expected PermissionedRegistry: ${name}`); + } + // TODO: do a supportsInterface check? + return castUserRegistry(address, account); + } + + function computeWrapperRegistryAddress(name: string) { + const labels = splitName(name); + let currentName = labels.pop(); + if (currentName !== "eth" || !labels.length) { + throw new Error(`expected .eth 2LD+: ${name}`); + } + let address = v2.LockedMigrationController.address; + while (labels.length) { + currentName = `${labels.pop()}.${currentName}`; + address = computeVerifiableProxyAddress( + address, + BigInt(namehash(currentName)), + ); + } + return address; + } + + function findWrapperRegistry( + name: string, + account: Account = namedAccounts.deployer, + ) { + const address = computeWrapperRegistryAddress(name); + // this may not be deployed yet + // this is equivalent to `findExactRegistry()` when deployed + return patchContractWrite( + getContract({ + abi: v2.WrapperRegistryImpl.abi, + address, + client: createClient(account), + }), + ); + } + + async function activateV2() { + // on fork the canonical v1 contracts are owned by the DAO multisig, not + // by the mnemonic-derived `owner` account — anvil autoImpersonate lets us + // call onlyOwner functions by passing the DAO address as a JSON-RPC + // account directly. + const account: Account | Address = isFork + ? ENS_DAO_MULTISIG + : namedAccounts.owner; + // lock NameWrapper if still owned (idempotent across fork + synthetic) + + if ((await v1.NameWrapper.read.owner()) !== zeroAddress) { + await v1.NameWrapper.write.renounceOwnership({ account }); + } + // disable every v1 path that can register .eth 2LDs by revoking it as + // a BaseRegistrarImplementation controller (routed via + // RegistrarSecurityController, which is BaseRegistrar's owner): + // - ETHRegistrarController / LegacyETHRegistrarController: direct + // controllers of BaseRegistrar. + // - NameWrapper: BaseRegistrar controller through which the + // WrappedETHRegistrarController registers wrapped 2LDs. + // - WrappedETHRegistrarController: not actually a BaseRegistrar + // controller on canonical mainnet (it routes through NameWrapper), + // but is on the synthetic devnet; included for parity. + // BaseRegistrarImplementation.removeController is idempotent (sets + // controllers[x]=false and emits an event), so revoking an address + // that isn't currently registered is a harmless no-op. The + // LegacyETHRegistrarController rocketh artifact is pre-populated by + // `bootstrapForkDeployments` in fork mode and by the v1 deploy scripts + // in synthetic-devnet mode. + const v1ControllerNames = [ + "ETHRegistrarController", + "LegacyETHRegistrarController", + "NameWrapper", + ] as const; + for (const name of v1ControllerNames) { + await v1.RegistrarSecurityController.write.removeRegistrarController( + [rocketh.get(name).address], + { account }, + ); + } + // add v2 eth controllers + await v1.RegistrarSecurityController.write.addRegistrarController( + [v2.Graveyard.address], + { account }, + ); + await v1.RegistrarSecurityController.write.addRegistrarController( + [v2.ETHRenewerV1.address], + { account }, + ); + // on fork, also grant deployer registrar-controller rights so morticia's + // e2e harness can call into v1.BaseRegistrar from the test mnemonic + // (matches the synthetic devnet's implicit "deployer can register" stance) + if (isFork) { + await v1.RegistrarSecurityController.write.addRegistrarController( + [namedAccounts.deployer.address], + { account }, + ); + } + // transfer to syncer for juggling + await v1.RegistrarSecurityController.write.transferRegistrarOwnership( + [v2.ETHRenewerV1.address], + { account }, + ); + // TODO: delay grant of registar/renewer-related roles until here? + } + + async function setupEnsDotEth() { + const { resolver } = namedAccounts.owner; + + // temporary registration of "ens.eth" by deployer + // (normally would be migrated by current ens.eth owner) + // Deployer has REGISTRAR_ADMIN but not REGISTRAR; grant self REGISTRAR for setup + await v2.ETHRegistry.write.grantRootRoles([ + ROLES.REGISTRY.REGISTRAR, + namedAccounts.deployer.address, + ]); + // create "ens.eth" (owner gets full roles for devnet setup) + await v2.ETHRegistry.write.register([ + "ens", + namedAccounts.owner.address, + zeroAddress, + resolver.address, + ROLES.ALL, + MAX_EXPIRY, + ]); + + await setName("namer", v2.ContractNamer.address); + + await setName("root", v2.RootRegistry.address); + await setName("registry", v2.ETHRegistry.address); + await setName("impl.registry", v2.UserRegistryImpl.address); + await setName("impl.wrapper-registry", v2.WrapperRegistryImpl.address); + + await setName("2to1.resolver", v2.ENSV1Resolver.address); + await setName("1to2.resolver", v2.ENSV2Resolver.address); + await setName("impl.resolver", v2.PermissionedResolverImpl.address); + // await setName("universal", v2.UniversalResolver.address); // devnet doesn't deploy a proxy + await setName("impl.universal", v2.UniversalResolver.address); + await setName("public.resolver", v2.PublicResolver.address); + await setName("dns.resolver", v2.DNSTLDResolver.address); + + await setName("dnsname", v2.DNSTXTResolver.address); // remap v1 ExtendedDNSResolver + await setName("dnstxt", v2.DNSTXTResolver.address); // TODO: could just use "dnsname"? + await setName("dnsalias", v2.DNSAliasResolver.address); + + await setName("registrar", v2.ETHRegistrar.address); + await setName("renewer", v2.ETHRenewerV1.address); + await setName("oracle", v2.StandardRentPriceOracle.address); + // await setName("batch.migration", v2.BatchRegistrar.address); // this is only used internally for premigration + await setName("addr.reverse", shared.ReverseRegistrarAdapter.address); + await setName( + "default.reverse", + shared.DefaultReverseRegistrarAdapter.address, + ); + + await setName( + "unlocked.migration", + v2.UnlockedMigrationController.address, + ); + await setName("locked.migration", v2.LockedMigrationController.address); + await setName("graveyard", v2.Graveyard.address); + // MigrationHelper + await setName("gate.wrapper-registry", v2.ApprovedUpgradeGate.address); + await setName("prset.migration", v2.PublicResolverSet.address); + + await setName("batch.gateways", shared.BatchGatewayProvider.address); + await setName("dnssec.gateways", shared.DNSSECGatewayProvider.address); + await setName("labelstore", v2.LabelStore.address); + await setName("verifiable-factory", v2.VerifiableFactory.address); + + async function setName( + prefix: string, + address: Address, + namer = namedAccounts.owner, + ) { + const name = `${prefix}.ens.eth`; + try { + await shared.ReverseRegistrarAdapter.write.claim( + [address, resolver.address], + { account: namer }, + ); + await resolver.write.setName([ + namehash(getReverseName(address)), + name, + ]); + } catch (err) { + console.log(`Cannot name: ${name}`); + } + await resolver.write.setAddr([namehash(name), 60n, address]); + } + } + + function handleTransferError(err: unknown): never { + // see: WrappedErrorLib.sol + const ERROR_STRING_SELECTOR = "0x08c379a0"; + const WRAPPED_ERROR_PREFIX = stringToHex("WrappedError::0x"); + if (err instanceof ContractFunctionExecutionError) { + if (err.cause instanceof ContractFunctionRevertedError) { + let { raw } = err.cause; + if (raw?.startsWith(ERROR_STRING_SELECTOR)) { + [raw] = decodeAbiParameters([{ type: "bytes" }], slice(raw, 4)); + if (raw.startsWith(WRAPPED_ERROR_PREFIX)) { + raw = `0x${hexToString(slice(raw, 16))}`; + } + } + const abi = [ + ...v2.UnlockedMigrationController.abi, + ...v2.LockedMigrationController.abi, + ...v2.WrapperRegistryImpl.abi, + ]; + const newErr = new ContractFunctionRevertedError({ + abi, + data: raw, + functionName: err.functionName, + }); + if (newErr.data) { + throw new ContractFunctionExecutionError(newErr, err); + } + } + } + throw err; + } } catch (err) { await shutdown(); throw err; @@ -485,59 +1017,3 @@ export async function setupDevnet({ unquiet(); } } - -async function setupEnsDotEth(deployment: Deployment, account: Account) { - // create registry for "ens.eth" - // const ens_ethRegistry = await deployment.deployPermissionedRegistry({ - // account, - // }); - - // created owned resolver for "ens.eth" - const resolver = await deployment.deployPermissionedResolver({ account }); - - // create "ens.eth" - await deployment.contracts.ETHRegistry.write.register([ - "ens", - account.address, - zeroAddress, //ens_ethRegistry.address, - resolver.address, - 0n, - MAX_EXPIRY, - ]); - - // create "dnsname.ens.eth" - // https://etherscan.io/address/0x08769D484a7Cd9c4A98E928D9E270221F3E8578c#code - await setupNamedResolver( - "dnsname", - await deployArtifact(deployment.client, { - file: new URL( - "../test/integration/dns/ExtendedDNSResolver_53f64de872aad627467a34836be1e2b63713a438.json", - import.meta.url, - ), - }), - ); - - // create "dnstxt.ens.eth" - await setupNamedResolver( - "dnstxt", - deployment.contracts.DNSTXTResolver.address, - ); - - // create "dnsalias.ens.eth" - await setupNamedResolver( - "dnsalias", - deployment.contracts.DNSAliasResolver.address, - ); - - async function setupNamedResolver(label: string, address: Address) { - await resolver.write.setAddr([namehash(`${label}.ens.eth`), 60n, address]); - // await ens_ethRegistry.write.register([ - // label, - // account.address, - // zeroAddress, - // resolver.address, - // 0n, - // MAX_EXPIRY, - // ]); - } -} diff --git a/contracts/script/solVersions.ts b/contracts/script/solVersions.ts index f0d7665d2..c8835505d 100755 --- a/contracts/script/solVersions.ts +++ b/contracts/script/solVersions.ts @@ -10,34 +10,34 @@ type Contract = { spec: string; file: string }; const specs: string[] = []; function uniqueColor(spec: string) { - let i = specs.indexOf(spec); - if (i < 0) { - i = specs.length; - specs.push(spec); - } - return `\x1b[${91 + (i % 6)}m${spec}\x1b[0m`; + let i = specs.indexOf(spec); + if (i < 0) { + i = specs.length; + specs.push(spec); + } + return `\x1b[${91 + (i % 6)}m${spec}\x1b[0m`; } -find(fileURLToPath(new URL("../src/", import.meta.url))) - .sort( - (a, b) => a.spec.localeCompare(b.spec) || a.file.localeCompare(b.file) - ) - .forEach((x) => console.log(uniqueColor(x.spec.padEnd(10)), x.file)); +const rootDir = fileURLToPath(new URL("../", import.meta.url)); +["src", "test"] + .flatMap((x) => find(join(rootDir, x), rootDir.length)) + .sort((a, b) => a.spec.localeCompare(b.spec) || a.file.localeCompare(b.file)) + .forEach((x) => console.log(uniqueColor(x.spec.padEnd(10)), x.file)); -function find(dir: string, found: Contract[] = [], skip = dir.length) { - for (const x of readdirSync(dir, { withFileTypes: true })) { - const path = join(dir, x.name); - if (x.isDirectory()) { - find(path, found, skip); - } else if (x.name.endsWith(".sol")) { - const code = readFileSync(path, { encoding: "utf-8" }); - const match = code.match(/^pragma solidity (.*?);/m); - if (!match) throw new Error(`expected pragma: ${path}`); - found.push({ - spec: match[1].trim(), - file: path.slice(skip), - }); - } - } - return found; +function find(dir: string, skip = dir.length, found: Contract[] = []) { + for (const x of readdirSync(dir, { withFileTypes: true })) { + const path = join(dir, x.name); + if (x.isDirectory()) { + find(path, skip, found); + } else if (x.name.endsWith(".sol")) { + const code = readFileSync(path, { encoding: "utf-8" }); + const match = code.match(/^pragma solidity (.*?);/m); + if (!match) throw new Error(`expected pragma: ${path}`); + found.push({ + spec: match[1].trim(), + file: path.slice(skip), + }); + } + } + return found; } diff --git a/contracts/script/testNames.ts b/contracts/script/testNames.ts index cad566841..37984a366 100644 --- a/contracts/script/testNames.ts +++ b/contracts/script/testNames.ts @@ -1,928 +1,47 @@ -import { - type Address, - type TransactionReceipt, - decodeFunctionResult, - encodeFunctionData, - getContract, - namehash, - zeroAddress, -} from "viem"; +import { encodeFunctionData, getContract, namehash, zeroAddress } from "viem"; -import { artifacts } from "@rocketh"; +import { Artifact_PermissionedResolver } from "generated/artifacts/PermissionedResolver.js"; import { MAX_EXPIRY, ROLES, STATUS } from "./deploy-constants.js"; -import { dnsEncodeName, idFromLabel } from "../test/utils/utils.js"; +import { dnsEncodeName, dnsDecodeName } from "../test/utils/utils.js"; import type { DevnetEnvironment } from "./setup.js"; - -// ========== Constants ========== - -const ONE_DAY_SECONDS = 86400; - -const PermissionedResolverAbi = artifacts.PermissionedResolver.abi; - -// ========== Gas Tracking ========== - -type GasRecord = { - operation: string; - gasUsed: bigint; - effectiveGasPrice?: bigint; - totalCost?: bigint; +import { + trackGas, + displayGasReport, + resetGasTracker, +} from "./testNames/gas.js"; +import { + getNameData, + createSubname, + linkName, + transferName, + changeRole, + reserveName, + unregisterName, +} from "./testNames/registry.js"; +import { + registerTestNames, + reregisterName, + renewName, +} from "./testNames/registrar.js"; +import { showName, showAlias, formatStatus } from "./testNames/display.js"; + +// Re-export all utilities for external consumers +export { + showName, + showAlias, + createSubname, + linkName, + renewName, + transferName, + changeRole, + registerTestNames, + reregisterName, + reserveName, + unregisterName, }; -const gasTracker: GasRecord[] = []; - -async function trackGas( - operation: string, - receipt: TransactionReceipt, -): Promise { - const gasUsed = BigInt(receipt.gasUsed); - const effectiveGasPrice = receipt.effectiveGasPrice - ? BigInt(receipt.effectiveGasPrice) - : 0n; - gasTracker.push({ - operation, - gasUsed, - effectiveGasPrice, - totalCost: gasUsed * effectiveGasPrice, - }); -} - -function displayGasReport() { - if (gasTracker.length === 0) { - console.log("\nNo gas data collected."); - return; - } - - console.log("\n========== Gas Usage Report =========="); - - const groupedByFunction = new Map(); - - for (const { operation, gasUsed } of gasTracker) { - const functionName = operation.split("(")[0]; - if (!groupedByFunction.has(functionName)) { - groupedByFunction.set(functionName, []); - } - groupedByFunction.get(functionName)!.push(gasUsed); - } - - const reportData = Array.from(groupedByFunction.entries()).map( - ([functionName, gasValues]) => { - const count = gasValues.length; - const total = gasValues.reduce((sum, val) => sum + val, 0n); - const avg = total / BigInt(count); - const min = gasValues.reduce( - (min, val) => (val < min ? val : min), - gasValues[0], - ); - const max = gasValues.reduce( - (max, val) => (val > max ? val : max), - gasValues[0], - ); - - return { - Function: functionName, - Calls: count, - "Avg Gas": avg.toString(), - "Min Gas": min.toString(), - "Max Gas": max.toString(), - "Total Gas": total.toString(), - }; - }, - ); - - console.table(reportData); - - const totalGas = gasTracker.reduce((sum, { gasUsed }) => sum + gasUsed, 0n); - const totalCostWei = gasTracker.reduce( - (sum, { totalCost }) => sum + (totalCost || 0n), - 0n, - ); - - console.log(`\nTotal Gas Used: ${totalGas.toString()}`); - console.log(`Total Cost: ${totalCostWei.toString()} wei`); - console.log(`Total Transactions: ${gasTracker.length}`); - console.log("======================================\n"); -} - -function resetGasTracker() { - gasTracker.length = 0; -} - -// ========== Helper Functions ========== - -/** - * Parse an ENS name into its components - */ -function parseName(name: string): { - label: string; - parentName: string; - parts: string[]; - isSecondLevel: boolean; - tld: string; -} { - const parts = name.split("."); - const tld = parts[parts.length - 1]; - - if (tld !== "eth") { - throw new Error(`Name must end with .eth, got: ${name}`); - } - - return { - label: parts[0], - parentName: parts.slice(1).join("."), - parts, - isSecondLevel: parts.length === 2, - tld, - }; -} - -/** - * Create a UserRegistry contract instance - */ -function getRegistryContract( - env: DevnetEnvironment, - registryAddress: `0x${string}`, -) { - return getContract({ - address: registryAddress, - abi: artifacts.UserRegistry.abi, - client: env.deployment.client, - }); -} - -/** - * Deploy a resolver and set default records - */ -async function deployResolverWithRecords( - env: DevnetEnvironment, - account: any, - name: string, - records: { - description?: string; - address?: Address; - }, - shouldTrackGas: boolean = false, -) { - const resolver = await env.deployment.deployPermissionedResolver({ account }); - const node = namehash(name); - - if (shouldTrackGas) { - await trackGas("deployResolver", resolver.deploymentReceipt); - } - - // Set ETH address (coin type 60) - if (records.address) { - const { receipt } = await env.waitFor( - resolver.write.setAddr([node, 60n, records.address], { account }), - ); - if (shouldTrackGas) await trackGas(`setAddr(${name})`, receipt); - } - - // Set description text record - if (records.description) { - const { receipt } = await env.waitFor( - resolver.write.setText([node, "description", records.description], { - account, - }), - ); - if (shouldTrackGas) await trackGas(`setText(${name})`, receipt); - } - - return resolver; -} - -/** - * Get parent name data and validate it has a subregistry - */ -async function getParentWithSubregistry( - env: DevnetEnvironment, - parentName: string, -): Promise<{ - data: NonNullable>>; - registry: ReturnType; -}> { - const data = await traverseRegistry(env, parentName); - if (!data || data.owner === zeroAddress) { - throw new Error(`${parentName} does not exist or has no owner`); - } - - if (!data.subregistry || data.subregistry === zeroAddress) { - throw new Error(`${parentName} has no subregistry`); - } - - return { - data, - registry: getRegistryContract(env, data.subregistry), - }; -} - -async function traverseRegistry( - env: DevnetEnvironment, - name: string, -): Promise<{ - owner?: `0x${string}`; - expiry?: bigint; - resolver?: `0x${string}`; - subregistry?: `0x${string}`; - registry?: `0x${string}`; -} | null> { - const nameParts = name.split("."); - - if (nameParts[nameParts.length - 1] !== "eth") { - return null; - } - - let currentRegistry = env.deployment.contracts.ETHRegistry; - - // Traverse from right to left: e.g., ["sub1", "sub2", "parent", "eth"] - for (let i = nameParts.length - 2; i >= 0; i--) { - const label = nameParts[i]; - - const [state, resolver, subregistry] = await Promise.all([ - currentRegistry.read.getState([idFromLabel(label)]), - currentRegistry.read.getResolver([label]), - currentRegistry.read.getSubregistry([label]), - ]); - - if (i === 0) { - // This is the final name/subname - const owner = await currentRegistry.read.ownerOf([state.tokenId]); - return { - owner, - expiry: state.expiry, - resolver, - subregistry, - registry: currentRegistry.address, - }; - } - - // Move to the subregistry - if (subregistry === zeroAddress) { - return null; - } - currentRegistry = getRegistryContract(env, subregistry) as any; - } - - return null; -} - -// ========== Main Functions ========== - -// Display name information -export async function showName(env: DevnetEnvironment, names: string[]) { - await env.sync(); - - const nameData = []; - - for (const name of names) { - const nameHash = namehash(name); - - const { label } = parseName(name); - - let owner: `0x${string}` | undefined = undefined; - let expiryDate: string = "N/A"; - let registryAddress: `0x${string}` | undefined = undefined; - - const data = await traverseRegistry(env, name); - if (data?.owner && data.owner !== zeroAddress) { - owner = data.owner; - registryAddress = data.registry; - if (data.expiry) { - const expiryTimestamp = Number(data.expiry); - if (data.expiry === MAX_EXPIRY || expiryTimestamp === 0) { - expiryDate = "Never"; - } else { - expiryDate = new Date(expiryTimestamp * 1000).toISOString(); - } - } - } - - const actualResolver = data?.resolver; - - // Batch addr and text resolution using resolver multicall - const resolverCalls = [ - encodeFunctionData({ - abi: PermissionedResolverAbi, - functionName: "addr", - args: [nameHash], - }), - encodeFunctionData({ - abi: PermissionedResolverAbi, - functionName: "text", - args: [nameHash, "description"], - }), - ]; - - const multicallData = encodeFunctionData({ - abi: PermissionedResolverAbi, - functionName: "multicall", - args: [resolverCalls], - }); - - // Single UniversalResolver call with multicall - const [result] = - await env.deployment.contracts.UniversalResolverV2.read.resolve([ - dnsEncodeName(name), - multicallData, - ]); - - // Decode the multicall result - returns array of bytes directly - const results = - result && result !== "0x" - ? (decodeFunctionResult({ - abi: PermissionedResolverAbi, - functionName: "multicall", - data: result, - }) as readonly `0x${string}`[]) - : []; - - // Decode individual results - const ethAddress = - results[0] && results[0] !== "0x" - ? (decodeFunctionResult({ - abi: PermissionedResolverAbi, - functionName: "addr", - data: results[0], - }) as string) - : undefined; - - const description = - results[1] && results[1] !== "0x" - ? (decodeFunctionResult({ - abi: PermissionedResolverAbi, - functionName: "text", - data: results[1], - }) as string) - : undefined; - - const truncateAddress = (addr: string | undefined) => { - if (!addr || addr === "0x") return "-"; - return addr.slice(0, 7); - }; - - nameData.push({ - Name: name, - Registry: truncateAddress(registryAddress), - Owner: truncateAddress(owner), - Expiry: expiryDate === "Never" ? "Never" : expiryDate.split("T")[0], - Resolver: truncateAddress(actualResolver), - Address: truncateAddress(ethAddress), - Description: description || "-", - }); - } - - console.log(`\nName Information:`); - console.table(nameData); -} - -// Create a subname (and all parent names if they don't exist) -export async function createSubname( - env: DevnetEnvironment, - fullName: string, - account = env.namedAccounts.owner, -): Promise { - const createdNames: string[] = []; - - // Parse the name - const { parts } = parseName(fullName); - - // Start from the parent name (e.g., "parent.eth") - const parentLabel = parts[parts.length - 2]; - const parentName = `${parentLabel}.eth`; - - console.log(`\nCreating subname: ${fullName}`); - console.log(`Parent name: ${parentName}`); - - // Get parent tokenId (assumes parent.eth already exists) - const parentTokenId = - await env.deployment.contracts.ETHRegistry.read.getTokenId([ - idFromLabel(parentLabel), - ]); - - // For each level of subnames, create UserRegistry and register - let currentParentTokenId = parentTokenId; - let currentRegistryAddress: `0x${string}` = - env.deployment.contracts.ETHRegistry.address; - let currentName = parentName; - - // Process subname parts from right to left (parent to child) - // e.g., for "sub1.sub2.parent.eth", process in order: sub2, sub1 - for (let i = parts.length - 3; i >= 0; i--) { - const label = parts[i]; - currentName = `${label}.${currentName}`; - - console.log(`\nProcessing level: ${currentName}`); - - // Check if current parent has a subregistry - let subregistryAddress: `0x${string}`; - - if ( - currentRegistryAddress === env.deployment.contracts.ETHRegistry.address - ) { - // Parent is in ETHRegistry - subregistryAddress = - await env.deployment.contracts.ETHRegistry.read.getSubregistry([ - parts[i + 1], - ]); - } else { - // Parent is in a UserRegistry - const parentRegistry = getRegistryContract(env, currentRegistryAddress); - subregistryAddress = await parentRegistry.read.getSubregistry([ - parts[i + 1], - ]); - } - - // Deploy UserRegistry if it doesn't exist - if (subregistryAddress === zeroAddress) { - console.log(`Deploying UserRegistry for ${currentName}...`); - - const userRegistry = await env.deployment.deployUserRegistry({ - account, - }); - subregistryAddress = userRegistry.address; - - // Set as subregistry on parent - if ( - currentRegistryAddress === env.deployment.contracts.ETHRegistry.address - ) { - await env.deployment.contracts.ETHRegistry.write.setSubregistry( - [currentParentTokenId, subregistryAddress], - { account }, - ); - } else { - const parentRegistry = getRegistryContract(env, currentRegistryAddress); - await parentRegistry.write.setSubregistry( - [currentParentTokenId, subregistryAddress], - { account }, - ); - } - - console.log(`✓ UserRegistry deployed at ${subregistryAddress}`); - } - - // Register the subname in the UserRegistry - const userRegistry = getRegistryContract(env, subregistryAddress); - - // Check if already registered and if it's expired - const state = await userRegistry.read.getState([idFromLabel(label)]); - - if (state.status === STATUS.REGISTERED) { - console.log(`✓ ${currentName} already exists and is not expired`); - } else { - if (state.latestOwner !== zeroAddress) { - console.log( - `${currentName} exists but is expired, re-registering with MAX_EXPIRY...`, - ); - } else { - console.log(`Registering ${currentName}...`); - } - - // Deploy resolver for this subname - const resolver = await deployResolverWithRecords( - env, - account, - currentName, - { - description: currentName, - address: account.address, - }, - ); - console.log(`✓ Resolver deployed at ${resolver.address}`); - - await userRegistry.write.register( - [ - label, - account.address, - zeroAddress, // no nested subregistry yet - resolver.address, - ROLES.ALL, - MAX_EXPIRY, - ], - { account }, - ); - - console.log(`✓ Registered ${currentName}`); - createdNames.push(currentName); - } - - // Update for next iteration - currentParentTokenId = state.tokenId; - currentRegistryAddress = subregistryAddress; - } - return createdNames; -} - -/** - * Link a name to appear under a different parent by pointing to the same subregistry. - * This creates multiple "entry points" into the same child namespace. - * - * @param sourceName - The existing name whose subregistry we want to link (e.g., "sub1.sub2.parent.eth") - * @param targetParentName - The parent under which we want to create a linked entry (e.g., "parent.eth") - * @param linkLabel - The label for the linked name - * - * Example: - * linkName(env, "sub1.sub2.parent.eth", "parent.eth", "linked") - * Creates "linked.parent.eth" that shares children with "sub1.sub2.parent.eth" - */ -export async function linkName( - env: DevnetEnvironment, - sourceName: string, - targetParentName: string, - linkLabel: string, - account = env.namedAccounts.owner, -) { - console.log(`\nLinking name: ${sourceName} to parent: ${targetParentName}`); - - // Parse and validate source name - const { - label: sourceLabel, - parentName: sourceParentName, - isSecondLevel, - } = parseName(sourceName); - - if (isSecondLevel) { - throw new Error( - `Cannot link second-level names directly. Source must be a subname.`, - ); - } - - // Get source name data - const sourceData = await traverseRegistry(env, sourceName); - if (!sourceData || sourceData.owner === zeroAddress) { - throw new Error(`Source name ${sourceName} does not exist or has no owner`); - } - - // Get source parent registry and validate - const { registry: sourceRegistry } = await getParentWithSubregistry( - env, - sourceParentName, - ); - const subregistry = await sourceRegistry.read.getSubregistry([sourceLabel]); - - if (subregistry === zeroAddress) { - throw new Error(`Source name ${sourceName} has no subregistry to link`); - } - - console.log(`Source subregistry: ${subregistry}`); - - // Get target parent registry and validate - const { registry: targetRegistry } = await getParentWithSubregistry( - env, - targetParentName, - ); - const linkedName = `${linkLabel}.${targetParentName}`; - - console.log(`Creating linked name: ${linkedName}`); - - // Check if the label already exists in the target registry - const existingTokenId = await targetRegistry.read.getTokenId([ - idFromLabel(linkLabel), - ]); - const existingOwner = await targetRegistry.read.ownerOf([existingTokenId]); - - if (existingOwner !== zeroAddress) { - console.log( - `Warning: ${linkedName} already exists. Updating its subregistry...`, - ); - await targetRegistry.write.setSubregistry([existingTokenId, subregistry], { - account, - }); - console.log(`✓ Updated ${linkedName} to point to shared subregistry`); - } else { - console.log(`Deploying resolver for ${linkedName}...`); - const resolver = await deployResolverWithRecords(env, account, linkedName, { - description: `Linked to ${sourceName}`, - address: account.address, - }); - console.log(`✓ Resolver deployed at ${resolver.address}`); - - await targetRegistry.write.register( - [ - linkLabel, - account.address, - subregistry, - resolver.address, - ROLES.ALL, - MAX_EXPIRY, - ], - { account }, - ); - - console.log(`✓ Registered ${linkedName} with shared subregistry`); - } - - console.log(`\n✓ Link complete!`); - console.log( - `Children of ${sourceName} and ${linkedName} now resolve to the same place.`, - ); - console.log( - `Example: wallet.${sourceName} and wallet.${linkedName} are the same token.`, - ); -} - -// Renew a name -export async function renewName( - env: DevnetEnvironment, - name: string, - durationInDays: number, - account = env.namedAccounts.owner, -) { - const { label } = parseName(name); - - const expiry = await env.deployment.contracts.ETHRegistry.read.getExpiry([ - idFromLabel(label), - ]); - - console.log(`\nRenewing ${name}...`); - if (expiry === MAX_EXPIRY) { - console.log(`Current expiry: Never (MAX_EXPIRY)`); - } else { - const currentExpiry = Number(expiry); - console.log( - `Current expiry: ${new Date(currentExpiry * 1000).toISOString()}`, - ); - } - console.log(`Extending by: ${durationInDays} days`); - - const duration = BigInt(durationInDays * ONE_DAY_SECONDS); - const paymentToken = env.deployment.contracts.MockUSDC.address; - const referrer = - "0x0000000000000000000000000000000000000000000000000000000000000000"; - - const [price] = await env.deployment.contracts.ETHRegistrar.read.rentPrice([ - label, - account.address, - duration, - paymentToken, - ]); - - console.log(`Renewal price: ${price}`); - - const balance = await env.deployment.contracts.MockUSDC.read.balanceOf([ - account.address, - ]); - console.log(`Current balance: ${balance}`); - - if (balance < price) { - const amountToMint = price - balance + 1000000n; - console.log(`Minting ${amountToMint} tokens...`); - await env.deployment.contracts.MockUSDC.write.mint( - [account.address, amountToMint], - { account }, - ); - } - - await env.deployment.contracts.MockUSDC.write.approve( - [env.deployment.contracts.ETHRegistrar.address, price], - { account }, - ); - - const { receipt } = await env.waitFor( - env.deployment.contracts.ETHRegistrar.write.renew( - [label, duration, paymentToken, referrer], - { account }, - ), - ); - - const newExpiry = Number( - await env.deployment.contracts.ETHRegistry.read.getExpiry([ - idFromLabel(label), - ]), - ); - console.log(`New expiry: ${new Date(newExpiry * 1000).toISOString()}`); - console.log(`✓ Renewal completed`); - - return receipt; -} - -// Transfer a name to a new owner -export async function transferName( - env: DevnetEnvironment, - name: string, - newOwner: `0x${string}`, - account = env.namedAccounts.owner, -) { - const { label } = parseName(name); - - const tokenId = await env.deployment.contracts.ETHRegistry.read.getTokenId([ - idFromLabel(label), - ]); - - console.log(`\nTransferring ${name}...`); - console.log(`TokenId: ${tokenId}`); - console.log(`From: ${account.address}`); - console.log(`To: ${newOwner}`); - - const { receipt } = await env.waitFor( - env.deployment.contracts.ETHRegistry.write.safeTransferFrom( - [account.address, newOwner, tokenId, 1n, "0x"], - { account }, - ), - ); - - console.log(`✓ Transfer completed`); - - return receipt; -} - -// Change roles for a name -export async function changeRole( - env: DevnetEnvironment, - name: string, - targetAccount: `0x${string}`, - rolesToGrant: bigint, - rolesToRevoke: bigint, - account = env.namedAccounts.owner, -) { - const { label } = parseName(name); - - const tokenId = await env.deployment.contracts.ETHRegistry.read.getTokenId([ - idFromLabel(label), - ]); - - console.log( - `\nChanging roles for ${name} (TokenId: ${tokenId}, Target: ${targetAccount}, Grant: ${rolesToGrant}, Revoke: ${rolesToRevoke})`, - ); - - const receipts: TransactionReceipt[] = []; - - if (rolesToGrant > 0n) { - const { receipt } = await env.waitFor( - env.deployment.contracts.ETHRegistry.write.grantRoles( - [tokenId, rolesToGrant, targetAccount], - { account }, - ), - ); - receipts.push(receipt); - } - - if (rolesToRevoke > 0n) { - const { receipt } = await env.waitFor( - env.deployment.contracts.ETHRegistry.write.revokeRoles( - [tokenId, rolesToRevoke, targetAccount], - { account }, - ), - ); - receipts.push(receipt); - } - - const newTokenId = await env.deployment.contracts.ETHRegistry.read.getTokenId( - [idFromLabel(label)], - ); - console.log(`TokenId changed from ${tokenId} to ${newTokenId}`); - - return receipts; -} - -// Register default test names -export async function registerTestNames( - env: DevnetEnvironment, - labels: string[], - options: { - account?: any; - expiry?: bigint; - registrarAccount?: any; - trackGas?: boolean; - } = {}, -) { - const account = options.account ?? env.namedAccounts.owner; - const registrarAccount = - options.registrarAccount ?? env.namedAccounts.deployer; - const shouldTrackGas = options.trackGas ?? false; - const currentTimestamp = await env.deployment.client - .getBlock() - .then((b) => b.timestamp); - - for (const label of labels) { - const resolver = await env.deployment.deployPermissionedResolver({ - account, - }); - - if (shouldTrackGas) - await trackGas("deployOwnedResolver", resolver.deploymentReceipt); - - let expiry: bigint; - if (options.expiry !== undefined) { - expiry = options.expiry; - } else { - expiry = currentTimestamp + BigInt(ONE_DAY_SECONDS); - } - - const registerTx = await env.waitFor( - env.deployment.contracts.ETHRegistry.write.register( - [ - label, - account.address, - zeroAddress, - resolver.address, - ROLES.ALL, - expiry, - ], - { account: registrarAccount }, - ), - ); - - if (shouldTrackGas) { - await trackGas(`register(${label})`, registerTx.receipt); - } - - const node = namehash(`${label}.eth`); - const setAddrTx = await env.waitFor( - resolver.write.setAddr( - [ - node, - 60n, // ETH coin type - account.address, - ], - { account }, - ), - ); - - if (shouldTrackGas) { - await trackGas(`setAddr(${label})`, setAddrTx.receipt); - } - - const setTextTx = await env.waitFor( - resolver.write.setText([node, "description", `${label}.eth`], { - account, - }), - ); - - if (shouldTrackGas) { - await trackGas(`setText(${label})`, setTextTx.receipt); - } - } -} - -// Test re-registration of an expired name -export async function reregisterName( - env: DevnetEnvironment, - label: string, - account = env.namedAccounts.owner, -) { - console.log( - `\n=== Testing Re-registration of Expired Name: ${label}.eth ===`, - ); - - const initialExpiry = - await env.deployment.contracts.ETHRegistry.read.getExpiry([ - idFromLabel(label), - ]); - console.log( - `Initial expiry: ${new Date(Number(initialExpiry) * 1000).toISOString()}`, - ); - - // Time warp past expiry - const warpSeconds = ONE_DAY_SECONDS + 1; - console.log(`\nTime warping ${warpSeconds} seconds...`); - await env.sync({ warpSec: warpSeconds }); - - console.log( - `\nCurrent onchain timestamp: ${new Date(Number(await env.deployment.client.getBlock().then((b) => b.timestamp)) * 1000).toISOString()}`, - ); - console.log( - `\nCurrent onchain expiry: ${new Date(Number(initialExpiry) * 1000).toISOString()}`, - ); - - // Verify name is available for re-registration - const isAvailable = - await env.deployment.contracts.ETHRegistrar.read.isAvailable([label]); - console.log(`Name available for re-registration: ${isAvailable}`); - - if (!isAvailable) { - throw new Error(`${label}.eth should be available after expiry`); - } - - // Re-register with proper expiry based on blockchain time - console.log(`\nRe-registering ${label}.eth...`); - - const currentBlock = await env.deployment.client.getBlock(); - const newExpiry = currentBlock.timestamp + BigInt(ONE_DAY_SECONDS); - - await registerTestNames(env, [label], { - account, - expiry: newExpiry, - }); - - // Verify re-registration succeeded - const reregisteredExpiry = Number( - await env.deployment.contracts.ETHRegistry.read.getExpiry([ - idFromLabel(label), - ]), - ); - console.log( - `New expiry: ${new Date(reregisteredExpiry * 1000).toISOString()}`, - ); - - if (reregisteredExpiry <= initialExpiry) { - throw new Error( - `Re-registration failed: new expiry (${reregisteredExpiry}) should be greater than initial expiry (${initialExpiry})`, - ); - } - - console.log( - `✓ Re-registration successful! Expiry extended from ${initialExpiry} to ${reregisteredExpiry}`, - ); -} +const ONE_DAY_SECONDS = 86400; +const PermissionedResolverAbi = Artifact_PermissionedResolver.abi; /** * Set up test names with various states and configurations for development/testing @@ -937,10 +56,19 @@ export async function testNames(env: DevnetEnvironment) { // Re-register reregister (with time warp, do first to avoid expiring other names) await reregisterName(env, "reregister"); - // Register all other test names with default 1 day expiry + // Register all other test names with default 28 day expiry await registerTestNames( env, - ["test", "example", "demo", "newowner", "renew", "parent", "changerole"], + [ + "test", + "example", + "demo", + "newowner", + "renew", + "parent", + "changerole", + "unregistered", + ], { trackGas: true }, ); @@ -950,41 +78,89 @@ export async function testNames(env: DevnetEnvironment) { "newowner.eth", env.namedAccounts.user.address, ); - await trackGas("transfer(newowner)", transferReceipt); + trackGas("transfer(newowner)", transferReceipt); // Renew renew.eth for 365 days const renewReceipt = await renewName(env, "renew.eth", 365); - await trackGas("renew(renew)", renewReceipt); + trackGas("renew(renew)", renewReceipt); // Register alias.eth pointing to test.eth's resolver, then set alias console.log("\nCreating alias: alias.eth → test.eth"); - const testNameData = await traverseRegistry(env, "test.eth"); + const testNameData = await getNameData(env, "test.eth"); if (!testNameData?.resolver || testNameData.resolver === zeroAddress) { throw new Error("test.eth has no resolver set"); } - const currentTimestamp = await env.deployment.client - .getBlock() - .then((b) => b.timestamp); - const aliasExpiry = currentTimestamp + BigInt(ONE_DAY_SECONDS); - const aliasRegisterTx = await env.waitFor( - env.deployment.contracts.ETHRegistry.write.register( + + // Commit-reveal for alias.eth, using test.eth's resolver + const aliasSecret = + "0x00000000000000000000000000000000000000000000000000000000000000ff"; + const aliasDuration = BigInt(28 * ONE_DAY_SECONDS); + const aliasPaymentToken = env.erc20.MockUSDC.address; + const aliasReferrer = + "0x0000000000000000000000000000000000000000000000000000000000000000"; + + const aliasCommitment = await env.v2.ETHRegistrar.read.makeCommitment([ + "alias", + env.namedAccounts.owner.address, + aliasSecret, + zeroAddress, + testNameData.resolver, + aliasDuration, + aliasReferrer, + ]); + const aliasCommitReceipt = await env.waitFor( + env.v2.ETHRegistrar.write.commit([aliasCommitment], { + account: env.namedAccounts.owner, + }), + ); + trackGas("commit(alias)", aliasCommitReceipt); + + const minAge = await env.v2.ETHRegistrar.read.MIN_COMMITMENT_AGE(); + await env.sync({ warpSec: Number(minAge) + 1 }); + + const [aliasBase, aliasPremium] = + await env.v2.StandardRentPriceOracle.read.getRegisterPrice([ + "alias", + MAX_EXPIRY, + aliasDuration, + aliasPaymentToken, + ]); + const aliasPrice = aliasBase + aliasPremium; + const aliasBalance = await env.erc20.MockUSDC.read.balanceOf([ + env.namedAccounts.owner.address, + ]); + if (aliasBalance < aliasPrice) { + await env.erc20.MockUSDC.write.mint( + [env.namedAccounts.owner.address, aliasPrice - aliasBalance + 1000000n], + { account: env.namedAccounts.owner }, + ); + } + await env.erc20.MockUSDC.write.approve( + [env.v2.ETHRegistrar.address, aliasPrice], + { account: env.namedAccounts.owner }, + ); + + const aliasRegisterReceipt = await env.waitFor( + env.v2.ETHRegistrar.write.register( [ "alias", env.namedAccounts.owner.address, + aliasSecret, zeroAddress, testNameData.resolver, - ROLES.ALL, - aliasExpiry, + aliasDuration, + aliasPaymentToken, + aliasReferrer, ], - { account: env.namedAccounts.deployer }, + { account: env.namedAccounts.owner }, ), ); - await trackGas("register(alias)", aliasRegisterTx.receipt); + trackGas("register(alias)", aliasRegisterReceipt); const testResolver = getContract({ address: testNameData.resolver, abi: PermissionedResolverAbi, - client: env.deployment.client, + client: env.client, }); const aliasTx = await env.waitFor( testResolver.write.setAlias( @@ -992,7 +168,7 @@ export async function testNames(env: DevnetEnvironment) { { account: env.namedAccounts.owner }, ), ); - await trackGas("setAlias(alias→test)", aliasTx.receipt); + trackGas("setAlias(alias→test)", aliasTx); console.log("✓ alias.eth → test.eth alias created"); // Set records for sub.test.eth on test.eth's resolver so sub.alias.eth resolves via alias @@ -1003,39 +179,84 @@ export async function testNames(env: DevnetEnvironment) { const setSubAddrTx = await env.waitFor( testResolver.write.setAddr( [subTestNode, 60n, env.namedAccounts.owner.address], - { account: env.namedAccounts.owner }, + { + account: env.namedAccounts.owner, + }, ), ); - await trackGas("setAddr(sub.test.eth)", setSubAddrTx.receipt); + trackGas("setAddr(sub.test.eth)", setSubAddrTx); const setSubTextTx = await env.waitFor( testResolver.write.setText( [subTestNode, "description", "sub.test.eth (via alias)"], { account: env.namedAccounts.owner }, ), ); - await trackGas("setText(sub.test.eth)", setSubTextTx.receipt); + trackGas("setText(sub.test.eth)", setSubTextTx); console.log( "✓ sub.test.eth records set — sub.alias.eth should resolve via alias", ); - // Create subnames - const createdSubnames = await createSubname( - env, - "wallet.sub1.sub2.parent.eth", - ); + // Create sub2.parent.eth with 1-year expiry to demonstrate subname expiration + const { timestamp } = await env.client.getBlock(); + const sub2Names = await createSubname(env, "sub2.parent.eth", { + expiry: timestamp + BigInt(365 * ONE_DAY_SECONDS), + }); + + await createSubname(env, "sub2.parent.eth"); + + // Create remaining subname levels (sub2 already exists, will be skipped) + const deeperNames = await createSubname(env, "wallet.sub1.sub2.parent.eth"); + + // Verify setParent works by checking both findCanonicalRegistry and findCanonicalName. + // These only work when setParent is correctly set on every UserRegistry in the chain. + // findCanonicalRegistry: walks top-down to find the registry, then verifies bottom-up. + // findCanonicalName: walks bottom-up from a registry to root, building the DNS name. + const namesWithSubregistries = [ + "parent.eth", + "sub2.parent.eth", + "sub1.sub2.parent.eth", + ]; + for (const name of namesWithSubregistries) { + const canonicalRegistry = + await env.v2.UniversalResolver.read.findCanonicalRegistry([ + dnsEncodeName(name), + ]); + if (canonicalRegistry === zeroAddress) { + throw new Error( + `findCanonicalRegistry failed for ${name} — setParent may be missing`, + ); + } + + const canonicalNameBytes = + await env.v2.UniversalResolver.read.findCanonicalName([ + canonicalRegistry, + ]); + const canonicalName = + canonicalNameBytes && canonicalNameBytes !== "0x" + ? dnsDecodeName(canonicalNameBytes) + : ""; + if (canonicalName !== name) { + throw new Error( + `findCanonicalName mismatch for ${name}: got "${canonicalName}"`, + ); + } + console.log( + `✓ setParent verified: ${name} ↔ ${canonicalRegistry.slice(0, 9)}..`, + ); + } // Link sub1.sub2.parent.eth to parent.eth with different label (creates linked.parent.eth with shared children) // Now wallet.linked.parent.eth and wallet.sub1.sub2.parent.eth will be the same token - await linkName(env, "sub1.sub2.parent.eth", "parent.eth", "linked"); + await linkName(env, "sub1.sub2.parent.eth", "linked.parent.eth"); - // With OwnedResolver (node-keyed), children of linked names need an alias so + // With PermissionedResolver (node-keyed), children of linked names need an alias so // that wallet.linked.parent.eth resolves to the same records as wallet.sub1.sub2.parent.eth - const walletData = await traverseRegistry(env, "wallet.sub1.sub2.parent.eth"); + const walletData = await getNameData(env, "wallet.sub1.sub2.parent.eth"); if (walletData?.resolver && walletData.resolver !== zeroAddress) { const walletResolver = getContract({ address: walletData.resolver, abi: PermissionedResolverAbi, - client: env.deployment.client, + client: env.client, }); await walletResolver.write.setAlias( [ @@ -1058,7 +279,27 @@ export async function testNames(env: DevnetEnvironment) { ROLES.REGISTRY.SET_SUBREGISTRY, ); for (const receipt of roleReceipts) { - await trackGas("changeRole(changerole)", receipt); + trackGas("changeRole(changerole)", receipt); + } + + // Reserve a name (no owner, no token minted) + { + const name = "reserved.eth"; + const reserveReceipt = await reserveName(env, name); + trackGas(`reserve(${name})`, reserveReceipt); + } + + // Register then unregister a name + // note: no one has permissions to unregister an .eth 2LD + { + const name = "sub.unregistered.eth"; + await createSubname(env, name); + const unregisterReceipt = await unregisterName( + env, + name, + env.namedAccounts.owner, + ); + trackGas(`unregister(${name})`, unregisterReceipt); } const allNames = [ @@ -1072,13 +313,26 @@ export async function testNames(env: DevnetEnvironment) { "changerole.eth", "alias.eth", "sub.alias.eth", - ...createdSubnames, + "reserved.eth", + "unregistered.eth", + "sub.unregistered.eth", + ...sub2Names, + ...deeperNames, "linked.parent.eth", "wallet.linked.parent.eth", ]; await showName(env, allNames); + // Show alias mappings for names that may have aliases + const aliasCandidates = [ + "alias.eth", + "sub.alias.eth", + "linked.parent.eth", + "wallet.linked.parent.eth", + ]; + await showAlias(env, aliasCandidates); + // Verify all names are properly registered await verifyNames(env, allNames); @@ -1090,49 +344,64 @@ export async function testNames(env: DevnetEnvironment) { async function verifyNames(env: DevnetEnvironment, names: string[]) { console.log("\n========== Verifying Names ==========\n"); - const errors: string[] = []; + const remainder = new Set(names); + + // Names that are reserved (no owner, no token) + for (const name of ["reserved.eth"]) { + remainder.delete(name); + const data = await getNameData(env, name); + if (data?.status !== STATUS.RESERVED) { + errors.push( + `${name}: expected RESERVED status (${formatStatus(STATUS.RESERVED)}), got ${formatStatus(data?.status)}`, + ); + } + } - // Names that resolve only via alias (not directly registered in registry) - const aliasOnlyNames = new Set(["sub.alias.eth"]); + // Names that were unregistered (back to AVAILABLE) + for (const name of ["sub.unregistered.eth"]) { + remainder.delete(name); + const data = await getNameData(env, name); + if (data?.status !== STATUS.AVAILABLE) { + errors.push( + `${name}: expected AVAILABLE status (${formatStatus(STATUS.AVAILABLE)}), got ${formatStatus(data?.status)}`, + ); + } + } - for (const name of names) { - if (aliasOnlyNames.has(name)) { + // Names that resolve only via alias (not directly registered in registry) + for (const name of ["sub.alias.eth"]) { + remainder.delete(name); + try { + const addrCall = encodeFunctionData({ + abi: PermissionedResolverAbi, + functionName: "addr", + args: [namehash(name)], + }); // Verify alias resolution via UniversalResolver - try { - const addrCall = encodeFunctionData({ - abi: PermissionedResolverAbi, - functionName: "addr", - args: [namehash(name)], - }); - const [result] = - await env.deployment.contracts.UniversalResolverV2.read.resolve([ - dnsEncodeName(name), - addrCall, - ]); - if (!result || result === "0x") { - errors.push(`${name}: alias resolution returned empty result`); - } - } catch (e) { - errors.push(`${name}: alias resolution failed — ${e}`); - } - continue; + await env.v2.UniversalResolver.read.resolve([ + dnsEncodeName(name), + addrCall, + ]); + } catch (e) { + errors.push(`${name}: alias resolution failed — ${e}`); } + } - const data = await traverseRegistry(env, name); - - if (!data || !data.owner || data.owner === zeroAddress) { - errors.push(`${name}: not registered (no owner)`); + for (const name of remainder) { + const data = await getNameData(env, name); + if (data?.status !== STATUS.REGISTERED) { + errors.push( + `${name}: not registered (status: ${formatStatus(data?.status)})`, + ); continue; } - - if (!data.resolver || data.resolver === zeroAddress) { + if (data.resolver === zeroAddress) { errors.push(`${name}: no resolver set`); } - // Check expiry is in the future if (data.expiry && data.expiry !== MAX_EXPIRY) { - const currentTimestamp = await env.deployment.client + const currentTimestamp = await env.client .getBlock() .then((b) => b.timestamp); if (data.expiry <= currentTimestamp) { @@ -1144,23 +413,23 @@ async function verifyNames(env: DevnetEnvironment, names: string[]) { } // Verify specific ownership expectations - const newownerData = await traverseRegistry(env, "newowner.eth"); - if ( - newownerData?.owner && - newownerData.owner !== env.namedAccounts.user.address - ) { - errors.push( - `newowner.eth: expected owner ${env.namedAccounts.user.address}, got ${newownerData.owner}`, - ); + { + const name = "newowner.eth"; + const data = await getNameData(env, name); + if (data?.owner !== env.namedAccounts.user.address) { + errors.push( + `${name}: expected owner ${env.namedAccounts.user.address}, got ${data?.owner}`, + ); + } } - if (errors.length > 0) { + if (errors.length) { console.error("Verification FAILED:"); for (const err of errors) { console.error(` ✗ ${err}`); } throw new Error(`Name verification failed with ${errors.length} error(s)`); + } else { + console.log(`✓ All ${names.length} names verified successfully`); } - - console.log(`✓ All ${names.length} names verified successfully`); } diff --git a/contracts/script/testNames/display.ts b/contracts/script/testNames/display.ts new file mode 100644 index 000000000..282e4c1ab --- /dev/null +++ b/contracts/script/testNames/display.ts @@ -0,0 +1,160 @@ +import { + decodeFunctionResult, + encodeFunctionData, + getContract, + namehash, + zeroAddress, +} from "viem"; + +import type { DevnetEnvironment } from "../setup.js"; +import { MAX_EXPIRY, STATUS } from "../deploy-constants.js"; +import { dnsEncodeName } from "../../test/utils/utils.js"; +import { dnsDecodeName } from "../../lib/ens-contracts/test/fixtures/dnsDecodeName.js"; +import { getNameData } from "./registry.js"; + +/** + * Display name information in a formatted table + */ +export async function showName(env: DevnetEnvironment, names: string[]) { + await env.sync(); + + const nameData = []; + + for (const name of names) { + const node = namehash(name); + + const data = await getNameData(env, name); + const { abi } = env.v2.PermissionedResolverImpl; + + // Batch addr and text resolution using resolver multicall + const resolverCalls = [ + encodeFunctionData({ + abi, + functionName: "addr", + args: [node], + }), + encodeFunctionData({ + abi, + functionName: "text", + args: [node, "description"], + }), + ]; + + const multicallData = encodeFunctionData({ + abi, + functionName: "multicall", + args: [resolverCalls], + }); + + // Single UniversalResolver call with multicall + let ethAddress: string | undefined; + let description: string | undefined; + + try { + const [result] = await env.v2.UniversalResolver.read.resolve([ + dnsEncodeName(name), + multicallData, + ]); + + // Decode the multicall result - returns array of bytes directly + const results = decodeFunctionResult({ + abi, + functionName: "multicall", + data: result, + }) as readonly `0x${string}`[]; + + // Decode individual results + ethAddress = decodeFunctionResult({ + abi, + functionName: "addr", + data: results[0], + }); + description = decodeFunctionResult({ + abi, + functionName: "text", + data: results[1], + }) as string; + } catch { + // Resolution may fail for names without a resolver (e.g., reserved or unregistered names) + } + + nameData.push({ + Name: name, + Registry: truncateAddress(data?.parentRegistry.address), + Status: formatStatus(data?.status), + Owner: truncateAddress(data?.owner), + Expiry: formatExpiry(data?.expiry ?? 0n), + Resolver: truncateAddress(data?.resolver), + Address: truncateAddress(ethAddress), + Description: description || "-", + }); + } + + console.log(`\nName Information:`); + console.table(nameData); +} + +/** + * Display alias information for a list of candidate names. + * For each name, queries its resolver's getAlias() to check for alias mappings. + * Wildcard aliases (e.g., sub.alias.eth → sub.test.eth) are discovered automatically. + * + * NOTE: This uses Approach 1 (known candidates). For dynamic discovery via + * AliasChanged events, see Approach 2 (planned for the indexer script). + */ +export async function showAlias(env: DevnetEnvironment, names: string[]) { + const aliasData = []; + + for (const name of names) { + const [resolverAddress] = await env.v2.UniversalResolver.read.findResolver([ + dnsEncodeName(name), + ]); + if (resolverAddress === zeroAddress) continue; + const resolver = env.castPermissionedResolver(resolverAddress); + try { + const aliasResult = await resolver.read.getAlias([dnsEncodeName(name)]); + if (aliasResult.length > 2) { + const aliasTarget = dnsDecodeName(aliasResult); + aliasData.push({ + Name: name, + Resolver: truncateAddress(resolverAddress), + "Alias Target": aliasTarget, + }); + } + } catch { + // getAlias may fail if resolver doesn't support it + } + } + + if (aliasData.length > 0) { + console.log(`\nAlias Information:`); + console.table(aliasData); + } else { + console.log(`\nNo aliases found.`); + } +} + +export function truncateAddress(addr: string | undefined) { + if (!addr || addr === "0x") return "-"; + return addr.slice(0, 7); +} + +export function formatExpiry(sec: bigint) { + switch (sec) { + case 0n: + return "Unset (0)"; + case MAX_EXPIRY: + return "Never (MAX_EXPIRY)"; + default: + return new Date(Number(sec) * 1000).toISOString(); + } +} + +export function formatStatus(status: number | undefined) { + for (const [k, x] of Object.entries(STATUS)) { + if (x === status) { + return k; + } + } + return "UKNOWN"; +} diff --git a/contracts/script/testNames/gas.ts b/contracts/script/testNames/gas.ts new file mode 100644 index 000000000..1fc0bbe33 --- /dev/null +++ b/contracts/script/testNames/gas.ts @@ -0,0 +1,86 @@ +import type { TransactionReceipt } from "viem"; + +// ========== Gas Tracking ========== + +type GasRecord = { + operation: string; + gasUsed: bigint; + effectiveGasPrice?: bigint; + totalCost?: bigint; +}; + +const gasTracker: GasRecord[] = []; + +export function trackGas(operation: string, receipt: TransactionReceipt) { + const gasUsed = BigInt(receipt.gasUsed); + const effectiveGasPrice = receipt.effectiveGasPrice + ? BigInt(receipt.effectiveGasPrice) + : 0n; + gasTracker.push({ + operation, + gasUsed, + effectiveGasPrice, + totalCost: gasUsed * effectiveGasPrice, + }); +} + +export function displayGasReport() { + if (gasTracker.length === 0) { + console.log("\nNo gas data collected."); + return; + } + + console.log("\n========== Gas Usage Report =========="); + + const groupedByFunction = new Map(); + + for (const { operation, gasUsed } of gasTracker) { + const functionName = operation.split("(")[0]; + if (!groupedByFunction.has(functionName)) { + groupedByFunction.set(functionName, []); + } + groupedByFunction.get(functionName)!.push(gasUsed); + } + + const reportData = Array.from(groupedByFunction.entries()).map( + ([functionName, gasValues]) => { + const count = gasValues.length; + const total = gasValues.reduce((sum, val) => sum + val, 0n); + const avg = total / BigInt(count); + const min = gasValues.reduce( + (min, val) => (val < min ? val : min), + gasValues[0], + ); + const max = gasValues.reduce( + (max, val) => (val > max ? val : max), + gasValues[0], + ); + + return { + Function: functionName, + Calls: count, + "Avg Gas": avg.toString(), + "Min Gas": min.toString(), + "Max Gas": max.toString(), + "Total Gas": total.toString(), + }; + }, + ); + + console.table(reportData); + + const totalGas = gasTracker.reduce((sum, { gasUsed }) => sum + gasUsed, 0n); + const totalCostWei = gasTracker.reduce( + (sum, { totalCost }) => sum + (totalCost || 0n), + 0n, + ); + + console.log(`\nTotal Gas Used: ${totalGas.toString()}`); + console.log(`Total Cost: ${totalCostWei.toString()} wei`); + console.log(`Total Transactions: ${gasTracker.length}`); + console.log("======================================\n"); +} + +export function resetGasTracker() { + gasTracker.length = 0; +} diff --git a/contracts/script/testNames/registrar.ts b/contracts/script/testNames/registrar.ts new file mode 100644 index 000000000..0bb177803 --- /dev/null +++ b/contracts/script/testNames/registrar.ts @@ -0,0 +1,243 @@ +import { type Hex, namehash, zeroAddress } from "viem"; +import type { DevnetAccount, DevnetEnvironment } from "../setup.js"; +import { idFromLabel } from "../../test/utils/utils.js"; +import { formatExpiry } from "./display.js"; +import { trackGas } from "./gas.js"; +import { MAX_EXPIRY } from "../deploy-constants.js"; + +const ONE_DAY_SECONDS = 86400; + +function secret(i: number): Hex { + return `0x${(i + 1).toString(16).padStart(64, "0")}`; +} + +/** + * Register names via the ETHRegistrar commit-reveal flow with batched commits. + * Commits all names, does one time warp, then registers all. + */ +export async function registerTestNames( + env: DevnetEnvironment, + labels: string[], + options: { + account?: DevnetAccount; + durationInDays?: number; + trackGas?: boolean; + } = {}, +) { + const account = options.account ?? env.namedAccounts.owner; + const shouldTrackGas = options.trackGas ?? false; + const durationInDays = options.durationInDays ?? 28; + const duration = BigInt(durationInDays * ONE_DAY_SECONDS); + const paymentToken = env.erc20.MockUSDC.address; + const referrer = + "0x0000000000000000000000000000000000000000000000000000000000000000"; + + // use account's resolver (already deployed by devnet) + const { resolver } = account; + if (shouldTrackGas) + trackGas("deployPermissionedResolver", resolver.deploymentReceipt); + + // Step 1: Commit all names + for (let i = 0; i < labels.length; i++) { + const commitment = await env.v2.ETHRegistrar.read.makeCommitment([ + labels[i], + account.address, + secret(i), + zeroAddress, + resolver.address, + duration, + referrer, + ]); + const receipt = await env.waitFor( + env.v2.ETHRegistrar.write.commit([commitment], { + account, + }), + ); + if (shouldTrackGas) { + trackGas(`commit(${labels[i]})`, receipt); + } + } + + // Step 2: Single time warp past minCommitmentAge + const minAge = await env.v2.ETHRegistrar.read.MIN_COMMITMENT_AGE(); + await env.sync({ warpSec: Number(minAge) + 1 }); + + // Step 3: Approve total payment + let totalPrice = 0n; + for (const label of labels) { + const [base, premium] = + await env.v2.StandardRentPriceOracle.read.getRegisterPrice([ + label, + MAX_EXPIRY, + duration, + paymentToken, + ]); + totalPrice += base + premium; + } + + const balance = await env.erc20.MockUSDC.read.balanceOf([account.address]); + if (balance < totalPrice) { + await env.erc20.MockUSDC.write.mint( + [account.address, totalPrice - balance + 1000000n], + { account }, + ); + } + await env.erc20.MockUSDC.write.approve( + [env.v2.ETHRegistrar.address, totalPrice], + { account }, + ); + + // Step 4: Register all names + for (let i = 0; i < labels.length; i++) { + const receipt = await env.waitFor( + env.v2.ETHRegistrar.write.register( + [ + labels[i], + account.address, + secret(i), + zeroAddress, + resolver.address, + duration, + paymentToken, + referrer, + ], + { account }, + ), + ); + if (shouldTrackGas) trackGas(`register(${labels[i]})`, receipt); + + // Set resolver records + const node = namehash(`${labels[i]}.eth`); + const setAddrReceipt = await env.waitFor( + resolver.write.setAddr([node, 60n, account.address]), + ); + if (shouldTrackGas) trackGas(`setAddr(${labels[i]})`, setAddrReceipt); + + const setTextReceipt = await env.waitFor( + resolver.write.setText([node, "description", `${labels[i]}.eth`]), + ); + if (shouldTrackGas) trackGas(`setText(${labels[i]})`, setTextReceipt); + } +} + +/** + * Re-register a name after it has expired (includes time warp) + */ +export async function reregisterName( + env: DevnetEnvironment, + label: string, + account = env.namedAccounts.owner, +) { + console.log( + `\n=== Testing Re-registration of Expired Name: ${label}.eth ===`, + ); + + const initialExpiry = await env.v2.ETHRegistry.read.getExpiry([ + idFromLabel(label), + ]); + console.log( + `Initial expiry: ${new Date(Number(initialExpiry) * 1000).toISOString()}`, + ); + + // Time warp past expiry (must exceed the registration duration, default 28 days) + const warpSeconds = 28 * ONE_DAY_SECONDS + 1; + console.log(`\nTime warping ${warpSeconds} seconds...`); + await env.sync({ warpSec: warpSeconds }); + + console.log( + `\nCurrent onchain timestamp: ${await env.client.getBlock().then((b) => formatExpiry(b.timestamp))}`, + ); + console.log(`\nCurrent onchain expiry: ${formatExpiry(initialExpiry)}`); + + // Verify name is available for re-registration + const isAvailable = await env.v2.ETHRegistrar.read.isAvailable([label]); + console.log(`Name available for re-registration: ${isAvailable}`); + + if (!isAvailable) { + throw new Error(`${label}.eth should be available after expiry`); + } + + // Re-register via commit-reveal + console.log(`\nRe-registering ${label}.eth...`); + + await registerTestNames(env, [label], { + account, + durationInDays: 28, + }); + + // Verify re-registration succeeded + const reregisteredExpiry = await env.v2.ETHRegistry.read.getExpiry([ + idFromLabel(label), + ]); + console.log(`New expiry: ${formatExpiry(reregisteredExpiry)}`); + + if (reregisteredExpiry <= initialExpiry) { + throw new Error( + `Re-registration failed: new expiry (${reregisteredExpiry}) should be greater than initial expiry (${initialExpiry})`, + ); + } + + console.log( + `✓ Re-registration successful! Expiry extended from ${initialExpiry} to ${reregisteredExpiry}`, + ); +} + +/** + * Renew a name via the ETHRegistrar + */ +export async function renewName( + env: DevnetEnvironment, + name: string, + durationInDays: number, + account = env.namedAccounts.owner, +) { + const label = name.split(".")[0]; + + const expiry = await env.v2.ETHRegistry.read.getExpiry([idFromLabel(label)]); + + console.log(`\nRenewing ${name}...`); + console.log(`Current expiry: ${formatExpiry(expiry)}`); + console.log(`Extending by: ${durationInDays} days`); + + const duration = BigInt(durationInDays * ONE_DAY_SECONDS); + const paymentToken = env.erc20.MockUSDC.address; + const referrer = + "0x0000000000000000000000000000000000000000000000000000000000000000"; + + const price = await env.v2.ETHRegistrar.read.getRenewPrice([ + label, + duration, + paymentToken, + ]); + + console.log(`Renewal price: ${price}`); + + const balance = await env.erc20.MockUSDC.read.balanceOf([account.address]); + console.log(`Current balance: ${balance}`); + + if (balance < price) { + const amountToMint = price - balance + 1000000n; + console.log(`Minting ${amountToMint} tokens...`); + await env.erc20.MockUSDC.write.mint([account.address, amountToMint], { + account, + }); + } + + await env.erc20.MockUSDC.write.approve([env.v2.ETHRegistrar.address, price], { + account, + }); + + const receipt = await env.waitFor( + env.v2.ETHRegistrar.write.renew([label, duration, paymentToken, referrer], { + account, + }), + ); + + const newExpiry = await env.v2.ETHRegistry.read.getExpiry([ + idFromLabel(label), + ]); + console.log(`New expiry: ${formatExpiry(newExpiry)}`); + console.log(`✓ Renewal completed`); + + return receipt; +} diff --git a/contracts/script/testNames/registry.ts b/contracts/script/testNames/registry.ts new file mode 100644 index 000000000..5810e410b --- /dev/null +++ b/contracts/script/testNames/registry.ts @@ -0,0 +1,348 @@ +import { + type Account, + type Address, + type TransactionReceipt, + zeroAddress, +} from "viem"; + +import type { DevnetAccount, DevnetEnvironment } from "../setup.js"; +import { MAX_EXPIRY, ROLES, STATUS } from "../deploy-constants.js"; +import { + splitName, + dnsEncodeName, + idFromLabel, + getLabelAt, +} from "../../test/utils/utils.js"; +import { setupResolver } from "./resolver.js"; +import { formatStatus } from "./display.js"; + +/** + * Traverse the registry hierarchy to find data for a name. + * Uses UniversalResolverV2.findRegistries() to locate the parent registry, + * then reads state directly from it. + */ +export async function getNameData( + env: DevnetEnvironment, + name: string, + account: Account = env.namedAccounts.deployer, +) { + const regs = await env.v2.UniversalResolver.read.findRegistries([ + dnsEncodeName(name), + ]); + if (regs.length < 2 || regs[1] === zeroAddress) return; // no parent + const parentRegistry = env.castUserRegistry(regs[1], account); + const exactRegistry = + regs[0] === zeroAddress + ? undefined + : env.castUserRegistry(regs[0], account); + const label = getLabelAt(name); + const [state, resolver] = await Promise.all([ + parentRegistry.read.getState([idFromLabel(label)]), + parentRegistry.read.getResolver([label]), + ]); + return { + ...state, + owner: state.status == STATUS.REGISTERED ? state.latestOwner : zeroAddress, + name, + label, + resolver, + exactRegistry, + parentRegistry, + }; +} + +/** + * Create a subname (and all parent registries if they don't exist) + */ +export async function createSubname( + env: DevnetEnvironment, + fullName: string, + options: { + account?: DevnetAccount; + expiry?: bigint; + } = {}, +): Promise { + const account = options.account ?? env.namedAccounts.owner; + const myResolver = account.resolver.address; + const expiry = options.expiry ?? MAX_EXPIRY; + const registeredNames: string[] = []; + + console.log(`\nCreating name: ${fullName}`); + const labels = splitName(fullName); + if (labels.length < 3) throw new Error(`expected 3LD+: ${fullName}`); + let name = labels.pop()!; + if (name !== "eth") throw new Error(`expected .eth: ${fullName}`); + + while (labels.length) { + const label = labels.pop()!; + name = `${label}.${name}`; + const data = await getNameData(env, name, account); + if (!data) throw new Error("bug"); + if (!data.exactRegistry) { + console.log(`Deploying UserRegistry for ${name}...`); + const registry = await env.deployUserRegistry({ + account, + salt: { name }, + }); + console.log(`✓ UserRegistry deployed at ${registry.address}`); + if (data.status === STATUS.REGISTERED) { + await data.parentRegistry.write.setSubregistry([ + data.tokenId, + registry.address, + ]); + await data.parentRegistry.write.setResolver([data.tokenId, myResolver]); + console.log(`✓ Updated ${name} subregistry and resolver`); + } else { + await data.parentRegistry.write.register([ + label, + account.address, + registry.address, + myResolver, + ROLES.ALL, + expiry, + ]); + console.log(`✓ Registered ${name}`); + registeredNames.push(name); + } + await registry.write.setParent([data.parentRegistry.address, label]); + console.log(`✓ Set ${name} canonical parent`); + } else if (data.resolver !== myResolver) { + await data.parentRegistry.write.setResolver([data.tokenId, myResolver]); + console.log(`✓ Updated ${name} resolver`); + } + await setupResolver(env, account, name, { + description: name, + address: account.address, + }); + console.log(`✓ Setup resolver for ${name}`); + } + return registeredNames; +} + +/** + * Link a name to appear under a different parent by pointing to the same subregistry. + * This creates multiple "entry points" into the same child namespace. + * + * @param sourceName - The existing name whose subregistry we want to link (e.g., "sub1.sub2.parent.eth") + * @param targetName - The created linked name whos subregistry is matches sourceName. + * + * Example: + * linkName(env, "sub1.sub2.parent.eth", "linked.parent.eth") + * Creates "linked.parent.eth" that shares children with "sub1.sub2.parent.eth" + */ +export async function linkName( + env: DevnetEnvironment, + sourceName: string, + targetName: string, + account = env.namedAccounts.owner, +) { + console.log(`\nLinking name: ${sourceName} to ${targetName}`); + + if (splitName(sourceName).length < 3) { + throw new Error( + `Cannot link second-level names directly. Source must be a subname.`, + ); + } + + const sourceData = await getNameData(env, sourceName); + if (sourceData?.status !== STATUS.REGISTERED) { + throw new Error(`Source name ${sourceName} not registered`); + } + if (!sourceData.exactRegistry) { + throw new Error(`Source name ${sourceName} has no subregistry to link`); + } + console.log(`Source subregistry: ${sourceData.exactRegistry.address}`); + + // Get target data + const targetData = await getNameData(env, targetName, account); + if (!targetData) { + throw new Error(`Target name ${targetName} has no parent registry`); + } + + console.log(`Creating linked name: ${targetName}`); + + // Check if the label already exists in the target registry + if (targetData.status === STATUS.AVAILABLE) { + await targetData.parentRegistry.write.register([ + targetData.label, + account.address, + sourceData.exactRegistry.address, + account.resolver.address, + ROLES.ALL, + MAX_EXPIRY, + ]); + + console.log(`✓ Registered ${targetName} with shared subregistry`); + } else { + console.log(`Warning: ${targetName} already exists. Updating...`); + await targetData.parentRegistry.write.setSubregistry([ + idFromLabel(targetData.label), + sourceData.exactRegistry.address, + ]); + await targetData.parentRegistry.write.setResolver([ + idFromLabel(targetData.label), + account.resolver.address, + ]); + console.log(`✓ Updated ${targetName} to point to shared subregistry`); + } + + await setupResolver(env, account, targetName, { + description: `Linked to ${sourceName}`, + address: account.address, + }); + + console.log(`\n✓ Link complete!`); + console.log( + `Children of ${sourceName} and ${targetName} now resolve to the same place.`, + ); + console.log( + `Example: wallet.${sourceName} and wallet.${targetName} are the same token.`, + ); +} + +/** + * Transfer a name to a new owner + */ +export async function transferName( + env: DevnetEnvironment, + name: string, + newOwner: Address, + account = env.namedAccounts.owner, +) { + const data = await getNameData(env, name, account); + if (data?.status !== STATUS.REGISTERED) throw new Error(`expected ${name}`); + + console.log(`\nTransferring ${name}...`); + console.log(`TokenId: ${data.tokenId}`); + console.log(`From: ${account.address}`); + console.log(`To: ${newOwner}`); + + const receipt = await env.waitFor( + data.parentRegistry.write.safeTransferFrom([ + account.address, + newOwner, + data.tokenId, + 1n, + "0x", + ]), + ); + + console.log(`✓ Transfer completed`); + + return receipt; +} + +/** + * Change roles for a name + */ +export async function changeRole( + env: DevnetEnvironment, + name: string, + targetAccount: Address, + rolesToGrant: bigint, + rolesToRevoke: bigint, + account = env.namedAccounts.owner, +) { + const data = await getNameData(env, name, account); + if (data?.status !== STATUS.REGISTERED) throw new Error(`expected ${name}`); + + console.log( + `\nChanging roles for ${name} (TokenId: ${data.tokenId}, Target: ${targetAccount}, Grant: ${rolesToGrant}, Revoke: ${rolesToRevoke})`, + ); + + const receipts: TransactionReceipt[] = []; + + if (rolesToGrant) { + const receipt = await env.waitFor( + data.parentRegistry.write.grantRoles([ + data.tokenId, + rolesToGrant, + targetAccount, + ]), + ); + receipts.push(receipt); + } + + if (rolesToRevoke) { + const receipt = await env.waitFor( + data.parentRegistry.write.revokeRoles([ + data.tokenId, + rolesToRevoke, + targetAccount, + ]), + ); + receipts.push(receipt); + } + + const newTokenId = await data.parentRegistry.read.getTokenId([data.tokenId]); + console.log(`TokenId changed from ${data.tokenId} to ${newTokenId}`); + + return receipts; +} + +/** + * Reserve a name (registers with owner = address(0) and roleBitmap = 0, no token minted) + */ +export async function reserveName( + env: DevnetEnvironment, + name: string, + options: { + expiry?: bigint; + account?: Account; + } = {}, +) { + const data = await getNameData(env, name); + if (data?.status !== STATUS.AVAILABLE) { + throw new Error(`already exists: ${name}`); + } + + const expiry: bigint = + options.expiry ?? + (await env.client.getBlock().then((b) => b.timestamp + 86400n)); + + console.log(`\nReserving ${name}...`); + + const receipt = await env.waitFor( + data.parentRegistry.write.register([ + data.label, + zeroAddress, // owner = address(0) triggers reservation + zeroAddress, // no subregistry + zeroAddress, // no resolver + 0n, // roleBitmap must be 0 for reservations + expiry, + ]), + ); + + const state = await data.parentRegistry.read.getState([data.tokenId]); + console.log( + `✓ Reserved ${name} (status: ${formatStatus(state.status)}, tokenId: ${state.tokenId})`, + ); + + return receipt; +} + +/** + * Unregister a name (deletes it from the registry) + */ +export async function unregisterName( + env: DevnetEnvironment, + name: string, + account: Account, +) { + const data = await getNameData(env, name, account); + if (!data || data.status === STATUS.AVAILABLE) { + throw new Error(`does not exist: ${name}`); + } + + console.log(`\nUnregistering ${name}...`); + console.log(`TokenId: ${data.tokenId}`); + + const receipt = await env.waitFor( + data.parentRegistry.write.unregister([data.tokenId]), + ); + + const state = await data.parentRegistry.read.getState([data.tokenId]); + console.log(`✓ Unregistered ${name} (status: ${formatStatus(state.status)})`); + + return receipt; +} diff --git a/contracts/script/testNames/resolver.ts b/contracts/script/testNames/resolver.ts new file mode 100644 index 000000000..5cbc7098b --- /dev/null +++ b/contracts/script/testNames/resolver.ts @@ -0,0 +1,43 @@ +import { type Address, namehash } from "viem"; + +import type { DevnetAccount, DevnetEnvironment } from "../setup.js"; +import { trackGas } from "./gas.js"; + +/** + * Deploy a resolver and set default records + */ +export async function setupResolver( + env: DevnetEnvironment, + account: DevnetAccount, + name: string, + records: { + description?: string; + address?: Address; + }, + shouldTrackGas: boolean = false, +) { + const { resolver } = account; + const node = namehash(name); + + if (shouldTrackGas) { + trackGas("deployResolver", resolver.deploymentReceipt); + } + + // Set ETH address (coin type 60) + if (records.address) { + const receipt = await env.waitFor( + resolver.write.setAddr([node, 60n, records.address]), + ); + if (shouldTrackGas) trackGas(`setAddr(${name})`, receipt); + } + + // Set description text record + if (records.description) { + const receipt = await env.waitFor( + resolver.write.setText([node, "description", records.description]), + ); + if (shouldTrackGas) trackGas(`setText(${name})`, receipt); + } + + return resolver; +} diff --git a/contracts/script/tsx.ts b/contracts/script/tsx.ts new file mode 100644 index 000000000..089b9424f --- /dev/null +++ b/contracts/script/tsx.ts @@ -0,0 +1,6 @@ +// Stub for tsx module - Bun handles TypeScript natively, so tsx is not needed. +// This file is mapped via tsconfig paths so that `import 'tsx'` resolves here +// instead of loading the real tsx package (which fails under Bun). +if (!("Bun" in globalThis)) { + await import("tsx"); +} diff --git a/contracts/script/universalResolverDeployUtils.ts b/contracts/script/universalResolverDeployUtils.ts new file mode 100644 index 000000000..a3b88dc57 --- /dev/null +++ b/contracts/script/universalResolverDeployUtils.ts @@ -0,0 +1,135 @@ +import type { ExecutionArgs, ReadFunction } from "@rocketh/read-execute"; +import type { Deployment } from "rocketh/types"; +import { + type Abi, + type Address, + type ContractFunctionName, + encodeFunctionData, + getAddress, +} from "viem"; + +import artifacts from "./artifacts.js"; +import { + DEPLOYED_UNIVERSAL_RESOLVER_PROXY, + KNOWN_INTERMEDIATE_URP, +} from "./deploy-constants.js"; + +export const TOP_URP_CREATE3_SALT = + "0xdeac7148fb7f566f1fc8c8d6720530de8809f3658cf10141ceee7ba0d45eef85" as const; + +const KNOWN_TOP_PROXY_NETWORKS = new Set(["holesky", "mainnet", "sepolia"]); + +const universalResolverProxyArtifact = + artifacts.UpgradableUniversalResolverProxy; + +export type UpgradableUniversalResolverProxyDeployment = Deployment< + typeof universalResolverProxyArtifact.abi +>; + +export async function loadKnownTopProxyDeployment( + networkName: string, +): Promise { + if (!KNOWN_TOP_PROXY_NETWORKS.has(networkName)) { + return null; + } + return { + address: DEPLOYED_UNIVERSAL_RESOLVER_PROXY, + argsData: "0x", + ...universalResolverProxyArtifact, + } as UpgradableUniversalResolverProxyDeployment; +} + +export async function loadKnownIntermediateUrpDeployment( + networkName: string, +): Promise { + const address = KNOWN_INTERMEDIATE_URP[networkName]; + if (!address) { + return null; + } + return { + address, + argsData: "0x", + ...universalResolverProxyArtifact, + } as UpgradableUniversalResolverProxyDeployment; +} + +export function isDeployedTopProxy( + deployment: UpgradableUniversalResolverProxyDeployment, +): boolean { + return ( + getAddress(deployment.address) === + getAddress(DEPLOYED_UNIVERSAL_RESOLVER_PROXY) + ); +} + +export function logUpgradeCalldata( + label: string, + target: Address, + implementation: Address, + ownerLabel = "DAO", +) { + const calldata = encodeFunctionData({ + abi: universalResolverProxyArtifact.abi, + functionName: "upgradeTo", + args: [implementation], + }); + console.log(`${label} requires a ${ownerLabel} transaction`); + console.log(` target: ${target}`); + console.log(` calldata: ${calldata}`); +} + +export function externalTopProxyOwnerLabel(tags: Record) { + return tags.hasDao ? "DAO" : tags.sepolia ? "top URP owner" : undefined; +} + +// Normalizes a deploy environment to the network key used by the known-proxy +// lookups, collapsing tag-aliased environments (e.g. dev variants) onto their +// base network and otherwise falling back to the environment name. +export function knownProxyNetworkName( + tags: Record, + name: string, +): string { + return tags.sepolia ? "sepolia" : tags.hasDao ? "mainnet" : name; +} + +// matches the bound `execute` deploy-script extension (see rocketh/config.ts); +// the return type is widened to `unknown` because the custom `execute` override +// returns a receipt rather than the EIP1193DATA of rocketh's ExecuteFunction +type WriteFunction = < + TAbi extends Abi, + TFunctionName extends ContractFunctionName, +>( + deployment: Deployment, + args: ExecutionArgs, +) => Promise; + +export async function setProxyImplementationIfNeeded({ + read, + write, + deployment, + implementation, + account, + label, +}: { + read: ReadFunction; + write: WriteFunction; + deployment: UpgradableUniversalResolverProxyDeployment; + implementation: Address; + account: string; + label: string; +}) { + const currentImplementation = await read(deployment, { + functionName: "implementation", + }); + if (getAddress(currentImplementation) === getAddress(implementation)) { + console.log(`${label}: already ${implementation}`); + return; + } + + console.log(`${label}: ${currentImplementation} -> ${implementation}`); + await write(deployment, { + functionName: "upgradeTo", + args: [implementation], + account, + }); +} diff --git a/contracts/script/uploadCoverage.ts b/contracts/script/uploadCoverage.ts index a9c6c63c0..638ee1ef8 100644 --- a/contracts/script/uploadCoverage.ts +++ b/contracts/script/uploadCoverage.ts @@ -5,6 +5,7 @@ import { basename, join } from "node:path"; const SUFFIX = ".lcov"; const PREFIX = "filtered-"; const DIR = "./coverage/"; +const CODECOV_PGP_KEY_URL = "https://keybase.io/codecovsecops/pgp_keys.asc"; const rootDir = new URL("../", import.meta.url); const coverageDir = new URL(DIR, rootDir); @@ -24,7 +25,7 @@ if (codecov.exitCode !== 0) { await $`curl -Os ${installUrl}`; // integrity check - await $`curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import`; + await $`curl ${CODECOV_PGP_KEY_URL} | gpg --no-default-keyring --keyring trustedkeys.gpg --import`; await $`curl -Os ${installUrl}.SHA256SUM`; await $`curl -Os ${installUrl}.SHA256SUM.sig`; @@ -44,6 +45,7 @@ const baseCmd = [ ? [`--git-service ${process.env.CC_GIT_SERVICE}`] : []), ...(process.env.CC_SHA ? [`--sha ${process.env.CC_SHA}`] : []), + ...(process.env.CC_PR ? [`--pr ${process.env.CC_PR}`] : []), ]; const coverageFiles = readdirSync(coverageDir).filter( diff --git a/contracts/script/verify.ts b/contracts/script/verify.ts new file mode 100644 index 000000000..26dd79a29 --- /dev/null +++ b/contracts/script/verify.ts @@ -0,0 +1,149 @@ +#!/usr/bin/env bun +import { execFileSync } from "node:child_process"; +import { + cpSync, + existsSync, + mkdtempSync, + readFileSync, + readdirSync, + rmSync, + writeFileSync, +} from "node:fs"; +import { tmpdir } from "node:os"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { keccak256, toBytes } from "viem"; + +// Submits every deployed contract of a network for source-code verification on +// Etherscan and Sourcify via @rocketh/verifier. +// +// The verifier rebuilds the solc standard-json input from each artifact's +// recorded metadata, which requires the literal source content of every input +// file. Hardhat-compiled artifacts embed that content, but forge-compiled ones +// record only each source's hash and URLs, leaving the verifier unable to +// reconstruct the input. To make verification work regardless of which compiler +// produced an artifact, this backfills any missing source content from disk — +// keyed by the metadata source paths and checked against the recorded hash — into +// a throwaway copy of the deployment set before handing off to the verifier. + +const contractsDir = resolve(dirname(fileURLToPath(import.meta.url)), ".."); + +type Backend = "etherscan" | "sourcify"; + +function parseArgs(argv: string[]) { + let network: string | undefined; + let backends: Backend[] = ["etherscan", "sourcify"]; + const passthrough: string[] = []; + for (let i = 0; i < argv.length; i++) { + const arg = argv[i]; + if (arg === "--network" || arg === "-n" || arg === "-e") { + network = argv[++i]; + } else if (arg === "--etherscan-only") { + backends = ["etherscan"]; + } else if (arg === "--sourcify-only") { + backends = ["sourcify"]; + } else { + passthrough.push(arg); + } + } + if (!network) { + throw new Error( + "usage: bun ./script/verify.ts --network [--etherscan-only|--sourcify-only] [-- ]", + ); + } + return { network, backends, passthrough }; +} + +// The deployed metadata records source paths under solc's source unit prefix +// (e.g. `project/src/...`, `project/lib/...`); the foundry project root maps to +// the contracts directory, so the prefix is stripped to resolve the file. +function diskPathForSource(sourceKey: string) { + return resolve(contractsDir, sourceKey.replace(/^project\//, "")); +} + +function backfillSourceContent(artifactPath: string) { + const artifact = JSON.parse(readFileSync(artifactPath, "utf8")); + if (typeof artifact.metadata !== "string") return false; + + const metadata = JSON.parse(artifact.metadata); + const sources = metadata.sources ?? {}; + let patched = 0; + for (const [sourceKey, source] of Object.entries(sources)) { + if (source.content !== undefined) continue; + const diskPath = diskPathForSource(sourceKey); + if (!existsSync(diskPath)) { + throw new Error( + `cannot backfill source for ${artifact.contractName ?? artifactPath}: ${sourceKey} not found at ${diskPath}`, + ); + } + const content = readFileSync(diskPath, "utf8"); + if (source.keccak256 && keccak256(toBytes(content)) !== source.keccak256) { + throw new Error( + `source hash mismatch for ${sourceKey} (file on disk differs from the deployed source)`, + ); + } + source.content = content; + patched++; + } + if (patched === 0) return false; + + artifact.metadata = JSON.stringify(metadata); + writeFileSync(artifactPath, JSON.stringify(artifact, null, 2)); + return true; +} + +function main() { + const { network, backends, passthrough } = parseArgs(process.argv.slice(2)); + + const srcDir = join(contractsDir, "deployments", network); + if (!existsSync(srcDir)) { + throw new Error( + `no deployments found for network "${network}" (${srcDir})`, + ); + } + + const stagingRoot = mkdtempSync(join(tmpdir(), "rocketh-verify-")); + const stagingDir = join(stagingRoot, network); + cpSync(srcDir, stagingDir, { recursive: true }); + + try { + let backfilled = 0; + for (const file of readdirSync(stagingDir)) { + if (!file.endsWith(".json") || file.startsWith(".")) continue; + if (backfillSourceContent(join(stagingDir, file))) { + console.log( + `backfilled source content for ${file.replace(/\.json$/, "")}`, + ); + backfilled++; + } + } + if (backfilled > 0) { + console.log( + `backfilled ${backfilled} artifact(s) missing literal sources\n`, + ); + } + + for (const backend of backends) { + console.log(`\n=== verifying ${network} on ${backend} ===`); + execFileSync( + "bun", + [ + "run", + "rocketh-verify", + "--", + "-d", + stagingRoot, + "-e", + network, + backend, + ...passthrough, + ], + { cwd: contractsDir, stdio: "inherit", env: process.env }, + ); + } + } finally { + rmSync(stagingRoot, { recursive: true, force: true }); + } +} + +main(); diff --git a/contracts/solgrid.test.toml b/contracts/solgrid.test.toml new file mode 100644 index 000000000..a8851a0a8 --- /dev/null +++ b/contracts/solgrid.test.toml @@ -0,0 +1,51 @@ +# Solgrid settings for Foundry tests, fixtures, mocks, and Solidity scripts. +# These files intentionally use test-oriented naming, layout, and documentation style. + +[lint] +preset = "recommended" + +[lint.rules] +"best-practices/code-complexity" = "off" +"best-practices/duplicated-imports" = "error" +"best-practices/function-max-lines" = "off" +"best-practices/imports-on-top" = "error" +"best-practices/max-states-count" = "off" +"best-practices/no-empty-blocks" = "off" +"best-practices/no-floating-pragma" = "off" +"best-practices/no-global-import" = "error" +"best-practices/no-unused-error" = "off" +"best-practices/no-unused-event" = "off" +"best-practices/no-unused-imports" = "error" +"best-practices/no-unused-state" = "off" +"best-practices/one-contract-per-file" = "off" +"best-practices/reason-string" = "warn" +"best-practices/visibility-modifier-order" = "error" +"docs/natspec" = "off" +"docs/selector-tags" = "off" +"naming/const-name-snakecase" = "error" +"naming/contract-name-capwords" = "error" +"naming/func-name-mixedcase" = "off" +"naming/immutable-name-snakecase" = "error" +"naming/modifier-name-mixedcase" = "error" +"naming/named-parameters-mapping" = "error" +"naming/param-name-mixedcase" = "off" +"naming/private-vars-underscore" = "off" +"naming/var-name-mixedcase" = "warn" +"security/compiler-version" = "error" +"security/low-level-calls" = "off" +"security/no-delegatecall-in-loop" = "off" +"security/no-inline-assembly" = "off" +"security/not-rely-on-time" = "off" +"security/payable-fallback" = "off" +"security/state-visibility" = "off" +"style/category-headers" = "off" +"style/imports-ordering" = "off" +"style/ordering" = "off" + +[lint.settings."security/compiler-version"] +allowed = [">=0.8.13"] + +[format] +line_length = 100 +operator_line_break = "trailing" +tab_width = 4 diff --git a/contracts/solgrid.toml b/contracts/solgrid.toml new file mode 100644 index 000000000..e2a6eddd1 --- /dev/null +++ b/contracts/solgrid.toml @@ -0,0 +1,103 @@ +# Closest built-in solgrid mapping of the previous Solidity lint ruleset. +# solgrid 0.0.16 adds the rule-level configuration needed to match the repo's +# NatSpec/category-header policy closely enough for migration. + +[lint] +preset = "recommended" + +[lint.rules] +"best-practices/code-complexity" = "off" +"best-practices/duplicated-imports" = "error" +"best-practices/function-max-lines" = "warn" +"best-practices/imports-on-top" = "error" +"best-practices/max-states-count" = "off" +"best-practices/no-empty-blocks" = "off" +"best-practices/no-floating-pragma" = "off" +"best-practices/no-global-import" = "error" +"best-practices/no-unused-error" = "off" +"best-practices/no-unused-event" = "off" +"best-practices/no-unused-imports" = "error" +"best-practices/no-unused-state" = "off" +"best-practices/one-contract-per-file" = "off" +"best-practices/reason-string" = "warn" +"best-practices/visibility-modifier-order" = "error" +"docs/natspec" = "error" +"docs/selector-tags" = "error" +"naming/const-name-snakecase" = "error" +"naming/contract-name-capwords" = "error" +"naming/func-name-mixedcase" = "warn" +"naming/immutable-name-snakecase" = "error" +"naming/modifier-name-mixedcase" = "error" +"naming/named-parameters-mapping" = "error" +"naming/param-name-mixedcase" = "off" +"naming/private-vars-underscore" = "error" +"naming/var-name-mixedcase" = "warn" +"security/compiler-version" = "error" +"security/low-level-calls" = "off" +"security/no-delegatecall-in-loop" = "off" +"security/no-inline-assembly" = "off" +"security/not-rely-on-time" = "off" +"security/payable-fallback" = "off" +"style/category-headers" = "error" +"style/imports-ordering" = "error" +"style/ordering" = "error" + +[lint.settings."security/compiler-version"] +allowed = [">=0.8.13"] + +[lint.settings."best-practices/function-max-lines"] +max_lines = 150 + +[lint.settings."style/imports-ordering"] +import_order = ["^forge-std/", "^@?\\w", "^\\.\\./", "^\\./"] + +[lint.settings."docs/natspec"] +comment_style = "triple_slash" +continuation_indent = "padded" + +[lint.settings."docs/natspec".tags.title] +enabled = false + +[lint.settings."docs/natspec".tags.author] +enabled = false + +[lint.settings."docs/natspec".tags.notice] +enabled = true +exclude = [ + "function:internal", + "function:private", + "function:default", + "contract:abstract", + "contract:interface", + "library", + "variable:internal", + "variable:private", +] + +[lint.settings."docs/natspec".tags.dev] +enabled = true +include = [ + "function:internal", + "function:private", + "contract:abstract", + "library", + "variable:internal", + "variable:private", +] + +[lint.settings."docs/natspec".tags.param] +enabled = true +exclude = ["function:internal", "function:private", "library"] + +[lint.settings."docs/natspec".tags.return] +enabled = true +exclude = ["function:internal", "function:private", "library"] + +[lint.settings."style/category-headers"] +min_categories = 3 +initialization_functions = ["constructor", "supportsInterface", "supportsFeature", "initialize"] + +[format] +line_length = 100 +operator_line_break = "trailing" +tab_width = 4 diff --git a/contracts/src/CommonErrors.sol b/contracts/src/CommonErrors.sol index 6d8a5e6e7..85a823652 100644 --- a/contracts/src/CommonErrors.sol +++ b/contracts/src/CommonErrors.sol @@ -12,9 +12,3 @@ error InvalidOwner(); /// @dev Error selector: `0xd86ad9cf` /// @param caller The address that attempted the unauthorized operation error UnauthorizedCaller(address caller); - -/// @notice Arrays have different lengths. -/// @param length1 The first array length. -/// @param length2 The second array length. -/// @dev Error selector: `0xfa5dbe08` -error ArrayLengthMismatch(uint256 length1, uint256 length2); diff --git a/contracts/src/access-control/EnhancedAccessControl.sol b/contracts/src/access-control/EnhancedAccessControl.sol index b5e799f17..3dc683f63 100644 --- a/contracts/src/access-control/EnhancedAccessControl.sol +++ b/contracts/src/access-control/EnhancedAccessControl.sol @@ -4,50 +4,48 @@ pragma solidity ^0.8.20; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; - -import {HCAContext} from "../hca/HCAContext.sol"; import {IEnhancedAccessControl} from "./interfaces/IEnhancedAccessControl.sol"; import {EACBaseRolesLib} from "./libraries/EACBaseRolesLib.sol"; /// @dev Resource-scoped access control system with bitmap-packed roles. /// -/// Subclasses define custom roles as constants and assign them to accounts within specific -/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by -/// the subclass (e.g. a token ID, a name hash, etc.). +/// Subclasses define custom roles as constants and assign them to accounts within specific +/// resources. A resource is an arbitrary uint256 identifier whose meaning is determined by +/// the subclass (e.g. a token ID, a name hash, etc.). +/// +/// Features: +/// - Resource-based roles: each resource has independent role assignments. +/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply +/// to all resources. Role checks OR the account's root roles with their resource-specific +/// roles, so holding a role in either scope satisfies the check. +/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role +/// grants authority to grant and revoke both the regular role and the admin role itself. +/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role. +/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react +/// to role changes (e.g. regenerating tokens, updating metadata). +/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly; +/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments. /// -/// Features: -/// - Resource-based roles: each resource has independent role assignments. -/// - ROOT_RESOURCE fallback: roles granted in `ROOT_RESOURCE` (0x0) automatically apply -/// to all resources. Role checks OR the account's root roles with their resource-specific -/// roles, so holding a role in either scope satisfies the check. -/// - Admin roles: each regular role has a corresponding admin role. Holding an admin role -/// grants authority to grant and revoke both the regular role and the admin role itself. -/// - Assignee counting: per-role assignee counts are tracked, with a maximum of 15 per role. -/// - Callbacks: subclasses can override `_onRolesGranted` and `_onRolesRevoked` to react -/// to role changes (e.g. regenerating tokens, updating metadata). -/// - Separate root operations: `grantRoles`/`revokeRoles` reject `ROOT_RESOURCE` directly; -/// use `grantRootRoles`/`revokeRootRoles` for root-level assignments. +/// Bitmap layout (uint256, 64 nybbles): /// -/// Bitmap layout (uint256, 64 nybbles): +/// 255 128 127 0 +/// ┌──────────────┬───────────────┐ +/// │ Admin Roles │ Regular Roles │ +/// └──────────────┴───────────────┘ +/// 63 32 31 0 /// -/// 255 128 127 0 -/// ┌──────────────┬───────────────┐ -/// │ Admin Roles │ Regular Roles │ -/// └──────────────┴───────────────┘ -/// 63 32 31 0 +/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits +/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper +/// half at bits N*4+128 to N*4+131. /// -/// Each role occupies one nybble (4 bits). A regular role at nybble index N occupies bits -/// N*4 to N*4+3, and its admin counterpart occupies the same relative position in the upper -/// half at bits N*4+128 to N*4+131. +/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index +/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`. /// -/// Defining roles: `uint256 constant MY_ROLE = 1 << (N * 4)` where N is the nybble index -/// (0-31), and the admin role as `uint256 constant MY_ROLE_ADMIN = MY_ROLE << 128`. +/// The same nybble-per-role layout is used for assignee counting: each nybble in the count +/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15). /// -/// The same nybble-per-role layout is used for assignee counting: each nybble in the count -/// bitmap tracks the number of accounts holding that role within a resource (4 bits = max 15). -abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessControl { +abstract contract EnhancedAccessControl is ERC165, IEnhancedAccessControl { //////////////////////////////////////////////////////////////////////// // Constants //////////////////////////////////////////////////////////////////////// @@ -65,35 +63,39 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo /// @dev The number of assignees for a given role in a given resource. /// - /// Each role's count is represented by 4 bits, in little-endian order. - /// This results in max. 64 roles, and 15 assignees per role. + /// Each role's count is represented by 4 bits, in little-endian order. + /// This results in max. 64 roles, and 15 assignees per role. + /// mapping(uint256 resource => uint256 roleCount) private _roleCount; + /// @dev Storage gap for future changes. + uint256[256] private __gap; + //////////////////////////////////////////////////////////////////////// // Modifiers //////////////////////////////////////////////////////////////////////// /// @dev Modifier that checks that sender has the admin roles for all the given roles. modifier canGrantRoles(uint256 resource, uint256 roleBitmap) { - _checkCanGrantRoles(resource, roleBitmap, _msgSender()); + _checkCanGrantRoles(resource, roleBitmap, msg.sender); _; } /// @dev Modifier that checks that sender has the admin roles for all the given roles and can revoke them. modifier canRevokeRoles(uint256 resource, uint256 roleBitmap) { - _checkCanRevokeRoles(resource, roleBitmap, _msgSender()); + _checkCanRevokeRoles(resource, roleBitmap, msg.sender); _; } /// @dev Modifier that checks that sender has all the given roles within the given resource or the ROOT_RESOURCE. modifier onlyRoles(uint256 resource, uint256 roleBitmap) { - _checkRoles(resource, roleBitmap, _msgSender()); + _checkRoles(resource, roleBitmap, msg.sender); _; } /// @dev Modifier that checks that sender has all the given roles within the `ROOT_RESOURCE`. modifier onlyRootRoles(uint256 roleBitmap) { - _checkRoles(ROOT_RESOURCE, roleBitmap, _msgSender()); + _checkRoles(ROOT_RESOURCE, roleBitmap, msg.sender); _; } @@ -101,10 +103,8 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo // Initialization //////////////////////////////////////////////////////////////////////// - /// @inheritdoc IERC165 - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165, IERC165) returns (bool) { + /// @inheritdoc ERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IEnhancedAccessControl).interfaceId || super.supportsInterface(interfaceId); @@ -113,128 +113,97 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo //////////////////////////////////////////////////////////////////////// // Implementation //////////////////////////////////////////////////////////////////////// - /// @dev Grants all roles in the given role bitmap to `account`. - /// - /// The caller must have all the necessary admin roles for the roles being granted. - /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead. - /// - /// @param resource The resource to grant roles within. - /// @param roleBitmap The roles bitmap to grant. - /// @param account The account to grant roles to. - /// @return `true` if the roles were granted, `false` otherwise. - function grantRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) public virtual canGrantRoles(resource, roleBitmap) returns (bool) { + + /// @inheritdoc IEnhancedAccessControl + /// @dev The caller must have all the necessary admin roles for the roles being granted. + /// Cannot be used with ROOT_RESOURCE directly, use grantRootRoles instead. + function grantRoles(uint256 resource, uint256 roleBitmap, address account) + public + virtual + canGrantRoles(resource, roleBitmap) + returns (bool) + { if (resource == ROOT_RESOURCE) { revert EACRootResourceNotAllowed(); } return _grantRoles(resource, roleBitmap, account, true); } - /// @dev Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE. - /// - /// The caller must have all the necessary admin roles for the roles being granted. - /// - /// @param roleBitmap The roles bitmap to grant. - /// @param account The account to grant roles to. - /// @return `true` if the roles were granted, `false` otherwise. - function grantRootRoles( - uint256 roleBitmap, - address account - ) public virtual canGrantRoles(ROOT_RESOURCE, roleBitmap) returns (bool) { + /// @inheritdoc IEnhancedAccessControl + /// @dev The caller must have all the necessary admin roles for the roles being granted. + function grantRootRoles(uint256 roleBitmap, address account) + public + virtual + canGrantRoles(ROOT_RESOURCE, roleBitmap) + returns (bool) + { return _grantRoles(ROOT_RESOURCE, roleBitmap, account, true); } - /// @dev Revokes all roles in the given role bitmap from `account`. - /// - /// The caller must have all the necessary admin roles for the roles being revoked. - /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead. - /// - /// @param resource The resource to revoke roles within. - /// @param roleBitmap The roles bitmap to revoke. - /// @param account The account to revoke roles from. - /// @return `true` if the roles were revoked, `false` otherwise. - function revokeRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) public virtual canRevokeRoles(resource, roleBitmap) returns (bool) { + /// @inheritdoc IEnhancedAccessControl + /// @dev The caller must have all the necessary admin roles for the roles being revoked. + /// Cannot be used with ROOT_RESOURCE directly, use revokeRootRoles instead. + function revokeRoles(uint256 resource, uint256 roleBitmap, address account) + public + virtual + canRevokeRoles(resource, roleBitmap) + returns (bool) + { if (resource == ROOT_RESOURCE) { revert EACRootResourceNotAllowed(); } return _revokeRoles(resource, roleBitmap, account, true); } - /// @dev Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE. - /// - /// The caller must have all the necessary admin roles for the roles being revoked. - /// - /// @param roleBitmap The roles bitmap to revoke. - /// @param account The account to revoke roles from. - /// @return `true` if the roles were revoked, `false` otherwise. - function revokeRootRoles( - uint256 roleBitmap, - address account - ) public virtual canRevokeRoles(ROOT_RESOURCE, roleBitmap) returns (bool) { + /// @inheritdoc IEnhancedAccessControl + /// @dev The caller must have all the necessary admin roles for the roles being revoked. + function revokeRootRoles(uint256 roleBitmap, address account) + public + virtual + canRevokeRoles(ROOT_RESOURCE, roleBitmap) + returns (bool) + { return _revokeRoles(ROOT_RESOURCE, roleBitmap, account, true); } - /// @notice Returns the roles bitmap for an account in a resource. + /// @inheritdoc IEnhancedAccessControl function roles(uint256 resource, address account) public view virtual returns (uint256) { - return _roles[resource][account]; + return _getRoles(resource, account); } - /// @notice Returns the role count bitmap for a resource. + /// @inheritdoc IEnhancedAccessControl function roleCount(uint256 resource) public view virtual returns (uint256) { return _roleCount[resource]; } - /// @dev Returns `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`. - /// - /// @param roleBitmap The roles bitmap to check. - /// @param account The account to check. - /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise. + /// @inheritdoc IEnhancedAccessControl function hasRootRoles(uint256 roleBitmap, address account) public view virtual returns (bool) { - return _roles[ROOT_RESOURCE][account] & roleBitmap == roleBitmap; + return _getRoles(ROOT_RESOURCE, account) & roleBitmap == roleBitmap; } - /// @dev Returns `true` if `account` has been granted all the given roles in `resource` or the `ROOT_RESOURCE`. - /// - /// @param resource The resource to check. - /// @param roleBitmap The roles bitmap to check. - /// @param account The account to check. - /// @return `true` if `account` has been granted all the given roles in either `resource` or the `ROOT_RESOURCE`, `false` otherwise. - function hasRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) public view virtual returns (bool) { - return - (_roles[ROOT_RESOURCE][account] | _roles[resource][account]) & roleBitmap == roleBitmap; + /// @inheritdoc IEnhancedAccessControl + function hasRoles(uint256 resource, uint256 roleBitmap, address account) + public + view + virtual + returns (bool) + { + return _effectiveRoles(resource, account) & roleBitmap == roleBitmap; } - /// @dev Get if any of the roles in the given role bitmap has assignees. - /// - /// @param resource The resource to check. - /// @param roleBitmap The roles bitmap to check. - /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise. + /// @inheritdoc IEnhancedAccessControl function hasAssignees(uint256 resource, uint256 roleBitmap) public view virtual returns (bool) { (uint256 counts, ) = getAssigneeCount(resource, roleBitmap); return counts != 0; } - /// @dev Get the no. of assignees for the roles in the given role bitmap. - /// - /// @param resource The resource to check. - /// @param roleBitmap The roles bitmap to check. - /// @return counts The no. of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints. - /// @return mask The mask for the given role bitmap. - function getAssigneeCount( - uint256 resource, - uint256 roleBitmap - ) public view virtual returns (uint256 counts, uint256 mask) { + /// @inheritdoc IEnhancedAccessControl + function getAssigneeCount(uint256 resource, uint256 roleBitmap) + public + view + virtual + returns (uint256 counts, uint256 mask) + { mask = _roleBitmapToMask(roleBitmap); counts = _roleCount[resource] & mask; } @@ -259,7 +228,10 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo address srcAccount, address dstAccount, bool executeCallbacks - ) internal virtual { + ) + internal + virtual + { uint256 srcRoles = _roles[resource][srcAccount]; if (srcRoles != 0) { // First revoke roles from source account to free up assignee slots @@ -270,7 +242,6 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo } /// @dev Grants multiple roles to `account`. - /// /// @param resource The resource to grant roles within. /// @param roleBitmap The roles bitmap to grant. /// @param account The account to grant roles to. @@ -281,7 +252,14 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo uint256 roleBitmap, address account, bool executeCallbacks - ) internal virtual returns (bool) { + ) + internal + virtual + returns (bool) + { + if (roleBitmap == 0) { + return false; + } _checkRoleBitmap(roleBitmap); if (account == address(0)) { revert EACInvalidAccount(); @@ -293,10 +271,10 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo _roles[resource][account] = updatedRoles; uint256 newlyAddedRoles = roleBitmap & ~currentRoles; _updateRoleCounts(resource, newlyAddedRoles, true); + emit EACRolesChanged(resource, account, currentRoles, updatedRoles); if (executeCallbacks) { _onRolesGranted(resource, account, currentRoles, updatedRoles, roleBitmap); } - emit EACRolesChanged(resource, account, currentRoles, updatedRoles); return true; } else { return false; @@ -304,7 +282,6 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo } /// @dev Attempts to revoke roles from `account` and returns a boolean indicating if roles were revoked. - /// /// @param resource The resource to revoke roles within. /// @param roleBitmap The roles bitmap to revoke. /// @param account The account to revoke roles from. @@ -315,7 +292,11 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo uint256 roleBitmap, address account, bool executeCallbacks - ) internal virtual returns (bool) { + ) + internal + virtual + returns (bool) + { _checkRoleBitmap(roleBitmap); uint256 currentRoles = _roles[resource][account]; uint256 updatedRoles = currentRoles & ~roleBitmap; @@ -324,25 +305,16 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo _roles[resource][account] = updatedRoles; uint256 newlyRemovedRoles = roleBitmap & currentRoles; _updateRoleCounts(resource, newlyRemovedRoles, false); + emit EACRolesChanged(resource, account, currentRoles, updatedRoles); if (executeCallbacks) { _onRolesRevoked(resource, account, currentRoles, updatedRoles, roleBitmap); } - emit EACRolesChanged(resource, account, currentRoles, updatedRoles); return true; } else { return false; } } - /// @dev Revoke all roles for account within resource. - function _revokeAllRoles( - uint256 resource, - address account, - bool executeCallbacks - ) internal virtual returns (bool) { - return _revokeRoles(resource, EACBaseRolesLib.ALL_ROLES, account, executeCallbacks); - } - /// @dev Updates role counts when roles are granted/revoked /// @param resource The resource to update counts for /// @param roleBitmap The roles being modified @@ -352,13 +324,13 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo if (isGrant) { // Check for overflow - if (_hasZeroNybbles(~(roleMask & _roleCount[resource]))) { + if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & _roleCount[resource]))) { revert EACMaxAssignees(resource, roleBitmap); } _roleCount[resource] += roleBitmap; } else { // Check for underflow - if (_hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) { + if (EACBaseRolesLib.hasZeroNybbles(~(roleMask & ~_roleCount[resource]))) { revert EACMinAssignees(resource, roleBitmap); } _roleCount[resource] -= roleBitmap; @@ -366,7 +338,6 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo } /// @dev Callback for when roles are granted. - /// /// @param resource The resource that the roles were granted within. /// @param account The account that the roles were granted to. /// @param oldRoles The old roles for the account. @@ -378,12 +349,12 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo uint256 oldRoles, uint256 newRoles, uint256 roleBitmap - ) internal virtual { - // solhint-disable-previous-line no-empty-blocks - } + ) + internal + virtual + {} /// @dev Callback for when roles are revoked. - /// /// @param resource The resource that the roles were revoked within. /// @param account The account that the roles were revoked from. /// @param oldRoles The old roles for the account. @@ -395,27 +366,28 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo uint256 oldRoles, uint256 newRoles, uint256 roleBitmap - ) internal virtual { - // solhint-disable-previous-line no-empty-blocks - } + ) + internal + virtual + {} /// @dev Reverts if `account` does not have all the given roles. - function _checkRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) internal view virtual { + function _checkRoles(uint256 resource, uint256 roleBitmap, address account) + internal + view + virtual + { if (!hasRoles(resource, roleBitmap, account)) { revert EACUnauthorizedAccountRoles(resource, roleBitmap, account); } } /// @dev Reverts if `account` does not have the admin roles for all the given roles. - function _checkCanGrantRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) internal view virtual { + function _checkCanGrantRoles(uint256 resource, uint256 roleBitmap, address account) + internal + view + virtual + { uint256 settableRoles = _getSettableRoles(resource, account); if ((roleBitmap & ~settableRoles) != 0) { revert EACCannotGrantRoles(resource, roleBitmap, account); @@ -423,11 +395,11 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo } /// @dev Reverts if `account` does not have the admin roles for all the given roles that are being revoked. - function _checkCanRevokeRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) internal view virtual { + function _checkCanRevokeRoles(uint256 resource, uint256 roleBitmap, address account) + internal + view + virtual + { uint256 revokableRoles = _getRevokableRoles(resource, account); if ((roleBitmap & ~revokableRoles) != 0) { revert EACCannotRevokeRoles(resource, roleBitmap, account); @@ -443,13 +415,13 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo /// @param resource The resource to get settable roles for. /// @param account The account to get settable roles for. /// @return The settable roles for `account` within `resource`. - function _getSettableRoles( - uint256 resource, - address account - ) internal view virtual returns (uint256) { - uint256 adminRoleBitmap = (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) & - EACBaseRolesLib.ADMIN_ROLES; - return (adminRoleBitmap >> 128) | adminRoleBitmap; + function _getSettableRoles(uint256 resource, address account) + internal + view + virtual + returns (uint256) + { + return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account)); } /// @dev Returns the revokable roles for `account` within `resource`. @@ -459,22 +431,30 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo /// @param resource The resource to get revokable roles for. /// @param account The account to get revokable roles for. /// @return The revokable roles for `account` within `resource`. - function _getRevokableRoles( - uint256 resource, - address account - ) internal view virtual returns (uint256) { - uint256 adminRoleBitmap = (_roles[resource][account] | _roles[ROOT_RESOURCE][account]) & - EACBaseRolesLib.ADMIN_ROLES; - uint256 regularRoles = adminRoleBitmap >> 128; - return regularRoles | adminRoleBitmap; + function _getRevokableRoles(uint256 resource, address account) + internal + view + virtual + returns (uint256) + { + return EACBaseRolesLib.withAdminRolesApplied(_effectiveRoles(resource, account)); + } + + /// @dev Returns the roles bitmap for an account for permission checks. + function _getRoles(uint256 resource, address account) internal view virtual returns (uint256) { + return _roles[resource][account]; } //////////////////////////////////////////////////////////////////////// // Private Functions //////////////////////////////////////////////////////////////////////// + /// @dev Returns the effective roles bitmap for an account for permission checks. + function _effectiveRoles(uint256 resource, address account) private view returns (uint256) { + return _getRoles(ROOT_RESOURCE, account) | _getRoles(resource, account); + } + /// @dev Checks if a role bitmap contains only valid role bits. - /// /// @param roleBitmap The role bitmap to check. function _checkRoleBitmap(uint256 roleBitmap) private pure { if ((roleBitmap & ~EACBaseRolesLib.ALL_ROLES) != 0) { @@ -493,20 +473,4 @@ abstract contract EnhancedAccessControl is HCAContext, ERC165, IEnhancedAccessCo roleMask = roleBitmap | (roleBitmap << 1); roleMask |= roleMask << 2; } - - /// @dev Checks if the given value has any zero nybbles. - /// - /// @param value The value to check. - /// @return `true` if the value has any zero nybbles, `false` otherwise. - function _hasZeroNybbles(uint256 value) private pure returns (bool) { - // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord - uint256 hasZeroNybbles; - unchecked { - hasZeroNybbles = - (value - 0x1111111111111111111111111111111111111111111111111111111111111111) & - ~value & - 0x8888888888888888888888888888888888888888888888888888888888888888; - } - return hasZeroNybbles != 0; - } } diff --git a/contracts/src/access-control/interfaces/IEnhancedAccessControl.sol b/contracts/src/access-control/interfaces/IEnhancedAccessControl.sol index 753db9327..fa6d7e059 100644 --- a/contracts/src/access-control/interfaces/IEnhancedAccessControl.sol +++ b/contracts/src/access-control/interfaces/IEnhancedAccessControl.sol @@ -1,20 +1,24 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; - /// @notice Interface for Enhanced Access Control system that allows for: /// * Resource-based roles /// * Obtaining assignee count for each role in each resource /// * Root resource override /// * Up to 32 roles and 32 corresponding admin roles /// * Up to 15 assignees per role +/// /// @dev Interface selector: `0x8f452d62` -interface IEnhancedAccessControl is IERC165 { +interface IEnhancedAccessControl { //////////////////////////////////////////////////////////////////////// // Events //////////////////////////////////////////////////////////////////////// + /// @notice Emitted when roles are changed. + /// @param resource The resource that the roles were changed within. + /// @param account The account that the roles were changed for. + /// @param oldRoleBitmap The old roles for the account. + /// @param newRoleBitmap The new roles for the account. event EACRolesChanged( uint256 indexed resource, address indexed account, @@ -54,51 +58,79 @@ interface IEnhancedAccessControl is IERC165 { // Functions //////////////////////////////////////////////////////////////////////// - /// @dev Grants all roles in the given role bitmap to `account`. - function grantRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) external returns (bool); - - /// @dev Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE. + /// @notice Grants all roles in the given role bitmap to `account`. + /// @param resource The resource to grant roles within. + /// @param roleBitmap The roles bitmap to grant. + /// @param account The account to grant roles to. + /// @return `true` if the roles were granted, `false` otherwise. + function grantRoles(uint256 resource, uint256 roleBitmap, address account) + external + returns (bool); + + /// @notice Grants all roles in the given role bitmap to `account` in the ROOT_RESOURCE. + /// @param roleBitmap The roles bitmap to grant. + /// @param account The account to grant roles to. + /// @return `true` if the roles were granted, `false` otherwise. function grantRootRoles(uint256 roleBitmap, address account) external returns (bool); - /// @dev Revokes all roles in the given role bitmap from `account`. - function revokeRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) external returns (bool); - - /// @dev Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE. + /// @notice Revokes all roles in the given role bitmap from `account`. + /// @param resource The resource to revoke roles within. + /// @param roleBitmap The roles bitmap to revoke. + /// @param account The account to revoke roles from. + /// @return `true` if the roles were revoked, `false` otherwise. + function revokeRoles(uint256 resource, uint256 roleBitmap, address account) + external + returns (bool); + + /// @notice Revokes all roles in the given role bitmap from `account` in the ROOT_RESOURCE. + /// @param roleBitmap The roles bitmap to revoke. + /// @param account The account to revoke roles from. + /// @return `true` if the roles were revoked, `false` otherwise. function revokeRootRoles(uint256 roleBitmap, address account) external returns (bool); - /// @dev Returns the `ROOT_RESOURCE` constant. + /// @notice Returns the `ROOT_RESOURCE` constant. function ROOT_RESOURCE() external view returns (uint256); - /// @dev Returns the roles bitmap for an account in a resource. + /// @notice Returns the roles bitmap for an account in a resource. + /// @param resource The resource to get the roles for. + /// @param account The account to get the roles for. + /// @return The roles bitmap for the account in the resource. function roles(uint256 resource, address account) external view returns (uint256); - /// @dev Returns the role count bitmap for a resource. + /// @notice Returns the role count bitmap for a resource. + /// @param resource The resource to get the role count for. + /// @return count The role count bitmap for the resource. function roleCount(uint256 resource) external view returns (uint256); - /// @dev Returns `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`. + /// @notice Checks if the given account has been granted all the given roles in the `ROOT_RESOURCE`. + /// @param roleBitmap The roles bitmap to check. + /// @param account The account to check. + /// @return `true` if `account` has been granted all the given roles in the `ROOT_RESOURCE`, `false` otherwise. function hasRootRoles(uint256 roleBitmap, address account) external view returns (bool); - /// @dev Returns `true` if `account` has been granted all the given roles in `resource` or the `ROOT_RESOURCE`. - function hasRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) external view returns (bool); - - /// @dev Get if any of the roles in the given role bitmap has assignees. + /// @notice Checks if the given account has been granted all the given roles in the given resource or the `ROOT_RESOURCE`. + /// @param resource The resource to check. + /// @param roleBitmap The roles bitmap to check. + /// @param account The account to check. + /// @return `true` if `account` has been granted all the given roles in the given resource or the `ROOT_RESOURCE`, `false` otherwise. + function hasRoles(uint256 resource, uint256 roleBitmap, address account) + external + view + returns (bool); + + /// @notice Checks if any of the roles in the given role bitmap has assignees. + /// @param resource The resource to check. + /// @param roleBitmap The roles bitmap to check. + /// @return `true` if any of the roles in the given role bitmap has assignees, `false` otherwise. function hasAssignees(uint256 resource, uint256 roleBitmap) external view returns (bool); - /// @dev Get the no. of assignees for the roles in the given role bitmap. - function getAssigneeCount( - uint256 resource, - uint256 roleBitmap - ) external view returns (uint256 counts, uint256 mask); + /// @notice Returns the number of assignees for the roles in the given role bitmap. + /// @param resource The resource to check. + /// @param roleBitmap The roles bitmap to check. + /// @return counts The number of assignees for each of the roles in the given role bitmap, expressed as a packed array of 4-bit ints. + /// @return mask The mask for the given role bitmap. + function getAssigneeCount(uint256 resource, uint256 roleBitmap) + external + view + returns (uint256 counts, uint256 mask); } diff --git a/contracts/src/access-control/libraries/EACBaseRolesLib.sol b/contracts/src/access-control/libraries/EACBaseRolesLib.sol index 348381028..0a636f658 100644 --- a/contracts/src/access-control/libraries/EACBaseRolesLib.sol +++ b/contracts/src/access-control/libraries/EACBaseRolesLib.sol @@ -3,18 +3,54 @@ pragma solidity ^0.8.20; /// @dev Defines the two fundamental bitmasks used by `EnhancedAccessControl`'s nybble-packed role system. /// -/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in -/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits -/// outside valid positions are set) and for revoking all roles. +/// `ALL_ROLES`: a mask with bit 0 of every nybble set (`0x1111...`), representing one unit in +/// each of the 64 role slots (32 regular + 32 admin). Used for validation (checking no bits +/// outside valid positions are set) and for revoking all roles. +/// +/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking +/// just the 32 admin role slots. Used to extract which admin roles an account holds. /// -/// `ADMIN_ROLES`: same pattern but only in the upper 128 bits (`0x1111...0000...`), masking -/// just the 32 admin role slots. Used to extract which admin roles an account holds. library EACBaseRolesLib { + //////////////////////////////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////////////////////////////// + /// @dev Mask with bit 0 set in every nybble — represents one unit per role slot across all 64 slots. - uint256 public constant ALL_ROLES = + uint256 internal constant ALL_ROLES = 0x1111111111111111111111111111111111111111111111111111111111111111; /// @dev Mask selecting only the 32 admin role nybbles (upper 128 bits). - uint256 public constant ADMIN_ROLES = + uint256 internal constant ADMIN_ROLES = 0x1111111111111111111111111111111100000000000000000000000000000000; + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @dev Admin roles imply their corresponding regular roles. + function withAdminRolesApplied(uint256 roleBitmap) internal pure returns (uint256) { + roleBitmap >>= 128; + return (roleBitmap << 128) | roleBitmap; + } + + /// @dev Derive roles bitmap from assignee counts. + /// @param counts Packed role counts (0-15) as `uint4x64`. + function fromCounts(uint256 counts) internal pure returns (uint256) { + return (counts | (counts >> 1) | (counts >> 2) | (counts >> 3)) & ALL_ROLES; + } + + /// @dev Checks if the given value has any zero nybbles. + /// @param value The value to check. + /// @return `true` if the value has any zero nybbles, `false` otherwise. + function hasZeroNybbles(uint256 value) internal pure returns (bool) { + // Algorithm source: https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord + uint256 zeroNybbles; + unchecked { + zeroNybbles = + (value - 0x1111111111111111111111111111111111111111111111111111111111111111) & + ~value & + 0x8888888888888888888888888888888888888888888888888888888888888888; + } + return zeroNybbles != 0; + } } diff --git a/contracts/src/dns/DNSAliasResolver.sol b/contracts/src/dns/DNSAliasResolver.sol index c072a7c5e..a5f5168bd 100755 --- a/contracts/src/dns/DNSAliasResolver.sol +++ b/contracts/src/dns/DNSAliasResolver.sol @@ -9,32 +9,40 @@ import {ResolverCaller} from "@ens/contracts/universalResolver/ResolverCaller.so import {BytesUtils} from "@ens/contracts/utils/BytesUtils.sol"; import {IERC7996} from "@ens/contracts/utils/IERC7996.sol"; import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; -import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; import {ResolverProfileRewriterLib} from "../resolver/libraries/ResolverProfileRewriterLib.sol"; -import {LibRegistry, IRegistry} from "../universalResolver/libraries/LibRegistry.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {LibRegistry} from "../universalResolver/libraries/LibRegistry.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; /// @notice Gasless DNSSEC resolver that rewrites DNS names according to an alias rule encoded in -/// a TXT record's context field. Supports two modes: +/// a TXT record's context field. Supports two modes: /// -/// - Rewrite: context is ` ` — replaces the matching suffix -/// (e.g., `*.nick.com` + context `com base.eth` → `*.nick.base.eth`). -/// - Replace: context is `` (no space) — replaces the entire name. +/// - Rewrite: context is ` ` — replaces the matching suffix +/// (e.g., `*.nick.com` + context `com base.eth` → `*.nick.base.eth`). +/// - Replace: context is `` (no space) — replaces the entire name. /// -/// After rewriting, resolves the new name through the v2 registry via -/// `LibRegistry.findResolver()`, rewriting the node in the calldata via -/// `ResolverProfileRewriterLib`. +/// After rewriting, resolves the new name through the v2 registry via +/// `LibRegistry.findResolver()`, rewriting the node in the calldata via +/// `ResolverProfileRewriterLib`. /// -/// Only invoked indirectly by `DNSTLDResolver` when processing an `ENS1` TXT record. -contract DNSAliasResolver is ERC165, ResolverCaller, IERC7996, IExtendedDNSResolver { +/// Only invoked indirectly by `DNSTLDResolver` when processing an `ENS1` TXT record. +/// +contract DNSAliasResolver is + DelegatedContractNamer, + ResolverCaller, + IERC7996, + IExtendedDNSResolver +{ //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// - /// @dev The ENSv2 root registry used to look up resolvers for rewritten names. - IRegistry public immutable ROOT_REGISTRY; + /// @notice The ENSv2 root registry used to look up resolvers for rewritten names. + IPermissionedRegistry public immutable ROOT_REGISTRY; - /// @dev Provider for batch CCIP-Read gateway URLs, used when forwarding resolution calls. + /// @notice Provider for batch CCIP-Read gateway URLs, used when forwarding resolution calls. IGatewayProvider public immutable BATCH_GATEWAY_PROVIDER; //////////////////////////////////////////////////////////////////////// @@ -52,18 +60,23 @@ contract DNSAliasResolver is ERC165, ResolverCaller, IERC7996, IExtendedDNSResol // Initialization //////////////////////////////////////////////////////////////////////// + /// @param rootRegistry The ENSv2 root registry. + /// @param batchGatewayProvider The batch gateway provider. + /// @param contractNamer Delegated contract namer. constructor( - IRegistry rootRegistry, - IGatewayProvider batchGatewayProvider - ) CCIPReader(DEFAULT_UNSAFE_CALL_GAS) { + IPermissionedRegistry rootRegistry, + IGatewayProvider batchGatewayProvider, + IContractNamer contractNamer + ) + CCIPReader(DEFAULT_UNSAFE_CALL_GAS) + DelegatedContractNamer(contractNamer) + { ROOT_REGISTRY = rootRegistry; BATCH_GATEWAY_PROVIDER = batchGatewayProvider; } - /// @inheritdoc ERC165 - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165) returns (bool) { + /// @inheritdoc DelegatedContractNamer + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return type(IExtendedDNSResolver).interfaceId == interfaceId || type(IERC7996).interfaceId == interfaceId || @@ -79,16 +92,18 @@ contract DNSAliasResolver is ERC165, ResolverCaller, IERC7996, IExtendedDNSResol // Implementation //////////////////////////////////////////////////////////////////////// - /// @dev Apply rewrite rule to name and resolve it instead. - /// - /// The operating assumption is that this contract is never called directly, - /// and instead only invoked by DNSTLDResolver in response to an TXT record. - /// - function resolve( - bytes calldata name, - bytes calldata data, - bytes calldata context - ) external view returns (bytes memory) { + /// @notice Apply rewrite rule to name and resolve it instead. + /// @dev The operating assumption is that this contract is never called directly, + /// and instead only invoked by DNSTLDResolver in response to an TXT record. + /// @param name The DNS-encoded name. + /// @param data The data to resolve. + /// @param context The TXT record context. + /// @return The abi-encoded result from the resolver. + function resolve(bytes calldata name, bytes calldata data, bytes calldata context) + external + view + returns (bytes memory) + { bytes memory newName = rewriteNameWithContext(name, context); (, address resolver, bytes32 node, ) = LibRegistry.findResolver(ROOT_REGISTRY, newName, 0); callResolver( @@ -101,31 +116,23 @@ contract DNSAliasResolver is ERC165, ResolverCaller, IERC7996, IExtendedDNSResol ); } - //////////////////////////////////////////////////////////////////////// - // Internal Functions - //////////////////////////////////////////////////////////////////////// - - /// @dev Applies the rewrite rule encoded in `context` to `name`. If `context` contains a - /// space, it is split into an old suffix and a new suffix; the old suffix is matched - /// against `name` and replaced with the new suffix. If there is no space, the entire - /// `name` is replaced with the DNS-encoding of `context`. - /// + /// @notice Applies the rewrite rule encoded in `context` to `name`. + /// @dev If `context` contains a space, it is split into an old suffix and a new suffix; + /// the old suffix is matched against `name` and replaced with the new suffix. If there + /// is no space, the entire `name` is replaced with the DNS-encoding of `context`. /// @param name The DNS-encoded name to rewrite. /// @param context The rewrite rule — either ` ` or ``. - /// /// @return The rewritten DNS-encoded name. - function rewriteNameWithContext( - bytes calldata name, - bytes calldata context - ) public pure returns (bytes memory) { + function rewriteNameWithContext(bytes calldata name, bytes calldata context) + public + pure + returns (bytes memory) + { uint256 sep = BytesUtils.find(context, 0, context.length, " "); if (sep < context.length) { bytes memory oldSuffix = NameCoder.encode(string(context[:sep])); - (bool matched, , , uint256 offset) = NameCoder.matchSuffix( - name, - 0, - NameCoder.namehash(oldSuffix, 0) - ); + (bool matched, , , uint256 offset) = + NameCoder.matchSuffix(name, 0, NameCoder.namehash(oldSuffix, 0)); if (!matched) { revert NoSuffixMatch(name, oldSuffix); } diff --git a/contracts/src/dns/DNSTLDResolver.sol b/contracts/src/dns/DNSTLDResolver.sol index ab711b8c6..f3b159610 100644 --- a/contracts/src/dns/DNSTLDResolver.sol +++ b/contracts/src/dns/DNSTLDResolver.sol @@ -6,23 +6,23 @@ import {IGatewayProvider} from "@ens/contracts/ccipRead/IGatewayProvider.sol"; import {DNSSEC} from "@ens/contracts/dnssec-oracle/DNSSEC.sol"; import {IDNSGateway} from "@ens/contracts/dnssec-oracle/IDNSGateway.sol"; import {RRUtils} from "@ens/contracts/dnssec-oracle/RRUtils.sol"; +import {ENS} from "@ens/contracts/registry/ENS.sol"; import {IAddrResolver} from "@ens/contracts/resolvers/profiles/IAddrResolver.sol"; import {ICompositeResolver} from "@ens/contracts/resolvers/profiles/ICompositeResolver.sol"; import {IExtendedResolver} from "@ens/contracts/resolvers/profiles/IExtendedResolver.sol"; import {IVerifiableResolver} from "@ens/contracts/resolvers/profiles/IVerifiableResolver.sol"; import {ResolverFeatures} from "@ens/contracts/resolvers/ResolverFeatures.sol"; -import { - RegistryUtils as RegistryUtilsV1, - ENS -} from "@ens/contracts/universalResolver/RegistryUtils.sol"; +import {RegistryUtils as RegistryUtilsV1} from "@ens/contracts/universalResolver/RegistryUtils.sol"; import {ResolverCaller} from "@ens/contracts/universalResolver/ResolverCaller.sol"; import {BytesUtils} from "@ens/contracts/utils/BytesUtils.sol"; import {HexUtils} from "@ens/contracts/utils/HexUtils.sol"; import {IERC7996} from "@ens/contracts/utils/IERC7996.sol"; import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; -import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -import {LibRegistry, IRegistry} from "../universalResolver/libraries/LibRegistry.sol"; +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {LibRegistry} from "../universalResolver/libraries/LibRegistry.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; /// @dev DNS resource-record class for the Internet (`IN`), as defined in RFC 1035 section 3.2.4. uint16 constant CLASS_INET = 1; @@ -36,44 +36,46 @@ bytes constant TXT_PREFIX = "ENS1 "; /// @notice Multi-step resolver for DNS TLD names. Resolution follows this priority: /// -/// 1. Check for an existing resolver in the ENSv1 registry. If found (and it's not the v1 -/// DNS TLD resolver or this contract), delegate to it directly. -/// 2. Otherwise, query the DNSSEC oracle via CCIP-Read (EIP-3668) for TXT records. -/// 3. Verify the DNSSEC proof, find the first `ENS1`-prefixed TXT record, parse it into a -/// resolver address and context. -/// 4. Call the parsed resolver with the context. +/// 1. Check for an existing resolver in the ENSv1 registry. If found (and it's not the v1 +/// DNS TLD resolver or this contract), delegate to it directly. +/// 2. Otherwise, query the DNSSEC oracle via CCIP-Read (EIP-3668) for TXT records. +/// 3. Verify the DNSSEC proof, find the first `ENS1`-prefixed TXT record, parse it into a +/// resolver address and context. +/// 4. Call the parsed resolver with the context. +/// +/// Implements `IVerifiableResolver` to expose the DNSSEC oracle address and gateways for +/// verification. /// -/// Implements `IVerifiableResolver` to expose the DNSSEC oracle address and gateways for -/// verification. contract DNSTLDResolver is + DelegatedContractNamer, + ResolverCaller, IERC7996, ICompositeResolver, - IVerifiableResolver, - ResolverCaller, - ERC165 + IVerifiableResolver { //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// - /// @dev The ENSv1 registry, used to check for existing resolvers on mainnet before falling - /// back to DNSSEC resolution. + + /// @notice The ENSv1 registry, used to check for existing resolvers on mainnet before falling + /// back to DNSSEC resolution. ENS public immutable ENS_REGISTRY_V1; - /// @dev The v1 DNS TLD resolver address. If the v1 registry points to this resolver (or to - /// this contract), the name is considered unresolved in v1 and DNSSEC fallback is used. + /// @notice The v1 DNS TLD resolver address. If the v1 registry points to this resolver (or to + /// this contract), the name is considered unresolved in v1 and DNSSEC fallback is used. address public immutable DNS_TLD_RESOLVER_V1; - /// @dev The ENSv2 root registry, used to resolve names parsed from `ENS1` TXT records. - IRegistry public immutable ROOT_REGISTRY; + /// @notice The ENSv2 root registry, used to resolve names parsed from `ENS1` TXT records. + IPermissionedRegistry public immutable ROOT_REGISTRY; - /// @dev The DNSSEC oracle contract that verifies signed DNS resource-record sets. + /// @notice The DNSSEC oracle contract that verifies signed DNS resource-record sets. DNSSEC public immutable DNSSEC_ORACLE; - /// @dev Gateway provider for the DNSSEC oracle CCIP-Read queries. + /// @notice Gateway provider for the DNSSEC oracle CCIP-Read queries. IGatewayProvider public immutable ORACLE_GATEWAY_PROVIDER; - /// @dev Gateway provider for batch CCIP-Read calls when forwarding resolution to downstream - /// resolvers. + /// @notice Gateway provider for batch CCIP-Read calls when forwarding resolution to downstream + /// resolvers. IGatewayProvider public immutable BATCH_GATEWAY_PROVIDER; //////////////////////////////////////////////////////////////////////// @@ -88,14 +90,25 @@ contract DNSTLDResolver is // Initialization //////////////////////////////////////////////////////////////////////// + /// @param ensRegistryV1 The ENSv1 registry. + /// @param dnsTLDResolverV1 The v1 DNS TLD resolver address. + /// @param rootRegistry The ENSv2 root registry. + /// @param dnssecOracle The DNSSEC oracle contract. + /// @param oracleGatewayProvider The gateway provider for the DNSSEC oracle CCIP-Read queries. + /// @param batchGatewayProvider The gateway provider for batch CCIP-Read calls when forwarding resolution to downstream resolvers. + /// @param contractNamer Delegated contract namer. constructor( ENS ensRegistryV1, address dnsTLDResolverV1, - IRegistry rootRegistry, + IPermissionedRegistry rootRegistry, DNSSEC dnssecOracle, IGatewayProvider oracleGatewayProvider, - IGatewayProvider batchGatewayProvider - ) CCIPReader(DEFAULT_UNSAFE_CALL_GAS) { + IGatewayProvider batchGatewayProvider, + IContractNamer contractNamer + ) + CCIPReader(DEFAULT_UNSAFE_CALL_GAS) + DelegatedContractNamer(contractNamer) + { ENS_REGISTRY_V1 = ensRegistryV1; DNS_TLD_RESOLVER_V1 = dnsTLDResolverV1; ROOT_REGISTRY = rootRegistry; @@ -104,10 +117,8 @@ contract DNSTLDResolver is BATCH_GATEWAY_PROVIDER = batchGatewayProvider; } - /// @inheritdoc ERC165 - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165) returns (bool) { + /// @inheritdoc DelegatedContractNamer + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return type(IExtendedResolver).interfaceId == interfaceId || type(ICompositeResolver).interfaceId == interfaceId || @@ -127,11 +138,8 @@ contract DNSTLDResolver is /// @notice Fetch the DNSSEC TXT record. /// Callers should enable EIP-3668. - /// /// @dev This function executes over multiple steps. - /// /// @param name The DNS-encoded name. - /// /// @return The verified DNSSEC TXT records. function getDNSSECRecords(bytes calldata name) external view returns (bytes[] memory) { address resolver = _determineMainnetResolver(name); @@ -148,14 +156,16 @@ contract DNSTLDResolver is } /// @notice CCIP-Read callback for `getDNSSECRecords()`. - function getDNSSECRecordsCallback( - bytes calldata response, - bytes calldata name - ) external view returns (bytes[] memory txts) { - DNSSEC.RRSetWithSignature[] memory rrsets = abi.decode( - response, - (DNSSEC.RRSetWithSignature[]) - ); + /// @param response The response data. + /// @param name The DNS-encoded name. + /// @return txts The verified DNSSEC TXT records. + function getDNSSECRecordsCallback(bytes calldata response, bytes calldata name) + external + view + returns (bytes[] memory txts) + { + DNSSEC.RRSetWithSignature[] memory rrsets = + abi.decode(response, (DNSSEC.RRSetWithSignature[])); (bytes memory data, ) = DNSSEC_ORACLE.verifyRRSet(rrsets); uint256 i; for ( @@ -181,20 +191,17 @@ contract DNSTLDResolver is } /// @inheritdoc IVerifiableResolver - function verifierMetadata( - bytes calldata name - ) external view returns (address verifier, string[] memory gateways) { + function verifierMetadata(bytes calldata name) + external + view + returns (address verifier, string[] memory gateways) + { if (_determineMainnetResolver(name) == address(0)) { verifier = address(DNSSEC_ORACLE); gateways = ORACLE_GATEWAY_PROVIDER.gateways(); } } - /// @inheritdoc ICompositeResolver - function requiresOffchain(bytes calldata name) external view returns (bool offchain) { - offchain = _determineMainnetResolver(name) == address(0); - } - /// @inheritdoc ICompositeResolver /// @dev This function executes over multiple steps. function getResolver(bytes calldata name) external view returns (address, bool) { @@ -212,22 +219,26 @@ contract DNSTLDResolver is } /// @notice CCIP-Read callback for `getResolver()`. - function getResolverCallback( - bytes calldata response, - bytes calldata name - ) external view returns (address, bool) { + /// @param response The response data. + /// @param name The DNS-encoded name. + /// @return resolver The underlying resolver address. + /// @return offchain `true` if `resolver` is offchain. + function getResolverCallback(bytes calldata response, bytes calldata name) + external + view + returns (address, bool) + { (address resolver, ) = _verifyDNSSEC(name, response); return (resolver, true); } /// @notice Resolve `name` using ENSv1 or DNSSEC. /// Caller should enable EIP-3668. - /// /// @dev This function executes over multiple steps. - function resolve( - bytes calldata name, - bytes calldata data - ) external view returns (bytes memory) { + /// @param name The DNS-encoded name. + /// @param data The data to resolve. + /// @return The abi-encoded result from the resolver. + function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory) { address resolver = _determineMainnetResolver(name); if (resolver != address(0)) { return callResolver(resolver, name, data, false, "", BATCH_GATEWAY_PROVIDER.gateways()); // ==> step 2 @@ -243,15 +254,14 @@ contract DNSTLDResolver is /// @notice CCIP-Read callback for `resolve()` from calling the DNSSEC oracle. /// Reverts `UnreachableName` if no "ENS1" TXT record is found. - /// /// @param response The response data. /// @param extraData The contextual data passed from `resolve()`. - /// /// @return The abi-encoded result from the resolver. - function resolveOracleCallback( - bytes calldata response, - bytes calldata extraData - ) external view returns (bytes memory) { + function resolveOracleCallback(bytes calldata response, bytes calldata extraData) + external + view + returns (bytes memory) + { (bytes memory name, bytes memory call) = abi.decode(extraData, (bytes, bytes)); (address resolver, bytes memory context) = _verifyDNSSEC(name, response); if (resolver == address(0)) { @@ -262,14 +272,14 @@ contract DNSTLDResolver is /// @notice Parse DNSSEC TXT record into parts. /// Format: "ENS1 ". - /// /// @param txt The DNSSEC TXT record. - /// /// @return resolver The resolver address or null if wrong format or name didn't resolve. /// @return context The context data. - function parseDNSSECRecord( - bytes memory txt - ) public view returns (address resolver, bytes memory context) { + function parseDNSSECRecord(bytes memory txt) + public + view + returns (address resolver, bytes memory context) + { uint256 p = TXT_PREFIX.length; uint256 n = txt.length; if (n > p && BytesUtils.equals(txt, 0, TXT_PREFIX, 0, p)) { @@ -290,9 +300,7 @@ contract DNSTLDResolver is /// @dev Looks up the resolver for `name` in the ENSv1 registry. Returns `address(0)` if /// no resolver is set, or if the resolver is the v1 DNS TLD resolver or this contract /// (indicating the name has not been explicitly configured in v1). - /// /// @param name The DNS-encoded name to look up. - /// /// @return resolver The v1 resolver address, or `address(0)` if none is applicable. function _determineMainnetResolver(bytes memory name) internal view returns (address resolver) { (resolver, , ) = RegistryUtilsV1.findResolver(ENS_REGISTRY_V1, name, 0); @@ -304,20 +312,17 @@ contract DNSTLDResolver is /// @dev Verifies a DNSSEC proof and scans the resulting resource records for the first /// valid `ENS1`-prefixed TXT record. Returns the parsed resolver and context from /// that record, or `address(0)` if no matching record is found. - /// /// @param name The DNS-encoded name the records should belong to. /// @param oracleWitness The ABI-encoded `DNSSEC.RRSetWithSignature[]` proof from the gateway. - /// /// @return resolver The resolver address parsed from the first valid `ENS1` TXT record. /// @return context The context bytes following the resolver in the TXT record. - function _verifyDNSSEC( - bytes memory name, - bytes calldata oracleWitness - ) internal view returns (address resolver, bytes memory context) { - DNSSEC.RRSetWithSignature[] memory rrsets = abi.decode( - oracleWitness, - (DNSSEC.RRSetWithSignature[]) - ); + function _verifyDNSSEC(bytes memory name, bytes calldata oracleWitness) + internal + view + returns (address resolver, bytes memory context) + { + DNSSEC.RRSetWithSignature[] memory rrsets = + abi.decode(oracleWitness, (DNSSEC.RRSetWithSignature[])); (bytes memory data, ) = DNSSEC_ORACLE.verifyRRSet(rrsets); for ( RRUtils.RRIterator memory iter = RRUtils.iterateRRs(data, 0); @@ -339,9 +344,7 @@ contract DNSTLDResolver is /// If the value matches `/^0x[0-9a-fA-F]{40}$/`, it's a literal address. /// Otherwise, it's considered a name and resolved in the registry. /// Reverts `DNSEncodingFailed` if the name cannot be encoded. - /// /// @param v The address or name. - /// /// @return resolver The corresponding resolver address. function _parseResolver(bytes memory v) internal view returns (address resolver) { if (v.length == 42 && bytes2(v) == "0x") { @@ -362,15 +365,14 @@ contract DNSTLDResolver is /// @dev Returns `true` if `iter` points to a TXT record of class `IN` whose owner name /// matches `name`. - /// /// @param iter The current position in the resource-record iteration. /// @param name The DNS-encoded name to match against the record's owner name. - /// /// @return `true` if the record is a matching Internet-class TXT record. - function _isTXTForName( - RRUtils.RRIterator memory iter, - bytes memory name - ) internal pure returns (bool) { + function _isTXTForName(RRUtils.RRIterator memory iter, bytes memory name) + internal + pure + returns (bool) + { return iter.class == CLASS_INET && iter.dnstype == QTYPE_TXT && @@ -380,18 +382,17 @@ contract DNSTLDResolver is /// @dev Decode `v[off:end]` as raw TXT chunks. /// Encoding: `(byte(n) )...` /// Reverts `InvalidTXT` if the data is malformed. - /// /// @param v The raw TXT data. /// @param off The offset of the record data. /// @param end The upper bound of the record data. - /// /// @return txt The decoded TXT value. - function _readTXT( - bytes memory v, - uint256 off, - uint256 end - ) internal pure returns (bytes memory txt) { - if (end > v.length) revert InvalidTXT(); + function _readTXT(bytes memory v, uint256 off, uint256 end) + internal + pure + returns (bytes memory txt) + { + if (end > v.length) + revert InvalidTXT(); txt = new bytes(end - off); assembly { let ptr := add(v, 32) @@ -415,6 +416,7 @@ contract DNSTLDResolver is } mstore(txt, sub(ptr, add(txt, 32))) // truncate } - if (off != end) revert InvalidTXT(); // overflow or junk at end + if (off != end) + revert InvalidTXT(); // overflow or junk at end } } diff --git a/contracts/src/dns/DNSTXTResolver.sol b/contracts/src/dns/DNSTXTResolver.sol index 442cfc720..d67b94a4a 100644 --- a/contracts/src/dns/DNSTXTResolver.sol +++ b/contracts/src/dns/DNSTXTResolver.sol @@ -5,6 +5,7 @@ import {IMulticallable} from "@ens/contracts/resolvers/IMulticallable.sol"; import {IAddressResolver} from "@ens/contracts/resolvers/profiles/IAddressResolver.sol"; import {IAddrResolver} from "@ens/contracts/resolvers/profiles/IAddrResolver.sol"; import {IContentHashResolver} from "@ens/contracts/resolvers/profiles/IContentHashResolver.sol"; +import {IDataResolver} from "@ens/contracts/resolvers/profiles/IDataResolver.sol"; import {IExtendedDNSResolver} from "@ens/contracts/resolvers/profiles/IExtendedDNSResolver.sol"; import {IHasAddressResolver} from "@ens/contracts/resolvers/profiles/IHasAddressResolver.sol"; import {IPubkeyResolver} from "@ens/contracts/resolvers/profiles/IPubkeyResolver.sol"; @@ -13,9 +14,11 @@ import {ResolverFeatures} from "@ens/contracts/resolvers/ResolverFeatures.sol"; import {ENSIP19, COIN_TYPE_ETH} from "@ens/contracts/utils/ENSIP19.sol"; import {HexUtils} from "@ens/contracts/utils/HexUtils.sol"; import {IERC7996} from "@ens/contracts/utils/IERC7996.sol"; -import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; + import {DNSTXTParserLib} from "./libraries/DNSTXTParserLib.sol"; /// @notice Resolver that answers requests with the data encoded into the context of a DNSSEC "ENS1" TXT record. @@ -36,10 +39,11 @@ import {DNSTXTParserLib} from "./libraries/DNSTXTParserLib.sol"; /// - Default EVM Address: `a[e0]=0x...` /// - Linea Address: `a[e59144]=0x...` /// - Bitcoin Address: `a[0]=0x00...` (see: ENSIP-9) +/// * `data(key)`: `d[key]=0x...` /// * `contenthash()`: `c=0x...` (see: ENSIP-7) /// * `pubkey()`: `xy=0x...` /// -contract DNSTXTResolver is ERC165, IERC7996, IExtendedDNSResolver { +contract DNSTXTResolver is DelegatedContractNamer, IERC7996, IExtendedDNSResolver { //////////////////////////////////////////////////////////////////////// // Errors //////////////////////////////////////////////////////////////////////// @@ -61,10 +65,11 @@ contract DNSTXTResolver is ERC165, IERC7996, IExtendedDNSResolver { // Initialization //////////////////////////////////////////////////////////////////////// - /// @inheritdoc ERC165 - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165) returns (bool) { + /// @param contractNamer Delegated contract namer. + constructor(IContractNamer contractNamer) DelegatedContractNamer(contractNamer) {} + + /// @inheritdoc DelegatedContractNamer + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return type(IExtendedDNSResolver).interfaceId == interfaceId || type(IERC7996).interfaceId == interfaceId || @@ -89,23 +94,26 @@ contract DNSTXTResolver is ERC165, IERC7996, IExtendedDNSResolver { /// /// Multicalling this contract directly will not include these values. /// + /// @param {name} Ignored. /// @param data The ABI-encoded resolver call (selector + arguments) to answer. /// @param context The human-readable context string from the `ENS1` TXT record, parsed by - /// `DNSTXTParserLib`. - /// + /// `DNSTXTParserLib`. /// @return result The ABI-encoded response matching the requested resolver profile. function resolve( bytes calldata /* name */, bytes calldata data, bytes calldata context - ) external view returns (bytes memory result) { + ) + external + view + returns (bytes memory result) + { bytes4 selector = bytes4(data); if (selector == IMulticallable.multicall.selector) { bytes[] memory m = abi.decode(data[4:], (bytes[])); for (uint256 i; i < m.length; ++i) { - (bool ok, bytes memory v) = address(this).staticcall( - abi.encodeCall(this.resolve, ("", m[i], context)) - ); + (bool ok, bytes memory v) = + address(this).staticcall(abi.encodeCall(this.resolve, ("", m[i], context))); if (ok) { v = abi.decode(v, (bytes)); // unwrap resolve() } @@ -126,6 +134,10 @@ contract DNSTXTResolver is ERC165, IERC7996, IExtendedDNSResolver { (, string memory key) = abi.decode(data[4:], (bytes32, string)); bytes memory v = DNSTXTParserLib.find(context, abi.encodePacked("t[", key, "]=")); return abi.encode(v); + } else if (selector == IDataResolver.data.selector) { + (, string memory key) = abi.decode(data[4:], (bytes32, string)); + bytes memory v = DNSTXTParserLib.find(context, abi.encodePacked("d[", key, "]=")); + return abi.encode(_parse0xString(v)); } else if (selector == IContentHashResolver.contenthash.selector) { return abi.encode(_parse0xString(DNSTXTParserLib.find(context, "c="))); } else if (selector == IPubkeyResolver.pubkey.selector) { @@ -148,17 +160,25 @@ contract DNSTXTResolver is ERC165, IERC7996, IExtendedDNSResolver { /// @dev Extract address from context according to coin type. /// Reverts `InvalidHexData` if non-null and not a hex string. /// Reverts `InvalidEVMAddress` if non-null, coin type is EVM, and address is not 20 bytes. - /// /// @param context The DNS context string. /// @param coinType The coin type. /// @param useDefault If true and address is null and coin type is EVM, use default EVM coin type. - /// /// @return v The address or null if not found. - function _extractAddress( - bytes memory context, - uint256 coinType, - bool useDefault - ) internal pure returns (bytes memory v) { + function _extractAddress(bytes memory context, uint256 coinType, bool useDefault) + internal + pure + returns (bytes memory v) + { + // support ExtendedDNSResolver syntax + if (context.length == 42 && bytes2(context) == "0x") { + (address a, bool valid) = HexUtils.hexToAddress(context, 2, 42); + if (valid) { + if (coinType == COIN_TYPE_ETH) { + v = abi.encodePacked(a); + } + return v; + } + } if (ENSIP19.isEVMCoinType(coinType)) { v = DNSTXTParserLib.find( context, @@ -188,15 +208,13 @@ contract DNSTXTResolver is ERC165, IERC7996, IExtendedDNSResolver { } /// @dev Convert 0x-prefixed hex-string to bytes. - /// Reverts `InvalidHexData` if non-null and not a hex string. - /// + /// Reverts `InvalidHexData` if non-null and not an even-length hex string. /// @param s The string to parse. - /// /// @return v The parsed bytes. function _parse0xString(bytes memory s) internal pure returns (bytes memory v) { if (s.length > 0) { bool valid; - if (s.length >= 2 && s[0] == "0" && s[1] == "x") { + if ((s.length & 1) == 0 && bytes2(s) == "0x") { (v, valid) = HexUtils.hexToBytes(s, 2, s.length); } if (!valid) { diff --git a/contracts/src/dns/libraries/DNSTXTParserLib.sol b/contracts/src/dns/libraries/DNSTXTParserLib.sol index f1baa0193..3a8bf633a 100644 --- a/contracts/src/dns/libraries/DNSTXTParserLib.sol +++ b/contracts/src/dns/libraries/DNSTXTParserLib.sol @@ -3,14 +3,17 @@ pragma solidity >=0.8.13; import {BytesUtils} from "@ens/contracts/utils/BytesUtils.sol"; -/// @notice Library for parsing ENS records from DNS TXT data. +/// @dev Library for parsing ENS records from DNS TXT data. /// -/// The record data consists of a series of key=value pairs, separated by spaces. Keys -/// may have an optional argument in square brackets, and values may be either unquoted -/// - in which case they may not contain spaces - or single-quoted. Single quotes in -/// a quoted value may be backslash-escaped. +/// The record data consists of a series of key=value pairs, separated by spaces. /// -/// eg. `a=x`, `a[]=x`, `a[b]=x`, `a[b]='x y'`, `a[b]='x y\'s'` +/// Keys may have an optional argument in square brackets. +/// Keys may contain additional square brackets but they must be balanced. +/// eg. `key`, `key[]`, `key[arg]`, `key[arg[abc]]` +/// +/// Values may be unquoted (therefore no spaces) or single-quoted. +/// Single quotes in a quoted value may be backslash-escaped. +/// eg. `x`, `'x y'`, `'x y\'s'` /// /// ::= " "* * " "* /// ::= | @@ -19,11 +22,15 @@ import {BytesUtils} from "@ens/contracts/utils/BytesUtils.sol"; /// ::= "=" /// ::= | "[" "]" /// ::= "'" "'" | -/// ::= +/// ::= /// ::= -/// ::= +/// ::= /// library DNSTXTParserLib { + //////////////////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////////////////// + /// @dev The DFA internal states. enum State { START, @@ -37,18 +44,35 @@ library DNSTXTParserLib { IGNORED_UNQUOTED_VALUE } - bytes1 private constant CH_BACKSLASH = bytes1(0x5C); // "\" + //////////////////////////////////////////////////////////////////////// + // Constants + //////////////////////////////////////////////////////////////////////// + + /// @dev The codepoint for the `\` character. + bytes1 private constant CH_BACKSLASH = bytes1(0x5C); + + /// @dev The codepoint for the `'` character. bytes1 private constant CH_QUOTE = "'"; + + /// @dev The codepoint for the ` ` character. bytes1 private constant CH_SPACE = " "; + + /// @dev The codepoint for the `=` character. bytes1 private constant CH_EQUAL = "="; + + /// @dev The codepoint for the `[` character. bytes1 private constant CH_ARG_OPEN = "["; + + /// @dev The codepoint for the `]` character. bytes1 private constant CH_ARG_CLOSE = "]"; + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + /// @dev Implements a DFA to parse the text record, looking for an entry matching `key`. - /// /// @param data The text record to parse. /// @param key The exact key to search for with trailing equals, eg. "key=". - /// /// @return value The value if found, or an empty string if `key` does not exist. function find(bytes memory data, bytes memory key) internal pure returns (bytes memory value) { // Here we use a simple state machine to parse the text record. We @@ -90,17 +114,24 @@ library DNSTXTParserLib { } } else if (state == State.IGNORED_KEY_ARG) { // look for the end of the key arg + uint256 depth; for (; i < len; ++i) { - if (data[i] == CH_ARG_CLOSE) { - ++i; // parsed key[arg] - if (i < len && data[i] == CH_EQUAL) { - state = State.IGNORED_VALUE; // ignore its value - ++i; + if (data[i] == CH_ARG_OPEN) { + ++depth; + } else if (data[i] == CH_ARG_CLOSE) { + if (depth == 0) { + ++i; // parsed key[arg] + if (i < len && data[i] == CH_EQUAL) { + state = State.IGNORED_VALUE; // ignore its value + ++i; + } else { + // this is recoverable parsing error + state = State.IGNORED_UNQUOTED_VALUE; // assume unquoted and ignore its value + } + break; } else { - // this is recoverable parsing error - state = State.IGNORED_UNQUOTED_VALUE; // assume unquoted and ignore its value + --depth; } - break; } } } else if (state == State.VALUE) { diff --git a/contracts/src/erc1155/ERC1155Singleton.sol b/contracts/src/erc1155/ERC1155Singleton.sol index 36c0a27c2..9a30f3a97 100644 --- a/contracts/src/erc1155/ERC1155Singleton.sol +++ b/contracts/src/erc1155/ERC1155Singleton.sol @@ -1,18 +1,4 @@ // SPDX-License-Identifier: MIT - -/// @notice ERC1155 variant enforcing exactly one owner per token ID. -/// -/// Instead of the standard nested balance mapping (`id → address → balance`), uses a flat -/// `id → address` ownership mapping. `balanceOf` returns 1 if the account is the owner, -/// 0 otherwise. Transferring value > 1 reverts. -/// -/// Used by `PermissionedRegistry` to represent domain name ownership as non-divisible tokens. -/// The registry overrides `ownerOf` to add expiry and version validation on top of raw ownership. -/// -/// Inherits `HCAContext` so that `_msgSender()` resolves HCA proxy accounts to their real -/// owners for approval checks and operator tracking. -/// -/// @dev Portions from OpenZeppelin Contracts (token/ERC1155/ERC1155.sol) pragma solidity >=0.8.13; import {IERC1155Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; @@ -25,18 +11,27 @@ import {Arrays} from "@openzeppelin/contracts/utils/Arrays.sol"; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import {HCAContext} from "../hca/HCAContext.sol"; - import {IERC1155Singleton} from "./interfaces/IERC1155Singleton.sol"; +/// @notice ERC1155 variant enforcing exactly one owner per token ID. +/// +/// Instead of the standard nested balance mapping (`id → address → balance`), uses a flat +/// `id → address` ownership mapping. `balanceOf` returns 1 if the account is the owner, +/// 0 otherwise. Transferring value > 1 reverts. +/// +/// Used by `PermissionedRegistry` to represent domain name ownership as non-divisible tokens. +/// The registry overrides `ownerOf` to add expiry and version validation on top of raw ownership. +/// +/// @author OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC1155/ERC1155.sol) +/// @dev This contract has been modified from the implementation at the above link. abstract contract ERC1155Singleton is - HCAContext, ERC165, IERC1155Singleton, IERC1155Errors, IERC1155MetadataURI { using Arrays for uint256[]; + using Arrays for address[]; //////////////////////////////////////////////////////////////////////// @@ -49,21 +44,18 @@ abstract contract ERC1155Singleton is /// @dev Standard ERC1155 operator approval mapping. mapping(address account => mapping(address operator => bool)) private _operatorApprovals; - //////////////////////////////////////////////////////////////////////// - // Events - //////////////////////////////////////////////////////////////////////// - - /// @dev Declared for ERC721-like per-token approval signaling but not emitted by this contract. - event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); - //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// /// @inheritdoc IERC165 - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165, IERC165) returns (bool) { + function supportsInterface(bytes4 interfaceId) + public + view + virtual + override(ERC165, IERC165) + returns (bool) + { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155Singleton).interfaceId || @@ -75,61 +67,84 @@ abstract contract ERC1155Singleton is // Implementation //////////////////////////////////////////////////////////////////////// - /// @dev See {IERC1155-setApprovalForAll}. + /// @notice Sets the approval for all operator. + /// @param operator The operator to set the approval for. + /// @param approved The approval status. function setApprovalForAll(address operator, bool approved) public virtual { - _setApprovalForAll(_msgSender(), operator, approved); + _setApprovalForAll(msg.sender, operator, approved); } - /// @dev See {IERC1155-safeTransferFrom}. - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 value, - bytes memory data - ) public virtual { - address sender = _msgSender(); - if (from != sender && !isApprovedForAll(from, sender)) { - revert ERC1155MissingApprovalForAll(sender, from); - } + /// @notice Transfers a single token from one address to another. + /// @param from The address to transfer the token from. + /// @param to The address to transfer the token to. + /// @param id The token ID. + /// @param value The amount of tokens to transfer. + /// @param data Additional data to pass to the receiver. + /// @dev `to` cannot be the zero address. + /// @dev If the caller is not `from`, it must have been approved to spend `from`'s tokens via `setApprovalForAll`. + /// @dev `from` must have a balance of tokens of type `id` of at least `value` amount. + /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155Received and return the + /// acceptance magic value. + function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) + public + virtual + { + _checkApproval(from, msg.sender); _safeTransferFrom(from, to, id, value, data); } - /// @dev See {IERC1155-safeBatchTransferFrom}. + /// @notice Transfers multiple tokens from one address to another. + /// @param from The address to transfer the tokens from. + /// @param to The address to transfer the tokens to. + /// @param ids The token IDs. + /// @param values The amounts of tokens to transfer. + /// @param data Additional data to pass to the receiver. + /// @dev `ids` and `values` must have the same length. + /// @dev If `to` refers to a smart contract, it must implement IERC1155Receiver.onERC1155BatchReceived and return the + /// acceptance magic value. function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data - ) public virtual { - address sender = _msgSender(); - if (from != sender && !isApprovedForAll(from, sender)) { - revert ERC1155MissingApprovalForAll(sender, from); - } + ) + public + virtual + { + _checkApproval(from, msg.sender); _safeBatchTransferFrom(from, to, ids, values, data); } + /// @inheritdoc IERC1155Singleton function ownerOf(uint256 id) public view virtual returns (address owner) { return _owners[id]; } - function uri(uint256 /* id */) public view virtual returns (string memory); + /// @notice Returns the URI for a token. + /// @param id The token ID. + /// @return uri The URI for the token. + function uri(uint256 id) public view virtual returns (string memory uri); - /// @dev See {IERC1155-balanceOf}. + /// @notice Returns the balance of a token for an account. + /// @param account The account to get the balance for. + /// @param id The token ID. + /// @return balance The balance of the token for the account. This will only ever be 1 or 0. function balanceOf(address account, uint256 id) public view virtual returns (uint256) { - return ownerOf(id) == account ? 1 : 0; + return account != address(0) && ownerOf(id) == account ? 1 : 0; } - /// @dev See {IERC1155-balanceOfBatch}. - /// - /// Requirements: - /// - /// - `accounts` and `ids` must have the same length. - function balanceOfBatch( - address[] memory accounts, - uint256[] memory ids - ) public view virtual returns (uint256[] memory) { + /// @notice Returns the balances of a batch of tokens for an account. + /// @param accounts The accounts to get the balances for. + /// @param ids The token IDs. + /// @return batchBalances The balances of the tokens for the accounts. These will only ever be 1 or 0. + /// @dev `accounts` and `ids` must have the same length. + function balanceOfBatch(address[] memory accounts, uint256[] memory ids) + public + view + virtual + returns (uint256[] memory) + { if (accounts.length != ids.length) { revert ERC1155InvalidArrayLength(ids.length, accounts.length); } @@ -143,11 +158,11 @@ abstract contract ERC1155Singleton is return batchBalances; } - /// @dev See {IERC1155-isApprovedForAll}. - function isApprovedForAll( - address account, - address operator - ) public view virtual returns (bool) { + /// @notice Returns the approval for all operator. + /// @param account The account to get the approval for. + /// @param operator The operator to get the approval for. + /// @return approved The approval status. + function isApprovedForAll(address account, address operator) public view virtual returns (bool) { return _operatorApprovals[account][operator]; } @@ -155,30 +170,23 @@ abstract contract ERC1155Singleton is // Internal Functions //////////////////////////////////////////////////////////////////////// - /// @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from` - /// (or `to`) is the zero address. - /// - /// Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise. - /// - /// Requirements: - /// - /// - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received} - /// or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value. - /// - `ids` and `values` must have the same length. - /// - /// NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead. - function _update( - address from, - address to, - uint256[] memory ids, - uint256[] memory values - ) internal virtual { + /// @notice Apply token updates for each pair in `ids` and `values`. + /// @param from Address tokens are moved from. Use `address(0)` for mints. + /// @param to Address tokens are moved to. Use `address(0)` for burns. + /// @param ids Token IDs to update. + /// @param values Amounts for each token ID. + /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`. + /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not the current owner or `value > 1`. + /// @dev This function does not perform ERC-1155 receiver acceptance checks. + /// @dev Emits `TransferSingle` when one token ID is updated, otherwise emits `TransferBatch`. + function _update(address from, address to, uint256[] memory ids, uint256[] memory values) + internal + virtual + { if (ids.length != values.length) { revert ERC1155InvalidArrayLength(ids.length, values.length); } - address operator = _msgSender(); - for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids.unsafeMemoryAccess(i); uint256 value = values.unsafeMemoryAccess(i); @@ -197,56 +205,64 @@ abstract contract ERC1155Singleton is if (ids.length == 1) { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); - emit TransferSingle(operator, from, to, id, value); + emit TransferSingle(msg.sender, from, to, id, value); } else { - emit TransferBatch(operator, from, to, ids, values); + emit TransferBatch(msg.sender, from, to, ids, values); } } - /// @dev Version of {_update} that performs the token acceptance check by calling - /// {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it - /// contains code (eg. is a smart contract at the moment of execution). - /// - /// IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any - /// update to the contract state after this function would break the check-effect-interaction pattern. Consider - /// overriding {_update} instead. + /// @notice Apply token updates and run ERC-1155 receiver acceptance checks. + /// @param from Address tokens are moved from. Use `address(0)` for mints. + /// @param to Address tokens are moved to. Use `address(0)` for burns. + /// @param ids Token IDs to update. + /// @param values Amounts for each token ID. + /// @param data Additional calldata passed to receiver hooks. + /// @param batch `true` if a batch operation. + /// @dev Calls `_update` before external receiver callbacks. + /// @dev If `to` is a contract, this calls `onERC1155Received` or `onERC1155BatchReceived`. + /// @dev Overriding is discouraged because post-callback state writes can introduce reentrancy bugs. function _updateWithAcceptanceCheck( address from, address to, uint256[] memory ids, uint256[] memory values, - bytes memory data - ) internal virtual { + bytes memory data, + bool batch + ) + internal + virtual + { _update(from, to, ids, values); if (to != address(0)) { - address operator = _msgSender(); - if (ids.length == 1) { + if (batch) { + ERC1155Utils.checkOnERC1155BatchReceived(msg.sender, from, to, ids, values, data); + } else { uint256 id = ids.unsafeMemoryAccess(0); uint256 value = values.unsafeMemoryAccess(0); - ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data); - } else { - ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data); + ERC1155Utils.checkOnERC1155Received(msg.sender, from, to, id, value, data); } } } - /// @dev Transfers a `value` tokens of token type `id` from `from` to `to`. - /// - /// Emits a {TransferSingle} event. - /// - /// Requirements: - /// - /// - `to` cannot be the zero address. - /// - `from` must have a balance of tokens of type `id` of at least `value` amount. - /// - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the - /// acceptance magic value. + /// @notice Safely transfer `value` tokens of token ID `id` from `from` to `to`. + /// @param from Address to transfer from. + /// @param to Address to transfer to. + /// @param id Token ID to transfer. + /// @param value Amount to transfer. + /// @param data Additional calldata passed to receiver hooks. + /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address. + /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address. + /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value. + /// @dev Emits `TransferSingle`. function _safeTransferFrom( address from, address to, uint256 id, uint256 value, bytes memory data - ) internal { + ) + internal + { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } @@ -254,112 +270,75 @@ abstract contract ERC1155Singleton is revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); - _updateWithAcceptanceCheck(from, to, ids, values, data); + _updateWithAcceptanceCheck(from, to, ids, values, data, false); } - /// @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. - /// - /// Emits a {TransferBatch} event. - /// - /// Requirements: - /// - /// - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the - /// acceptance magic value. - /// - `ids` and `values` must have the same length. + /// @notice Safely transfer multiple token IDs from `from` to `to`. + /// @param from Address to transfer from. + /// @param to Address to transfer to. + /// @param ids Token IDs to transfer. + /// @param values Amounts to transfer for each token ID. + /// @param data Additional calldata passed to receiver hooks. + /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address. + /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address. + /// @dev Reverts with `ERC1155InvalidArrayLength` if `ids.length != values.length`. + /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value. + /// @dev Emits `TransferBatch`. function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data - ) internal { + ) + internal + { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } - _updateWithAcceptanceCheck(from, to, ids, values, data); + _updateWithAcceptanceCheck(from, to, ids, values, data, true); } - /// @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`. - /// - /// Emits a {TransferSingle} event. - /// - /// Requirements: - /// - /// - `to` cannot be the zero address. - /// - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the - /// acceptance magic value. + /// @notice Mint `value` tokens of token ID `id` to `to`. + /// @param to Address receiving the minted token. + /// @param id Token ID to mint. + /// @param value Amount to mint. + /// @param data Additional calldata passed to receiver hooks. + /// @dev Reverts with `ERC1155InvalidReceiver` if `to` is the zero address. + /// @dev If `to` is a contract, it must return the ERC-1155 acceptance magic value. + /// @dev Emits `TransferSingle`. function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); - _updateWithAcceptanceCheck(address(0), to, ids, values, data); + _updateWithAcceptanceCheck(address(0), to, ids, values, data, false); } - /// @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. - /// - /// Emits a {TransferBatch} event. - /// - /// Requirements: - /// - /// - `ids` and `values` must have the same length. - /// - `to` cannot be the zero address. - /// - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the - /// acceptance magic value. - function _mintBatch( - address to, - uint256[] memory ids, - uint256[] memory values, - bytes memory data - ) internal { - if (to == address(0)) { - revert ERC1155InvalidReceiver(address(0)); - } - _updateWithAcceptanceCheck(address(0), to, ids, values, data); - } - - /// @dev Destroys a `value` amount of tokens of type `id` from `from` - /// - /// Emits a {TransferSingle} event. - /// - /// Requirements: - /// - /// - `from` cannot be the zero address. - /// - `from` must have at least `value` amount of tokens of type `id`. + /// @notice Burn `value` tokens of token ID `id` from `from`. + /// @param from Address to burn from. + /// @param id Token ID to burn. + /// @param value Amount to burn. + /// @dev Reverts with `ERC1155InvalidSender` if `from` is the zero address. + /// @dev Reverts with `ERC1155InsufficientBalance` if `from` is not current owner or `value > 1`. + /// @dev Emits `TransferSingle`. function _burn(address from, uint256 id, uint256 value) internal { if (from == address(0)) { revert ERC1155InvalidSender(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); - _updateWithAcceptanceCheck(from, address(0), ids, values, ""); + _updateWithAcceptanceCheck(from, address(0), ids, values, "", false); } - /// @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. - /// - /// Emits a {TransferBatch} event. - /// - /// Requirements: - /// - /// - `from` cannot be the zero address. - /// - `from` must have at least `value` amount of tokens of type `id`. - /// - `ids` and `values` must have the same length. - function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal { - if (from == address(0)) { - revert ERC1155InvalidSender(address(0)); - } - _updateWithAcceptanceCheck(from, address(0), ids, values, ""); - } - - /// @dev Approve `operator` to operate on all of `owner` tokens - /// - /// Emits an {ApprovalForAll} event. - /// - /// Requirements: - /// - /// - `operator` cannot be the zero address. + /// @notice Set or clear approval for `operator` to manage all tokens owned by `owner`. + /// @param owner Token owner granting or revoking approval. + /// @param operator Operator receiving approval. + /// @param approved Approval status to set. + /// @dev Reverts with `ERC1155InvalidOperator` if `operator` is the zero address. + /// @dev Emits `ApprovalForAll`. function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { if (operator == address(0)) { revert ERC1155InvalidOperator(address(0)); @@ -372,13 +351,21 @@ abstract contract ERC1155Singleton is // Private Functions //////////////////////////////////////////////////////////////////////// + /// @dev Ensure operator is approved. + function _checkApproval(address from, address operator) private view { + if (from != operator && !isApprovedForAll(from, operator)) { + revert ERC1155MissingApprovalForAll(operator, from); + } + } + /// @dev Gas-optimized assembly helper that creates two length-1 memory arrays without Solidity's /// default zero-initialization overhead. Used to adapt single-token operations (`_mint`, /// `_burn`, `_safeTransferFrom`) to the array-based `_update` function. - function _asSingletonArrays( - uint256 element1, - uint256 element2 - ) private pure returns (uint256[] memory array1, uint256[] memory array2) { + function _asSingletonArrays(uint256 element1, uint256 element2) + private + pure + returns (uint256[] memory array1, uint256[] memory array2) + { /// @solidity memory-safe-assembly assembly { // Load the free memory pointer diff --git a/contracts/src/erc1155/interfaces/IERC1155Singleton.sol b/contracts/src/erc1155/interfaces/IERC1155Singleton.sol index e64f2d3ab..47a301487 100644 --- a/contracts/src/erc1155/interfaces/IERC1155Singleton.sol +++ b/contracts/src/erc1155/interfaces/IERC1155Singleton.sol @@ -7,5 +7,8 @@ import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; /// (analogous to ERC721's `ownerOf`). /// @dev Interface selector: `0x6352211e` interface IERC1155Singleton is IERC1155 { + /// @notice Returns the owner of a token. + /// @param id The token ID. + /// @return owner The owner of the token. function ownerOf(uint256 id) external view returns (address owner); } diff --git a/contracts/src/hca/HCAContext.sol b/contracts/src/hca/HCAContext.sol deleted file mode 100644 index 8ff53756f..000000000 --- a/contracts/src/hca/HCAContext.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; - -import {HCAEquivalence} from "./HCAEquivalence.sol"; - -/// @dev Drop-in replacement for OpenZeppelin's `Context` that overrides `_msgSender()` with -/// HCA-aware sender resolution. Inherit this instead of `Context` to make all `_msgSender()` -/// calls in the contract (including inherited modifiers and access control) automatically -/// resolve HCA proxy accounts to their owners. -abstract contract HCAContext is Context, HCAEquivalence { - /// @notice Returns either the account owner of an HCA or the original sender - function _msgSender() internal view virtual override returns (address) { - return _msgSenderWithHcaEquivalence(); - } -} diff --git a/contracts/src/hca/HCAContextUpgradeable.sol b/contracts/src/hca/HCAContextUpgradeable.sol deleted file mode 100644 index d23211f73..000000000 --- a/contracts/src/hca/HCAContextUpgradeable.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; - -import {HCAEquivalence} from "./HCAEquivalence.sol"; - -/// @dev Same as `HCAContext` but extends `ContextUpgradeable` for use in UUPS-upgradeable -/// contracts. Used by `PermissionedResolver`. -abstract contract HCAContextUpgradeable is ContextUpgradeable, HCAEquivalence { - /// @notice Returns either the account owner of an HCA or the original sender - function _msgSender() internal view virtual override(ContextUpgradeable) returns (address) { - return _msgSenderWithHcaEquivalence(); - } -} diff --git a/contracts/src/hca/HCAEquivalence.sol b/contracts/src/hca/HCAEquivalence.sol deleted file mode 100644 index 371e9ddc6..000000000 --- a/contracts/src/hca/HCAEquivalence.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import {IHCAFactoryBasic} from "./interfaces/IHCAFactoryBasic.sol"; - -/// @dev Provides sender-identity resolution for Hidden Contract Accounts (HCAs). An HCA is a -/// contract-based account whose actions should be attributed to its registered owner rather -/// than to the contract address itself. -/// -/// Queries the HCA factory to resolve `msg.sender` to the real owner. If the factory is not -/// configured (address zero), or the caller is not a registered HCA (returns address zero), -/// `msg.sender` is returned unchanged. -/// -/// This enables transparent proxy wallet support: contracts using HCA-aware `_msgSender()` -/// automatically attribute actions to the account owner regardless of whether the caller is -/// an EOA or an HCA proxy. -abstract contract HCAEquivalence { - /// @notice The HCA factory contract - IHCAFactoryBasic public immutable HCA_FACTORY; - - constructor(IHCAFactoryBasic hcaFactory) { - HCA_FACTORY = hcaFactory; - } - - /// @dev Returns the HCA owner if `msg.sender` is a registered HCA, otherwise returns `msg.sender`. - function _msgSenderWithHcaEquivalence() internal view returns (address) { - if (address(HCA_FACTORY) == address(0)) return msg.sender; - address accountOwner = HCA_FACTORY.getAccountOwner(msg.sender); - if (accountOwner == address(0)) return msg.sender; - return accountOwner; - } -} diff --git a/contracts/src/hca/interfaces/IHCAFactoryBasic.sol b/contracts/src/hca/interfaces/IHCAFactoryBasic.sol deleted file mode 100644 index d1d31a62f..000000000 --- a/contracts/src/hca/interfaces/IHCAFactoryBasic.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -/// @notice Basic interface for the HCA factory. -/// @dev Interface selector: `0x442b172c` -interface IHCAFactoryBasic { - /// @notice Returns the account owner of the given HCA - /// @param hca The HCA to get the account owner of - /// @return The account owner of the given HCA - function getAccountOwner(address hca) external view returns (address); -} diff --git a/contracts/src/migration/AbstractWrapperReceiver.sol b/contracts/src/migration/AbstractWrapperReceiver.sol index fae78992a..a9ce8de73 100755 --- a/contracts/src/migration/AbstractWrapperReceiver.sol +++ b/contracts/src/migration/AbstractWrapperReceiver.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.13; import {ENS} from "@ens/contracts/registry/ENS.sol"; -import {INameWrapper, CANNOT_UNWRAP} from "@ens/contracts/wrapper/INameWrapper.sol"; +import {INameWrapper} from "@ens/contracts/wrapper/INameWrapper.sol"; import {IERC1155Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; @@ -13,7 +13,7 @@ import {WrappedErrorLib} from "../utils/WrappedErrorLib.sol"; import {LibMigration} from "./libraries/LibMigration.sol"; /// @title AbstractWrapperReceiver -/// @notice Abstract IERC1155Receiver which handles NameWrapper token migration via transfer. +/// @dev Abstract IERC1155Receiver which handles NameWrapper token migration via transfer. /// /// NameWrapper only allows `Error(string)` exceptions during transfer and squelches typed errors. /// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L317-L335 @@ -23,16 +23,19 @@ import {LibMigration} from "./libraries/LibMigration.sol"; /// 1. UnlockedMigrationController accepts unlocked tokens. /// 2. LockedWrapperReceiver accepts locked tokens. /// -/// `_isLocked()` determines lock status. +/// `LibMigration.isLocked()` determines lock status. /// abstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver { //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// /// @notice The ENSv1 `NameWrapper` contract that holds wrapped names as ERC1155 tokens. INameWrapper public immutable NAME_WRAPPER; + /// @notice The ENSv1 `BaseRegistrar` token graveyard. + address public immutable GRAVEYARD; + /// @dev The ENSv1 `ENSRegistry` contract. ENS internal immutable _REGISTRY_V1; @@ -55,9 +58,7 @@ abstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver { /// Reverts wrapped errors for use inside of legacy IERC1155Receiver handler. modifier withData(bytes calldata data, uint256 minimumSize) { if (data.length < minimumSize) { - WrappedErrorLib.wrapAndRevert( - abi.encodeWithSelector(LibMigration.InvalidData.selector) - ); + WrappedErrorLib.wrapAndRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector)); } _; } @@ -66,15 +67,22 @@ abstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver { // Initialization //////////////////////////////////////////////////////////////////////// - constructor(INameWrapper nameWrapper) { + /// @param nameWrapper The ENSv1 `NameWrapper` contract. + /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard. + constructor(INameWrapper nameWrapper, address graveyard) { NAME_WRAPPER = nameWrapper; + GRAVEYARD = graveyard; _REGISTRY_V1 = nameWrapper.ens(); } /// @inheritdoc IERC165 - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165, IERC165) returns (bool) { + function supportsInterface(bytes4 interfaceId) + public + view + virtual + override(ERC165, IERC165) + returns (bool) + { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); @@ -88,7 +96,6 @@ abstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver { /// @notice Migrate one NameWrapper token via `safeTransferFrom()`. /// @dev Only callable by NameWrapper. /// Reverts require `WrappedErrorLib.unwrap()` before processing. - /// /// @param id The NameWrapper token ID (namehash) of the name being migrated. /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters. function onERC1155Received( @@ -97,7 +104,12 @@ abstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver { uint256 id, uint256 /*amount*/, bytes calldata data - ) external onlyWrapper withData(data, LibMigration.MIN_DATA_SIZE) returns (bytes4) { + ) + external + onlyWrapper + withData(data, LibMigration.MIN_DATA_SIZE) + returns (bytes4) + { // if (amount != 1) { ... } => never happens :: caught by ERC1155Fuse // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L293 uint256[] memory ids = new uint256[](1); @@ -115,7 +127,6 @@ abstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver { /// @notice Migrate multiple NameWrapper tokens via `safeBatchTransferFrom()`. /// @dev Only callable by NameWrapper. /// Reverts require `WrappedErrorLib.unwrap()` before processing. - /// /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated. /// @param data ABI-encoded `LibMigration.Data[]` array containing migration parameters for each name. function onERC1155BatchReceived( @@ -142,15 +153,17 @@ abstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver { } } - /// @dev Convert NameWrapper tokens to their equivalent ENSv2 form. - /// Only callable by ourself and invoked by our `IERC1155Receiver` handlers. + /// @notice Convert NameWrapper tokens to their equivalent ENSv2 form. + /// @dev Only callable by ourself and invoked by our `IERC1155Receiver` handlers. /// /// TODO: gas analysis and optimization /// NOTE: converting this to an internal call requires catching many reverts - function finishERC1155Migration( - uint256[] calldata ids, - LibMigration.Data[] calldata mds - ) external { + /// + /// @param ids The NameWrapper token IDs (namehashes) of the names being migrated. + /// @param mds The migration parameters for each name, indexed in parallel with `ids`. + function finishERC1155Migration(uint256[] calldata ids, LibMigration.Data[] calldata mds) + external + { if (msg.sender != address(this)) { revert UnauthorizedCaller(msg.sender); } @@ -167,15 +180,7 @@ abstract contract AbstractWrapperReceiver is ERC165, IERC1155Receiver { /// @dev Migrate received NameWrapper tokens. /// Token owner is this contract. /// Token is not expired. - function _migrateWrapped( - uint256[] calldata ids, - LibMigration.Data[] calldata mds - ) internal virtual; - - /// @dev Returns `true` if the NameWrapper token is locked. - function _isLocked(uint32 fuses) internal pure returns (bool) { - // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient - // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()` - return (fuses & CANNOT_UNWRAP) != 0; - } + function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds) + internal + virtual; } diff --git a/contracts/src/migration/Graveyard.sol b/contracts/src/migration/Graveyard.sol new file mode 100755 index 000000000..d9f353c03 --- /dev/null +++ b/contracts/src/migration/Graveyard.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import { + BaseRegistrarImplementation +} from "@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol"; +import {IBaseRegistrar} from "@ens/contracts/ethregistrar/IBaseRegistrar.sol"; +import {ENS} from "@ens/contracts/registry/ENS.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {INameWrapper} from "@ens/contracts/wrapper/INameWrapper.sol"; +import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; + +import {LibMigration} from "./libraries/LibMigration.sol"; + +/// @notice The ENSv1 ETHRegistrarController for ENSv2 launch which becomes the burn address for migrated tokens. +/// +/// 1. Claim any expired ENSv1 name and assign ownership to this contract. +/// 2. Clear the registry for any owned token. +/// +contract Graveyard is ERC721Holder, ERC1155Holder, DelegatedContractNamer { + //////////////////////////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////////////////////////// + + /// @dev The internal states of registry ownership. + enum State { + ROOT, + ETH, + OWNED, + LOCKED + } + + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The ENSv1 `NameWrapper` contract. + INameWrapper public immutable NAME_WRAPPER; + + /// @dev The ENSv1 `ENSRegistry` contract. + ENS internal immutable _REGISTRY_V1; + + /// @dev The ENSv1 `BaseRegistrar` contract. + IBaseRegistrar internal immutable _BASE_REGISTRAR; + + /// @dev Same as `BaseRegistrarImplementation.GRACE_PERIOD()`. + uint256 internal immutable _GRACE_PERIOD; + + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice Name cannot be cleared. + /// @dev Error selector: `0xacae6b3b` + error NameNotClearable(); + + /// @notice Wrapped names require preimage. + /// @dev Error selector: `0xa3f28cee` + error NameRequiresPreimage(); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @notice Create a graveyard. + /// @param nameWrapper The ENSv1 `NameWrapper` contract. + /// @param contractNamer Delegated contract namer. + constructor(INameWrapper nameWrapper, IContractNamer contractNamer) + DelegatedContractNamer(contractNamer) + { + NAME_WRAPPER = nameWrapper; + _REGISTRY_V1 = nameWrapper.ens(); + _BASE_REGISTRAR = nameWrapper.registrar(); + _GRACE_PERIOD = BaseRegistrarImplementation(address(_BASE_REGISTRAR)).GRACE_PERIOD(); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) + public + view + override(ERC1155Holder, DelegatedContractNamer) + returns (bool) + { + return + interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Clear registry for migrated names. + /// @param names The array of names to clear. + function clear(bytes[] calldata names) external { + for (uint256 i; i < names.length; ++i) { + _clear(names[i], 0); + } + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + /// @dev Recursively clear ancestor namespace. + /// + /// Wrapped labels are 1-255 bytes and always have a preimage. + /// see: V1Fixture.t.sol: `test_nameWrapper_labelTooShort` and `test_nameWrapper_labelTooLong` + /// see: https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/NameWrapper.sol#L865-L876 + /// + /// This function supports a modified DNS-encoding where zero-length labels + /// in the middle of name must be followed with exactly 32 bytes of labelhash. + /// + /// This is safe because zero-length non-terminating labels normally revert. + /// + function _clear(bytes calldata name, uint256 offset) internal returns (bytes32 node, State) { + bytes32 labelHash; + uint256 nextOffset; + // modified DNS-encoding: interpret zero-length labels differently + if (offset + 1 < name.length && uint8(name[offset]) == 0) { + nextOffset = offset + 33; // skip length and ensure next 32 bytes exist + if (nextOffset >= name.length) { + revert NameCoder.DNSDecodingFailed(name); + } + labelHash = bytes32(name[offset + 1:nextOffset]); // cast as literal bytes32 + } else { + (labelHash, nextOffset) = NameCoder.readLabel(name, offset); // use standard logic + if (labelHash == bytes32(0)) { + return (bytes32(0), State.ROOT); + } + } + (bytes32 parentNode, State parentState) = _clear(name, nextOffset); + node = NameCoder.namehash(parentNode, labelHash); + if (parentState == State.ROOT) { + if (node != NameCoder.ETH_NODE) { + revert NameNotClearable(); + } + return (node, State.ETH); + } else if (parentState == State.ETH) { + address owner = _REGISTRY_V1.owner(node); + if (owner == address(this)) { + // resolver is cleared by migration + return (node, State.OWNED); + } + uint32 fuses; + (owner, fuses, ) = NAME_WRAPPER.getData(uint256(node)); + if (LibMigration.isLocked(fuses)) { + if (owner != address(this)) { + revert NameNotClearable(); + } + // resolver is cleared by migration + return (node, State.LOCKED); + } + if (_BASE_REGISTRAR.nameExpires(uint256(labelHash)) == 0) { + revert NameNotClearable(); + } + _BASE_REGISTRAR.register( + uint256(labelHash), + address(this), + type(uint64).max - block.timestamp - _GRACE_PERIOD // max duration? + ); + // lock expired? so clear it + if (_REGISTRY_V1.resolver(node) != address(0)) { + _REGISTRY_V1.setResolver(node, address(0)); + } + return (node, State.OWNED); + } else if (parentState == State.OWNED) { + _REGISTRY_V1.setSubnodeRecord(parentNode, labelHash, address(this), address(0), 0); + return (node, State.OWNED); + } else { + (address owner, uint32 fuses, ) = NAME_WRAPPER.getData(uint256(node)); + if (LibMigration.isLocked(fuses)) { + if (owner != address(this)) { + revert NameNotClearable(); + } + // resolver is cleared by migration + return (node, State.LOCKED); + } else if (LibMigration.isEmancipatedChild(fuses)) { + if (owner != address(0) || _REGISTRY_V1.owner(node) != address(this)) { + revert NameNotClearable(); + } + // resolver is cleared by migration + } else { + if (uint8(name[offset]) == 0) { + revert NameRequiresPreimage(); + } + NAME_WRAPPER.setSubnodeRecord( + parentNode, + string(name[offset + 1:nextOffset]), + address(this), // owner + address(0), // resolver is cleared + 0, // ttl + 0, // fuses + 0 // expiry (uses min) + ); // reverts if not migrated + NAME_WRAPPER.unwrap(parentNode, labelHash, address(this)); + } + return (node, State.OWNED); + } + } +} diff --git a/contracts/src/migration/LockedMigrationController.sol b/contracts/src/migration/LockedMigrationController.sol index 8281845b3..a8a7fb151 100644 --- a/contracts/src/migration/LockedMigrationController.sol +++ b/contracts/src/migration/LockedMigrationController.sol @@ -7,7 +7,11 @@ import {VerifiableFactory} from "@ensdomains/verifiable-factory/VerifiableFactor import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; import {IRegistry} from "../registry/interfaces/IRegistry.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; +import {IAddressSet} from "../utils/interfaces/IAddressSet.sol"; +import {AbstractWrapperReceiver} from "./AbstractWrapperReceiver.sol"; import {LockedWrapperReceiver} from "./LockedWrapperReceiver.sol"; /// @notice Migration controller for handling locked .eth names. @@ -15,9 +19,9 @@ import {LockedWrapperReceiver} from "./LockedWrapperReceiver.sol"; /// Assumes premigration has `RESERVED` existing ENSv1 names. /// Requires `ROLE_REGISTER_RESERVED` on .eth registry to perform migration. /// -contract LockedMigrationController is LockedWrapperReceiver { +contract LockedMigrationController is LockedWrapperReceiver, DelegatedContractNamer { //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// /// @notice The ENSv2 .eth `PermissionedRegistry` where migrated names are registered. @@ -27,16 +31,53 @@ contract LockedMigrationController is LockedWrapperReceiver { // Initialization //////////////////////////////////////////////////////////////////////// + /// @param nameWrapper The ENSv1 `NameWrapper` contract. + /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard. + /// @param ethRegistry The ENSv2 .eth `PermissionedRegistry` where migrated names are registered. + /// @param verifiableFactory The shared factory for verifiable deployments. + /// @param wrapperRegistryImpl The `WrapperRegistry` implementation contract. + /// @param publicResolverSet The list of `PublicResolver` contracts that require replacement. + /// @param publicResolver The replacement `PublicResolver`. + /// @param contractNamer Delegated contract namer. constructor( - IPermissionedRegistry ethRegistry, INameWrapper nameWrapper, + address graveyard, + IPermissionedRegistry ethRegistry, VerifiableFactory verifiableFactory, - address wrapperRegistryImpl - ) LockedWrapperReceiver(nameWrapper, verifiableFactory, wrapperRegistryImpl) { + address wrapperRegistryImpl, + IAddressSet publicResolverSet, + address publicResolver, + IContractNamer contractNamer + ) + LockedWrapperReceiver( + nameWrapper, + graveyard, + verifiableFactory, + wrapperRegistryImpl, + publicResolverSet, + publicResolver + ) + DelegatedContractNamer(contractNamer) + { ETH_REGISTRY = ethRegistry; } - /// @notice The DNS-encoded name for "eth". + /// @inheritdoc DelegatedContractNamer + function supportsInterface(bytes4 interfaceId) + public + view + virtual + override(AbstractWrapperReceiver, DelegatedContractNamer) + returns (bool) + { + return super.supportsInterface(interfaceId); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Returns the DNS-encoded name for "eth". function getWrappedNode() public pure override returns (bytes32) { return NameCoder.ETH_NODE; } @@ -53,7 +94,11 @@ contract LockedMigrationController is LockedWrapperReceiver { address resolver, uint256 roleBitmap, uint64 /*expiry*/ - ) internal override returns (uint256 tokenId) { + ) + internal + override + returns (uint256 tokenId) + { return ETH_REGISTRY.register( label, diff --git a/contracts/src/migration/LockedWrapperReceiver.sol b/contracts/src/migration/LockedWrapperReceiver.sol index a0697f15a..096bce1c0 100755 --- a/contracts/src/migration/LockedWrapperReceiver.sol +++ b/contracts/src/migration/LockedWrapperReceiver.sol @@ -5,31 +5,25 @@ import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import { INameWrapper, CAN_EXTEND_EXPIRY, - CANNOT_BURN_FUSES, - CANNOT_TRANSFER, + CANNOT_APPROVE, + CANNOT_CREATE_SUBDOMAIN, CANNOT_SET_RESOLVER, - CANNOT_SET_TTL, - CANNOT_CREATE_SUBDOMAIN + CANNOT_TRANSFER } from "@ens/contracts/wrapper/INameWrapper.sol"; -import {VerifiableFactory} from "@ensdomains/verifiable-factory/VerifiableFactory.sol"; +import {IVerifiableFactory} from "@ensdomains/verifiable-factory/IVerifiableFactory.sol"; import {InvalidOwner} from "../CommonErrors.sol"; +import {REGISTRATION_ROLE_BITMAP} from "../registrar/ETHRegistrar.sol"; import {IRegistry} from "../registry/interfaces/IRegistry.sol"; import {IWrapperRegistry} from "../registry/interfaces/IWrapperRegistry.sol"; import {RegistryRolesLib} from "../registry/libraries/RegistryRolesLib.sol"; +import {IAddressSet} from "../utils/interfaces/IAddressSet.sol"; import {AbstractWrapperReceiver} from "./AbstractWrapperReceiver.sol"; import {LibMigration} from "./libraries/LibMigration.sol"; -/// @dev Fuses which translate directly to PermissionedRegistry logic. -uint32 constant FUSES_TO_BURN = CANNOT_BURN_FUSES | - CANNOT_TRANSFER | - CANNOT_SET_RESOLVER | - CANNOT_SET_TTL | - CANNOT_CREATE_SUBDOMAIN; - /// @title LockedWrappedReceiver -/// @notice AbstractWrapperReceiver for locked NameWrapper tokens. +/// @dev AbstractWrapperReceiver for locked NameWrapper tokens. /// /// There are (2) LockedWrapperReceiver implementations: /// 1. LockedMigrationController only accepts .eth 2LD tokens. @@ -49,38 +43,57 @@ uint32 constant FUSES_TO_BURN = CANNOT_BURN_FUSES | /// abstract contract LockedWrapperReceiver is AbstractWrapperReceiver { //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// /// @notice The shared factory for verifiable deployments. - VerifiableFactory public immutable VERIFIABLE_FACTORY; + IVerifiableFactory public immutable VERIFIABLE_FACTORY; /// @notice The `WrapperRegistry` implementation contract. address public immutable WRAPPER_REGISTRY_IMPL; + /// @notice The list of `PublicResolver` contracts that require replacement. + IAddressSet public immutable PUBLIC_RESOLVER_SET; + + /// @notice The replacement `PublicResolver`. + address public immutable PUBLIC_RESOLVER; + //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// + /// @param nameWrapper The ENSv1 `NameWrapper` contract. + /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard. + /// @param verifiableFactory The shared factory for verifiable deployments. + /// @param wrapperRegistryImpl The `WrapperRegistry` implementation contract. + /// @param publicResolverSet The list of `PublicResolver` contracts that require replacement. + /// @param publicResolver The replacement `PublicResolver`. constructor( INameWrapper nameWrapper, - VerifiableFactory verifiableFactory, - address wrapperRegistryImpl - ) AbstractWrapperReceiver(nameWrapper) { + address graveyard, + IVerifiableFactory verifiableFactory, + address wrapperRegistryImpl, + IAddressSet publicResolverSet, + address publicResolver + ) + AbstractWrapperReceiver(nameWrapper, graveyard) + { VERIFIABLE_FACTORY = verifiableFactory; WRAPPER_REGISTRY_IMPL = wrapperRegistryImpl; + PUBLIC_RESOLVER_SET = publicResolverSet; + PUBLIC_RESOLVER = publicResolver; } //////////////////////////////////////////////////////////////////////// // Implementation //////////////////////////////////////////////////////////////////////// - /// @notice The DNS-encoded name for this registry. + /// @notice Returns the DNS-encoded name for this registry. function getWrappedName() public view virtual returns (bytes memory) { return NAME_WRAPPER.names(getWrappedNode()); } - /// @notice The NameWrapper node (namehash). + /// @notice Returns the NameWrapper node (namehash). function getWrappedNode() public view virtual returns (bytes32); //////////////////////////////////////////////////////////////////////// @@ -88,10 +101,10 @@ abstract contract LockedWrapperReceiver is AbstractWrapperReceiver { //////////////////////////////////////////////////////////////////////// /// @inheritdoc AbstractWrapperReceiver - function _migrateWrapped( - uint256[] calldata ids, - LibMigration.Data[] calldata mds - ) internal override { + function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds) + internal + override + { IRegistry parentRegistry = _getRegistry(); bytes32 parentNode = getWrappedNode(); for (uint256 i; i < ids.length; ++i) { @@ -104,55 +117,75 @@ abstract contract LockedWrapperReceiver is AbstractWrapperReceiver { if (node != NameCoder.namehash(parentNode, labelHash)) { revert LibMigration.NameDataMismatch(uint256(node)); } + // by construction: 1 <= length(label) <= 255 // same as NameCoder.assertLabelSize() // see: V1Fixture.t.sol: `test_nameWrapper_labelTooShort()` and `test_nameWrapper_labelTooLong()`. + address resolver = md.resolver; (, uint32 fuses, uint64 expiry) = NAME_WRAPPER.getData(uint256(node)); - if (!_isLocked(fuses)) { - revert LibMigration.NameNotLocked(uint256(node)); - } - - if ((fuses & CANNOT_SET_RESOLVER) != 0) { - md.resolver = _REGISTRY_V1.resolver(node); // replace with ENSv1 resolver - } else { - NAME_WRAPPER.setResolver(node, address(0)); // clear ENSv1 resolver - } - - // create subregistry - IRegistry subregistry = IRegistry( - VERIFIABLE_FACTORY.deployProxy( - WRAPPER_REGISTRY_IMPL, - md.salt, - abi.encodeCall( - IWrapperRegistry.initialize, - ( - node, - parentRegistry, - md.label, - md.owner, - _subregistryRoleBitmapFromFuses(fuses) + if (LibMigration.isLocked(fuses)) { + if ( + (fuses & CANNOT_APPROVE) != 0 && + NAME_WRAPPER.getApproved(uint256(node)) != address(0) + ) { + revert LibMigration.FrozenTokenApproval(uint256(node)); + } + + if ((fuses & CANNOT_SET_RESOLVER) == 0) { + NAME_WRAPPER.setResolver(node, address(0)); // clear ENSv1 resolver + } else { + resolver = _REGISTRY_V1.resolver(node); // replace with ENSv1 resolver + if (resolver != address(0) && PUBLIC_RESOLVER_SET.includes(resolver)) { + resolver = PUBLIC_RESOLVER; // replace with new PublicResolver + } + } + + NAME_WRAPPER.safeTransferFrom(address(this), GRAVEYARD, uint256(node), 1, ""); // transfer to graveyard + + // create subregistry + IRegistry subregistry = + IRegistry( + VERIFIABLE_FACTORY.deployProxy( + WRAPPER_REGISTRY_IMPL, + uint256(node), + abi.encodeCall( + IWrapperRegistry.initialize, + ( + node, + parentRegistry, + md.label, + _subregistryRoleBitmapFromFuses(fuses) + ) + ) ) - ) - ) - ); - - // add name to ENSv2 - // PermissionedRegistry._register() => CannotSetPastExpiration :: see expiry check - // PermissionedRegistry._register() => NameAlreadyRegistered :: only have ROLE_REGISTER_RESERVED - // ERC1155._safeTransferFrom() => ERC1155InvalidReceiver :: see owner check - _inject( - md.label, - md.owner, - subregistry, - md.resolver, - _tokenRoleBitmapFromFuses(fuses), - expiry - ); - - // Burn all migration fuses - if (_notFrozen(fuses)) { - NAME_WRAPPER.setFuses(node, uint16(FUSES_TO_BURN)); + ); + + // add name to ENSv2 + // PermissionedRegistry._register() => CannotSetPastExpiry :: see expiry check + // PermissionedRegistry._register() => LabelAlreadyRegistered :: only have ROLE_REGISTER_RESERVED + // ERC1155._safeTransferFrom() => ERC1155InvalidReceiver :: see owner check + _inject( + md.label, + md.owner, + subregistry, + resolver, + _tokenRoleBitmapFromFuses(fuses), + expiry + ); + } else if (LibMigration.isEmancipatedChild(fuses)) { + NAME_WRAPPER.setResolver(node, address(0)); // clear ENSv1 resolver + NAME_WRAPPER.unwrap(parentNode, labelHash, GRAVEYARD); // unwrap and transfer to graveyard + + // add name to ENSv2 (same as UnlockedMigrationController, plus + // renewal rights when the name could extend its own expiry in v1) + uint256 roleBitmap = REGISTRATION_ROLE_BITMAP; + if ((fuses & CAN_EXTEND_EXPIRY) != 0) { + roleBitmap |= RegistryRolesLib.ROLE_RENEW | RegistryRolesLib.ROLE_RENEW_ADMIN; + } + _inject(md.label, md.owner, md.subregistry, resolver, roleBitmap, expiry); + } else { + revert LibMigration.NameNotLocked(uint256(node)); } } } @@ -165,34 +198,30 @@ abstract contract LockedWrapperReceiver is AbstractWrapperReceiver { address resolver, uint256 roleBitmap, uint64 expiry - ) internal virtual returns (uint256 tokenId); + ) + internal + virtual + returns (uint256 tokenId); /// @dev The ENSv2 registry being migrated to. function _getRegistry() internal view virtual returns (IRegistry); - /// @dev Determine if `label` is emancipated but not-yet migrated. - function _isMigratableChild(string memory label) internal view returns (bool) { - bytes32 node = NameCoder.namehash(getWrappedNode(), keccak256(bytes(label))); - (address ownerV1, uint32 fuses, ) = NAME_WRAPPER.getData(uint256(node)); - return ownerV1 != address(this) && _isLocked(fuses); - } - - /// @dev Returns `true` if the NameWrapper token fuses are not frozen. - function _notFrozen(uint32 fuses) internal pure returns (bool) { - return (fuses & CANNOT_BURN_FUSES) == 0; - } - /// @dev Convert fuses to equivalent subregistry root roles. - function _subregistryRoleBitmapFromFuses( - uint32 fuses - ) internal pure returns (uint256 roleBitmap) { + function _subregistryRoleBitmapFromFuses(uint32 fuses) + internal + pure + returns (uint256 roleBitmap) + { if ((fuses & CANNOT_CREATE_SUBDOMAIN) == 0) { roleBitmap |= RegistryRolesLib.ROLE_REGISTRAR; } - if (_notFrozen(fuses)) { + roleBitmap |= + RegistryRolesLib.ROLE_RENEW | + RegistryRolesLib.ROLE_UPGRADE | + RegistryRolesLib.ROLE_CAN_NAME; + if (LibMigration.notFrozen(fuses)) { roleBitmap |= roleBitmap << 128; // give admin } - roleBitmap |= RegistryRolesLib.ROLE_RENEW | RegistryRolesLib.ROLE_RENEW_ADMIN; } /// @dev Convert fuses to equivalent token roles. @@ -203,11 +232,11 @@ abstract contract LockedWrapperReceiver is AbstractWrapperReceiver { if ((fuses & CANNOT_SET_RESOLVER) == 0) { roleBitmap |= RegistryRolesLib.ROLE_SET_RESOLVER; } - if (_notFrozen(fuses)) { + if (LibMigration.notFrozen(fuses)) { roleBitmap |= roleBitmap << 128; // give admin } if ((fuses & CANNOT_TRANSFER) == 0) { - roleBitmap |= RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; + roleBitmap |= RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; // no user } } } diff --git a/contracts/src/migration/MigrationHelper.sol b/contracts/src/migration/MigrationHelper.sol new file mode 100755 index 000000000..c66772054 --- /dev/null +++ b/contracts/src/migration/MigrationHelper.sol @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IBaseRegistrar} from "@ens/contracts/ethregistrar/IBaseRegistrar.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {INameWrapper} from "@ens/contracts/wrapper/INameWrapper.sol"; + +import {IRegistry} from "../registry/interfaces/IRegistry.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {LibRegistry} from "../universalResolver/libraries/LibRegistry.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; + +import {AbstractWrapperReceiver} from "./AbstractWrapperReceiver.sol"; +import {LibMigration} from "./libraries/LibMigration.sol"; + +/// @dev Struct for migrating locked 3LD+ tokens. +struct LockedChildren { + /// @param parentName The parent name. + bytes parentName; + /// @param groups Array of Groups of `LibMigration.Data` for locked tokens with a common owner. + LibMigration.Data[][] groups; +} + +/// @notice Migration helper for mixed (ERC-721 and ERC-1155) batch migration using approval. +contract MigrationHelper is DelegatedContractNamer { + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The ENSv2 root registry. + IRegistry public immutable ROOT_REGISTRY; + + /// @notice The ENSv2 `UnlockedMigrationController` contract. + AbstractWrapperReceiver public immutable UNLOCKED_CONTROLLER; + + /// @notice The ENSv2 `LockedMigrationController` contract. + AbstractWrapperReceiver public immutable LOCKED_CONTROLLER; + + /// @notice The ENSv1 `NameWrapper` contract. + INameWrapper public immutable NAME_WRAPPER; + + /// @dev The ENSv1 `BaseRegistrar` contract. + IBaseRegistrar internal immutable _BASE_REGISTRAR; + + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice A group has multiple owners. + /// @dev Error selector: `0xd04374c0` + error WrappedOwnerMismatch(uint256 tokenId); + + /// @notice A parent has not been migrated yet. + /// @dev Error selector: `0x83d435f1` + error ParentNotMigrated(bytes name); + + /// @notice Caller is not an approved operator by `owner` on `nft`. + /// @dev Error selector: `0x1cf8fdfe` + error NotApprovedOperator(address nft, address owner); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param rootRegistry The root registry. + /// @param unlockedController The ENSv2 `UnlockedMigrationController`. + /// @param lockedController The ENSv2 `LockedMigrationController`. + /// @param contractNamer Delegated contract namer. + constructor( + IRegistry rootRegistry, + AbstractWrapperReceiver unlockedController, + AbstractWrapperReceiver lockedController, + IContractNamer contractNamer + ) + DelegatedContractNamer(contractNamer) + { + ROOT_REGISTRY = rootRegistry; + UNLOCKED_CONTROLLER = unlockedController; + LOCKED_CONTROLLER = lockedController; + + NAME_WRAPPER = unlockedController.NAME_WRAPPER(); + _BASE_REGISTRAR = NAME_WRAPPER.registrar(); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Optimized batch migration helper. + /// @param unwrapped Array of `LibMigration.Data` for unwrapped tokens. + /// @param unlockedGroups Array of Groups of `LibMigration.Data` for unlocked 2LD tokens with a common owner. + /// @param lockedGroups Array of Groups of `LibMigration.Data` for locked 2LD tokens with a common owner. + /// @param lockedChildrenGroups Array of `LockedChildren` for 3LD+ tokens. + function migrate( + LibMigration.Data[] calldata unwrapped, + LibMigration.Data[][] calldata unlockedGroups, + LibMigration.Data[][] calldata lockedGroups, + LockedChildren[] calldata lockedChildrenGroups + ) + external + { + address sender = msg.sender; + for (uint256 i; i < unwrapped.length; ++i) { + LibMigration.Data calldata md = unwrapped[i]; + uint256 tokenId = uint256(keccak256(bytes(md.label))); + address owner = _BASE_REGISTRAR.ownerOf(tokenId); + _requireOperatorApproval(address(_BASE_REGISTRAR), owner, sender); + _BASE_REGISTRAR.safeTransferFrom( + owner, + address(UNLOCKED_CONTROLLER), + tokenId, + abi.encode(md) + ); + } + _transferWrappedGroups( + sender, + NameCoder.ETH_NODE, + address(UNLOCKED_CONTROLLER), + unlockedGroups + ); + _transferWrappedGroups(sender, NameCoder.ETH_NODE, address(LOCKED_CONTROLLER), lockedGroups); + for (uint256 j; j < lockedChildrenGroups.length; ++j) { + LockedChildren calldata lc = lockedChildrenGroups[j]; + IRegistry registry = LibRegistry.findExactRegistry(ROOT_REGISTRY, lc.parentName, 0); + if (address(registry) == address(0)) { + revert ParentNotMigrated(lc.parentName); + } + _transferWrappedGroups( + sender, + NameCoder.namehash(lc.parentName, 0), + address(registry), + lc.groups + ); + } + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + /// @dev Batch transfer groups of NameWrapper tokens. + function _transferWrappedGroups( + address sender, + bytes32 parentNode, + address receiver, + LibMigration.Data[][] calldata groups + ) + internal + { + for (uint256 i; i < groups.length; ++i) { + _transferWrapped(sender, parentNode, receiver, groups[i]); + } + } + + /// @dev Batch transfer NameWrapper tokens. + function _transferWrapped( + address sender, + bytes32 parentNode, + address receiver, + LibMigration.Data[] memory mds + ) + internal + { + uint256 n = mds.length; + if (n == 0) { + return; + } + address from; + uint256[] memory ids = new uint256[](n); + for (uint256 i; i < n; ++i) { + LibMigration.Data memory md = mds[i]; + uint256 id = uint256(NameCoder.namehash(parentNode, keccak256(bytes(md.label)))); + (address owner, , ) = NAME_WRAPPER.getData(id); + _requireOperatorApproval(address(NAME_WRAPPER), owner, sender); + if (i == 0) { + from = owner; + } else if (from != owner) { + revert WrappedOwnerMismatch(id); + } + ids[i] = id; + } + if (n == 1) { + NAME_WRAPPER.safeTransferFrom(from, receiver, ids[0], 1, abi.encode(mds[0])); + } else { + uint256[] memory amounts = new uint256[](n); + for (uint256 i; i < n; ++i) { + amounts[i] = 1; + } + NAME_WRAPPER.safeBatchTransferFrom(from, receiver, ids, amounts, abi.encode(mds)); + } + } + + /// @dev Ensure operator is owner or approved by owner. + function _requireOperatorApproval(address nft, address owner, address operator) internal view { + // transfer() will check if from is approved by this contract + // note: both IBaseRegistrar and INameWrapper implement isApprovedForAll() + if (owner != operator && !INameWrapper(nft).isApprovedForAll(owner, operator)) { + revert NotApprovedOperator(nft, owner); + } + } +} diff --git a/contracts/src/migration/UnlockedMigrationController.sol b/contracts/src/migration/UnlockedMigrationController.sol index e4b7948f9..840ba8f61 100644 --- a/contracts/src/migration/UnlockedMigrationController.sol +++ b/contracts/src/migration/UnlockedMigrationController.sol @@ -5,11 +5,12 @@ import {IBaseRegistrar} from "@ens/contracts/ethregistrar/IBaseRegistrar.sol"; import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import {INameWrapper} from "@ens/contracts/wrapper/INameWrapper.sol"; import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; -import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {InvalidOwner, UnauthorizedCaller} from "../CommonErrors.sol"; import {REGISTRATION_ROLE_BITMAP} from "../registrar/ETHRegistrar.sol"; import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; import {AbstractWrapperReceiver} from "./AbstractWrapperReceiver.sol"; import {LibMigration} from "./libraries/LibMigration.sol"; @@ -22,59 +23,82 @@ import {LibMigration} from "./libraries/LibMigration.sol"; /// /// Supports (2) token sources: /// 1. NameWrapper (ERC-1155) but unlocked only. -/// Reverts with `NameIsWrapped` if `_isLocked()` => use LockedMigrationController instead. +/// Reverts with `NameIsWrapped` if `LibMigration.isLocked()` => use LockedMigrationController instead. /// 2. BaseRegistrar (ERC-721) /// /// Unlike locked migration, no subregistry is deployed and no fuse-to-role translation is /// performed. The name is registered in the .eth registry with the roles and subregistry /// specified in the caller-provided `LibMigration.Data`. /// -contract UnlockedMigrationController is AbstractWrapperReceiver, IERC721Receiver { +contract UnlockedMigrationController is + AbstractWrapperReceiver, + IERC721Receiver, + DelegatedContractNamer +{ //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// /// @notice The ENSv2 .eth `PermissionedRegistry` where migrated names are registered. IPermissionedRegistry public immutable ETH_REGISTRY; /// @dev The ENSv1 `BaseRegistrar` contract. - IBaseRegistrar internal immutable _REGISTRAR_V1; + IBaseRegistrar internal immutable _BASE_REGISTRAR; //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// + /// @param nameWrapper The ENSv1 `NameWrapper` contract. + /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard. + /// @param ethRegistry The ENSv2 .eth `PermissionedRegistry` where migrated names are registered. + /// @param contractNamer Delegated contract namer. constructor( + INameWrapper nameWrapper, + address graveyard, IPermissionedRegistry ethRegistry, - INameWrapper nameWrapper - ) AbstractWrapperReceiver(nameWrapper) { + IContractNamer contractNamer + ) + AbstractWrapperReceiver(nameWrapper, graveyard) + DelegatedContractNamer(contractNamer) + { ETH_REGISTRY = ethRegistry; - _REGISTRAR_V1 = nameWrapper.registrar(); + _BASE_REGISTRAR = nameWrapper.registrar(); } - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + /// @inheritdoc DelegatedContractNamer + function supportsInterface(bytes4 interfaceId) + public + view + virtual + override(AbstractWrapperReceiver, DelegatedContractNamer) + returns (bool) + { return - interfaceId == type(IERC721Receiver).interfaceId || - super.supportsInterface(interfaceId); + interfaceId == type(IERC721Receiver).interfaceId || super.supportsInterface(interfaceId); } //////////////////////////////////////////////////////////////////////// // Implementation //////////////////////////////////////////////////////////////////////// - /// @dev Receives an unwrapped .eth name via ERC721 `safeTransferFrom` from the `BaseRegistrar`. - /// Decodes a single `LibMigration.Data` from `data` and registers the equivalent name in ENSv2. - /// + /// @notice Receives an unwrapped .eth name via ERC721 `safeTransferFrom` from the `BaseRegistrar`. + /// Decodes a single `LibMigration.Data` from `data` and registers the equivalent name in ENSv2. + /// @param {operator} Ignored. + /// @param {from} Ignored. /// @param tokenId The BaseRegistrar token ID (labelhash) of the name being migrated. /// @param data ABI-encoded `LibMigration.Data` struct containing migration parameters. + /// @return The selector of the `onERC721Received` function. function onERC721Received( address /*operator*/, address /*from*/, uint256 tokenId, bytes calldata data - ) external returns (bytes4) { - if (msg.sender != address(_REGISTRAR_V1)) { + ) + external + returns (bytes4) + { + if (msg.sender != address(_BASE_REGISTRAR)) { revert UnauthorizedCaller(msg.sender); } if (data.length < LibMigration.MIN_DATA_SIZE) { @@ -84,12 +108,14 @@ contract UnlockedMigrationController is AbstractWrapperReceiver, IERC721Receiver if (tokenId != uint256(keccak256(bytes(md.label)))) { revert LibMigration.NameDataMismatch(tokenId); } - // clear ENSv1 resolver - _REGISTRAR_V1.reclaim(tokenId, address(this)); - _REGISTRY_V1.setResolver( + _BASE_REGISTRAR.reclaim(tokenId, address(this)); + _REGISTRY_V1.setRecord( NameCoder.namehash(NameCoder.ETH_NODE, bytes32(tokenId)), - address(0) + GRAVEYARD, // transfer ownership to graveyard + address(0), // clear ENSv1 resolver + 0 ); + _BASE_REGISTRAR.safeTransferFrom(address(this), GRAVEYARD, tokenId); // transfer token to graveyard _inject(md); return this.onERC721Received.selector; } @@ -101,25 +127,24 @@ contract UnlockedMigrationController is AbstractWrapperReceiver, IERC721Receiver /// @inheritdoc AbstractWrapperReceiver /// @dev Reverts `NameIsLocked` if any token is locked. /// Reverts `NameDataMismatch` if any token is mislabeled. - /// /// @param ids The NameWrapper token IDs (namehash) of the names to migrate. /// @param mds The migration parameters for each name, indexed in parallel with `ids`. - function _migrateWrapped( - uint256[] calldata ids, - LibMigration.Data[] calldata mds - ) internal override { + function _migrateWrapped(uint256[] calldata ids, LibMigration.Data[] calldata mds) + internal + override + { for (uint256 i; i < ids.length; ++i) { uint256 id = ids[i]; (, uint32 fuses, ) = NAME_WRAPPER.getData(id); - if (_isLocked(fuses)) { + if (LibMigration.isLocked(fuses)) { revert LibMigration.NameIsLocked(id); } bytes32 labelHash = keccak256(bytes(mds[i].label)); if (bytes32(id) != NameCoder.namehash(NameCoder.ETH_NODE, labelHash)) { revert LibMigration.NameDataMismatch(id); } - // clear ENSv1 resolver - NAME_WRAPPER.setResolver(bytes32(id), address(0)); + NAME_WRAPPER.setResolver(bytes32(id), address(0)); // clear ENSv1 resolver + NAME_WRAPPER.unwrapETH2LD(labelHash, GRAVEYARD, GRAVEYARD); // unwrap and transfer to graveyard _inject(mds[i]); } } diff --git a/contracts/src/migration/libraries/LibMigration.sol b/contracts/src/migration/libraries/LibMigration.sol index 4be6193b7..308a7d536 100644 --- a/contracts/src/migration/libraries/LibMigration.sol +++ b/contracts/src/migration/libraries/LibMigration.sol @@ -1,8 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; +import { + CANNOT_BURN_FUSES, + CANNOT_UNWRAP, + IS_DOT_ETH, + PARENT_CANNOT_CONTROL +} from "@ens/contracts/wrapper/INameWrapper.sol"; + import {IRegistry} from "../../registry/interfaces/IRegistry.sol"; +/// @dev Primitives for migration. library LibMigration { //////////////////////////////////////////////////////////////////////// // Types @@ -20,9 +28,6 @@ library LibMigration { /// @dev Resolver address to set for the migrated name. /// Ignored if locked and `CANNOT_SET_RESOLVER`. address resolver; - /// @dev CREATE2 salt for deterministic WrapperRegistry deployment. - /// Ignored by unlocked migration.. - uint256 salt; } //////////////////////////////////////////////////////////////////////// @@ -30,7 +35,7 @@ library LibMigration { //////////////////////////////////////////////////////////////////////// /// @dev Minimum size of `abi.encode(Data({...}))`. - uint256 internal constant MIN_DATA_SIZE = 8 * 32; + uint256 internal constant MIN_DATA_SIZE = 7 * 32; //////////////////////////////////////////////////////////////////////// // Errors @@ -52,7 +57,34 @@ library LibMigration { /// @dev Error selector: `0xedec3569` error NameDataMismatch(uint256 tokenId); + /// @notice NameWrapper token has existing approval and burned `CANNOT_APPROVE`. + /// @dev Error selector: `0xa4f07713` + error FrozenTokenApproval(uint256 tokenId); + /// @notice The encoded data is invalid. /// @dev Error selector: `0x5cb045db` error InvalidData(); + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @dev Returns `true` if the NameWrapper token is locked. + function isLocked(uint32 fuses) internal pure returns (bool) { + // PARENT_CANNOT_CONTROL is required to set CANNOT_UNWRAP, so CANNOT_UNWRAP is sufficient + // see: V1Fixture.t.sol: `test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL()` + return (fuses & CANNOT_UNWRAP) != 0; + } + + /// @dev Returns `true` if the NameWrapper token fuses are not frozen. + function notFrozen(uint32 fuses) internal pure returns (bool) { + return (fuses & CANNOT_BURN_FUSES) == 0; + } + + /// @dev Returns `true` if the NameWrapper token is emancipated and not 2LD .eth. + function isEmancipatedChild(uint32 fuses) internal pure returns (bool) { + // PARENT_CANNOT_CONTROL must be set for the entire ancestory. + // see: V1Fixture.t.sol: `test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent()` + return (fuses & (IS_DOT_ETH | PARENT_CANNOT_CONTROL)) == PARENT_CANNOT_CONTROL; + } } diff --git a/contracts/src/registrar/AbstractETHRegistrar.sol b/contracts/src/registrar/AbstractETHRegistrar.sol new file mode 100755 index 000000000..c03ecc503 --- /dev/null +++ b/contracts/src/registrar/AbstractETHRegistrar.sol @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {LibLabel} from "../utils/LibLabel.sol"; + +import {IETHRenewer} from "./interfaces/IETHRenewer.sol"; +import {IRentPriceOracle} from "./interfaces/IRentPriceOracle.sol"; + +/// @dev Abstract registrar implementation shared between `ETHRegistrar` and `ETHRenewerV1`. +abstract contract AbstractETHRegistrar is Ownable, ERC165, IETHRenewer { + //////////////////////////////////////////////////////////////////////// + // Constants & Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice Minimum renew duration, in seconds. + uint64 public constant MIN_RENEW_DURATION = 1; + + /// @notice ENSv2 .eth `PermissionedRegistry`. + IPermissionedRegistry public immutable ETH_REGISTRY; + + /// @notice Address that receives payments. + address public immutable BENEFICIARY; + + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// + + /// @notice Oracle for registration and renewal costs. + IRentPriceOracle public rentPriceOracle; + + //////////////////////////////////////////////////////////////////////// + // Events + //////////////////////////////////////////////////////////////////////// + + /// @notice `IRentPriceOracle` was replaced. + /// @param oracle The new `IRentPriceOracle` contract. + event RentPriceOracleUpdated(IRentPriceOracle oracle); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param owner_ Contract owner. + /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`. + /// @param beneficiary Address that receives payments. + /// @param oracle Initial oracle for registration and renewal costs. + constructor( + address owner_, + IPermissionedRegistry ethRegistry, + address beneficiary, + IRentPriceOracle oracle + ) + Ownable(owner_) + { + ETH_REGISTRY = ethRegistry; + BENEFICIARY = beneficiary; + + rentPriceOracle = oracle; + emit RentPriceOracleUpdated(oracle); + } + + /// @inheritdoc ERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IETHRenewer).interfaceId || super.supportsInterface(interfaceId); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Change the rent price oracle. + /// @param oracle The new `IRentPriceOracle` instance. + function setRentPriceOracle(IRentPriceOracle oracle) external onlyOwner { + rentPriceOracle = oracle; + emit RentPriceOracleUpdated(oracle); + } + + /// @inheritdoc IETHRenewer + function renew(string calldata label, uint64 duration, IERC20 paymentToken, bytes32 referrer) + external + { + IPermissionedRegistry.State memory state = _requireRenewable(label, duration); // reverts if not + uint64 newExpiry = state.expiry + duration; // reverts if overflow + uint256 amount = rentPriceOracle.getRenewPrice(label, state.expiry, duration, paymentToken); // reverts if invalid + SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, amount); // reverts if payment failed + ETH_REGISTRY.renew(state.tokenId, newExpiry); + _onRenew(label, duration); + emit NameRenewed(state.tokenId, label, duration, newExpiry, paymentToken, referrer, amount); + } + + /// @inheritdoc IETHRenewer + function isRenewable(string calldata label) external view returns (bool) { + return _isRenewable(ETH_REGISTRY.getState(LibLabel.id(label))); + } + + /// @inheritdoc IETHRenewer + function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken) + public + view + returns (uint256) + { + return + rentPriceOracle.getRenewPrice( + label, + _requireRenewable(label, duration).expiry, + duration, + paymentToken + ); + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + /// @dev Callback for when a name is renewed. + function _onRenew(string calldata label, uint64 duration) internal virtual {} + + /// @dev Returns whether the name is renewable by this contract. + function _isRenewable(IPermissionedRegistry.State memory state) + internal + view + virtual + returns (bool); + + /// @dev Ensure name is renewable. + function _requireRenewable(string calldata label, uint64 duration) + internal + view + returns (IPermissionedRegistry.State memory state) + { + state = ETH_REGISTRY.getState(LibLabel.id(label)); + if (!_isRenewable(state)) { + revert NameNotRenewable(label); + } + if (duration < MIN_RENEW_DURATION) { + revert DurationTooShort(duration, MIN_RENEW_DURATION); + } + } +} diff --git a/contracts/src/registrar/BatchRegistrar.sol b/contracts/src/registrar/BatchRegistrar.sol new file mode 100644 index 000000000..e510820d2 --- /dev/null +++ b/contracts/src/registrar/BatchRegistrar.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {IRegistry} from "../registry/interfaces/IRegistry.sol"; +import {LibLabel} from "../utils/LibLabel.sol"; + +/// @title BatchRegistrar +/// @notice Simple batch registration contract for pre-migration of ENS names. +/// Only the owner can invoke batch registration. +contract BatchRegistrar is Ownable { + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The ETH registry to use for batch registration. + IPermissionedRegistry public immutable ETH_REGISTRY; + + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice Thrown when batch registration inputs have different lengths. + /// @dev Error selector: `0xaaad13f7` + error InputLengthMismatch(); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param ethRegistry_ The ETH registry to use for batch registration. + /// @param owner_ The owner of the contract. + constructor(IPermissionedRegistry ethRegistry_, address owner_) Ownable(owner_) { + ETH_REGISTRY = ethRegistry_; + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Batch reserve or renew names for pre-migration + /// @param registry The registry for all names + /// @param resolver The resolver for all names + /// @param labels Array of labels to reserve or renew + /// @param expires Array of expiry timestamps corresponding to each label + function batchRegister( + IRegistry registry, + address resolver, + string[] calldata labels, + uint64[] calldata expires + ) + external + onlyOwner + { + if (labels.length != expires.length) { + revert InputLengthMismatch(); + } + + for (uint256 i = 0; i < labels.length; i++) { + IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(labels[i])); + + if (state.status == IPermissionedRegistry.Status.AVAILABLE) { + ETH_REGISTRY.register(labels[i], address(0), registry, resolver, 0, expires[i]); + } else if ( + state.status == IPermissionedRegistry.Status.RESERVED && expires[i] > state.expiry + ) { + ETH_REGISTRY.renew(state.tokenId, expires[i]); + } + } + } +} diff --git a/contracts/src/registrar/DOSRegistrar.sol b/contracts/src/registrar/DOSRegistrar.sol index f5c6f5c76..1d2e69d11 100644 --- a/contracts/src/registrar/DOSRegistrar.sol +++ b/contracts/src/registrar/DOSRegistrar.sol @@ -1,263 +1,43 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; -import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; - -import {EnhancedAccessControl} from "../access-control/EnhancedAccessControl.sol"; -import {EACBaseRolesLib} from "../access-control/libraries/EACBaseRolesLib.sol"; -import {InvalidOwner} from "../CommonErrors.sol"; -import {HCAEquivalence} from "../hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "../hca/interfaces/IHCAFactoryBasic.sol"; import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; -import {IRegistry} from "../registry/interfaces/IRegistry.sol"; -import {RegistryRolesLib} from "../registry/libraries/RegistryRolesLib.sol"; -import {LibLabel} from "../utils/LibLabel.sol"; -import {IDOSRegistrar} from "./interfaces/IDOSRegistrar.sol"; +import {ETHRegistrar} from "./ETHRegistrar.sol"; import {IRentPriceOracle} from "./interfaces/IRentPriceOracle.sol"; -/// @dev Composite role bitmap granted to name owners at registration — includes set-subregistry, set-resolver, and can-transfer (with admin variants). -uint256 constant REGISTRATION_ROLE_BITMAP = 0 | - RegistryRolesLib.ROLE_SET_SUBREGISTRY | - RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN | - RegistryRolesLib.ROLE_SET_RESOLVER | - RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN | - RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; - -/// @dev Root-level role authorizing oracle updates. -uint256 constant ROLE_SET_ORACLE = 1 << 0; - -/// @notice Commit-reveal registrar for .dos names. Registration requires two transactions: first -/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment -/// age but before the maximum commitment age has elapsed. The commitment hash binds all -/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer) -/// to prevent front-running. -/// -/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed -/// set of roles (set subregistry, set resolver, and transfer — each with their admin -/// counterpart). -/// -/// Payment is collected via ERC20 `safeTransferFrom` to an immutable beneficiary address. -/// Pricing is delegated to a swappable `IRentPriceOracle`. Renewals pay only the base rate; -/// registrations pay base + premium (for recently expired names). -contract DOSRegistrar is IDOSRegistrar, EnhancedAccessControl { - //////////////////////////////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////////////////////////////// - - /// @dev The permissioned registry where .dos names are stored and managed. - IPermissionedRegistry public immutable REGISTRY; - - /// @dev Address that receives all registration and renewal payments. - address public immutable BENEFICIARY; - - /// @dev Minimum seconds a commitment must age before registration can proceed. - uint64 public immutable MIN_COMMITMENT_AGE; - - /// @dev Maximum seconds a commitment remains valid; expired commitments are rejected. - uint64 public immutable MAX_COMMITMENT_AGE; - - /// @dev Shortest allowed registration duration, in seconds. - uint64 public immutable MIN_REGISTER_DURATION; - - //////////////////////////////////////////////////////////////////////// - // Storage - //////////////////////////////////////////////////////////////////////// - - /// @dev Current pricing oracle used for computing registration and renewal costs. - IRentPriceOracle public rentPriceOracle; - - /// @inheritdoc IDOSRegistrar - mapping(bytes32 commitment => uint64 commitTime) public commitmentAt; - - //////////////////////////////////////////////////////////////////////// - // Events - //////////////////////////////////////////////////////////////////////// - - /// @dev Emitted when the rent price oracle is replaced. - /// @param oracle The new `IRentPriceOracle` instance. - event RentPriceOracleChanged(IRentPriceOracle oracle); - - //////////////////////////////////////////////////////////////////////// - // Initialization - //////////////////////////////////////////////////////////////////////// - +/// @title DOS Registrar +/// @notice DOS Chain deployment profile for registering and renewing `.dos` names. +/// @dev The implementation deliberately inherits the audited ENSv2 registrar without +/// overriding registration behavior so future upstream fixes remain easy to adopt. +contract DOSRegistrar is ETHRegistrar { + /// @param owner_ Contract owner. + /// @param dosRegistry ENSv2 `.dos` permissioned registry. + /// @param beneficiary Address that receives registration and renewal payments. + /// @param oracle Initial oracle for registration and renewal prices. + /// @param gracePeriod Post-expiry period where names remain renewable. + /// @param minCommitmentAge Minimum commitment age before registration. + /// @param maxCommitmentAge Maximum commitment age before expiration. + /// @param minRegisterDuration Minimum registration duration. constructor( - IPermissionedRegistry registry, - IHCAFactoryBasic hcaFactory, + address owner_, + IPermissionedRegistry dosRegistry, address beneficiary, + IRentPriceOracle oracle, + uint64 gracePeriod, uint64 minCommitmentAge, uint64 maxCommitmentAge, - uint64 minRegisterDuration, - IRentPriceOracle rentPriceOracle_ - ) HCAEquivalence(hcaFactory) { - if (maxCommitmentAge <= minCommitmentAge) { - revert MaxCommitmentAgeTooLow(); - } - _grantRoles(ROOT_RESOURCE, EACBaseRolesLib.ALL_ROLES, _msgSender(), true); - - REGISTRY = registry; - BENEFICIARY = beneficiary; - MIN_COMMITMENT_AGE = minCommitmentAge; - MAX_COMMITMENT_AGE = maxCommitmentAge; - MIN_REGISTER_DURATION = minRegisterDuration; - - rentPriceOracle = rentPriceOracle_; - emit RentPriceOracleChanged(rentPriceOracle_); - } - - /// @inheritdoc EnhancedAccessControl - function supportsInterface( - bytes4 interfaceId - ) public view override(EnhancedAccessControl) returns (bool) { - return - interfaceId == type(IDOSRegistrar).interfaceId || - interfaceId == type(IRentPriceOracle).interfaceId || - super.supportsInterface(interfaceId); - } - - //////////////////////////////////////////////////////////////////////// - // Implementation - //////////////////////////////////////////////////////////////////////// - - /// @dev Change the rent price oracle. - function setRentPriceOracle(IRentPriceOracle oracle) external onlyRootRoles(ROLE_SET_ORACLE) { - rentPriceOracle = oracle; - emit RentPriceOracleChanged(oracle); - } - - /// @inheritdoc IDOSRegistrar - function commit(bytes32 commitment) external { - if (commitmentAt[commitment] + MAX_COMMITMENT_AGE > block.timestamp) { - revert UnexpiredCommitmentExists(commitment); - } - commitmentAt[commitment] = uint64(block.timestamp); - emit CommitmentMade(commitment); - } - - /// @inheritdoc IDOSRegistrar - function register( - string calldata label, - address owner, - bytes32 secret, - IRegistry subregistry, - address resolver, - uint64 duration, - IERC20 paymentToken, - bytes32 referrer - ) external returns (uint256 tokenId) { - if (duration < MIN_REGISTER_DURATION) { - revert DurationTooShort(duration, MIN_REGISTER_DURATION); - } - if (owner == address(0)) { - revert InvalidOwner(); - } - if (!isAvailable(label)) { - revert NameNotAvailable(label); // otherwise register() reverts EACUnauthorizedAccountRoles - } - _consumeCommitment( - makeCommitment(label, owner, secret, subregistry, resolver, duration, referrer) - ); // reverts if no commitment - (uint256 base, uint256 premium) = rentPrice(label, owner, duration, paymentToken); // reverts if !isValid or !isPaymentToken - SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, base + premium); // reverts if payment failed - tokenId = REGISTRY.register( - label, - owner, - subregistry, - resolver, - REGISTRATION_ROLE_BITMAP, - uint64(block.timestamp) + duration - ); // reverts if not available - emit NameRegistered( - tokenId, - label, - owner, - subregistry, - resolver, - duration, - paymentToken, - referrer, - base, - premium - ); - } - - /// @inheritdoc IDOSRegistrar - function renew( - string calldata label, - uint64 duration, - IERC20 paymentToken, - bytes32 referrer - ) external { - IPermissionedRegistry.State memory state = REGISTRY.getState(LibLabel.id(label)); - if (state.status == IPermissionedRegistry.Status.AVAILABLE) { - revert NameIsAvailable(label); - } - uint64 expiry = state.expiry + duration; - (uint256 base, ) = rentPrice(label, state.latestOwner, duration, paymentToken); // reverts if !isValid or !isPaymentToken or duration is 0 - SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, base); // reverts if payment failed - REGISTRY.renew(state.tokenId, expiry); - emit NameRenewed(state.tokenId, label, duration, expiry, paymentToken, referrer, base); - } - - /// @inheritdoc IRentPriceOracle - function isPaymentToken(IERC20 paymentToken) external view returns (bool) { - return rentPriceOracle.isPaymentToken(paymentToken); - } - - /// @inheritdoc IRentPriceOracle - function isValid(string calldata label) external view returns (bool) { - return rentPriceOracle.isValid(label); - } - - /// @inheritdoc IDOSRegistrar - /// @dev Does not check if normalized or valid. - function isAvailable(string memory label) public view returns (bool) { - return REGISTRY.getStatus(LibLabel.id(label)) == IPermissionedRegistry.Status.AVAILABLE; - } - - /// @inheritdoc IRentPriceOracle - function rentPrice( - string memory label, - address owner, - uint64 duration, - IERC20 paymentToken - ) public view returns (uint256 base, uint256 premium) { - return rentPriceOracle.rentPrice(label, owner, duration, paymentToken); - } - - /// @inheritdoc IDOSRegistrar - function makeCommitment( - string calldata label, - address owner, - bytes32 secret, - IRegistry subregistry, - address resolver, - uint64 duration, - bytes32 referrer - ) public pure override returns (bytes32) { - return - keccak256(abi.encode(label, owner, secret, subregistry, resolver, duration, referrer)); - } - - //////////////////////////////////////////////////////////////////////// - // Internal Functions - //////////////////////////////////////////////////////////////////////// - - /// @dev Validates that the given `commitment` was recorded within the allowed time window - /// (between minimum and maximum commitment age), then deletes it so it cannot be reused. - /// @param commitment The commitment hash to validate and consume. - function _consumeCommitment(bytes32 commitment) internal { - uint64 t = uint64(block.timestamp); - uint64 t0 = commitmentAt[commitment]; - uint64 tMin = t0 + MIN_COMMITMENT_AGE; - if (t < tMin) { - revert CommitmentTooNew(commitment, tMin, t); - } - uint64 tMax = t0 + MAX_COMMITMENT_AGE; - if (t >= tMax) { - revert CommitmentTooOld(commitment, tMax, t); - } - delete commitmentAt[commitment]; - } + uint64 minRegisterDuration + ) + ETHRegistrar( + owner_, + dosRegistry, + beneficiary, + oracle, + gracePeriod, + minCommitmentAge, + maxCommitmentAge, + minRegisterDuration + ) + {} } diff --git a/contracts/src/registrar/ETHRegistrar.sol b/contracts/src/registrar/ETHRegistrar.sol index 4672593b3..9a46380ec 100644 --- a/contracts/src/registrar/ETHRegistrar.sol +++ b/contracts/src/registrar/ETHRegistrar.sol @@ -3,129 +3,113 @@ pragma solidity >=0.8.13; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import {EnhancedAccessControl} from "../access-control/EnhancedAccessControl.sol"; -import {EACBaseRolesLib} from "../access-control/libraries/EACBaseRolesLib.sol"; import {InvalidOwner} from "../CommonErrors.sol"; -import {HCAEquivalence} from "../hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "../hca/interfaces/IHCAFactoryBasic.sol"; import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; import {IRegistry} from "../registry/interfaces/IRegistry.sol"; import {RegistryRolesLib} from "../registry/libraries/RegistryRolesLib.sol"; import {LibLabel} from "../utils/LibLabel.sol"; +import {AbstractETHRegistrar} from "./AbstractETHRegistrar.sol"; import {IETHRegistrar} from "./interfaces/IETHRegistrar.sol"; +import {IETHRenewer} from "./interfaces/IETHRenewer.sol"; import {IRentPriceOracle} from "./interfaces/IRentPriceOracle.sol"; -/// @dev Composite role bitmap granted to name owners at registration — includes set-subregistry, set-resolver, and can-transfer (with admin variants). -uint256 constant REGISTRATION_ROLE_BITMAP = 0 | +/// @dev Roles assigned to owners at registration. Includes set-subregistry, set-resolver, and can-transfer (with admin variants). +uint256 constant REGISTRATION_ROLE_BITMAP = RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN | RegistryRolesLib.ROLE_SET_RESOLVER | RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN | RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; -/// @dev Root-level role authorizing oracle updates. -uint256 constant ROLE_SET_ORACLE = 1 << 0; - /// @notice Commit-reveal registrar for .eth names. Registration requires two transactions: first -/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment -/// age but before the maximum commitment age has elapsed. The commitment hash binds all -/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer) -/// to prevent front-running. +/// `commit(hash)` to record a commitment, then `register(...)` after the minimum commitment +/// age but before the maximum commitment age has elapsed. The commitment hash binds all +/// registration parameters (label, owner, secret, subregistry, resolver, duration, referrer) +/// to prevent front-running. +/// +/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed +/// set of roles (set subregistry, set resolver, and transfer — each with their admin +/// counterpart). /// -/// Delegates actual name storage to an `IPermissionedRegistry`, granting the owner a fixed -/// set of roles (set subregistry, set resolver, and transfer — each with their admin -/// counterpart). +/// Pricing and payment are delegated to a swappable `IRentPriceOracle`. /// -/// Payment is collected via ERC20 `safeTransferFrom` to an immutable beneficiary address. -/// Pricing is delegated to a swappable `IRentPriceOracle`. Renewals pay only the base rate; -/// registrations pay base + premium (for recently expired names). -contract ETHRegistrar is IETHRegistrar, EnhancedAccessControl { +contract ETHRegistrar is AbstractETHRegistrar, IETHRegistrar { //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// - /// @dev The permissioned registry where .eth names are stored and managed. - IPermissionedRegistry public immutable REGISTRY; - - /// @dev Address that receives all registration and renewal payments. - address public immutable BENEFICIARY; + /// @inheritdoc IETHRenewer + uint64 public immutable GRACE_PERIOD; - /// @dev Minimum seconds a commitment must age before registration can proceed. + /// @notice Minimum seconds a commitment must age before registration can proceed. + /// @dev If zero, front-running protection is disabled. uint64 public immutable MIN_COMMITMENT_AGE; - /// @dev Maximum seconds a commitment remains valid; expired commitments are rejected. + /// @notice Maximum seconds a commitment remains valid; expired commitments are rejected. uint64 public immutable MAX_COMMITMENT_AGE; - /// @dev Shortest allowed registration duration, in seconds. + /// @notice Minimum register duration, in seconds. uint64 public immutable MIN_REGISTER_DURATION; //////////////////////////////////////////////////////////////////////// // Storage //////////////////////////////////////////////////////////////////////// - /// @dev Current pricing oracle used for computing registration and renewal costs. - IRentPriceOracle public rentPriceOracle; - /// @inheritdoc IETHRegistrar mapping(bytes32 commitment => uint64 commitTime) public commitmentAt; //////////////////////////////////////////////////////////////////////// - // Events + // Errors //////////////////////////////////////////////////////////////////////// - /// @dev Emitted when the rent price oracle is replaced. - /// @param oracle The new `IRentPriceOracle` instance. - event RentPriceOracleChanged(IRentPriceOracle oracle); + /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`. + /// @dev Error selector: `0x3e5aa838` + error MaxCommitmentAgeTooLow(); //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// + /// @param owner_ Contract owner. + /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`. + /// @param beneficiary Address that receives payments. + /// @param oracle Initial oracle for registration and renewal costs. + /// @param gracePeriod Post-expiry period where still renewable and not available, in seconds. + /// @param minCommitmentAge Minimum seconds a commitment must age before registration can proceed. + /// @param maxCommitmentAge Maximum seconds a commitment remains valid; expired commitments are rejected. + /// @param minRegisterDuration Minimum register duration, in seconds. constructor( - IPermissionedRegistry registry, - IHCAFactoryBasic hcaFactory, + address owner_, + IPermissionedRegistry ethRegistry, address beneficiary, + IRentPriceOracle oracle, + uint64 gracePeriod, uint64 minCommitmentAge, uint64 maxCommitmentAge, - uint64 minRegisterDuration, - IRentPriceOracle rentPriceOracle_ - ) HCAEquivalence(hcaFactory) { + uint64 minRegisterDuration + ) + AbstractETHRegistrar(owner_, ethRegistry, beneficiary, oracle) + { if (maxCommitmentAge <= minCommitmentAge) { revert MaxCommitmentAgeTooLow(); } - _grantRoles(ROOT_RESOURCE, EACBaseRolesLib.ALL_ROLES, _msgSender(), true); - - REGISTRY = registry; - BENEFICIARY = beneficiary; + GRACE_PERIOD = gracePeriod; MIN_COMMITMENT_AGE = minCommitmentAge; MAX_COMMITMENT_AGE = maxCommitmentAge; MIN_REGISTER_DURATION = minRegisterDuration; - - rentPriceOracle = rentPriceOracle_; - emit RentPriceOracleChanged(rentPriceOracle_); } - /// @inheritdoc EnhancedAccessControl - function supportsInterface( - bytes4 interfaceId - ) public view override(EnhancedAccessControl) returns (bool) { + /// @inheritdoc AbstractETHRegistrar + function supportsInterface(bytes4 interfaceId) public view override returns (bool) { return - interfaceId == type(IETHRegistrar).interfaceId || - interfaceId == type(IRentPriceOracle).interfaceId || - super.supportsInterface(interfaceId); + interfaceId == type(IETHRegistrar).interfaceId || super.supportsInterface(interfaceId); } //////////////////////////////////////////////////////////////////////// // Implementation //////////////////////////////////////////////////////////////////////// - /// @dev Change the rent price oracle. - function setRentPriceOracle(IRentPriceOracle oracle) external onlyRootRoles(ROLE_SET_ORACLE) { - rentPriceOracle = oracle; - emit RentPriceOracleChanged(oracle); - } - /// @inheritdoc IETHRegistrar function commit(bytes32 commitment) external { if (commitmentAt[commitment] + MAX_COMMITMENT_AGE > block.timestamp) { @@ -145,29 +129,33 @@ contract ETHRegistrar is IETHRegistrar, EnhancedAccessControl { uint64 duration, IERC20 paymentToken, bytes32 referrer - ) external returns (uint256 tokenId) { - if (duration < MIN_REGISTER_DURATION) { - revert DurationTooShort(duration, MIN_REGISTER_DURATION); - } + ) + external + returns (uint256 tokenId) + { if (owner == address(0)) { revert InvalidOwner(); } - if (!isAvailable(label)) { - revert NameNotAvailable(label); // otherwise register() reverts EACUnauthorizedAccountRoles - } _consumeCommitment( makeCommitment(label, owner, secret, subregistry, resolver, duration, referrer) ); // reverts if no commitment - (uint256 base, uint256 premium) = rentPrice(label, owner, duration, paymentToken); // reverts if !isValid or !isPaymentToken - SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, base + premium); // reverts if payment failed - tokenId = REGISTRY.register( + IPermissionedRegistry.State memory state = _requireAvailable(label, duration); // reverts if not + (uint256 base, uint256 premium) = + rentPriceOracle.getRegisterPrice( + label, + _availablePeriod(state.expiry), + duration, + paymentToken + ); // reverts if invalid + SafeERC20.safeTransferFrom(paymentToken, msg.sender, BENEFICIARY, base + premium); // reverts if payment failed + tokenId = ETH_REGISTRY.register( label, owner, subregistry, resolver, REGISTRATION_ROLE_BITMAP, - uint64(block.timestamp) + duration - ); // reverts if not available + uint64(block.timestamp) + duration // new expiry + ); // should not revert emit NameRegistered( tokenId, label, @@ -183,47 +171,34 @@ contract ETHRegistrar is IETHRegistrar, EnhancedAccessControl { } /// @inheritdoc IETHRegistrar - function renew( - string calldata label, - uint64 duration, - IERC20 paymentToken, - bytes32 referrer - ) external { - IPermissionedRegistry.State memory state = REGISTRY.getState(LibLabel.id(label)); - if (state.status == IPermissionedRegistry.Status.AVAILABLE) { - revert NameIsAvailable(label); - } - uint64 expiry = state.expiry + duration; - (uint256 base, ) = rentPrice(label, state.latestOwner, duration, paymentToken); // reverts if !isValid or !isPaymentToken or duration is 0 - SafeERC20.safeTransferFrom(paymentToken, _msgSender(), BENEFICIARY, base); // reverts if payment failed - REGISTRY.renew(state.tokenId, expiry); - emit NameRenewed(state.tokenId, label, duration, expiry, paymentToken, referrer, base); - } - - /// @inheritdoc IRentPriceOracle - function isPaymentToken(IERC20 paymentToken) external view returns (bool) { - return rentPriceOracle.isPaymentToken(paymentToken); - } - - /// @inheritdoc IRentPriceOracle - function isValid(string calldata label) external view returns (bool) { - return rentPriceOracle.isValid(label); + function isAvailable(string calldata label) external view returns (bool) { + return _isAvailable(ETH_REGISTRY.getState(LibLabel.id(label))); } /// @inheritdoc IETHRegistrar - /// @dev Does not check if normalized or valid. - function isAvailable(string memory label) public view returns (bool) { - return REGISTRY.getStatus(LibLabel.id(label)) == IPermissionedRegistry.Status.AVAILABLE; + function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken) + external + view + returns (uint256 base, uint256 premium) + { + return + rentPriceOracle.getRegisterPrice( + label, + _availablePeriod(_requireAvailable(label, duration).expiry), + duration, + paymentToken + ); } - /// @inheritdoc IRentPriceOracle - function rentPrice( - string memory label, - address owner, - uint64 duration, - IERC20 paymentToken - ) public view returns (uint256 base, uint256 premium) { - return rentPriceOracle.rentPrice(label, owner, duration, paymentToken); + /// @inheritdoc IETHRenewer + function getRemainingGracePeriod(string calldata label) external view returns (uint64) { + IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label)); + return + uint64( + _isRenewableGrace(state) + ? GRACE_PERIOD - (block.timestamp - state.expiry) + : 0 + ); } /// @inheritdoc IETHRegistrar @@ -235,7 +210,12 @@ contract ETHRegistrar is IETHRegistrar, EnhancedAccessControl { address resolver, uint64 duration, bytes32 referrer - ) public pure override returns (bytes32) { + ) + public + pure + override + returns (bytes32) + { return keccak256(abi.encode(label, owner, secret, subregistry, resolver, duration, referrer)); } @@ -260,4 +240,64 @@ contract ETHRegistrar is IETHRegistrar, EnhancedAccessControl { } delete commitmentAt[commitment]; } + + /// @dev Ensure name is registerable. + function _requireAvailable(string calldata label, uint64 duration) + internal + view + returns (IPermissionedRegistry.State memory state) + { + state = ETH_REGISTRY.getState(LibLabel.id(label)); + if (!_isAvailable(state)) { + revert NameNotAvailable(label); + } + if (duration < MIN_REGISTER_DURATION) { + revert DurationTooShort(duration, MIN_REGISTER_DURATION); + } + } + + /// @dev Determine if `AVAILABLE` and not in grace. + function _isAvailable(IPermissionedRegistry.State memory state) internal view returns (bool) { + return _checkGrace(state, false); + } + + /// @dev Determine if `REGISTERED` or in grace was `REGISTERED`. + function _isRenewable(IPermissionedRegistry.State memory state) + internal + view + override + returns (bool) + { + return state.status == IPermissionedRegistry.Status.REGISTERED || _isRenewableGrace(state); + } + + /// @dev Determine if was `REGISTERED` and in grace. + function _isRenewableGrace(IPermissionedRegistry.State memory state) + internal + view + returns (bool) + { + return state.latestOwner != address(0) && _checkGrace(state, true); + } + + /// @dev Check if `AVAILABLE` and conditionally in grace. + function _checkGrace(IPermissionedRegistry.State memory state, bool grace) + internal + view + returns (bool) + { + return + state.status == IPermissionedRegistry.Status.AVAILABLE && + (grace == (block.timestamp - state.expiry) < GRACE_PERIOD); + } + + /// @dev Determine duration name has been available. + function _availablePeriod(uint64 expiry) internal view returns (uint64) { + uint64 t = uint64(block.timestamp); + if (expiry == 0) { + return t; // never registered + } + expiry += GRACE_PERIOD; + return t > expiry ? t - expiry : 0; + } } diff --git a/contracts/src/registrar/ETHRenewerV1.sol b/contracts/src/registrar/ETHRenewerV1.sol new file mode 100755 index 000000000..6995b7500 --- /dev/null +++ b/contracts/src/registrar/ETHRenewerV1.sol @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import { + BaseRegistrarImplementation +} from "@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol"; +import {INameWrapper} from "@ens/contracts/wrapper/INameWrapper.sol"; + +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {LibLabel} from "../utils/LibLabel.sol"; + +import {AbstractETHRegistrar} from "./AbstractETHRegistrar.sol"; +import {IETHRenewer} from "./interfaces/IETHRenewer.sol"; +import {IRentPriceOracle} from "./interfaces/IRentPriceOracle.sol"; + +/// @notice `ETHRegistrarController.renew()` stub interface. +/// @dev Interface selector: `0xacf1a841` +// https://github.com/ensdomains/ens-contracts/blob/staging/deployments/mainnet/WrappedETHRegistrarController.json +/// @dev Interface selector: `0xacf1a841` +interface IWrappedETHRegistrarController { + /// @notice Renew an ENSv1 name. + /// @param label The name to renew. + /// @param duration The expiry extension, in seconds. + function renew(string calldata label, uint256 duration) external payable; +} + + +/// @notice .eth registrar that only renews premigrated ENSv2 reservations +/// and syncs with ENSv1. +/// +/// Pricing and payment are delegated to a swappable `IRentPriceOracle`. +/// +/// Provides a mechanism for syncing `NameWrapper` expiry. +/// +contract ETHRenewerV1 is AbstractETHRegistrar { + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @inheritdoc IETHRenewer + uint64 public immutable GRACE_PERIOD; + + /// @dev ENSv2 `GRACE_PERIOD`. + uint64 internal immutable _GRACE_PERIOD_V2; + + /// @notice The ENSv1 `NameWrapper` contract. + INameWrapper public immutable NAME_WRAPPER; + + /// @notice ENSv1 `BaseRegistrarImplementation` contract. + BaseRegistrarImplementation public immutable BASE_REGISTRAR; + + /// @notice ENSv1 `ETHRegistrarController` that is an active `NameWrapper` controller. + IWrappedETHRegistrarController public immutable WRAPPED_CONTROLLER; + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param owner_ Contract owner. + /// @param ethRegistry ENSv2 .eth `PermissionedRegistry`. + /// @param beneficiary Address that receives payments. + /// @param oracle Initial oracle for registration and renewal costs. + /// @param gracePeriod Post-expiry period where renewable and not available, in seconds. + /// @param bonusPeriod Duration added by premigration, in seconds. + /// @param nameWrapper ENSv1 `NameWrapper` contract. + /// @param wrappedController ENSv1 `ETHRegistrarController` that is a `NameWrapper` controller. + constructor( + address owner_, + IPermissionedRegistry ethRegistry, + address beneficiary, + IRentPriceOracle oracle, + uint64 gracePeriod, + uint64 bonusPeriod, + INameWrapper nameWrapper, + address wrappedController + ) + AbstractETHRegistrar(owner_, ethRegistry, beneficiary, oracle) + { + GRACE_PERIOD = bonusPeriod + gracePeriod; + _GRACE_PERIOD_V2 = gracePeriod; + NAME_WRAPPER = nameWrapper; + BASE_REGISTRAR = BaseRegistrarImplementation(address(nameWrapper.registrar())); + WRAPPED_CONTROLLER = IWrappedETHRegistrarController(wrappedController); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Transfers ownership of the registrar. + /// @dev Same as `RegistrarSecurityController`. + /// @param newOwner The new owner for the registrar. + function transferRegistrarOwnership(address newOwner) external onlyOwner { + BASE_REGISTRAR.transferOwnership(newOwner); + } + + /// @notice Sets the registrar's resolver for the base node. + /// @dev Same as `RegistrarSecurityController`. + /// @param resolver The resolver address to set. + function setRegistrarResolver(address resolver) external onlyOwner { + BASE_REGISTRAR.setResolver(resolver); + } + + /// @notice Sync `NameWrapper` expiry with `BaseRegistrarImplementation` expiry. + /// @param labels The labels to sync. + function syncWrapper(string[] calldata labels) external { + BASE_REGISTRAR.addController(address(NAME_WRAPPER)); + for (uint256 i; i < labels.length; ++i) { + WRAPPED_CONTROLLER.renew(labels[i], 0); + } + BASE_REGISTRAR.removeController(address(NAME_WRAPPER)); + } + + /// @inheritdoc IETHRenewer + function getRemainingGracePeriod(string calldata label) external view returns (uint64) { + IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label)); + uint64 bonusPeriod = GRACE_PERIOD - _GRACE_PERIOD_V2; + if (state.latestOwner == address(0) && state.expiry > bonusPeriod) { + uint64 expiryV1 = state.expiry - bonusPeriod; + uint64 t = uint64(block.timestamp); + if (t >= expiryV1 && t < expiryV1 + GRACE_PERIOD) { + return GRACE_PERIOD - (t - expiryV1); + } + } + return 0; + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + /// @dev Update ENSv1 during renew. + function _onRenew(string calldata label, uint64 duration) internal override { + BASE_REGISTRAR.renew(LibLabel.id(label), duration); + } + + /// @dev Determine if `RESERVED` or in grace was `RESERVED`. + function _isRenewable(IPermissionedRegistry.State memory state) + internal + view + override + returns (bool) + { + return + state.status == IPermissionedRegistry.Status.RESERVED || + (state.status == IPermissionedRegistry.Status.AVAILABLE && + state.latestOwner == address(0) && + (block.timestamp - state.expiry) < _GRACE_PERIOD_V2); + } +} diff --git a/contracts/src/registrar/StandardRentPriceOracle.sol b/contracts/src/registrar/StandardRentPriceOracle.sol index 27d02b755..fb1897f02 100644 --- a/contracts/src/registrar/StandardRentPriceOracle.sol +++ b/contracts/src/registrar/StandardRentPriceOracle.sol @@ -2,47 +2,78 @@ pragma solidity >=0.8.13; import {StringUtils} from "@ens/contracts/utils/StringUtils.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; -import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; -import {LibLabel} from "../utils/LibLabel.sol"; +import {EnhancedAccessControl} from "../access-control/EnhancedAccessControl.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; import {IRentPriceOracle} from "./interfaces/IRentPriceOracle.sol"; import {LibHalving} from "./libraries/LibHalving.sol"; -/// @dev Defines one segment of the piecewise-linear discount function. -/// @param t Incremental time interval for discount, in seconds. -/// @param value Discount percentage, relative to `type(uint128).max`. +/// @dev Nybble 0: authorizes updating tokens. Root only. +uint256 constant ROLE_UPDATE_TOKEN = 1 << 0; + +/// @dev Nybble 32: authorizes setting `ROLE_UPDATE_TOKEN`. +uint256 constant ROLE_UPDATE_TOKEN_ADMIN = ROLE_UPDATE_TOKEN << 128; + +/// @dev Nybble 1: authorizes disabling tokens. Root only. +uint256 constant ROLE_DISABLE_TOKEN = 1 << 4; + +/// @dev Nybble 33: authorizes setting `ROLE_DISABLE_TOKEN`. +uint256 constant ROLE_DISABLE_TOKEN_ADMIN = ROLE_DISABLE_TOKEN << 128; + +/// @dev Nybble 2: authorizes contract naming. Root only. +uint256 constant ROLE_CAN_NAME = 1 << 8; + +/// @dev Nybble 34: authorizes setting `ROLE_CAN_NAME`. +uint256 constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128; + +/// @dev Default root roles assigned at construction. +uint256 constant DEFAULT_ROLE_BITMAP = + ROLE_UPDATE_TOKEN | + ROLE_UPDATE_TOKEN_ADMIN | + ROLE_DISABLE_TOKEN | + ROLE_DISABLE_TOKEN_ADMIN | + ROLE_CAN_NAME | + ROLE_CAN_NAME_ADMIN; + +/// @dev Initialization-time structure for a discount point. +/// @param duration Duration threshold, in seconds. +/// @param numer Discount numerator, relative to `DISCOUNT_DENOMINATOR`. struct DiscountPoint { - uint64 t; - uint128 value; + uint64 duration; + uint128 numer; } -/// @dev Initialization-time structure pairing a payment token with its exchange rate (numerator/denominator). +/// @dev Initialization-time structure for a payment token and exchange rate. +/// @param paymenToken The payment token. +/// @param numer Exchange rate numerator, relative to base units. +/// @param denom Exchange rate denominator, relative to base units. struct PaymentRatio { - IERC20 token; + IERC20 paymentToken; uint128 numer; uint128 denom; } -/// @notice Configurable rent pricing oracle with three components: +/// @notice Rent pricing oracle with (4) components: /// -/// 1. Base rate: per-second cost indexed by label codepoint count. Shorter names cost more. -/// Rates are stored in an array where index `i` corresponds to `i+1` codepoints; labels -/// longer than the array use the last entry. -/// 2. Duration discount: piecewise-linear function defined by discount points. Each point -/// specifies an interval duration and its discount rate. The integral over the registration -/// period determines the effective discount. Rewards longer registrations. -/// 3. Expiry premium: exponential decay from an initial premium with a configurable halving -/// period, reaching zero at the end of the premium period. Only charged to new owners of -/// recently expired names; prior owners and renewals are exempt. +/// 1. Base rates: per-second cost indexed by label codepoint count. Shorter names cost more. +/// Rates are stored in an array where index `i` corresponds to `i+1` codepoints; labels +/// longer than the array use the last entry. +/// 2. Duration discounts: increasing expiry reduce costs. Each dicount point specifies a +/// duration and a numerator. `1 - numerator / DISCOUNT_DENOMINATOR` determines the +/// discount percentage. Rewards longer registrations. +/// 3. Expiry premium: exponential decay from an initial premium with a configurable halving +/// period, reaching zero at the end of the premium period. Only charged to new owners of +/// recently expired names; renewals are exempt. +/// 4. Configurable payment tokens: payment tokens and their exchange rates can be managed +/// with `ROLE_UPDATE_TOKEN`. The exchange rate converts the token to standard units. +/// Since no external oracle is consulted, only stablecoins. +/// Accounts with `ROLE_DISABLE_TOKEN` can only disable payment tokens. /// -/// Payment tokens have configurable exchange rates (numerator/denominator ratios). Final -/// prices are converted via `Math.mulDiv` with ceiling rounding to prevent underpayment. -contract StandardRentPriceOracle is ERC165, Ownable, IRentPriceOracle { +contract StandardRentPriceOracle is EnhancedAccessControl, IRentPriceOracle, IContractNamer { //////////////////////////////////////////////////////////////////////// // Types //////////////////////////////////////////////////////////////////////// @@ -54,96 +85,128 @@ contract StandardRentPriceOracle is ERC165, Ownable, IRentPriceOracle { } //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// - /// @dev The permissioned registry used to look up name state (expiry, latest owner) for premium and discount calculations. - IPermissionedRegistry public immutable REGISTRY; + /// @notice Denominator for discounts. + uint128 public immutable DISCOUNT_DENOMINATOR; - //////////////////////////////////////////////////////////////////////// - // Storage - //////////////////////////////////////////////////////////////////////// + /// @notice Starting value of the exponential decay premium for recently expired names, in base pricing units. + uint256 public immutable PREMIUM_PRICE_INITIAL; + + /// @notice Number of seconds for the premium to halve in value. + uint64 public immutable PREMIUM_HALVING_PERIOD; - /// @dev Starting value of the exponential decay premium for recently expired names, in base pricing units. - uint256 public premiumPriceInitial; + /// @notice Total duration of the premium window; the premium reaches zero at this offset from expiry. + uint64 public immutable PREMIUM_PERIOD; - /// @dev Number of seconds for the premium to halve in value. - uint64 public premiumHalvingPeriod; + /// @notice Precomputed premium halving at end of period. + uint256 public immutable PREMIUM_PRICE_OFFSET; - /// @dev Total duration of the premium window; the premium reaches zero at this offset from expiry. - uint64 public premiumPeriod; + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// /// @dev Per-second base rates indexed by codepoint count; `_baseRatePerCp[i]` prices labels with `i+1` codepoints. - uint256[] private _baseRatePerCp; + uint256[] internal _baseRatePerCp; - /// @dev Ordered segments of the piecewise-linear duration discount function. - DiscountPoint[] private _discountPoints; + /// @dev Ordered discount points, relative to `DISCOUNT_DENOMINATOR`. + DiscountPoint[] internal _discountPoints; /// @dev Exchange rates for each accepted payment token, mapping token address to its numerator/denominator ratio. - mapping(IERC20 tokenAddress => Ratio ratio) private _paymentRatios; + mapping(IERC20 paymentToken => Ratio ratio) internal _paymentRatios; //////////////////////////////////////////////////////////////////////// // Events //////////////////////////////////////////////////////////////////////// - /// @notice Discount points were changed. - event DiscountPointsChanged(DiscountPoint[] points); - - /// @notice Base rates were changed. - event BaseRatesChanged(uint256[] ratePerCp); - - /// @notice Premium pricing was changed. - event PremiumPricingChanged( - uint256 indexed initialPrice, - uint64 indexed halvingPeriod, - uint64 indexed period - ); + /// @notice `paymentToken` has changed. + /// @param paymentToken The payment token. + /// @param numer Exchange rate numerator, relative to base units. + /// @param denom Exchange rate denominator, relative to base units, or 0 if disabled. + event PaymentTokenUpdated(IERC20 indexed paymentToken, uint128 numer, uint128 denom); //////////////////////////////////////////////////////////////////////// // Errors //////////////////////////////////////////////////////////////////////// + /// @notice Invalid base rates. + /// @dev Error selector: `0xde276447` + error InvalidBaseRates(); + /// @notice Invalid payment token exchange rate. /// @dev Error selector: `0x648564d3` error InvalidRatio(); - /// @notice Invalid discount point. - /// @dev Error selector: `0xd1be8bbe` - error InvalidDiscountPoint(); + /// @notice Invalid discount configuration. + /// @dev Error selector: `0x997ea360` + error InvalidDiscount(); //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// + /// @param rootAccount Account granted root roles. + /// @param baseRatePerCp Base rates, in standard units per second. + /// @param discountPoints List of discount points. + /// @param discountDenominator Denominator for discounts. + /// @param premiumPriceInitial Premium initial price, in standard units. + /// @param premiumHalvingPeriod Premium halving period, in seconds. + /// @param premiumPeriod Premium period, in seconds. + /// @param paymentRatios List of payment tokens with exchange rates. constructor( - address owner_, - IPermissionedRegistry registry, + address rootAccount, uint256[] memory baseRatePerCp, DiscountPoint[] memory discountPoints, - uint256 premiumPriceInitial_, - uint64 premiumHalvingPeriod_, - uint64 premiumPeriod_, + uint128 discountDenominator, + uint256 premiumPriceInitial, + uint64 premiumHalvingPeriod, + uint64 premiumPeriod, PaymentRatio[] memory paymentRatios - ) Ownable(owner_) { - REGISTRY = registry; + ) + { + _grantRoles(ROOT_RESOURCE, DEFAULT_ROLE_BITMAP, rootAccount, false); + if (baseRatePerCp.length == 0) { + revert InvalidBaseRates(); + } _baseRatePerCp = baseRatePerCp; - emit BaseRatesChanged(baseRatePerCp); - _setDiscountPoints(discountPoints); + uint256 n = discountPoints.length; + if (n > 0) { + uint64 duration; // must increase + uint128 numer = discountDenominator; // must decrease + for (uint256 i; i < n; ++i) { + DiscountPoint memory p = discountPoints[i]; + if (p.duration <= duration || p.numer >= numer) { + revert InvalidDiscount(); // not strictly monotonic + } + duration = p.duration; + numer = p.numer; + _discountPoints.push(p); + } + if (numer == 0) { + revert InvalidDiscount(); // free + } + DISCOUNT_DENOMINATOR = discountDenominator; + } - premiumPriceInitial = premiumPriceInitial_; - premiumHalvingPeriod = premiumHalvingPeriod_; - premiumPeriod = premiumPeriod_; - emit PremiumPricingChanged(premiumPriceInitial_, premiumHalvingPeriod_, premiumPeriod_); + PREMIUM_PRICE_INITIAL = premiumPriceInitial; + PREMIUM_HALVING_PERIOD = premiumHalvingPeriod; + PREMIUM_PERIOD = premiumPeriod; + PREMIUM_PRICE_OFFSET = LibHalving.halving( + premiumPriceInitial, + premiumHalvingPeriod, + premiumPeriod + ); for (uint256 i; i < paymentRatios.length; ++i) { - PaymentRatio memory x = paymentRatios[i]; - if (x.numer == 0 || x.denom == 0) { + PaymentRatio memory pr = paymentRatios[i]; + if (pr.numer == 0 || pr.denom == 0) { revert InvalidRatio(); } - _paymentRatios[x.token] = Ratio(x.numer, x.denom); - emit PaymentTokenAdded(x.token); + _paymentRatios[pr.paymentToken] = Ratio(pr.numer, pr.denom); + emit PaymentTokenUpdated(pr.paymentToken, pr.numer, pr.denom); } } @@ -151,6 +214,7 @@ contract StandardRentPriceOracle is ERC165, Ownable, IRentPriceOracle { function supportsInterface(bytes4 interfaceId) public view override returns (bool) { return interfaceId == type(IRentPriceOracle).interfaceId || + interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId); } @@ -158,211 +222,205 @@ contract StandardRentPriceOracle is ERC165, Ownable, IRentPriceOracle { // Implementation //////////////////////////////////////////////////////////////////////// - /// @notice Update base rates per codepoint. - /// - /// @dev - `ratePerCp[i]` corresponds to `i+1` codepoints. - /// - Larger lengths are priced by `ratePerCp[-1]`. - /// - Use rate of `0` to disable a specific length. - /// - Use empty array to disable all registrations. - /// - Emits `BaseRatesChanged`. - /// - /// @param ratePerCp The base rates, in base units per second. - function updateBaseRates(uint256[] calldata ratePerCp) external onlyOwner { - _baseRatePerCp = ratePerCp; - emit BaseRatesChanged(ratePerCp); - } - - /// @notice Update the discount function. - /// - /// @dev - Each point is (∆t, intervalDiscount). - /// - Discounts are relative to `type(uint128).max`. - /// - Given an average discount, solve for the corresponding interval: - /// * Assume: 1yr at 0% discount - /// * Solve: 2yr * 5% == 1yr * 0% + 1yr * x => x = 10.00% - // * Point: (1yr, 10%) == (1 years, type(uint128).max / 10) - /// - Final discount is the derived from the weighted average over the intervals. - /// - Use empty array to disable. - /// - Emits `DiscountPointsChanged`. - function updateDiscountPoints(DiscountPoint[] calldata points) external onlyOwner { - _setDiscountPoints(points); - } - - /// @notice Update premium pricing function. - /// - /// @dev - Use `initialPrice = 0` to disable. - /// - Use `premiumPriceAfter(0)` to get exact starting price. - /// - `premiumPriceAfter(halvingPeriod) ~= premiumPriceAfter(0) / 2`. - /// - `premiumPriceAfter(halvingPeriod * x) ~= premiumPriceAfter(0) / 2^x`. - /// - `premiumPriceAfter(period) = 0`. - /// - Emits `PremiumPricingChanged`. - /// - /// @param initialPrice The initial price, in base units. - /// @param halvingPeriod Duration until the price is reduced in half. - /// @param period Number of seconds until the price is reduced to 0. - function updatePremiumPricing( - uint256 initialPrice, - uint64 halvingPeriod, - uint64 period - ) external onlyOwner { - premiumPriceInitial = initialPrice; - premiumHalvingPeriod = halvingPeriod; - premiumPeriod = period; - emit PremiumPricingChanged(initialPrice, halvingPeriod, period); - } - /// @notice Update `paymentToken` support and/or exchange rate. - /// - /// @dev - Use `denom = 0` to remove. - /// - Emits `PaymentTokenAdded` if now supported. - /// - Emits `PaymentTokenRemoved` if no longer supported. - /// - Reverts if invalid exchange rate. - function updatePaymentToken( - IERC20 paymentToken, - uint128 numer, - uint128 denom - ) external onlyOwner { - bool active = isPaymentToken(paymentToken); + /// @param paymentToken The payment token. + /// @param numer The numerator of the exchange rate. + /// @param denom The denominator of the exchange rate, or 0 to disable. + function updatePaymentToken(IERC20 paymentToken, uint128 numer, uint128 denom) + external + onlyRootRoles(ROLE_UPDATE_TOKEN) + { + Ratio memory ratio = _paymentRatios[paymentToken]; if (denom > 0) { if (numer == 0) { revert InvalidRatio(); } - _paymentRatios[paymentToken] = Ratio(numer, denom); - if (!active) { - emit PaymentTokenAdded(paymentToken); + if (ratio.numer != numer || ratio.denom != denom) { + _paymentRatios[paymentToken] = Ratio(numer, denom); + emit PaymentTokenUpdated(paymentToken, numer, denom); } - } else if (active) { + } else if (ratio.denom > 0) { + delete _paymentRatios[paymentToken]; + emit PaymentTokenUpdated(paymentToken, 0, 0); + } + } + + /// @notice Disable `paymentToken` support. + /// @param paymentToken The payment token. + function disablePaymentToken(IERC20 paymentToken) external onlyRootRoles(ROLE_DISABLE_TOKEN) { + if (_paymentRatios[paymentToken].denom > 0) { delete _paymentRatios[paymentToken]; - emit PaymentTokenRemoved(paymentToken); + emit PaymentTokenUpdated(paymentToken, 0, 0); } } - /// @notice Get all base rates, in base units per second. + /// @inheritdoc IContractNamer + function isContractNamer(address namer) external view returns (bool) { + return hasRootRoles(ROLE_CAN_NAME, namer); + } + + /// @notice Get all base rates, in standard units per second. function getBaseRates() external view returns (uint256[] memory) { return _baseRatePerCp; } - /// @notice Get all discount function points. - function getDiscountPoints() external view returns (DiscountPoint[] memory) { + /// @notice Get all discount durations, in seconds. + function getDiscountPoints() external view returns (DiscountPoint[] memory v) { return _discountPoints; } - /// @inheritdoc IRentPriceOracle - /// @notice Does not check if normalized. + /// @notice Check if a `label` is valid. Does not check if normalized. + /// @param label The name to check. + /// @return `true` if the `label` is valid. function isValid(string calldata label) external view returns (bool) { - return baseRate(label) > 0; + return getBasePrice(label, 1) > 0; } - /// @inheritdoc IRentPriceOracle - function isPaymentToken(IERC20 paymentToken) public view returns (bool) { + /// @notice Get numerator/denominator for `paymentToken`. + /// @param paymentToken The payment token. + /// @return numer The numerator of the exchange rate. + /// @return denom The denominator of the exchange rate. + function getPaymentTokenRatio(IERC20 paymentToken) + external + view + returns (uint128 numer, uint128 denom) + { + Ratio storage ratio = _paymentRatios[paymentToken]; + return (ratio.numer, ratio.denom); + } + + /// @notice Check if `paymentToken` is supported for payment. + /// @param paymentToken The payment token. + /// @return `true` if `paymentToken` is supported. + function isPaymentToken(IERC20 paymentToken) external view returns (bool) { return _paymentRatios[paymentToken].denom > 0; } - /// @notice Get base rate to register or renew `label` for 1 second. - /// - /// @param label The name to price. - /// - /// @return The base rate or 0 if not valid, in base units. - function baseRate(string memory label) public view returns (uint256) { - uint256 len = bytes(label).length; - if (len == 0 || len > 255) return 0; // too long or too short - uint256 nbr = _baseRatePerCp.length; - if (nbr == 0) return 0; // no base rates - uint256 ncp = StringUtils.strlen(label); - return _baseRatePerCp[(ncp > nbr ? nbr : ncp) - 1]; + /// @inheritdoc IRentPriceOracle + function getRegisterPrice( + string calldata label, + uint64 available, + uint64 duration, + IERC20 paymentToken + ) + external + view + returns (uint256 base, uint256 premium) + { + base = _requireBasePrice(label, duration); + Ratio memory ratio = _requirePaymentToken(paymentToken); + premium = getPremiumPriceAfter(available); + if (premium > 0) { + base += premium; // total + premium = _toAmount(premium, ratio); + } + base = _toAmount(base, ratio) - premium; // ensure: f(a+b) - f(a) == f(b) + } + + /// @inheritdoc IRentPriceOracle + function getRenewPrice( + string calldata label, + uint64 /*expiry*/, + uint64 duration, + IERC20 paymentToken + ) + external + view + returns (uint256) + { + return _toAmount(_requireBasePrice(label, duration), _requirePaymentToken(paymentToken)); + } + + /// @notice Convert arbitrary standard units to payment token amount. + /// @param value An arbitrary value, in standard units. + /// @param paymentToken The payment token. + /// @return The amount of payment token. + function convertUnits(uint256 value, IERC20 paymentToken) external view returns (uint256) { + return _toAmount(value, _requirePaymentToken(paymentToken)); } - /// @notice Compute integral of discount function for `duration`. - /// - /// @dev Use `integratedDiscount(t) / t` to compute average discount. - /// - /// @param duration The time since now, in seconds. - /// - /// @return Integral of discount function over `[0, duration)`. - function integratedDiscount(uint64 duration) public view returns (uint256) { + /// @notice Apply discount function to an arbitrary value. + /// @param value An arbitrary value. + /// @param duration The duration, in seconds. + /// @return `value` reduced by discount. + function applyDiscount(uint256 value, uint64 duration) public view returns (uint256) { uint256 n = _discountPoints.length; - if (n == 0) return 0; - uint256 acc; - uint256 sum; + uint128 numer; for (uint256 i; i < n; ++i) { - DiscountPoint memory p = _discountPoints[i]; - if (duration <= p.t) { - return acc + duration * uint256(p.value); - } - duration -= p.t; - acc += p.t * uint256(p.value); - sum += p.t; + DiscountPoint storage p = _discountPoints[i]; + if (duration < p.duration) + break; + numer = p.numer; } - return acc + (duration * acc + sum - 1) / sum; + return + numer == 0 + ? value + : Math.mulDiv(value, numer, DISCOUNT_DENOMINATOR); } - /// @notice Get premium price for an expiry relative to now. - function premiumPrice(uint64 expiry) public view returns (uint256) { - uint64 t = uint64(block.timestamp); - return t >= expiry ? premiumPriceAfter(t - expiry) : 0; + /// @notice Get base price to register or renew `label` for `duration` seconds. + /// @param label The name to price. + /// @param duration The duration, in seconds. + /// @return The base price, in standard units, or 0 if not valid. + function getBasePrice(string calldata label, uint64 duration) public view returns (uint256) { + uint256 n = bytes(label).length; + if (n == 0 || n > 255) + return 0; // too long or too short + uint256 i = getLength(label); + if (i > _baseRatePerCp.length) { + i = _baseRatePerCp.length; + } + return applyDiscount(_baseRatePerCp[i - 1] * duration, duration); } /// @notice Get premium price for a duration after expiry. - /// /// @dev Defined over `[0, premiumPeriod)`. - /// /// @param duration The time after expiration, in seconds. - /// - /// @return The premium price, in base units. - function premiumPriceAfter(uint64 duration) public view returns (uint256) { - if (duration >= premiumPeriod) return 0; + /// @return The premium price, in standard units. + function getPremiumPriceAfter(uint64 duration) public view returns (uint256) { return - LibHalving.halving(premiumPriceInitial, premiumHalvingPeriod, duration) - - LibHalving.halving(premiumPriceInitial, premiumHalvingPeriod, premiumPeriod); + duration < PREMIUM_PERIOD + ? LibHalving.halving(PREMIUM_PRICE_INITIAL, PREMIUM_HALVING_PERIOD, duration) - + PREMIUM_PRICE_OFFSET + : 0; } - /// @inheritdoc IRentPriceOracle - function rentPrice( - string memory label, - address owner, - uint64 duration, - IERC20 paymentToken - ) public view returns (uint256 base, uint256 premium) { - Ratio memory ratio = _paymentRatios[paymentToken]; - if (ratio.denom == 0) { - revert PaymentTokenNotSupported(paymentToken); - } - uint256 baseUnits = baseRate(label) * duration; - if (baseUnits == 0) { - revert NotValid(label); - } - IPermissionedRegistry.State memory state = REGISTRY.getState(LibLabel.id(label)); - uint64 t = state.expiry > block.timestamp ? state.expiry - uint64(block.timestamp) : 0; - baseUnits -= Math.mulDiv( - baseUnits, - integratedDiscount(t + duration) - integratedDiscount(t), - uint256(type(uint128).max) * duration - ); - uint256 premiumUnits; - // prior owner pays no premium - // use null owner to exclude premium for estimation - if (owner != address(0) && owner != state.latestOwner) { - premiumUnits = premiumPrice(state.expiry); - } - // reverts on overflow - premium = Math.mulDiv(premiumUnits, ratio.numer, ratio.denom); - base = - Math.mulDiv(baseUnits + premiumUnits, ratio.numer, ratio.denom, Math.Rounding.Ceil) - - premium; // ensure: f(a+b) - f(a) == f(b) + /// @notice Check length of a name. + /// @param label The name to check. + /// @return The number of Unicode codepoints. + function getLength(string calldata label) public pure returns (uint256) { + return StringUtils.strlen(label); } //////////////////////////////////////////////////////////////////////// // Internal Functions //////////////////////////////////////////////////////////////////////// - /// @dev Replace the discount function points. - function _setDiscountPoints(DiscountPoint[] memory points) internal { - delete _discountPoints; - for (uint256 i; i < points.length; ++i) { - if (points[i].t == 0) { - revert InvalidDiscountPoint(); - } - _discountPoints.push(points[i]); + /// @dev Compute `rate * duration` and apply discount. + function _requireBasePrice(string calldata label, uint64 duration) + internal + view + returns (uint256 rate) + { + rate = getBasePrice(label, duration); + if (rate == 0) { + revert NotValid(label); } - emit DiscountPointsChanged(points); + } + + /// @dev Ensure `paymentToken` is supported. + function _requirePaymentToken(IERC20 paymentToken) internal view returns (Ratio memory ratio) { + ratio = _paymentRatios[paymentToken]; + if (ratio.denom == 0) { + revert PaymentTokenNotSupported(paymentToken); + } + } + + /// @dev Convert standard units to token amount. + function _toAmount(uint256 value, Ratio memory ratio) internal pure returns (uint256) { + return + ratio.numer == ratio.denom + ? value + : Math.mulDiv(value, ratio.numer, ratio.denom, Math.Rounding.Ceil); } } diff --git a/contracts/src/registrar/interfaces/IDOSRegistrar.sol b/contracts/src/registrar/interfaces/IDOSRegistrar.sol deleted file mode 100644 index 9ea29dfa5..000000000 --- a/contracts/src/registrar/interfaces/IDOSRegistrar.sol +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import {IRegistry} from "../../registry/interfaces/IRegistry.sol"; - -import {IRentPriceOracle} from "./IRentPriceOracle.sol"; - -/// @notice Interface for the ".dos" registrar which manages the ".dos" registry. -/// @dev Interface selector: `0x29071951` -interface IDOSRegistrar is IRentPriceOracle { - //////////////////////////////////////////////////////////////////////// - // Events - //////////////////////////////////////////////////////////////////////// - - /// @notice `commitment` was recorded onchain at `block.timestamp`. - /// - /// @param commitment The commitment hash from `makeCommitment()`. - event CommitmentMade(bytes32 commitment); - - /// @notice `{label}.dos` was registered for `duration`. - /// - /// @param tokenId The registry token id. - /// @param label The name of the registration. - /// @param owner The owner address. - /// @param subregistry The initial registry address. - /// @param resolver The initial resolver address. - /// @param duration The registration duration, in seconds. - /// @param paymentToken The ERC-20 used for payment. - /// @param referrer The referrer hash. - /// @param base The base price, relative to `paymentToken`. - /// @param premium The premium price, relative to `paymentToken`. - event NameRegistered( - uint256 indexed tokenId, - string label, - address owner, - IRegistry subregistry, - address resolver, - uint64 duration, - IERC20 paymentToken, - bytes32 referrer, - uint256 base, - uint256 premium - ); - - /// @notice `{label}.dos` was extended by `duration`. - /// - /// @param tokenId The registry token id. - /// @param label The name of the renewal. - /// @param duration The duration extension, in seconds. - /// @param newExpiry The new expiry, in seconds. - /// @param paymentToken The ERC-20 used for payment. - /// @param referrer The referrer hash. - /// @param base The base price, relative to `paymentToken`. - event NameRenewed( - uint256 indexed tokenId, - string label, - uint64 duration, - uint64 newExpiry, - IERC20 paymentToken, - bytes32 referrer, - uint256 base - ); - - //////////////////////////////////////////////////////////////////////// - // Errors - //////////////////////////////////////////////////////////////////////// - - /// @notice `label` is AVAILABLE. - /// @dev Error selector: `0xf7681f14` - error NameIsAvailable(string label); - - /// @notice `label` is not AVAILABLE. - /// @dev Error selector: `0x477707e8` - error NameNotAvailable(string label); - - /// @notice `duration` less than `minDuration`. - /// @dev Error selector: `0xa096b844` - error DurationTooShort(uint64 duration, uint64 minDuration); - - /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`. - /// @dev Error selector: `0x3e5aa838` - error MaxCommitmentAgeTooLow(); - - /// @notice `commitment` is still usable for registration. - /// @dev Error selector: `0x0a059d71` - error UnexpiredCommitmentExists(bytes32 commitment); - - /// @notice `commitment` cannot be consumed yet. - /// @dev Error selector: `0x6be614e3` - error CommitmentTooNew(bytes32 commitment, uint64 validFrom, uint64 blockTimestamp); - - /// @notice `commitment` has expired. - /// @dev Error selector: `0x0cb9df3f` - error CommitmentTooOld(bytes32 commitment, uint64 validTo, uint64 blockTimestamp); - - //////////////////////////////////////////////////////////////////////// - // Functions - //////////////////////////////////////////////////////////////////////// - - /// @notice Registration step #1: record intent to register without revealing any information. - /// - /// @dev Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`. - /// - /// @param commitment The commitment hash. - function commit(bytes32 commitment) external; - - /// @notice Registration step #2: reveal committed registration parameters, then register `{label}.dos`. - /// - /// @dev Emits `NameRegistered` or reverts with a variety of errors. - /// - /// @param label The name from commitment. - /// @param owner The owner from commitment. - /// @param secret The secret from commitment. - /// @param subregistry The registry from commitment. - /// @param resolver The resolver from commitment. - /// @param duration The registration from commitment. - /// @param paymentToken The ERC-20 to use for payment. - /// @param referrer The referrer hash. - /// @return tokenId The registered token ID. - function register( - string memory label, - address owner, - bytes32 secret, - IRegistry subregistry, - address resolver, - uint64 duration, - IERC20 paymentToken, - bytes32 referrer - ) external returns (uint256 tokenId); - - /// @notice Renew an existing registration. - /// - /// @dev Emits `NameRenewed` or reverts with a variety of errors. - /// - /// @param label The name to renew. - /// @param duration The registration extension, in seconds. - /// @param paymentToken The ERC-20 to use for payment. - /// @param referrer The referrer hash. - function renew( - string memory label, - uint64 duration, - IERC20 paymentToken, - bytes32 referrer - ) external; - - /// @notice Check if `label` is available for registration. - /// - /// @param label The name to check. - /// - /// @return `true` if the `label` is available. - function isAvailable(string memory label) external view returns (bool); - - /// @notice Get timestamp of `commitment`. - /// - /// @param commitment The commitment hash. - /// - /// @return The commitment time, in seconds. - function commitmentAt(bytes32 commitment) external view returns (uint64); - - /// @notice Compute hash of registration parameters. - /// - /// @param label The name to register. - /// @param owner The owner address. - /// @param secret The secret for the registration. - /// @param subregistry The initial registry address. - /// @param resolver The initial resolver address. - /// @param duration The registration duration, in seconds. - /// @param referrer The referrer hash. - /// - /// @return The commitment hash. - function makeCommitment( - string memory label, - address owner, - bytes32 secret, - IRegistry subregistry, - address resolver, - uint64 duration, - bytes32 referrer - ) external pure returns (bytes32); -} diff --git a/contracts/src/registrar/interfaces/IETHRegistrar.sol b/contracts/src/registrar/interfaces/IETHRegistrar.sol old mode 100644 new mode 100755 index 69e5aca4f..6c69a19c2 --- a/contracts/src/registrar/interfaces/IETHRegistrar.sol +++ b/contracts/src/registrar/interfaces/IETHRegistrar.sol @@ -5,32 +5,30 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IRegistry} from "../../registry/interfaces/IRegistry.sol"; -import {IRentPriceOracle} from "./IRentPriceOracle.sol"; +import {IETHRenewer} from "./IETHRenewer.sol"; -/// @notice Interface for the ".eth" registrar which manages the ".eth" registry. -/// @dev Interface selector: `0x29071951` -interface IETHRegistrar is IRentPriceOracle { +/// @notice Interface for registering ".eth" names. +/// @dev Interface selector: `0xc1401b80` +interface IETHRegistrar is IETHRenewer { //////////////////////////////////////////////////////////////////////// // Events //////////////////////////////////////////////////////////////////////// /// @notice `commitment` was recorded onchain at `block.timestamp`. - /// /// @param commitment The commitment hash from `makeCommitment()`. event CommitmentMade(bytes32 commitment); - /// @notice `{label}.eth` was registered for `duration`. - /// + /// @notice A name was registered. /// @param tokenId The registry token id. /// @param label The name of the registration. /// @param owner The owner address. /// @param subregistry The initial registry address. /// @param resolver The initial resolver address. /// @param duration The registration duration, in seconds. - /// @param paymentToken The ERC-20 used for payment. + /// @param paymentToken The payment token. /// @param referrer The referrer hash. - /// @param base The base price, relative to `paymentToken`. - /// @param premium The premium price, relative to `paymentToken`. + /// @param base The amount of `paymentToken` for the registration. + /// @param premium The amount of `paymentToken` due to premium. event NameRegistered( uint256 indexed tokenId, string label, @@ -39,50 +37,15 @@ interface IETHRegistrar is IRentPriceOracle { address resolver, uint64 duration, IERC20 paymentToken, - bytes32 referrer, + bytes32 indexed referrer, uint256 base, uint256 premium ); - /// @notice `{label}.eth` was extended by `duration`. - /// - /// @param tokenId The registry token id. - /// @param label The name of the renewal. - /// @param duration The duration extension, in seconds. - /// @param newExpiry The new expiry, in seconds. - /// @param paymentToken The ERC-20 used for payment. - /// @param referrer The referrer hash. - /// @param base The base price, relative to `paymentToken`. - event NameRenewed( - uint256 indexed tokenId, - string label, - uint64 duration, - uint64 newExpiry, - IERC20 paymentToken, - bytes32 referrer, - uint256 base - ); - //////////////////////////////////////////////////////////////////////// // Errors //////////////////////////////////////////////////////////////////////// - /// @notice `label` is AVAILABLE. - /// @dev Error selector: `0xf7681f14` - error NameIsAvailable(string label); - - /// @notice `label` is not AVAILABLE. - /// @dev Error selector: `0x477707e8` - error NameNotAvailable(string label); - - /// @notice `duration` less than `minDuration`. - /// @dev Error selector: `0xa096b844` - error DurationTooShort(uint64 duration, uint64 minDuration); - - /// @notice `maxCommitmentAge` was not greater than `minCommitmentAge`. - /// @dev Error selector: `0x3e5aa838` - error MaxCommitmentAgeTooLow(); - /// @notice `commitment` is still usable for registration. /// @dev Error selector: `0x0a059d71` error UnexpiredCommitmentExists(bytes32 commitment); @@ -95,30 +58,29 @@ interface IETHRegistrar is IRentPriceOracle { /// @dev Error selector: `0x0cb9df3f` error CommitmentTooOld(bytes32 commitment, uint64 validTo, uint64 blockTimestamp); + /// @notice `label` cannot be registered. + /// @dev Error selector: `0x477707e8` + error NameNotAvailable(string label); + //////////////////////////////////////////////////////////////////////// // Functions //////////////////////////////////////////////////////////////////////// /// @notice Registration step #1: record intent to register without revealing any information. - /// /// @dev Emits `CommitmentMade` or reverts with `UnexpiredCommitmentExists`. - /// /// @param commitment The commitment hash. function commit(bytes32 commitment) external; - /// @notice Registration step #2: reveal committed registration parameters, then register `{label}.eth`. - /// - /// @dev Emits `NameRegistered` or reverts with a variety of errors. - /// + /// @notice Register a name. /// @param label The name from commitment. /// @param owner The owner from commitment. /// @param secret The secret from commitment. /// @param subregistry The registry from commitment. /// @param resolver The resolver from commitment. /// @param duration The registration from commitment. - /// @param paymentToken The ERC-20 to use for payment. + /// @param paymentToken The payment token. /// @param referrer The referrer hash. - /// @return tokenId The registered token ID. + /// @return The registered token ID. function register( string memory label, address owner, @@ -128,39 +90,32 @@ interface IETHRegistrar is IRentPriceOracle { uint64 duration, IERC20 paymentToken, bytes32 referrer - ) external returns (uint256 tokenId); - - /// @notice Renew an existing registration. - /// - /// @dev Emits `NameRenewed` or reverts with a variety of errors. - /// - /// @param label The name to renew. - /// @param duration The registration extension, in seconds. - /// @param paymentToken The ERC-20 to use for payment. - /// @param referrer The referrer hash. - function renew( - string memory label, - uint64 duration, - IERC20 paymentToken, - bytes32 referrer - ) external; + ) + external + returns (uint256); - /// @notice Check if `label` is available for registration. - /// - /// @param label The name to check. - /// - /// @return `true` if the `label` is available. - function isAvailable(string memory label) external view returns (bool); - - /// @notice Get timestamp of `commitment`. - /// + /// @notice Get timestamp of a prior commitment. /// @param commitment The commitment hash. - /// - /// @return The commitment time, in seconds. + /// @return The commitment time, in seconds, or 0 if unknown. function commitmentAt(bytes32 commitment) external view returns (uint64); + /// @notice Determine register price for a name. + /// @param label The name to register. + /// @param duration The registration duration, in seconds. + /// @param paymentToken The payment token. + /// @return base The amount of `paymentToken` for registration. + /// @return premium The amount of `paymentToken` due to premium. + function getRegisterPrice(string calldata label, uint64 duration, IERC20 paymentToken) + external + view + returns (uint256 base, uint256 premium); + + /// @notice Check if name is available. + /// @param label The name to check. + /// @return `true` if registerable. + function isAvailable(string memory label) external view returns (bool); + /// @notice Compute hash of registration parameters. - /// /// @param label The name to register. /// @param owner The owner address. /// @param secret The secret for the registration. @@ -168,15 +123,17 @@ interface IETHRegistrar is IRentPriceOracle { /// @param resolver The initial resolver address. /// @param duration The registration duration, in seconds. /// @param referrer The referrer hash. - /// /// @return The commitment hash. function makeCommitment( - string memory label, + string calldata label, address owner, bytes32 secret, IRegistry subregistry, address resolver, uint64 duration, bytes32 referrer - ) external pure returns (bytes32); + ) + external + pure + returns (bytes32); } diff --git a/contracts/src/registrar/interfaces/IETHRenewer.sol b/contracts/src/registrar/interfaces/IETHRenewer.sol new file mode 100755 index 000000000..c84a17ccf --- /dev/null +++ b/contracts/src/registrar/interfaces/IETHRenewer.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/// @notice Interface for renewing ".eth" names. +/// @dev Interface selector: `0x06aaeb32` +interface IETHRenewer { + //////////////////////////////////////////////////////////////////////// + // Events + //////////////////////////////////////////////////////////////////////// + + /// @notice A name was extended by `duration`. + /// @param tokenId The registry token id. + /// @param label The name of the renewal. + /// @param duration The duration extension, in seconds. + /// @param newExpiry The new expiry, in seconds. + /// @param paymentToken The payment token. + /// @param referrer The referrer hash. + /// @param amount The amount of `paymentToken`. + event NameRenewed( + uint256 indexed tokenId, + string label, + uint64 duration, + uint64 newExpiry, + IERC20 paymentToken, + bytes32 indexed referrer, + uint256 amount + ); + + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice `duration` less than `minDuration`. + /// @dev Error selector: `0xa096b844` + error DurationTooShort(uint64 duration, uint64 minDuration); + + /// @notice `label` cannot be renewed. + /// @dev Error selector: `0x1caefaa0` + error NameNotRenewable(string label); + + //////////////////////////////////////////////////////////////////////// + // Functions + //////////////////////////////////////////////////////////////////////// + + /// @notice Renew a name. + /// @param label The name to renew. + /// @param duration The duration extension, in seconds. + /// @param paymentToken The payment token. + /// @param referrer The referrer hash. + function renew(string memory label, uint64 duration, IERC20 paymentToken, bytes32 referrer) + external; + + /// @notice Determine renew price for a name. + /// @param label The name to renew. + /// @param duration The duration extension, in seconds. + /// @param paymentToken The payment token. + /// @return The amount of `paymentToken`. + function getRenewPrice(string calldata label, uint64 duration, IERC20 paymentToken) + external + view + returns (uint256); + + /// @notice Check if name is renewable. + /// @param label The name to check. + /// @return `true` if renewable. + function isRenewable(string calldata label) external view returns (bool); + + /// @notice Determine remaining grace period. + /// @dev Defined over `[expiry, expiry + GRACE_PERIOD)`. + /// @param label The name to check. + /// @return The remaining grace period, in seconds. + function getRemainingGracePeriod(string calldata label) external view returns (uint64); + + /// @notice Post-expiry period where still renewable and not available, in seconds. + function GRACE_PERIOD() external view returns (uint64); +} diff --git a/contracts/src/registrar/interfaces/IRentPriceOracle.sol b/contracts/src/registrar/interfaces/IRentPriceOracle.sol index 5706b8da4..80be985ce 100644 --- a/contracts/src/registrar/interfaces/IRentPriceOracle.sol +++ b/contracts/src/registrar/interfaces/IRentPriceOracle.sol @@ -4,18 +4,8 @@ pragma solidity >=0.8.13; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @notice Interface for pricing registration and renewals. -/// @dev Interface selector: `0x53b53cee`. +/// @dev Interface selector: `0xdb06fc00` interface IRentPriceOracle { - //////////////////////////////////////////////////////////////////////// - // Events - //////////////////////////////////////////////////////////////////////// - - /// @notice `paymentToken` is now supported. - event PaymentTokenAdded(IERC20 indexed paymentToken); - - /// @notice `paymentToken` is no longer supported. - event PaymentTokenRemoved(IERC20 indexed paymentToken); - //////////////////////////////////////////////////////////////////////// // Errors //////////////////////////////////////////////////////////////////////// @@ -32,35 +22,36 @@ interface IRentPriceOracle { // Functions //////////////////////////////////////////////////////////////////////// - /// @notice Check if `paymentToken` is supported for payment. - /// - /// @param paymentToken The ERC-20 to check. - /// - /// @return `true` if `paymentToken` is supported. - function isPaymentToken(IERC20 paymentToken) external view returns (bool); - - /// @notice Check if a `label` is valid. - /// - /// @param label The name. - /// - /// @return `true` if the `label` is valid. - function isValid(string memory label) external view returns (bool); - - /// @notice Get rent price for `label`. - /// - /// @dev Reverts `PaymentTokenNotSupported` or `NotValid`. - /// - /// @param label The name. - /// @param owner The new owner address. - /// @param duration The duration to price, in seconds. - /// @param paymentToken The ERC-20 to use. - /// - /// @return base The base price, relative to `paymentToken`. - /// @return premium The premium price, relative to `paymentToken`. - function rentPrice( - string memory label, - address owner, + /// @notice Determine registration price for `label`. + /// @param label The name to price. + /// @param available The duration the name has been available, in seconds. + /// @param duration The duration to register for, in seconds. + /// @param paymentToken The payment token. + /// @return base The amount of `paymentToken` for the registration. + /// @return premium The amount of `paymentToken` due to premium. + function getRegisterPrice( + string calldata label, + uint64 available, + uint64 duration, + IERC20 paymentToken + ) + external + view + returns (uint256 base, uint256 premium); + + /// @notice Determine renewal price for `label`. + /// @param label The name to price. + /// @param expiry The current expiry, in seconds. + /// @param duration The extension to price, in seconds. + /// @param paymentToken The payment token. + /// @return The amount of `paymentToken`. + function getRenewPrice( + string calldata label, + uint64 expiry, uint64 duration, IERC20 paymentToken - ) external view returns (uint256 base, uint256 premium); + ) + external + view + returns (uint256); } diff --git a/contracts/src/registrar/libraries/LibHalving.sol b/contracts/src/registrar/libraries/LibHalving.sol index 97f44f060..2d3a3f101 100755 --- a/contracts/src/registrar/libraries/LibHalving.sol +++ b/contracts/src/registrar/libraries/LibHalving.sol @@ -13,6 +13,8 @@ library LibHalving { /// @dev Fixed-point scale factor (10^18). uint256 private constant PRECISION = 1e18; + // solgrid-disable docs/natspec + /// @dev Precomputed values of `0.5^(2^k / 65536) * 10^18` for the corresponding power-of-two /// bit position. Together they compose any fractional power of 0.5 in 16-bit resolution /// via binary decomposition. @@ -33,6 +35,8 @@ library LibHalving { uint256 private constant BIT15 = 840896415253714560; uint256 private constant BIT16 = 707106781186547584; + // solgrid-enable docs/natspec + //////////////////////////////////////////////////////////////////////// // Library Functions //////////////////////////////////////////////////////////////////////// @@ -41,13 +45,15 @@ library LibHalving { /// @param initial The initial value. /// @param half The halving period. /// @param elapsed The elapsed duration. - function halving( - uint256 initial, - uint256 half, - uint256 elapsed - ) internal pure returns (uint256) { - if (initial == 0 || half == 0) return 0; - if (elapsed == 0) return initial; + function halving(uint256 initial, uint256 half, uint256 elapsed) + internal + pure + returns (uint256) + { + if (initial == 0 || half == 0) + return 0; + if (elapsed == 0) + return initial; uint256 x = (elapsed * PRECISION) / half; uint256 i = x / PRECISION; uint256 f = x - i * PRECISION; diff --git a/contracts/src/registry/ApprovedUpgradeGate.sol b/contracts/src/registry/ApprovedUpgradeGate.sol new file mode 100644 index 000000000..43d342da4 --- /dev/null +++ b/contracts/src/registry/ApprovedUpgradeGate.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +/// @notice Allowlist for approved implementation upgrade targets. +contract ApprovedUpgradeGate is Ownable { + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// + + /// @notice Returns whether an implementation may be used as an upgrade target. + mapping(address implementation => bool approved) public approvedImplementations; + + //////////////////////////////////////////////////////////////////////// + // Events + //////////////////////////////////////////////////////////////////////// + + /// @notice Approval status changed for an implementation. + /// @param implementation The implementation address. + /// @param approved Whether upgrades to the implementation are approved. + event ImplementationApprovalChanged(address indexed implementation, bool indexed approved); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param owner_ The address that controls implementation approvals. + constructor(address owner_) Ownable(owner_) {} + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Set whether an implementation may be used as an upgrade target. + /// @param implementation The implementation address. + /// @param approved Whether upgrades to the implementation are approved. + function setImplementationApproval(address implementation, bool approved) external onlyOwner { + approvedImplementations[implementation] = approved; + emit ImplementationApprovalChanged(implementation, approved); + } +} diff --git a/contracts/src/registry/BaseUriRegistryMetadata.sol b/contracts/src/registry/BaseUriRegistryMetadata.sol deleted file mode 100644 index 3ef531a5d..000000000 --- a/contracts/src/registry/BaseUriRegistryMetadata.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import {EnhancedAccessControl} from "../access-control/EnhancedAccessControl.sol"; -import {EACBaseRolesLib} from "../access-control/libraries/EACBaseRolesLib.sol"; -import {HCAEquivalence} from "../hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "../hca/interfaces/IHCAFactoryBasic.sol"; - -import {IRegistryMetadata} from "./interfaces/IRegistryMetadata.sol"; - -/// @notice `IRegistryMetadata` implementation that returns a single shared base URI for all tokens. -/// The base URI can be updated by accounts holding the metadata update role in the root resource. -contract BaseUriRegistryMetadata is EnhancedAccessControl, IRegistryMetadata { - //////////////////////////////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////////////////////////////// - - /// @dev Role bit allowing an account to update the token base URI. - uint256 private constant _ROLE_UPDATE_METADATA = 1 << 0; - - /// @dev Admin-tier counterpart of the metadata update role, shifted into the upper half of the bitmap. - uint256 private constant _ROLE_UPDATE_METADATA_ADMIN = _ROLE_UPDATE_METADATA << 128; - - //////////////////////////////////////////////////////////////////////// - // Storage - //////////////////////////////////////////////////////////////////////// - - /// @dev Shared base URI returned for every token. - string private _tokenBaseUri; - - //////////////////////////////////////////////////////////////////////// - // Initialization - //////////////////////////////////////////////////////////////////////// - - constructor(IHCAFactoryBasic hcaFactory) HCAEquivalence(hcaFactory) { - _grantRoles(ROOT_RESOURCE, EACBaseRolesLib.ALL_ROLES, _msgSender(), true); - } - - function supportsInterface(bytes4 interfaceId) public view override returns (bool) { - return - interfaceId == type(IRegistryMetadata).interfaceId || - super.supportsInterface(interfaceId); - } - - //////////////////////////////////////////////////////////////////////// - // Implementation - //////////////////////////////////////////////////////////////////////// - - /// @notice Replaces the shared base URI for all tokens. - /// @dev Restricted to accounts holding the metadata update role on the root resource. - /// @param uri The new base URI to store. - function setTokenBaseUri( - string calldata uri - ) external onlyRoles(ROOT_RESOURCE, _ROLE_UPDATE_METADATA) { - _tokenBaseUri = uri; - } - - /// @notice Returns the metadata URI for the given token. - /// @dev Because this implementation uses a single shared URI, the token ID parameter is ignored. - /// @return The shared base URI. - function tokenUri(uint256 /*tokenId*/) external view returns (string memory) { - return _tokenBaseUri; - } -} diff --git a/contracts/src/registry/MetadataMixin.sol b/contracts/src/registry/MetadataMixin.sol deleted file mode 100644 index 1240a52f5..000000000 --- a/contracts/src/registry/MetadataMixin.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; - -import {IRegistryMetadata} from "./interfaces/IRegistryMetadata.sol"; - -/// @title MetadataMixin -/// -/// @notice Mixin contract for Registry implementations to delegate metadata to an external provider -/// -/// @dev Inherit this contract to add metadata functionality to Registry contracts -abstract contract MetadataMixin { - /// @notice The metadata provider contract - IRegistryMetadata public immutable METADATA_PROVIDER; - - /// @notice Initializes the mixin with a metadata provider - /// - /// @param metadataProvider_ Address of the metadata provider contract - constructor(IRegistryMetadata metadataProvider_) { - METADATA_PROVIDER = metadataProvider_; - } - - /// @notice Returns the token URI for a given token ID - /// - /// @param tokenId The ID of the token to query - /// - /// @return URI string for the token metadata - function _tokenURI(uint256 tokenId) internal view virtual returns (string memory) { - if (address(METADATA_PROVIDER) == address(0)) { - return ""; - } - return METADATA_PROVIDER.tokenUri(tokenId); - } -} diff --git a/contracts/src/registry/PermissionedRegistry.sol b/contracts/src/registry/PermissionedRegistry.sol index 8b7ca15b7..cfb8d06f3 100644 --- a/contracts/src/registry/PermissionedRegistry.sol +++ b/contracts/src/registry/PermissionedRegistry.sol @@ -1,24 +1,24 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; -import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {EnhancedAccessControl} from "../access-control/EnhancedAccessControl.sol"; import {IEnhancedAccessControl} from "../access-control/interfaces/IEnhancedAccessControl.sol"; -import {EACBaseRolesLib} from "../access-control/libraries/EACBaseRolesLib.sol"; import {ERC1155Singleton} from "../erc1155/ERC1155Singleton.sol"; import {IERC1155Singleton} from "../erc1155/interfaces/IERC1155Singleton.sol"; -import {HCAEquivalence} from "../hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "../hca/interfaces/IHCAFactoryBasic.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {ILabelStore} from "../utils/interfaces/ILabelStore.sol"; import {LibLabel} from "../utils/LibLabel.sol"; +import {IOwnedRegistry} from "./interfaces/IOwnedRegistry.sol"; import {IPermissionedRegistry} from "./interfaces/IPermissionedRegistry.sol"; import {IRegistry} from "./interfaces/IRegistry.sol"; -import {IRegistryMetadata} from "./interfaces/IRegistryMetadata.sol"; +import {IRegistryURIRenderer} from "./interfaces/IRegistryURIRenderer.sol"; import {IStandardRegistry} from "./interfaces/IStandardRegistry.sol"; +import {ITemporalRegistry} from "./interfaces/ITemporalRegistry.sol"; +import {ITokenizedRegistry} from "./interfaces/ITokenizedRegistry.sol"; import {RegistryRolesLib} from "./libraries/RegistryRolesLib.sol"; -import {MetadataMixin} from "./MetadataMixin.sol"; /// @notice A tokenized (ERC1155) registry with resource-scoped access control for subdomain management. /// @@ -55,13 +55,7 @@ import {MetadataMixin} from "./MetadataMixin.sol"; /// unregister() /// +ROLE_UNREGISTER /// -contract PermissionedRegistry is - IRegistry, - ERC1155Singleton, - EnhancedAccessControl, - IPermissionedRegistry, - MetadataMixin -{ +contract PermissionedRegistry is ERC1155Singleton, EnhancedAccessControl, IPermissionedRegistry { //////////////////////////////////////////////////////////////////////// // Types //////////////////////////////////////////////////////////////////////// @@ -79,33 +73,50 @@ contract PermissionedRegistry is address resolver; } + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The shared label database. + ILabelStore public immutable LABEL_STORE; + //////////////////////////////////////////////////////////////////////// // Storage //////////////////////////////////////////////////////////////////////// - IRegistry internal _parent; + /// @dev The parent registry of this registry. + IRegistry internal _parentRegistry; + + /// @dev The child label of this registry. string internal _childLabel; + + /// @dev The metadata URI. + string internal _uri; + + /// @dev The metadata renderer. + IRegistryURIRenderer internal _uriRenderer; + + /// @dev The entries of this registry. mapping(uint256 storageId => Entry entry) internal _entries; + /// @dev Storage gap for future changes. + uint256[256] private __gap; + //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// - constructor( - IHCAFactoryBasic hcaFactory, - IRegistryMetadata metadata, - address ownerAddress, - uint256 ownerRoles - ) HCAEquivalence(hcaFactory) MetadataMixin(metadata) { - if (ownerRoles != 0) { - _grantRoles(ROOT_RESOURCE, ownerRoles, ownerAddress, false); - } + /// @param labelStore The shared label database. + /// @param rootAccount Account granted root roles. + /// @param roleBitmap The role bitmap granted to `rootAccount`. + constructor(ILabelStore labelStore, address rootAccount, uint256 roleBitmap) { + emit RegistryCreated(); + LABEL_STORE = labelStore; + _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false); } /// @inheritdoc IERC165 - function supportsInterface( - bytes4 interfaceId - ) + function supportsInterface(bytes4 interfaceId) public view virtual @@ -115,7 +126,11 @@ contract PermissionedRegistry is return interfaceId == type(IPermissionedRegistry).interfaceId || interfaceId == type(IStandardRegistry).interfaceId || + interfaceId == type(ITokenizedRegistry).interfaceId || + interfaceId == type(ITemporalRegistry).interfaceId || + interfaceId == type(IOwnedRegistry).interfaceId || interfaceId == type(IRegistry).interfaceId || + interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId); } @@ -125,39 +140,44 @@ contract PermissionedRegistry is /// @inheritdoc IStandardRegistry function setSubregistry(uint256 anyId, IRegistry registry) public virtual { - (uint256 tokenId, Entry storage entry) = _checkExpiryAndTokenRoles( - anyId, - RegistryRolesLib.ROLE_SET_SUBREGISTRY - ); + (uint256 tokenId, Entry storage entry) = + _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_SUBREGISTRY); entry.subregistry = registry; - emit SubregistryUpdated(tokenId, registry, _msgSender()); + emit SubregistryUpdated(tokenId, registry, msg.sender); } /// @inheritdoc IStandardRegistry function setResolver(uint256 anyId, address resolver) public virtual { - (uint256 tokenId, Entry storage entry) = _checkExpiryAndTokenRoles( - anyId, - RegistryRolesLib.ROLE_SET_RESOLVER - ); + (uint256 tokenId, Entry storage entry) = + _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_SET_RESOLVER); entry.resolver = resolver; - emit ResolverUpdated(tokenId, resolver, _msgSender()); + emit ResolverUpdated(tokenId, resolver, msg.sender); + } + + /// @notice Set the URI for the registry. + /// @param uri_ The new URI. + /// @param renderer The new renderer address. + function setURI(string calldata uri_, IRegistryURIRenderer renderer) + public + virtual + onlyRootRoles(RegistryRolesLib.ROLE_SET_URI) + { + _uri = uri_; + _uriRenderer = renderer; + emit URIUpdated(uri_, address(renderer), msg.sender); } /// @inheritdoc IStandardRegistry - function setParent( - IRegistry parent, - string memory label - ) public virtual onlyRootRoles(RegistryRolesLib.ROLE_SET_PARENT) { - _parent = parent; + function setParent(IRegistry parent, string memory label) + public + onlyRootRoles(RegistryRolesLib.ROLE_SET_PARENT) + { + _parentRegistry = parent; _childLabel = label; - emit ParentUpdated(parent, label, _msgSender()); + emit ParentUpdated(parent, label, msg.sender); } /// @inheritdoc IStandardRegistry - /// @dev If `AVAILABLE`, requires `ROLE_REGISTRAR` on root. - /// * If `owner` is null (`roleBitmap` must be 0), status becomes `RESERVED` instead of `REGISTERED`. - /// If `RESERVED`, requires `ROLE_REGISTER_RESERVED` on root. - /// * If `expiry` is 0, uses current expiry. function register( string memory label, address owner, @@ -165,71 +185,20 @@ contract PermissionedRegistry is address resolver, uint256 roleBitmap, uint64 expiry - ) public virtual override returns (uint256 tokenId) { - NameCoder.assertLabelSize(label); - uint256 labelId = LibLabel.id(label); - Entry storage entry = _entry(labelId); - tokenId = _constructTokenId(labelId, entry); - address prevOwner = super.ownerOf(tokenId); - address sender = _msgSender(); // the registrar, not the registrant - if (_isExpired(entry.expiry)) { - if (sender != address(this)) { - _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTRAR, sender); - } - if (owner == address(0) && roleBitmap != 0) { - revert EACCannotGrantRoles(ROOT_RESOURCE, roleBitmap, sender); // strict - } - } else { - if (prevOwner != address(0)) { - revert NameAlreadyRegistered(label); // cannot overwrite REGISTERED - } else if (owner == address(0)) { - revert NameAlreadyReserved(label); // cannot reserve/register RESERVED - } - if (sender != address(this)) { - _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTER_RESERVED, sender); - } - if (expiry == 0) { - expiry = entry.expiry; // use current expiry - } - } - if (_isExpired(expiry)) { - revert CannotSetPastExpiration(expiry); - } - if (prevOwner != address(0)) { - _burn(prevOwner, tokenId, 1); - ++entry.eacVersionId; - ++entry.tokenVersionId; - tokenId = _constructTokenId(tokenId, entry); - } - entry.expiry = expiry; - entry.subregistry = registry; - entry.resolver = resolver; - // emit NameRegistered before mint so we can determine this is a registry (in an indexer) - if (owner == address(0)) { - emit NameReserved(tokenId, bytes32(labelId), label, expiry, sender); - } else { - emit NameRegistered(tokenId, bytes32(labelId), label, owner, expiry, sender); - _mint(owner, tokenId, 1, ""); - uint256 resource = _constructResource(tokenId, entry); - emit TokenResource(tokenId, resource); - _grantRoles(resource, roleBitmap, owner, false); - } - if (address(registry) != address(0)) { - emit SubregistryUpdated(tokenId, registry, sender); - } - if (address(resolver) != address(0)) { - emit ResolverUpdated(tokenId, resolver, sender); - } + ) + public + virtual + returns (uint256) + { + return _register(label, owner, registry, resolver, roleBitmap, expiry, true); } /// @inheritdoc IStandardRegistry /// @dev Requires `REGISTERED | RESERVED` and `ROLE_UNREGISTER`. - function unregister(uint256 anyId) public virtual { - (uint256 tokenId, Entry storage entry) = _checkExpiryAndTokenRoles( - anyId, - RegistryRolesLib.ROLE_UNREGISTER - ); - emit NameUnregistered(tokenId, _msgSender()); + function unregister(uint256 anyId) public { + (uint256 tokenId, Entry storage entry) = + _checkExpiryAndTokenRoles(anyId, RegistryRolesLib.ROLE_UNREGISTER); + emit LabelUnregistered(tokenId, msg.sender); address owner = super.ownerOf(tokenId); if (owner != address(0)) { _burn(owner, tokenId, 1); @@ -240,34 +209,41 @@ contract PermissionedRegistry is } /// @inheritdoc IStandardRegistry - /// @dev Requires an `REGISTERED | RESERVED` and `ROLE_RENEW`. + /// @dev If `REGISTERED | RESERVED`, requires `ROLE_RENEW`. + /// If `AVAILABLE`, requires expiry > 0 and `ROLE_RENEW` on root. function renew(uint256 anyId, uint64 newExpiry) public override { - (uint256 tokenId, Entry storage entry) = _checkExpiryAndTokenRoles( - anyId, - RegistryRolesLib.ROLE_RENEW - ); - if (newExpiry < entry.expiry) { - revert CannotReduceExpiration(entry.expiry, newExpiry); + Entry storage entry = _entry(anyId); + uint256 tokenId = _constructTokenId(anyId, entry); + uint64 expiry = entry.expiry; + if (_isExpired(expiry)) { + if (expiry == 0 || !_canRevive(tokenId, msg.sender)) { + revert LabelExpired(tokenId); // never registered OR cannot revive + } + } else { + _checkRoles(_constructResource(anyId, entry), RegistryRolesLib.ROLE_RENEW, msg.sender); + } + if (newExpiry < expiry) { + revert CannotReduceExpiry(expiry, newExpiry); } entry.expiry = newExpiry; - emit ExpiryUpdated(tokenId, newExpiry, _msgSender()); + emit ExpiryUpdated(tokenId, newExpiry, msg.sender); } /// @inheritdoc IEnhancedAccessControl - function grantRoles( - uint256 anyId, - uint256 roleBitmap, - address account - ) public override(EnhancedAccessControl, IEnhancedAccessControl) returns (bool) { + function grantRoles(uint256 anyId, uint256 roleBitmap, address account) + public + override(EnhancedAccessControl, IEnhancedAccessControl) + returns (bool) + { return super.grantRoles(getResource(anyId), roleBitmap, account); } /// @inheritdoc IEnhancedAccessControl - function revokeRoles( - uint256 anyId, - uint256 roleBitmap, - address account - ) public override(EnhancedAccessControl, IEnhancedAccessControl) returns (bool) { + function revokeRoles(uint256 anyId, uint256 roleBitmap, address account) + public + override(EnhancedAccessControl, IEnhancedAccessControl) + returns (bool) + { return super.revokeRoles(getResource(anyId), roleBitmap, account); } @@ -284,13 +260,36 @@ contract PermissionedRegistry is } /// @inheritdoc IRegistry - function getParent() public view virtual returns (IRegistry parent, string memory label) { - return (_parent, _childLabel); + function getParent() public view returns (IRegistry parent, string memory label) { + return (_parentRegistry, _childLabel); + } + + /// @inheritdoc IContractNamer + function isContractNamer(address namer) public view virtual returns (bool) { + return hasRootRoles(RegistryRolesLib.ROLE_CAN_NAME, namer); + } + + /// @inheritdoc ITemporalRegistry + function findExpiry(string calldata label) public view returns (uint64) { + return getExpiry(LibLabel.id(label)); + } + + /// @inheritdoc IOwnedRegistry + function findOwner(string calldata label) public view returns (address) { + return getOwner(LibLabel.id(label)); + } + + /// @inheritdoc ITokenizedRegistry + function findTokenId(string calldata label) public view returns (uint256) { + return getTokenId(LibLabel.id(label)); } /// @inheritdoc ERC1155Singleton function uri(uint256 tokenId) public view override returns (string memory) { - return _tokenURI(tokenId); + return + address(_uriRenderer) != address(0) + ? _uriRenderer.renderURI(this, tokenId) + : _uri; } /// @inheritdoc IStandardRegistry @@ -300,7 +299,7 @@ contract PermissionedRegistry is /// @inheritdoc IPermissionedRegistry function getResource(uint256 anyId) public view returns (uint256) { - return anyId == ROOT_RESOURCE ? ROOT_RESOURCE : _constructResource(anyId, _entry(anyId)); + return _constructResource(anyId, _entry(anyId)); } /// @inheritdoc IPermissionedRegistry @@ -308,6 +307,11 @@ contract PermissionedRegistry is return _constructTokenId(anyId, _entry(anyId)); } + /// @inheritdoc IPermissionedRegistry + function getOwner(uint256 anyId) public view returns (address) { + return _isExpired(getExpiry(anyId)) ? address(0) : super.ownerOf(getTokenId(anyId)); + } + /// @inheritdoc IPermissionedRegistry function getStatus(uint256 anyId) public view returns (Status) { Entry storage entry = _entry(anyId); @@ -328,14 +332,17 @@ contract PermissionedRegistry is } /// @inheritdoc IPermissionedRegistry - function latestOwnerOf(uint256 tokenId) public view virtual returns (address) { + function latestOwnerOf(uint256 tokenId) public view returns (address) { return super.ownerOf(tokenId); } /// @inheritdoc IERC1155Singleton - function ownerOf( - uint256 tokenId - ) public view virtual override(ERC1155Singleton, IERC1155Singleton) returns (address) { + function ownerOf(uint256 tokenId) + public + view + override(ERC1155Singleton, IERC1155Singleton) + returns (address) + { Entry storage entry = _entry(tokenId); return tokenId != _constructTokenId(tokenId, entry) || _isExpired(entry.expiry) @@ -343,46 +350,48 @@ contract PermissionedRegistry is : super.ownerOf(tokenId); } - /// @dev EAC view overrides — each translates `anyId` to the canonical EAC resource - /// (via `getResource`) before delegating to the base `EnhancedAccessControl` implementation. - /// @inheritdoc IEnhancedAccessControl - function roles( - uint256 anyId, - address account - ) public view override(EnhancedAccessControl, IEnhancedAccessControl) returns (uint256) { + function roles(uint256 anyId, address account) + public + view + override(EnhancedAccessControl, IEnhancedAccessControl) + returns (uint256) + { return super.roles(getResource(anyId), account); } /// @inheritdoc IEnhancedAccessControl - function roleCount( - uint256 anyId - ) public view override(EnhancedAccessControl, IEnhancedAccessControl) returns (uint256) { + function roleCount(uint256 anyId) + public + view + override(EnhancedAccessControl, IEnhancedAccessControl) + returns (uint256) + { return super.roleCount(getResource(anyId)); } /// @inheritdoc IEnhancedAccessControl - function hasRoles( - uint256 anyId, - uint256 roleBitmap, - address account - ) public view override(EnhancedAccessControl, IEnhancedAccessControl) returns (bool) { + function hasRoles(uint256 anyId, uint256 roleBitmap, address account) + public + view + override(EnhancedAccessControl, IEnhancedAccessControl) + returns (bool) + { return super.hasRoles(getResource(anyId), roleBitmap, account); } /// @inheritdoc IEnhancedAccessControl - function hasAssignees( - uint256 anyId, - uint256 roleBitmap - ) public view override(EnhancedAccessControl, IEnhancedAccessControl) returns (bool) { + function hasAssignees(uint256 anyId, uint256 roleBitmap) + public + view + override(EnhancedAccessControl, IEnhancedAccessControl) + returns (bool) + { return super.hasAssignees(getResource(anyId), roleBitmap); } /// @inheritdoc IEnhancedAccessControl - function getAssigneeCount( - uint256 anyId, - uint256 roleBitmap - ) + function getAssigneeCount(uint256 anyId, uint256 roleBitmap) public view override(EnhancedAccessControl, IEnhancedAccessControl) @@ -395,27 +404,95 @@ contract PermissionedRegistry is // Internal Functions //////////////////////////////////////////////////////////////////////// - /// @dev Override the base registry _update function to transfer the roles to the new owner when the token is transferred. - function _update( - address from, - address to, - uint256[] memory tokenIds, - uint256[] memory values - ) internal virtual override { - bool externalTransfer = to != address(0) && from != address(0); - if (externalTransfer) { - // Check ROLE_CAN_TRANSFER for actual transfers only - // Skip check for mints (from == address(0)) and burns (to == address(0)) - for (uint256 i; i < tokenIds.length; ++i) { - if (!hasRoles(tokenIds[i], RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, from)) { - revert TransferDisallowed(tokenIds[i], from); - } + /// @dev If `AVAILABLE`, requires `ROLE_REGISTRAR` on root and status becomes `REGISTERED`. + /// * If `owner` is null (`roleBitmap` must be 0), status becomes `RESERVED`. + /// If `RESERVED`, requires `ROLE_REGISTER_RESERVED` on root and status becomes `REGISTERED`. + /// * If `expiry` is 0, uses current expiry. + function _register( + string memory label, + address owner, + IRegistry registry, + address resolver, + uint256 roleBitmap, + uint64 expiry, + bool checkRoles + ) + internal + returns (uint256 tokenId) + { + LABEL_STORE.setLabel(label); + uint256 labelId = LibLabel.id(label); + Entry storage entry = _entry(labelId); + tokenId = _constructTokenId(labelId, entry); + address prevOwner = super.ownerOf(tokenId); + if (_isExpired(entry.expiry)) { + if (checkRoles) { + _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTRAR, msg.sender); + } + if (owner == address(0) && roleBitmap != 0) { + revert EACCannotGrantRoles(ROOT_RESOURCE, roleBitmap, msg.sender); // strict + } + } else { + if (prevOwner != address(0)) { + revert LabelAlreadyRegistered(label); // cannot overwrite REGISTERED + } else if (owner == address(0)) { + revert LabelAlreadyReserved(label); // cannot overwrite RESERVED + } + if (checkRoles) { + _checkRoles(ROOT_RESOURCE, RegistryRolesLib.ROLE_REGISTER_RESERVED, msg.sender); } + if (expiry == 0) { + expiry = entry.expiry; // use RESERVED expiry + } + roleBitmap |= RegistryRolesLib.ROLE_WAS_RESERVED; // remember + } + if (owner == address(0) ? expiry == 0 : _isExpired(expiry)) { + revert CannotSetPastExpiry(expiry); + } + if (prevOwner != address(0)) { + _burn(prevOwner, tokenId, 1); + ++entry.eacVersionId; + ++entry.tokenVersionId; + tokenId = _constructTokenId(tokenId, entry); + } + entry.expiry = expiry; + entry.subregistry = registry; + entry.resolver = resolver; + if (owner == address(0)) { + emit LabelReserved(tokenId, bytes32(labelId), label, expiry, msg.sender); + } else { + emit LabelRegistered(tokenId, bytes32(labelId), label, owner, expiry, msg.sender); + _mint(owner, tokenId, 1, ""); + uint256 resource = _constructResource(tokenId, entry); + assert(resource != ROOT_RESOURCE); + emit TokenResource(tokenId, resource); + _grantRoles(resource, roleBitmap, owner, false); } - super._update(from, to, tokenIds, values); - if (externalTransfer) { + if (address(registry) != address(0)) { + emit SubregistryUpdated(tokenId, registry, msg.sender); + } + if (address(resolver) != address(0)) { + emit ResolverUpdated(tokenId, resolver, msg.sender); + } + } + + /// @dev Override `ERC1155Singleton._update()` to transfer the roles to the new owner if the token is transferred. + function _update(address from, address to, uint256[] memory tokenIds, uint256[] memory amounts) + internal + override + { + super._update(from, to, tokenIds, amounts); // ensures amounts[i] is 0 or 1 + if (to != address(0) && from != address(0)) { + // only transfers (skip mint and burn) for (uint256 i; i < tokenIds.length; ++i) { - _transferRoles(getResource(tokenIds[i]), from, to, false); + uint256 tokenId = tokenIds[i]; + // only check ROLE_CAN_TRANSFER_ADMIN on original owner (from) + // ROLE_CAN_TRANSFER_ADMIN is technically a property of the token + if (!hasRoles(tokenId, RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, from)) { + revert TransferDisallowed(tokenId, from); + } else if (amounts[i] > 0) { + _transferRoles(getResource(tokenId), from, to, false); + } } } } @@ -427,8 +504,11 @@ contract PermissionedRegistry is uint256 /*oldRoles*/, uint256 /*newRoles*/, uint256 /*roleBitmap*/ - ) internal virtual override { - _regenerateToken(resource); + ) + internal + override + { + _regenerate(resource); } /// @dev Override the base registry _onRolesRevoked function to regenerate the token when the roles are revoked. @@ -438,43 +518,75 @@ contract PermissionedRegistry is uint256 /*oldRoles*/, uint256 /*newRoles*/, uint256 /*roleBitmap*/ - ) internal virtual override { - _regenerateToken(resource); + ) + internal + override + { + _regenerate(resource); } /// @dev Bump `tokenVersionId` via burn+mint if token is not expired. - function _regenerateToken(uint256 anyId) internal { - Entry storage entry = _entry(anyId); - if (!_isExpired(entry.expiry)) { - uint256 tokenId = _constructTokenId(anyId, entry); - address owner = super.ownerOf(tokenId); // skip expiry check - if (owner != address(0)) { - _burn(owner, tokenId, 1); - ++entry.tokenVersionId; - uint256 newTokenId = _constructTokenId(tokenId, entry); - _mint(owner, newTokenId, 1, ""); - emit TokenRegenerated(tokenId, newTokenId); // resource is unchanged - } + function _regenerate(uint256 resource) internal { + if (resource != ROOT_RESOURCE) { + Entry storage entry = _entry(resource); + uint256 tokenId = _constructTokenId(resource, entry); + address owner = super.ownerOf(tokenId); // grant/revoke only on registered + _burn(owner, tokenId, 1); + ++entry.tokenVersionId; + uint256 newTokenId = _constructTokenId(tokenId, entry); + emit TokenRegenerated(tokenId, newTokenId); // resource is unchanged + _mint(owner, newTokenId, 1, ""); } } - /// @dev Override to prevent admin roles from being granted in the registry. + /// @inheritdoc EnhancedAccessControl + /// @dev Override for token-dependent logic: + /// + /// Token non-admin roles can only be granted to registered tokens. /// - /// In the registry context, admin roles are only assigned during name registration - /// to maintain controlled permission management. This ensures that role delegation + /// Token admin roles are only assigned during name registration to maintain + /// controlled permission management. This ensures that role delegation /// follows the intended security model where admin privileges are granted at /// registration time and cannot be arbitrarily granted afterward. /// + /// Root admin roles are unaffected. + /// /// @param resource The resource to get settable roles for. /// @param account The account to get settable roles for. /// @return The settable roles (regular roles only, not admin roles). - function _getSettableRoles( - uint256 resource, - address account - ) internal view virtual override returns (uint256) { - uint256 allRoles = super.roles(resource, account) | super.roles(ROOT_RESOURCE, account); - uint256 adminRoleBitmap = allRoles & EACBaseRolesLib.ADMIN_ROLES; - return adminRoleBitmap >> 128; + function _getSettableRoles(uint256 resource, address account) + internal + view + virtual + override + returns (uint256) + { + if (resource != ROOT_RESOURCE && getOwner(resource) == address(0)) { + return 0; + } + uint256 roleBitmap = super._getSettableRoles(resource, account); + return resource == ROOT_RESOURCE ? roleBitmap : roleBitmap >> 128; + } + + /// @inheritdoc EnhancedAccessControl + /// @dev Override for token-dependent logic: + /// + /// * if caller is approved by token owner, combine the caller's roles with the owner's roles + /// + function _getRoles(uint256 resource, address account) + internal + view + virtual + override + returns (uint256 roleBitmap) + { + roleBitmap = super._getRoles(resource, account); + if (resource != ROOT_RESOURCE) { + address owner = getOwner(resource); + if (owner != address(0) && owner != account && isApprovedForAll(owner, account)) { + roleBitmap |= super._getRoles(resource, owner); + } + } } /// @dev Zeroes version bits in `anyId` to return the canonical storage entry for the name. @@ -482,35 +594,51 @@ contract PermissionedRegistry is return _entries[LibLabel.withVersion(anyId, 0)]; } + /// @dev Determine if token can be revived. + function _canRevive( + uint256 /*tokenId*/, + address sender + ) + internal + view + virtual + returns (bool) + { + return hasRootRoles(RegistryRolesLib.ROLE_RENEW, sender); + } + /// @dev Assert token is not expired and caller has necessary roles. - function _checkExpiryAndTokenRoles( - uint256 anyId, - uint256 roleBitmap - ) internal view returns (uint256 tokenId, Entry storage entry) { + function _checkExpiryAndTokenRoles(uint256 anyId, uint256 roleBitmap) + internal + view + returns (uint256 tokenId, Entry storage entry) + { entry = _entry(anyId); tokenId = _constructTokenId(anyId, entry); if (_isExpired(entry.expiry)) { - revert NameExpired(tokenId); + revert LabelExpired(tokenId); } - _checkRoles(_constructResource(anyId, entry), roleBitmap, _msgSender()); + _checkRoles(_constructResource(anyId, entry), roleBitmap, msg.sender); } /// @dev Internal logic for expired status. - /// Only use of `block.timestamp`. function _isExpired(uint64 expiry) internal view returns (bool) { return block.timestamp >= expiry; } /// @dev Create `resource` from parts. + /// Does nothing if `ROOT_RESOURCE`. /// Returns next resource if expired. - function _constructResource( - uint256 anyId, - Entry storage entry - ) internal view returns (uint256) { + function _constructResource(uint256 anyId, Entry storage entry) internal view returns (uint256) { + if (anyId == ROOT_RESOURCE) { + return anyId; + } return LibLabel.withVersion( anyId, - _isExpired(entry.expiry) ? entry.eacVersionId + 1 : entry.eacVersionId + _isExpired(entry.expiry) + ? entry.eacVersionId + 1 + : entry.eacVersionId ); } diff --git a/contracts/src/registry/SimpleRegistryMetadata.sol b/contracts/src/registry/SimpleRegistryMetadata.sol deleted file mode 100644 index b84a63966..000000000 --- a/contracts/src/registry/SimpleRegistryMetadata.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import {EnhancedAccessControl} from "../access-control/EnhancedAccessControl.sol"; -import {EACBaseRolesLib} from "../access-control/libraries/EACBaseRolesLib.sol"; -import {HCAEquivalence} from "../hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "../hca/interfaces/IHCAFactoryBasic.sol"; - -import {IRegistryMetadata} from "./interfaces/IRegistryMetadata.sol"; - -/// @notice `IRegistryMetadata` implementation that stores a distinct URI per token ID. URIs can be -/// set by accounts holding the metadata update role in the root resource. -contract SimpleRegistryMetadata is EnhancedAccessControl, IRegistryMetadata { - //////////////////////////////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////////////////////////////// - - /// @dev Role bit allowing an account to update individual token URIs. - uint256 private constant _ROLE_UPDATE_METADATA = 1 << 0; - - /// @dev Admin-tier counterpart of the metadata update role, shifted into the upper half of the bitmap. - uint256 private constant _ROLE_UPDATE_METADATA_ADMIN = _ROLE_UPDATE_METADATA << 128; - - //////////////////////////////////////////////////////////////////////// - // Storage - //////////////////////////////////////////////////////////////////////// - - /// @dev Per-token mapping from token ID to its metadata URI. - mapping(uint256 id => string uri) private _tokenUris; - - //////////////////////////////////////////////////////////////////////// - // Initialization - //////////////////////////////////////////////////////////////////////// - - constructor(IHCAFactoryBasic hcaFactory) HCAEquivalence(hcaFactory) { - _grantRoles(ROOT_RESOURCE, EACBaseRolesLib.ALL_ROLES, _msgSender(), true); - } - - function supportsInterface(bytes4 interfaceId) public view override returns (bool) { - return - interfaceId == type(IRegistryMetadata).interfaceId || - super.supportsInterface(interfaceId); - } - - //////////////////////////////////////////////////////////////////////// - // Implementation - //////////////////////////////////////////////////////////////////////// - - /// @notice Sets the metadata URI for a specific token. - /// @dev Restricted to accounts holding the metadata update role on the root resource. - /// @param tokenId The token identifier whose URI is being set. - /// @param uri The new metadata URI for the token. - function setTokenUri( - uint256 tokenId, - string calldata uri - ) external onlyRoles(ROOT_RESOURCE, _ROLE_UPDATE_METADATA) { - _tokenUris[tokenId] = uri; - } - - /// @notice Returns the metadata URI for the given token. - /// @param tokenId The token identifier to look up. - /// @return The stored URI for `tokenId`, or an empty string if none has been set. - function tokenUri(uint256 tokenId) external view override returns (string memory) { - return _tokenUris[tokenId]; - } -} diff --git a/contracts/src/registry/UserRegistry.sol b/contracts/src/registry/UserRegistry.sol index 87e21cd7f..8e64f4884 100644 --- a/contracts/src/registry/UserRegistry.sol +++ b/contracts/src/registry/UserRegistry.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; +import {IProxyAuthorization} from "@ensdomains/verifiable-factory/IProxyAuthorization.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {InvalidOwner} from "../CommonErrors.sol"; -import {IHCAFactoryBasic} from "../hca/interfaces/IHCAFactoryBasic.sol"; +import {ILabelStore} from "../utils/interfaces/ILabelStore.sol"; -import {IRegistryMetadata} from "./interfaces/IRegistryMetadata.sol"; import {RegistryRolesLib} from "./libraries/RegistryRolesLib.sol"; import {PermissionedRegistry} from "./PermissionedRegistry.sol"; @@ -16,35 +17,42 @@ import {PermissionedRegistry} from "./PermissionedRegistry.sol"; /// `VerifiableFactory` for user-owned subdomain registries. The constructor disables /// initializers on the implementation contract; proxies call `initialize()` to set up the /// admin and initial roles. Upgrade authorization requires the upgrade role in the root resource. -contract UserRegistry is Initializable, PermissionedRegistry, UUPSUpgradeable { +contract UserRegistry is Initializable, PermissionedRegistry, UUPSUpgradeable, IProxyAuthorization { //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// - constructor( - IHCAFactoryBasic hcaFactory_, - IRegistryMetadata metadataProvider_ - ) PermissionedRegistry(hcaFactory_, metadataProvider_, address(0), 0) { + /// @param labelStore The shared label database. + /// @param namer The implementation namer. + constructor(ILabelStore labelStore, address namer) + PermissionedRegistry( + labelStore, + namer, + RegistryRolesLib.ROLE_CAN_NAME | RegistryRolesLib.ROLE_CAN_NAME_ADMIN + ) + { // This disables initialization for the implementation contract _disableInitializers(); } /// @notice Initializes a proxy instance of `UserRegistry`. - /// @dev Grants the supplied role bitmap to `admin` on the root resource. Reverts if `admin` - /// is the zero address. - /// @param admin The address that will receive the specified roles. - /// @param roleBitmap The role bitmap to grant to `admin`. - function initialize(address admin, uint256 roleBitmap) public initializer { - if (admin == address(0)) { + /// @dev Grants the supplied role bitmap to `rootAccount` on the root resource. + /// Reverts if the zero address. + /// @param rootAccount Account granted root roles. + /// @param roleBitmap The role bitmap granted to `rootAccount`. + function initialize(address rootAccount, uint256 roleBitmap) public initializer { + if (rootAccount == address(0)) { revert InvalidOwner(); } - _grantRoles(ROOT_RESOURCE, roleBitmap, admin, false); + emit RegistryCreated(); + _grantRoles(ROOT_RESOURCE, roleBitmap, rootAccount, false); } - /// @dev See {IERC165-supportsInterface}. + /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(UUPSUpgradeable).interfaceId || + interfaceId == type(IProxyAuthorization).interfaceId || super.supportsInterface(interfaceId); } @@ -52,9 +60,28 @@ contract UserRegistry is Initializable, PermissionedRegistry, UUPSUpgradeable { // Implementation //////////////////////////////////////////////////////////////////////// + /// @notice Declares this implementation as an eligible verifiable proxy upgrade target. + /// @dev Upgrade authorization is still enforced by the current implementation during the UUPS + /// upgrade call. + /// @param {previousImplementation} Ignored. + /// @return allowed Always `true` for implementations in this registry family. + function canUpgradeFrom( + address /* previousImplementation */ + ) + external + pure + virtual + override + returns (bool allowed) + { + return true; + } + /// @dev Restricts UUPS upgrades to accounts holding the upgrade role on the root resource. /// @param newImplementation The address of the new implementation contract. - function _authorizeUpgrade( - address newImplementation - ) internal override onlyRootRoles(RegistryRolesLib.ROLE_UPGRADE) {} + function _authorizeUpgrade(address newImplementation) + internal + override + onlyRootRoles(RegistryRolesLib.ROLE_UPGRADE) + {} } diff --git a/contracts/src/registry/WrapperRegistry.sol b/contracts/src/registry/WrapperRegistry.sol index 10298aafc..ee98f663b 100755 --- a/contracts/src/registry/WrapperRegistry.sol +++ b/contracts/src/registry/WrapperRegistry.sol @@ -1,20 +1,24 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import {INameWrapper} from "@ens/contracts/wrapper/INameWrapper.sol"; -import {VerifiableFactory} from "@ensdomains/verifiable-factory/VerifiableFactory.sol"; +import {IProxyAuthorization} from "@ensdomains/verifiable-factory/IProxyAuthorization.sol"; +import {IVerifiableFactory} from "@ensdomains/verifiable-factory/IVerifiableFactory.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import {IHCAFactoryBasic} from "../hca/interfaces/IHCAFactoryBasic.sol"; import {AbstractWrapperReceiver} from "../migration/AbstractWrapperReceiver.sol"; import {LibMigration} from "../migration/libraries/LibMigration.sol"; import {LockedWrapperReceiver} from "../migration/LockedWrapperReceiver.sol"; import {IWrapperRegistry} from "../registry/interfaces/IWrapperRegistry.sol"; +import {IAddressSet} from "../utils/interfaces/IAddressSet.sol"; +import {ILabelStore} from "../utils/interfaces/ILabelStore.sol"; +import {LibLabel} from "../utils/LibLabel.sol"; +import {ApprovedUpgradeGate} from "./ApprovedUpgradeGate.sol"; import {IRegistry} from "./interfaces/IRegistry.sol"; -import {IRegistryMetadata} from "./interfaces/IRegistryMetadata.sol"; import {IStandardRegistry} from "./interfaces/IStandardRegistry.sol"; import {RegistryRolesLib} from "./libraries/RegistryRolesLib.sol"; import {PermissionedRegistry} from "./PermissionedRegistry.sol"; @@ -26,15 +30,19 @@ contract WrapperRegistry is PermissionedRegistry, LockedWrapperReceiver, Initializable, - UUPSUpgradeable + UUPSUpgradeable, + IProxyAuthorization { //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// - /// @dev Fallback resolver for ENSv1 resolution. + /// @notice Fallback resolver for ENSv1 resolution. address public immutable V1_RESOLVER; + /// @notice Gate for approved implementation upgrade targets. + ApprovedUpgradeGate public immutable UPGRADE_GATE; + //////////////////////////////////////////////////////////////////////// // Storage //////////////////////////////////////////////////////////////////////// @@ -42,28 +50,54 @@ contract WrapperRegistry is /// @dev The namehash of this registry. bytes32 internal _node; + /// @dev The initial roles derived from the NameWrapper. + uint256 internal _initialRoleBitmap; + //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// + /// @param nameWrapper The ENSv1 NameWrapper. + /// @param graveyard The ENSv1 `BaseRegistrar` token graveyard. + /// @param verifiableFactory The VerifiableFactory. + /// @param ensV1Resolver The ENSv1 resolver. + /// @param upgradeGate The upgrade target allowlist. + /// @param labelStore The shared label database. + /// @param publicResolverSet The approved list of `PublicResolver` contracts. + /// @param publicResolver The replacement `PublicResolver`. + /// @param namer The implementation namer. constructor( INameWrapper nameWrapper, - VerifiableFactory verifiableFactory, + address graveyard, + IVerifiableFactory verifiableFactory, address ensV1Resolver, - IHCAFactoryBasic hcaFactory, - IRegistryMetadata metadataProvider + ApprovedUpgradeGate upgradeGate, + ILabelStore labelStore, + IAddressSet publicResolverSet, + address publicResolver, + address namer ) - PermissionedRegistry(hcaFactory, metadataProvider, address(0), 0) // no roles are granted - LockedWrapperReceiver(nameWrapper, verifiableFactory, address(this)) + PermissionedRegistry( + labelStore, + namer, + RegistryRolesLib.ROLE_CAN_NAME | RegistryRolesLib.ROLE_CAN_NAME_ADMIN + ) + LockedWrapperReceiver( + nameWrapper, + graveyard, + verifiableFactory, + address(this), + publicResolverSet, + publicResolver + ) { V1_RESOLVER = ensV1Resolver; + UPGRADE_GATE = upgradeGate; _disableInitializers(); } /// @inheritdoc IERC165 - function supportsInterface( - bytes4 interfaceId - ) + function supportsInterface(bytes4 interfaceId) public view virtual @@ -73,6 +107,7 @@ contract WrapperRegistry is return type(IWrapperRegistry).interfaceId == interfaceId || type(UUPSUpgradeable).interfaceId == interfaceId || + type(IProxyAuthorization).interfaceId == interfaceId || super.supportsInterface(interfaceId); } @@ -81,25 +116,43 @@ contract WrapperRegistry is bytes32 node, IRegistry parentRegistry, string calldata childLabel, - address admin, uint256 roleBitmap - ) public initializer { + ) + public + initializer + { _node = node; // setup canonical parent (ROLE_SET_PARENT is not granted) _parentRegistry = parentRegistry; _childLabel = childLabel; - _grantRoles( - ROOT_RESOURCE, - RegistryRolesLib.ROLE_UPGRADE | RegistryRolesLib.ROLE_UPGRADE_ADMIN | roleBitmap, - admin, - false - ); + _initialRoleBitmap = roleBitmap; + emit RegistryCreated(); + address virtualOwner = address(_parentRegistry); + emit ParentUpdated(parentRegistry, childLabel, virtualOwner); + _grantRoles(ROOT_RESOURCE, roleBitmap, virtualOwner, false); } //////////////////////////////////////////////////////////////////////// // Implementation //////////////////////////////////////////////////////////////////////// + /// @notice Declares this implementation as an eligible verifiable proxy upgrade target. + /// @dev Upgrade authorization is still enforced by the current implementation during the UUPS + /// upgrade call, including the wrapper upgrade target allowlist. + /// @param {previousImplementation} Ignored. + /// @return allowed Always `true` for implementations in this wrapper registry family. + function canUpgradeFrom( + address /* previousImplementation */ + ) + external + pure + virtual + override + returns (bool allowed) + { + return true; + } + /// @inheritdoc PermissionedRegistry /// @dev Blocks registration of emancipated children. function register( @@ -109,7 +162,11 @@ contract WrapperRegistry is address resolver, uint256 roleBitmap, uint64 expiry - ) public override(IStandardRegistry, PermissionedRegistry) returns (uint256 tokenId) { + ) + public + override(IStandardRegistry, PermissionedRegistry) + returns (uint256 tokenId) + { if (_isMigratableChild(label)) { revert LibMigration.NameRequiresMigration(); } @@ -118,9 +175,12 @@ contract WrapperRegistry is /// @inheritdoc PermissionedRegistry /// @dev Return `V1_RESOLVER` upon visiting migratable children. - function getResolver( - string calldata label - ) public view override(IRegistry, PermissionedRegistry) returns (address) { + function getResolver(string calldata label) + public + view + override(IRegistry, PermissionedRegistry) + returns (address) + { return _isMigratableChild(label) ? V1_RESOLVER : super.getResolver(label); } @@ -157,19 +217,87 @@ contract WrapperRegistry is address resolver, uint256 roleBitmap, uint64 expiry - ) internal override returns (uint256 tokenId) { - return super.register(label, owner, subregistry, resolver, roleBitmap, expiry); + ) + internal + override + returns (uint256 tokenId) + { + return _register(label, owner, subregistry, resolver, roleBitmap, expiry, false); } - /// @dev Requires `ROLE_UPGRADE` to upgrade. - function _authorizeUpgrade( - address - ) internal override onlyRootRoles(RegistryRolesLib.ROLE_UPGRADE) { - // + /// @inheritdoc PermissionedRegistry + /// @dev Override for token-dependent logic: + /// + /// Root admin roles cannot be granted. + /// + /// @param resource The resource to get settable roles for. + /// @param account The account to get settable roles for. + /// @return The settable roles. + function _getSettableRoles(uint256 resource, address account) + internal + view + override + returns (uint256) + { + uint256 roleBitmap = super._getSettableRoles(resource, account); + return resource == ROOT_RESOURCE ? roleBitmap >> 128 : roleBitmap; + } + + /// @inheritdoc PermissionedRegistry + /// @dev Override for token-dependent logic: + /// + /// * if root and account is token owner, remap to virtual owner. + /// + function _getRoles(uint256 resource, address account) internal view override returns (uint256) { + if (resource == ROOT_RESOURCE) { + address parent = address(_parentRegistry); // virtual owner + if ( + parent != address(0) && + account == PermissionedRegistry(parent).findOwner(_childLabel) + ) { + return super._getRoles(resource, parent); // replace, instead of OR + } + } + return super._getRoles(resource, account); + } + + /// @dev Override to prevent revive if `CANNOT_CREATE_SUBDOMAIN` fuse was burned. + function _canRevive(uint256 tokenId, address sender) internal view override returns (bool) { + return + (_initialRoleBitmap & RegistryRolesLib.ROLE_REGISTRAR) != 0 && + super._canRevive(tokenId, sender); + } + + /// @dev Requires `ROLE_UPGRADE` and approval for the target implementation. + function _authorizeUpgrade(address newImplementation) + internal + view + override + onlyRootRoles(RegistryRolesLib.ROLE_UPGRADE) + { + if (!UPGRADE_GATE.approvedImplementations(newImplementation)) { + revert UpgradeTargetNotApproved(newImplementation); + } } /// @inheritdoc LockedWrapperReceiver function _getRegistry() internal view override returns (IRegistry) { return this; } + + /// @dev Determine if `label` is emancipated but not-yet migrated. + function _isMigratableChild(string memory label) internal view returns (bool) { + uint256 labelId = LibLabel.id(label); + if (getExpiry(labelId) > 0) { + return false; // has been registered before, v2 is authority + } + bytes32 node = NameCoder.namehash(_node, bytes32(labelId)); + (, uint32 fuses, ) = NAME_WRAPPER.getData(uint256(node)); + // NameWrapper preserves fuses across `_burn()`, so the PARENT_CANNOT_CONTROL + // bit stays readable after unwrap and is the primary signal. Require an + // active v1 registry owner. A null owner means the subname was ABANDONED + // and reserving the label would lock it forever; positive expiry on either + // side marks a completed migration. + return LibMigration.isEmancipatedChild(fuses) && _REGISTRY_V1.owner(node) != address(0); + } } diff --git a/contracts/src/registry/interfaces/IOwnedRegistry.sol b/contracts/src/registry/interfaces/IOwnedRegistry.sol new file mode 100755 index 000000000..2a6218377 --- /dev/null +++ b/contracts/src/registry/interfaces/IOwnedRegistry.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IRegistry} from "./IRegistry.sol"; + +/// @notice A registry with owners. +/// @dev Interface selector: `0x63560a8e` +interface IOwnedRegistry is IRegistry { + /// @notice Fetches the label owner. + /// @param label The label to query. + /// @return The owner of the label. + function findOwner(string calldata label) external view returns (address); +} diff --git a/contracts/src/registry/interfaces/IPermissionedRegistry.sol b/contracts/src/registry/interfaces/IPermissionedRegistry.sol index 38aa832dd..80e1f52c1 100644 --- a/contracts/src/registry/interfaces/IPermissionedRegistry.sol +++ b/contracts/src/registry/interfaces/IPermissionedRegistry.sol @@ -2,23 +2,24 @@ pragma solidity >=0.8.13; import {IEnhancedAccessControl} from "../../access-control/interfaces/IEnhancedAccessControl.sol"; +import {IContractNamer} from "../../reverse-registrar/interfaces/IContractNamer.sol"; import {IStandardRegistry} from "./IStandardRegistry.sol"; -/// @dev Interface selector: `0xafff3a63` -interface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl { +/// @dev Interface selector: `0x6be50c69` +interface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl, IContractNamer { //////////////////////////////////////////////////////////////////////// // Types //////////////////////////////////////////////////////////////////////// - /// @notice The registration status of a subdomain. + /// @notice The registration status of a label. enum Status { AVAILABLE, RESERVED, REGISTERED } - /// @notice The registration state of a subdomain. + /// @notice The registration state of a label. struct State { Status status; // getStatus() uint64 expiry; // getExpiry() @@ -32,14 +33,17 @@ interface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl { //////////////////////////////////////////////////////////////////////// /// @notice Associate a token with an EAC resource. + /// @param tokenId The token ID. + /// @param resource The EAC resource. event TokenResource(uint256 indexed tokenId, uint256 indexed resource); //////////////////////////////////////////////////////////////////////// // Errors //////////////////////////////////////////////////////////////////////// - /// @dev Error selector: `0xee7f75f7` - error NameAlreadyReserved(string label); + /// @notice Label cannot be reserved again. + /// @dev Error selector: `0xf60759e0` + error LabelAlreadyReserved(string label); //////////////////////////////////////////////////////////////////////// // Functions @@ -48,26 +52,31 @@ interface IPermissionedRegistry is IStandardRegistry, IEnhancedAccessControl { /// @notice Get the latest owner of a token. /// If the token was burned, returns null. /// @param tokenId The token ID to query. - /// @return The latest owner address. - function latestOwnerOf(uint256 tokenId) external view returns (address); + /// @return owner The latest owner address. + function latestOwnerOf(uint256 tokenId) external view returns (address owner); - /// @notice Get the state of a subdomain. + /// @notice Get the state of a label. /// @param anyId The labelhash, token ID, or resource. - /// @return The state of the subdomain. - function getState(uint256 anyId) external view returns (State memory); + /// @return state The state of the label. + function getState(uint256 anyId) external view returns (State memory state); /// @notice Get `Status` from `anyId`. /// @param anyId The labelhash, token ID, or resource. - /// @return The status of the subdomain. - function getStatus(uint256 anyId) external view returns (Status); + /// @return status The status of the label. + function getStatus(uint256 anyId) external view returns (Status status); /// @notice Get `resource` from `anyId`. /// @param anyId The labelhash, token ID, or resource. - /// @return The resource. - function getResource(uint256 anyId) external view returns (uint256); + /// @return resource The resource. + function getResource(uint256 anyId) external view returns (uint256 resource); /// @notice Get `tokenId` from `anyId`. /// @param anyId The labelhash, token ID, or resource. - /// @return The token ID. - function getTokenId(uint256 anyId) external view returns (uint256); + /// @return tokenId The token ID. + function getTokenId(uint256 anyId) external view returns (uint256 tokenId); + + /// @notice Get token owner from `anyId`. + /// @param anyId The labelhash, token ID, or resource. + /// @return owner The token owner. + function getOwner(uint256 anyId) external view returns (address owner); } diff --git a/contracts/src/registry/interfaces/IRegistry.sol b/contracts/src/registry/interfaces/IRegistry.sol index 839710248..eb8743f18 100644 --- a/contracts/src/registry/interfaces/IRegistry.sol +++ b/contracts/src/registry/interfaces/IRegistry.sol @@ -1,72 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; -import {IERC1155Singleton} from "../../erc1155/interfaces/IERC1155Singleton.sol"; +import {IRegistryEvents} from "./IRegistryEvents.sol"; /// @dev Interface selector: `0x51f67f40` -interface IRegistry is IERC1155Singleton { - //////////////////////////////////////////////////////////////////////// - // Events - //////////////////////////////////////////////////////////////////////// - - /// @dev A subdomain was registered. - event NameRegistered( - uint256 indexed tokenId, - bytes32 indexed labelHash, - string label, - address owner, - uint64 expiry, - address indexed sender - ); - - /// @dev A subdomain was reserved. - event NameReserved( - uint256 indexed tokenId, - bytes32 indexed labelHash, - string label, - uint64 expiry, - address indexed sender - ); - - /// @dev A subdomain was unregistered. - event NameUnregistered(uint256 indexed tokenId, address indexed sender); - - /// @notice Expiry was changed. - event ExpiryUpdated(uint256 indexed tokenId, uint64 newExpiry, address indexed sender); - - /// @notice Subregistry was changed. - event SubregistryUpdated( - uint256 indexed tokenId, - IRegistry subregistry, - address indexed sender - ); - - /// @notice Resolver was changed. - event ResolverUpdated(uint256 indexed tokenId, address resolver, address indexed sender); - - /// @notice Token was regenerated with a new token ID. - /// This occurs when roles are granted or revoked to maintain ERC1155 compliance. - event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId); - - /// @notice Parent was changed. - event ParentUpdated(IRegistry indexed parent, string label, address indexed sender); - - //////////////////////////////////////////////////////////////////////// - // Functions - //////////////////////////////////////////////////////////////////////// - - /// @dev Fetches the registry for a subdomain. +interface IRegistry is IRegistryEvents { + /// @notice Fetches the registry for a label. /// @param label The label to resolve. - /// @return The address of the registry for this subdomain, or `address(0)` if none exists. + /// @return The address of the registry for this label, or `address(0)` if none exists. function getSubregistry(string calldata label) external view returns (IRegistry); - /// @dev Fetches the resolver responsible for the specified label. + /// @notice Fetches the resolver responsible for the specified label. /// @param label The label to fetch a resolver for. - /// @return resolver The address of a resolver responsible for this name, or `address(0)` if none exists. + /// @return resolver The address of a resolver responsible for this label, or `address(0)` if none exists. function getResolver(string calldata label) external view returns (address); /// @notice Get canonical "location" of this registry. - /// /// @return parent The canonical parent of this registry. /// @return label The canonical subdomain of this registry. function getParent() external view returns (IRegistry parent, string memory label); diff --git a/contracts/src/registry/interfaces/IRegistryEvents.sol b/contracts/src/registry/interfaces/IRegistryEvents.sol new file mode 100644 index 000000000..30e83ca05 --- /dev/null +++ b/contracts/src/registry/interfaces/IRegistryEvents.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IRegistry} from "./IRegistry.sol"; + +/// @notice Events interface for the registry, following ENSIP16. +interface IRegistryEvents { + /// @notice A registry was created/initialized. + event RegistryCreated(); + + /// @notice A label was registered. + /// @param tokenId The token ID registered. + /// @param labelHash The label hash registered. + /// @param label The label registered. + /// @param owner The owner of the label. + /// @param expiry The expiry of the label. + /// @param sender The sender of the call to register. + event LabelRegistered( + uint256 indexed tokenId, + bytes32 indexed labelHash, + string label, + address owner, + uint64 expiry, + address indexed sender + ); + + /// @notice A label was reserved. + /// @param tokenId The token ID reserved. + /// @param labelHash The label hash reserved. + /// @param label The label reserved. + /// @param expiry The expiry of the label. + /// @param sender The sender of the call to reserve. + event LabelReserved( + uint256 indexed tokenId, + bytes32 indexed labelHash, + string label, + uint64 expiry, + address indexed sender + ); + + /// @notice A label was unregistered. + /// @param tokenId The token ID unregistered. + /// @param sender The sender of the call to unregister. + event LabelUnregistered(uint256 indexed tokenId, address indexed sender); + + /// @notice Expiry of label was changed. + /// @param tokenId The token ID of the label. + /// @param newExpiry The new expiry of the label. + /// @param sender The sender of the call to update the expiry. + event ExpiryUpdated(uint256 indexed tokenId, uint64 indexed newExpiry, address indexed sender); + + /// @notice Subregistry of label was changed. + /// @param tokenId The token ID of the label. + /// @param subregistry The new subregistry. + /// @param sender The sender of the call to update the subregistry. + event SubregistryUpdated( + uint256 indexed tokenId, + IRegistry indexed subregistry, + address indexed sender + ); + + /// @notice Resolver of label was changed. + /// @param tokenId The token ID of the label. + /// @param resolver The new resolver. + /// @param sender The sender of the call to update the resolver. + event ResolverUpdated( + uint256 indexed tokenId, + address indexed resolver, + address indexed sender + ); + + /// @notice URI was changed. + /// @param uri The new URI. + /// @param renderer The new render address. + /// @param sender The sender of the call to update the URI. + event URIUpdated(string uri, address renderer, address indexed sender); + + /// @notice Token was regenerated with a new token ID. + /// This occurs when roles are granted or revoked to maintain ERC1155 compliance. + /// @param oldTokenId The old token ID. + /// @param newTokenId The new token ID. + event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId); + + /// @notice Parent was changed. + /// @param parent The new parent. + /// @param label The new label. + /// @param sender The sender of the call to update the parent. + event ParentUpdated(IRegistry indexed parent, string label, address indexed sender); +} diff --git a/contracts/src/registry/interfaces/IRegistryMetadata.sol b/contracts/src/registry/interfaces/IRegistryMetadata.sol deleted file mode 100644 index 80bc98240..000000000 --- a/contracts/src/registry/interfaces/IRegistryMetadata.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -/// @notice Metadata URI generator for registries. -/// @dev Interface selector: `0x1675f455` -interface IRegistryMetadata { - /// @dev Fetches the token URI for a token ID. - /// @param tokenId The ID of the token to fetch a URI for. - /// @return The token URI for the token. - function tokenUri(uint256 tokenId) external view returns (string calldata); -} diff --git a/contracts/src/registry/interfaces/IRegistryURIRenderer.sol b/contracts/src/registry/interfaces/IRegistryURIRenderer.sol new file mode 100755 index 000000000..cd2896b1e --- /dev/null +++ b/contracts/src/registry/interfaces/IRegistryURIRenderer.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IRegistry} from "./IRegistry.sol"; + +/// @dev Interface selector: `0x6c55e19b` +interface IRegistryURIRenderer { + /// @notice Generate URI for `tokenId` from `registry`. + /// @param registry The registry. + /// @param tokenId The token ID in the registry. + /// @return The generated URI. + function renderURI(IRegistry registry, uint256 tokenId) external view returns (string memory); +} diff --git a/contracts/src/registry/interfaces/IStandardRegistry.sol b/contracts/src/registry/interfaces/IStandardRegistry.sol index 6397ecb06..dd4b775f9 100644 --- a/contracts/src/registry/interfaces/IStandardRegistry.sol +++ b/contracts/src/registry/interfaces/IStandardRegistry.sol @@ -2,30 +2,32 @@ pragma solidity >=0.8.13; import {IRegistry} from "./IRegistry.sol"; +import {ITemporalRegistry} from "./ITemporalRegistry.sol"; +import {ITokenizedRegistry} from "./ITokenizedRegistry.sol"; /// @title IStandardRegistry -/// @notice A tokenized registry. +/// @notice A tokenized registry with registrations that expire. /// @dev Interface selector: `0xb844ab6c` -interface IStandardRegistry is IRegistry { +interface IStandardRegistry is ITemporalRegistry, ITokenizedRegistry { //////////////////////////////////////////////////////////////////////// // Errors //////////////////////////////////////////////////////////////////////// - /// @notice Name is already registered. - /// @dev Error selector: `0x6dbb87d0` - error NameAlreadyRegistered(string label); + /// @notice Label is already registered. + /// @dev Error selector: `0xdef545a4` + error LabelAlreadyRegistered(string label); - /// @notice Name is expired/unregistered. - /// @dev Error selector: `0x0c23d840` - error NameExpired(uint256 tokenId); + /// @notice Label is expired/unregistered. + /// @dev Error selector: `0xc44e2374` + error LabelExpired(uint256 tokenId); - /// @notice Name expiry cannot be reduced. - /// @dev Error selector: `0x9967595a` - error CannotReduceExpiration(uint64 oldExpiration, uint64 newExpiration); + /// @notice Label expiry cannot be reduced. + /// @dev Error selector: `0x68c1425a` + error CannotReduceExpiry(uint64 oldExpiry, uint64 newExpiry); - /// @notice Name expiry cannot be before now. - /// @dev Error selector: `0x6a0147dc` - error CannotSetPastExpiration(uint64 expiry); + /// @notice Label expiry cannot be before now. + /// @dev Error selector: `0xf1d446c3` + error CannotSetPastExpiry(uint64 expiry); /// @notice Transfer is not allowed due to missing transfer admin role. /// @dev Error selector: `0xe58f6d5a` @@ -35,13 +37,13 @@ interface IStandardRegistry is IRegistry { // Functions //////////////////////////////////////////////////////////////////////// - /// @notice Registers a new name. + /// @notice Registers a new label. /// @param label The label to register. - /// @param owner The address of the owner of the name. - /// @param registry The registry to set as the name. - /// @param resolver The resolver to set for the name. - /// @param roleBitmap The role bitmap to set for the name. - /// @param expires The expiration date of the name. + /// @param owner The address of the owner of the label. + /// @param registry The registry to set as the label. + /// @param resolver The resolver to set for the label. + /// @param roleBitmap The role bitmap to set for the label. + /// @param expiry The expiry of the label, in seconds. /// @return tokenId The token ID. function register( string calldata label, @@ -49,24 +51,26 @@ interface IStandardRegistry is IRegistry { IRegistry registry, address resolver, uint256 roleBitmap, - uint64 expires - ) external returns (uint256 tokenId); + uint64 expiry + ) + external + returns (uint256 tokenId); - /// @notice Renew a subdomain. + /// @notice Renew a label. /// @param anyId The labelhash, token ID, or resource. - /// @param newExpiry The new expiration. + /// @param newExpiry The new expiry, in seconds. function renew(uint256 anyId, uint64 newExpiry) external; - /// @notice Delete a subdomain. + /// @notice Delete a label. /// @param anyId The labelhash, token ID, or resource. function unregister(uint256 anyId) external; - /// @notice Change registry of name. + /// @notice Change registry of label. /// @param anyId The labelhash, token ID, or resource. /// @param registry The new registry. function setSubregistry(uint256 anyId, IRegistry registry) external; - /// @notice Change resolver of name. + /// @notice Change resolver of label. /// @param anyId The labelhash, token ID, or resource. /// @param resolver The new resolver. function setResolver(uint256 anyId, address resolver) external; @@ -77,8 +81,8 @@ interface IStandardRegistry is IRegistry { /// @param label The canonical subdomain of this registry. function setParent(IRegistry parent, string calldata label) external; - /// @notice Get expiry of name. + /// @notice Get expiry of label. /// @param anyId The labelhash, token ID, or resource. - /// @return The expiry for name. - function getExpiry(uint256 anyId) external view returns (uint64); + /// @return expiry The expiry of the label, in seconds. + function getExpiry(uint256 anyId) external view returns (uint64 expiry); } diff --git a/contracts/src/registry/interfaces/ITemporalRegistry.sol b/contracts/src/registry/interfaces/ITemporalRegistry.sol new file mode 100755 index 000000000..de6e01a57 --- /dev/null +++ b/contracts/src/registry/interfaces/ITemporalRegistry.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IRegistry} from "./IRegistry.sol"; + +/// @notice A registry with expirations. +/// @dev Interface selector: `0x6f537c72` +interface ITemporalRegistry is IRegistry { + /// @notice Fetches the label expiry. + /// @param label The label to query. + /// @return The expiry of the label. + function findExpiry(string calldata label) external view returns (uint64); +} diff --git a/contracts/src/registry/interfaces/ITokenizedRegistry.sol b/contracts/src/registry/interfaces/ITokenizedRegistry.sol new file mode 100755 index 000000000..aa60ce11c --- /dev/null +++ b/contracts/src/registry/interfaces/ITokenizedRegistry.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IERC1155Singleton} from "../../erc1155/interfaces/IERC1155Singleton.sol"; + +import {IOwnedRegistry} from "./IOwnedRegistry.sol"; + +/// @notice A tokenized registry. +/// @dev Interface selector: `0x91b3c037` +interface ITokenizedRegistry is IOwnedRegistry, IERC1155Singleton { + /// @notice Fetches the token ID for a label. + /// @param label The label to query. + /// @return The token ID of the label. + function findTokenId(string calldata label) external view returns (uint256); +} diff --git a/contracts/src/registry/interfaces/IWrapperRegistry.sol b/contracts/src/registry/interfaces/IWrapperRegistry.sol index 5f5934d88..f6db7d492 100755 --- a/contracts/src/registry/interfaces/IWrapperRegistry.sol +++ b/contracts/src/registry/interfaces/IWrapperRegistry.sol @@ -5,24 +5,37 @@ import {IPermissionedRegistry} from "./IPermissionedRegistry.sol"; import {IRegistry} from "./IRegistry.sol"; /// @notice Interface for a registry that manages a locked NameWrapper name. -/// @dev Interface selector: `0x6b2f7339` +/// @dev Interface selector: `0xe01aaa11` interface IWrapperRegistry is IPermissionedRegistry { + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice Upgrade target is not approved for `WrapperRegistry` proxies. + /// @dev Error selector: `0xf74d7dd0` + /// @param implementation The disallowed implementation address. + error UpgradeTargetNotApproved(address implementation); + + //////////////////////////////////////////////////////////////////////// + // Functions + //////////////////////////////////////////////////////////////////////// + + /// @notice Initializes WrapperRegistry. /// @param node Namehash of this registry. /// @param parentRegistry The parent of this registry. /// @param childLabel The subdomain for this registry. - /// @param admin Address that will control this registry. - /// @param roleBitmap The roles assigned to `admin`. + /// @param roleBitmap The role bitmap granted to the virtual admin. function initialize( bytes32 node, IRegistry parentRegistry, string calldata childLabel, - address admin, uint256 roleBitmap - ) external; + ) + external; - /// @notice The DNS-encoded name for this registry. + /// @notice Returns the DNS-encoded name for this registry. function getWrappedName() external view returns (bytes memory); - /// @notice The NameWrapper node (namehash). + /// @notice Returns the NameWrapper node (namehash). function getWrappedNode() external view returns (bytes32); } diff --git a/contracts/src/registry/libraries/RegistryRolesLib.sol b/contracts/src/registry/libraries/RegistryRolesLib.sol index f8b54d420..6db55c1da 100644 --- a/contracts/src/registry/libraries/RegistryRolesLib.sol +++ b/contracts/src/registry/libraries/RegistryRolesLib.sol @@ -5,38 +5,60 @@ pragma solidity >=0.8.13; /// `EnhancedAccessControl` nybble-packed bitmap system. Each role occupies one nybble (4 bits) /// at a specific index, with its admin counterpart shifted 128 bits higher. library RegistryRolesLib { - /// @dev Nybble 0 — authorizes registering and reserving new names. Root only. + /// @dev Nybble 0: authorizes registering and reserving new names. Root only. uint256 internal constant ROLE_REGISTRAR = 1 << 0; + /// @dev Nybble 32: authorizes setting `ROLE_REGISTRAR`. uint256 internal constant ROLE_REGISTRAR_ADMIN = ROLE_REGISTRAR << 128; - /// @dev Nybble 1 — authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only. + /// @dev Nybble 1: authorizes registering a reserved name (promoting it from RESERVED to REGISTERED). Root-only. uint256 internal constant ROLE_REGISTER_RESERVED = 1 << 4; + /// @dev Nybble 33: authorizes setting `ROLE_REGISTER_RESERVED`. uint256 internal constant ROLE_REGISTER_RESERVED_ADMIN = ROLE_REGISTER_RESERVED << 128; - /// @dev Nybble 2 — authorizes setting the parent registry. Root-only. + /// @dev Nybble 2: authorizes setting the parent registry. Root-only. uint256 internal constant ROLE_SET_PARENT = 1 << 8; + /// @dev Nybble 34: authorizes setting `ROLE_SET_PARENT`. uint256 internal constant ROLE_SET_PARENT_ADMIN = ROLE_SET_PARENT << 128; - /// @dev Nybble 3 — authorizes unregistering names. Root or token. + /// @dev Nybble 3: authorizes unregistering names. Root or token. uint256 internal constant ROLE_UNREGISTER = 1 << 12; + /// @dev Nybble 35: authorizes setting `ROLE_UNREGISTER`. uint256 internal constant ROLE_UNREGISTER_ADMIN = ROLE_UNREGISTER << 128; - /// @dev Nybble 4 — authorizes extending name expiry. Root or token. + /// @dev Nybble 4: authorizes extending name expiry. Root or token. uint256 internal constant ROLE_RENEW = 1 << 16; + /// @dev Nybble 36: authorizes setting `ROLE_RENEW`. uint256 internal constant ROLE_RENEW_ADMIN = ROLE_RENEW << 128; - /// @dev Nybble 5 — authorizes changing a name's child registry. Root or token. + /// @dev Nybble 5: authorizes changing a name's child registry. Root or token. uint256 internal constant ROLE_SET_SUBREGISTRY = 1 << 20; + /// @dev Nybble 37: authorizes setting `ROLE_SET_SUBREGISTRY`. uint256 internal constant ROLE_SET_SUBREGISTRY_ADMIN = ROLE_SET_SUBREGISTRY << 128; - /// @dev Nybble 6 — authorizes changing a name's resolver. Root or token. + /// @dev Nybble 6: authorizes changing a name's resolver. Root or token. uint256 internal constant ROLE_SET_RESOLVER = 1 << 24; + /// @dev Nybble 38: authorizes setting `ROLE_SET_RESOLVER`. uint256 internal constant ROLE_SET_RESOLVER_ADMIN = ROLE_SET_RESOLVER << 128; - /// @dev Nybble 7 — admin-only, authorizes ERC1155 token transfers. Token-only. + /// @dev Nybble 39: authorizes ERC1155 token transfers. Root or token. + /// This role is only checked on the token owner, not the operator. uint256 internal constant ROLE_CAN_TRANSFER_ADMIN = (1 << 28) << 128; - /// @dev Nybble 31 — authorizes UUPS proxy upgrades. Root-only. + /// @dev Nybble 8: tags a name that was registered via `ROLE_REGISTER_RESERVED`. Token only. Not revokable. + uint256 internal constant ROLE_WAS_RESERVED = (1 << 32); + + /// @dev Nybble 9: authorizes setting the URI. Root-only. + uint256 internal constant ROLE_SET_URI = 1 << 36; + /// @dev Nybble 41: authorizes setting `ROLE_SET_URI`. + uint256 internal constant ROLE_SET_URI_ADMIN = ROLE_SET_URI << 128; + + /// @dev Nybble 30: authorizes contract naming. Root-only. + uint256 internal constant ROLE_CAN_NAME = 1 << 120; + /// @dev Nybble 62: authorizes setting ROLE_CAN_NAME. + uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128; + + /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only. uint256 internal constant ROLE_UPGRADE = 1 << 124; + /// @dev Nybble 63: authorizes setting `ROLE_UPGRADE`. uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128; } diff --git a/contracts/src/resolver/AbstractMirrorResolver.sol b/contracts/src/resolver/AbstractMirrorResolver.sol index 550a822a7..18e9e2042 100755 --- a/contracts/src/resolver/AbstractMirrorResolver.sol +++ b/contracts/src/resolver/AbstractMirrorResolver.sol @@ -10,27 +10,44 @@ import {ResolverCaller} from "@ens/contracts/universalResolver/ResolverCaller.so import {IERC7996} from "@ens/contracts/utils/IERC7996.sol"; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -/// @notice Resolver that mirrors resolution of the same name to a different registry. -abstract contract AbstractMirrorResolver is ICompositeResolver, IERC7996, ResolverCaller, ERC165 { +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; + +/// @dev Resolver that mirrors resolution of the same name to a different registry. +abstract contract AbstractMirrorResolver is + ICompositeResolver, + IERC7996, + ResolverCaller, + DelegatedContractNamer +{ //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// - /// @dev Shared batch gateway provider. + /// @notice Shared batch gateway provider. IGatewayProvider public immutable BATCH_GATEWAY_PROVIDER; //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// - constructor(IGatewayProvider batchGatewayProvider) CCIPReader(DEFAULT_UNSAFE_CALL_GAS) { + /// @param batchGatewayProvider The batch gateway provider. + /// @param contractNamer Delegated contract namer. + constructor(IGatewayProvider batchGatewayProvider, IContractNamer contractNamer) + CCIPReader(DEFAULT_UNSAFE_CALL_GAS) + DelegatedContractNamer(contractNamer) + { BATCH_GATEWAY_PROVIDER = batchGatewayProvider; } /// @inheritdoc ERC165 - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165) returns (bool) { + function supportsInterface(bytes4 interfaceId) + public + view + virtual + override(DelegatedContractNamer) + returns (bool) + { return type(IExtendedResolver).interfaceId == interfaceId || type(ICompositeResolver).interfaceId == interfaceId || @@ -48,10 +65,7 @@ abstract contract AbstractMirrorResolver is ICompositeResolver, IERC7996, Resolv //////////////////////////////////////////////////////////////////////// /// @inheritdoc IExtendedResolver - function resolve( - bytes calldata name, - bytes calldata data - ) external view returns (bytes memory) { + function resolve(bytes calldata name, bytes calldata data) external view returns (bytes memory) { callResolver(_findResolver(name), name, data, false, "", BATCH_GATEWAY_PROVIDER.gateways()); } @@ -60,11 +74,6 @@ abstract contract AbstractMirrorResolver is ICompositeResolver, IERC7996, Resolv return (_findResolver(name), false); } - /// @inheritdoc ICompositeResolver - function requiresOffchain(bytes calldata) external pure returns (bool) { - return false; - } - //////////////////////////////////////////////////////////////////////// // Internal Functions //////////////////////////////////////////////////////////////////////// diff --git a/contracts/src/resolver/DOSResolver.sol b/contracts/src/resolver/DOSResolver.sol deleted file mode 100644 index feacc7c84..000000000 --- a/contracts/src/resolver/DOSResolver.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import {IGatewayProvider} from "@ens/contracts/ccipRead/IGatewayProvider.sol"; - -import {IRegistry} from "../registry/interfaces/IRegistry.sol"; -import {LibRegistry} from "../universalResolver/libraries/LibRegistry.sol"; - -import {AbstractMirrorResolver} from "./AbstractMirrorResolver.sol"; - -/// @notice Resolver that performs resolutions using the DOS Name Service (ENSv2-based). -contract DOSResolver is AbstractMirrorResolver { - //////////////////////////////////////////////////////////////////////// - // Constants - //////////////////////////////////////////////////////////////////////// - - /// @dev The root registry used to traverse the registry hierarchy and locate resolvers. - IRegistry public immutable ROOT_REGISTRY; - - //////////////////////////////////////////////////////////////////////// - // Initialization - //////////////////////////////////////////////////////////////////////// - - constructor( - IRegistry rootRegistry, - IGatewayProvider batchGatewayProvider - ) AbstractMirrorResolver(batchGatewayProvider) { - ROOT_REGISTRY = rootRegistry; - } - - //////////////////////////////////////////////////////////////////////// - // Internal Functions - //////////////////////////////////////////////////////////////////////// - - /// @inheritdoc AbstractMirrorResolver - function _findResolver(bytes calldata name) internal view override returns (address resolver) { - (, resolver, , ) = LibRegistry.findResolver(ROOT_REGISTRY, name, 0); - } -} diff --git a/contracts/src/resolver/ENSV1Resolver.sol b/contracts/src/resolver/ENSV1Resolver.sol index a8e8cab3b..b43605866 100644 --- a/contracts/src/resolver/ENSV1Resolver.sol +++ b/contracts/src/resolver/ENSV1Resolver.sol @@ -2,27 +2,32 @@ pragma solidity >=0.8.13; import {IGatewayProvider} from "@ens/contracts/ccipRead/IGatewayProvider.sol"; -import {RegistryUtils, ENS} from "@ens/contracts/universalResolver/RegistryUtils.sol"; +import {ENS} from "@ens/contracts/registry/ENS.sol"; +import {RegistryUtils} from "@ens/contracts/universalResolver/RegistryUtils.sol"; + +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; import {AbstractMirrorResolver} from "./AbstractMirrorResolver.sol"; /// @notice Resolver that performs resolutions using ENSv1. contract ENSV1Resolver is AbstractMirrorResolver { //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// - /// @dev The ENSv1 registry used to look up resolvers for names. + /// @notice The ENSv1 registry used to look up resolvers for names. ENS public immutable REGISTRY_V1; //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// - constructor( - ENS registryV1, - IGatewayProvider batchGatewayProvider - ) AbstractMirrorResolver(batchGatewayProvider) { + /// @param batchGatewayProvider The batch gateway provider. + /// @param contractNamer Delegated contract namer. + /// @param registryV1 The ENSv1 registry. + constructor(IGatewayProvider batchGatewayProvider, IContractNamer contractNamer, ENS registryV1) + AbstractMirrorResolver(batchGatewayProvider, contractNamer) + { REGISTRY_V1 = registryV1; } diff --git a/contracts/src/resolver/ENSV2Resolver.sol b/contracts/src/resolver/ENSV2Resolver.sol index 882660166..d21bd927c 100755 --- a/contracts/src/resolver/ENSV2Resolver.sol +++ b/contracts/src/resolver/ENSV2Resolver.sol @@ -2,30 +2,44 @@ pragma solidity >=0.8.13; import {IGatewayProvider} from "@ens/contracts/ccipRead/IGatewayProvider.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; -import {IRegistry} from "../registry/interfaces/IRegistry.sol"; +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; import {LibRegistry} from "../universalResolver/libraries/LibRegistry.sol"; import {AbstractMirrorResolver} from "./AbstractMirrorResolver.sol"; -/// @notice Resolver that performs resolutions using ENSv2. +/// @notice Resolver that performs resolutions using ENSv2 with override for ENSv1 "eth" resolver. contract ENSV2Resolver is AbstractMirrorResolver { //////////////////////////////////////////////////////////////////////// - // Constants + // Immutables //////////////////////////////////////////////////////////////////////// - /// @dev The ENS v2 root registry used to traverse the registry hierarchy and locate resolvers. - IRegistry public immutable ROOT_REGISTRY; + /// @notice The ENSv2 root registry used to traverse the registry hierarchy and locate resolvers. + IPermissionedRegistry public immutable ROOT_REGISTRY; + + /// @notice The ENSv1 resolver for "eth". + address public immutable ETH_RESOLVER; //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// + /// @param batchGatewayProvider The batch gateway provider. + /// @param contractNamer Delegated contract namer. + /// @param rootRegistry The ENSv2 root registry. + /// @param ethResolver The override resolver for "eth" or null to use ENSv2. constructor( - IRegistry rootRegistry, - IGatewayProvider batchGatewayProvider - ) AbstractMirrorResolver(batchGatewayProvider) { + IGatewayProvider batchGatewayProvider, + IContractNamer contractNamer, + IPermissionedRegistry rootRegistry, + address ethResolver + ) + AbstractMirrorResolver(batchGatewayProvider, contractNamer) + { ROOT_REGISTRY = rootRegistry; + ETH_RESOLVER = ethResolver; } //////////////////////////////////////////////////////////////////////// @@ -34,6 +48,10 @@ contract ENSV2Resolver is AbstractMirrorResolver { /// @inheritdoc AbstractMirrorResolver function _findResolver(bytes calldata name) internal view override returns (address resolver) { - (, resolver, , ) = LibRegistry.findResolver(ROOT_REGISTRY, name, 0); + bytes32 node; + (, resolver, node, ) = LibRegistry.findResolver(ROOT_REGISTRY, name, 0); + if (node == NameCoder.ETH_NODE && address(ETH_RESOLVER) != address(0)) { + resolver = ETH_RESOLVER; + } } } diff --git a/contracts/src/resolver/PermissionedResolver.sol b/contracts/src/resolver/PermissionedResolver.sol index 015587412..949aca41f 100644 --- a/contracts/src/resolver/PermissionedResolver.sol +++ b/contracts/src/resolver/PermissionedResolver.sol @@ -6,6 +6,7 @@ import {IABIResolver} from "@ens/contracts/resolvers/profiles/IABIResolver.sol"; import {IAddressResolver} from "@ens/contracts/resolvers/profiles/IAddressResolver.sol"; import {IAddrResolver} from "@ens/contracts/resolvers/profiles/IAddrResolver.sol"; import {IContentHashResolver} from "@ens/contracts/resolvers/profiles/IContentHashResolver.sol"; +import {IDataResolver} from "@ens/contracts/resolvers/profiles/IDataResolver.sol"; import {IExtendedResolver} from "@ens/contracts/resolvers/profiles/IExtendedResolver.sol"; import {IHasAddressResolver} from "@ens/contracts/resolvers/profiles/IHasAddressResolver.sol"; import {IInterfaceResolver} from "@ens/contracts/resolvers/profiles/IInterfaceResolver.sol"; @@ -17,22 +18,35 @@ import {ResolverFeatures} from "@ens/contracts/resolvers/ResolverFeatures.sol"; import {ENSIP19, COIN_TYPE_ETH, COIN_TYPE_DEFAULT} from "@ens/contracts/utils/ENSIP19.sol"; import {IERC7996} from "@ens/contracts/utils/IERC7996.sol"; import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {IProxyAuthorization} from "@ensdomains/verifiable-factory/IProxyAuthorization.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import {EnhancedAccessControl} from "../access-control/EnhancedAccessControl.sol"; -import {InvalidOwner} from "../CommonErrors.sol"; -import {HCAContext} from "../hca/HCAContext.sol"; -import {HCAContextUpgradeable} from "../hca/HCAContextUpgradeable.sol"; -import {HCAEquivalence} from "../hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "../hca/interfaces/IHCAFactoryBasic.sol"; +import {IEnhancedAccessControl} from "../access-control/interfaces/IEnhancedAccessControl.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {IPermissionedResolver} from "./interfaces/IPermissionedResolver.sol"; import {PermissionedResolverLib} from "./libraries/PermissionedResolverLib.sol"; import {ResolverProfileRewriterLib} from "./libraries/ResolverProfileRewriterLib.sol"; -/// @notice An owned resolver that supports multiple names, internal aliasing, and fine-grained permissions. +/// @notice A resolver that supports many profiles, multiple names, internal aliasing, and fine-grained permissions. +/// +/// Supported profiles and standards: +/// +/// - ENSIP-1 / EIP-137: addr() +/// - ENSIP-3 / EIP-181: name() +/// - ENSIP-4 / EIP-205: ABI() +/// - EIP-619: pubkey() +/// - ENSIP-5 / EIP-634: text(key) +/// - ENSIP-7 / EIP-1577: contenthash() +/// - ENSIP-8: interfaceImplementer() +/// - ENSIP-9 / EIP-2304: addr(coinType) +/// - ENSIP-19: addr(default) +/// - ENSIP-24: data(key) +/// - IERC7996: supportsFeature() +/// - IVersionableResolver: version() +/// - IHasAddrResolver: hasAddr() /// /// Internal Aliasing: /// @@ -50,11 +64,18 @@ import {ResolverProfileRewriterLib} from "./libraries/ResolverProfileRewriterLib /// /// Fine-grained Permissions: /// -/// `setText(key)` can be restricted to a key using: `part = textPart()`. -/// `setAddr(coinType)` can be restricted to a coinType using: `part = addrPart()`. +/// * `setText(key)` can be permissioned with `authorizeTextRoles()` +/// - caller requires `ROLE_SET_TEXT_ADMIN` on `resource(, 0)` +/// - `ROLE_SET_TEXT` is authorized on `resource(, )` +/// * `setData(key)` can be permissioned with `authorizeDataRoles()` +/// - caller requires `ROLE_SET_DATA_ADMIN` on `resource(, 0)` +/// - `ROLE_SET_DATA` is authorized on `resource(, )` +/// * `setAddr(coinType)` can be permissioned with `authorizeAddrRoles()` +/// - caller requires `ROLE_SET_ADDR_ADMIN` on `resource(, 0)` +/// - `ROLE_SET_ADDR` is authorized on `resource(, )` /// /// Setters with `node` check (4) EAC resources: -/// Parts +/// Parts /// Resources +-----------------------------+------------------------------+ /// | Any (*) | Specific (1) | /// +--------------+-----------------------------+------------------------------+ @@ -64,39 +85,67 @@ import {ResolverProfileRewriterLib} from "./libraries/ResolverProfileRewriterLib /// +--------------+-----------------------------+------------------------------+ /// contract PermissionedResolver is - HCAContextUpgradeable, + IPermissionedResolver, UUPSUpgradeable, EnhancedAccessControl, IERC7996, - IExtendedResolver, IMulticallable, IABIResolver, IAddrResolver, IAddressResolver, IContentHashResolver, + IDataResolver, IHasAddressResolver, IInterfaceResolver, INameResolver, IPubkeyResolver, ITextResolver, - IVersionableResolver + IVersionableResolver, + IProxyAuthorization, + IContractNamer { //////////////////////////////////////////////////////////////////////// - // Events + // Types //////////////////////////////////////////////////////////////////////// - /// @notice Alias was changed. - event AliasChanged( - bytes indexed indexedFromName, - bytes indexed indexedToName, - bytes fromName, - bytes toName - ); + struct Record { + bytes contenthash; + bytes32[2] pubkey; + string name; + mapping(uint256 coinType => bytes addressBytes) addresses; + mapping(string key => string value) texts; + mapping(string key => bytes value) datas; + mapping(uint256 contentType => bytes value) abis; + mapping(bytes4 interfaceId => address implementer) interfaces; + } + + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// + + /// @dev Aliases for names. + mapping(bytes32 node => bytes name) internal _aliases; + + /// @dev Versions for nodes. + mapping(bytes32 node => uint64 version) internal _versions; + + /// @dev Records for nodes. + mapping(bytes32 node => mapping(uint64 version => Record)) internal _records; + + //////////////////////////////////////////////////////////////////////// + // Events + //////////////////////////////////////////////////////////////////////// /// @notice Associate an EAC resource with a name. + /// @param resource The EAC resource. + /// @param name The name. event NamedResource(uint256 indexed resource, bytes name); /// @notice Associate an EAC resource with a name and specific `text(key)` record. + /// @param resource The EAC resource. + /// @param name The name. + /// @param keyHash The hash of the key. + /// @param key The key. event NamedTextResource( uint256 indexed resource, bytes name, @@ -104,36 +153,35 @@ contract PermissionedResolver is string key ); + /// @notice Associate an EAC resource with a name and specific `data(key)` record. + /// @param resource The EAC resource. + /// @param name The name. + /// @param keyHash The hash of the key. + /// @param key The key. + event NamedDataResource( + uint256 indexed resource, + bytes name, + bytes32 indexed keyHash, + string key + ); + /// @notice Associate an EAC resource with a name and specific `addr(coinType)` record. + /// @param resource The EAC resource. + /// @param name The name. + /// @param coinType The coin type. event NamedAddrResource(uint256 indexed resource, bytes name, uint256 indexed coinType); - //////////////////////////////////////////////////////////////////////// - // Errors - //////////////////////////////////////////////////////////////////////// - - /// @notice The resolver profile cannot be answered. - /// @dev Error selector: `0x7b1c461b` - error UnsupportedResolverProfile(bytes4 selector); - - /// @notice The address could not be converted to `address`. - /// @dev Error selector: `0x8d666f60` - error InvalidEVMAddress(bytes addressBytes); - - /// @notice The content type is not a power of 2. - /// @dev Error selector: `0x5742bb26` - error InvalidContentType(uint256 contentType); - //////////////////////////////////////////////////////////////////////// // Modifiers //////////////////////////////////////////////////////////////////////// modifier onlyPartRoles(bytes32 node, bytes32 part, uint256 roleBitmap) { - address sender = _msgSender(); if ( - !hasRoles(PermissionedResolverLib.resource(node, part), roleBitmap, sender) && - !hasRoles(PermissionedResolverLib.resource(0, part), roleBitmap, sender) + part == bytes32(0) || + (!hasRoles(PermissionedResolverLib.resource(node, part), roleBitmap, msg.sender) && + !hasRoles(PermissionedResolverLib.resource(0, part), roleBitmap, msg.sender)) ) { - _checkRoles(PermissionedResolverLib.resource(node, 0), roleBitmap, sender); // reverts using "widest" resource + _checkRoles(PermissionedResolverLib.resource(node, 0), roleBitmap, msg.sender); // reverts using "widest" resource } _; } @@ -142,15 +190,21 @@ contract PermissionedResolver is // Initialization //////////////////////////////////////////////////////////////////////// - constructor(IHCAFactoryBasic hcaFactory) HCAEquivalence(hcaFactory) { + /// @param namer The implementation namer. + constructor(address namer) { + _grantRoles( + ROOT_RESOURCE, + PermissionedResolverLib.ROLE_CAN_NAME | PermissionedResolverLib.ROLE_CAN_NAME_ADMIN, + namer, + false + ); _disableInitializers(); } /// @inheritdoc EnhancedAccessControl - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(EnhancedAccessControl) returns (bool) { + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return + type(IPermissionedResolver).interfaceId == interfaceId || type(IExtendedResolver).interfaceId == interfaceId || type(IERC7996).interfaceId == interfaceId || type(IMulticallable).interfaceId == interfaceId || @@ -158,6 +212,7 @@ contract PermissionedResolver is type(IAddrResolver).interfaceId == interfaceId || type(IAddressResolver).interfaceId == interfaceId || type(IContentHashResolver).interfaceId == interfaceId || + type(IDataResolver).interfaceId == interfaceId || type(IHasAddressResolver).interfaceId == interfaceId || type(IInterfaceResolver).interfaceId == interfaceId || type(INameResolver).interfaceId == interfaceId || @@ -165,6 +220,8 @@ contract PermissionedResolver is type(ITextResolver).interfaceId == interfaceId || type(IVersionableResolver).interfaceId == interfaceId || type(UUPSUpgradeable).interfaceId == interfaceId || + type(IProxyAuthorization).interfaceId == interfaceId || + type(IContractNamer).interfaceId == interfaceId || super.supportsInterface(interfaceId); } @@ -173,120 +230,180 @@ contract PermissionedResolver is return ResolverFeatures.RESOLVE_MULTICALL == feature; } - //////////////////////////////////////////////////////////////////////// - // Implementation - //////////////////////////////////////////////////////////////////////// - - /// @notice Initialize the contract. - /// - /// @param admin The resolver owner. - /// @param roleBitmap The roles granted to `admin`. - function initialize(address admin, uint256 roleBitmap) external initializer { - if (admin == address(0)) { - revert InvalidOwner(); - } + /// @inheritdoc IPermissionedResolver + function initialize(address admin, uint256 roleBitmap, bytes[] calldata setters) + external + initializer + { __UUPSUpgradeable_init(); _grantRoles(ROOT_RESOURCE, roleBitmap, admin, false); + multicall(setters); } + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + /// @notice Clear all records for `node`. - /// /// @param node The node to update. - function clearRecords( - bytes32 node - ) external onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_CLEAR) { - uint64 version = ++_storage().versions[node]; + function clearRecords(bytes32 node) + external + onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_CLEAR) + { + uint64 version = ++_versions[node]; emit VersionChanged(node, version); } - /// @notice Create an alias from `fromName` to `toName`. - /// - /// @param fromName The source DNS-encoded name. - /// @param toName The destination DNS-encoded name. - function setAlias( - bytes calldata fromName, - bytes calldata toName - ) external onlyRootRoles(PermissionedResolverLib.ROLE_SET_ALIAS) { - _storage().aliases[NameCoder.namehash(fromName, 0)] = toName; + /// @inheritdoc IPermissionedResolver + function setAlias(bytes calldata fromName, bytes calldata toName) + external + onlyRootRoles(PermissionedResolverLib.ROLE_SET_ALIAS) + { + _aliases[NameCoder.namehash(fromName, 0)] = toName; emit AliasChanged(fromName, toName, fromName, toName); } - /// @notice Grant `roleBitmap` permissions to `account` for `toName`. + /// @notice Authorize `roleBitmap` permissions to `account` for `toName`. /// Use `NameCoder.encode("")` for any name, which is equivalent to `grantRootRoles()`. - function grantNameRoles( + /// @param toName The name to authorize roles for. + /// @param roleBitmap The roles to authorize. + /// @param account The account to authorize roles to. + /// @param grant If `true`, grants, otherwise, revokes. + /// @return success Whether the roles were updated. + function authorizeNameRoles( bytes calldata toName, uint256 roleBitmap, - address account - ) external returns (bool) { + address account, + bool grant + ) + external + returns (bool) + { bytes32 node = NameCoder.namehash(toName, 0); uint256 resource = PermissionedResolverLib.resource(node, 0); - _checkCanGrantRoles(resource, roleBitmap, _msgSender()); - emit NamedResource(resource, toName); - return _grantRoles(resource, roleBitmap, account, true); + if (grant) { + _checkCanGrantRoles(resource, roleBitmap, msg.sender); + if (resource != ROOT_RESOURCE && roleCount(resource) == 0) { + emit NamedResource(resource, toName); + } + return _grantRoles(resource, roleBitmap, account, true); + } else { + _checkCanRevokeRoles(resource, roleBitmap, msg.sender); + return _revokeRoles(resource, roleBitmap, account, true); + } } - /// @notice Grant `setText(key)` permission to `account` for `toName`. + /// @notice Authorize `setText(key)` permission to `account` for `toName`. /// Use `NameCoder.encode("")` for any name. - function grantTextRoles( + /// @param toName The name to authorize roles for. + /// @param key The text key to authorize roles for. + /// @param account The account to authorize roles to. + /// @param grant If `true`, grants, otherwise, revokes. + /// @return `true` if the roles were updated. + function authorizeTextRoles( bytes calldata toName, string calldata key, - address account - ) external returns (bool) { + address account, + bool grant + ) + external + returns (bool) + { bytes32 node = NameCoder.namehash(toName, 0); - _checkCanGrantRoles( - PermissionedResolverLib.resource(node, 0), - PermissionedResolverLib.ROLE_SET_TEXT, - _msgSender() - ); - uint256 resource = PermissionedResolverLib.resource( - node, - PermissionedResolverLib.textPart(key) - ); - emit NamedTextResource(resource, toName, keccak256(bytes(key)), key); - return _grantRoles(resource, PermissionedResolverLib.ROLE_SET_TEXT, account, true); + uint256 roleBit = PermissionedResolverLib.ROLE_SET_TEXT; + uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0)); + uint256 partResource = + PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(key)); + if (grant) { + _checkCanGrantRoles(nodeResource, roleBit, msg.sender); + if (roleCount(partResource) == 0) { + emit NamedTextResource(partResource, toName, keccak256(bytes(key)), key); + } + return _grantRoles(partResource, roleBit, account, true); + } else { + _checkCanRevokeRoles(nodeResource, roleBit, msg.sender); + return _revokeRoles(partResource, roleBit, account, true); + } } - /// @notice Grant `setAddr(coinType)` permission to `account` for `toName`. + /// @notice Authorize `setData(key)` permission to `account` for `toName`. /// Use `NameCoder.encode("")` for any name. - function grantAddrRoles( + /// @param toName The name to authorize roles for. + /// @param key The data key to authorize roles for. + /// @param account The account to authorize roles to. + /// @param grant If `true`, grants, otherwise, revokes. + /// @return `true` if the roles were updated. + function authorizeDataRoles( bytes calldata toName, - uint256 coinType, - address account - ) external returns (bool) { + string calldata key, + address account, + bool grant + ) + external + returns (bool) + { bytes32 node = NameCoder.namehash(toName, 0); - _checkCanGrantRoles( - PermissionedResolverLib.resource(node, 0), - PermissionedResolverLib.ROLE_SET_ADDR, - _msgSender() - ); - uint256 resource = PermissionedResolverLib.resource( - node, - PermissionedResolverLib.addrPart(coinType) - ); - emit NamedAddrResource(resource, toName, coinType); - return _grantRoles(resource, PermissionedResolverLib.ROLE_SET_ADDR, account, true); + uint256 roleBit = PermissionedResolverLib.ROLE_SET_DATA; + uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0)); + uint256 partResource = + PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(key)); + if (grant) { + _checkCanGrantRoles(nodeResource, roleBit, msg.sender); + if (roleCount(partResource) == 0) { + emit NamedDataResource(partResource, toName, keccak256(bytes(key)), key); + } + return _grantRoles(partResource, roleBit, account, true); + } else { + _checkCanRevokeRoles(nodeResource, roleBit, msg.sender); + return _revokeRoles(partResource, roleBit, account, true); + } + } + + /// @notice Authorize `setAddr(coinType)` permission to `account` for `toName`. + /// Use `NameCoder.encode("")` for any name. + /// @param toName The name to authorize roles for. + /// @param coinType The coin type to authorize roles for. + /// @param account The account to authorize roles to. + /// @param grant If `true`, grants, otherwise, revokes. + /// @return updated `true` if the roles were updated. + function authorizeAddrRoles(bytes calldata toName, uint256 coinType, address account, bool grant) + external + returns (bool updated) + { + bytes32 node = NameCoder.namehash(toName, 0); + uint256 roleBit = PermissionedResolverLib.ROLE_SET_ADDR; + uint256 nodeResource = PermissionedResolverLib.resource(node, bytes32(0)); + uint256 partResource = + PermissionedResolverLib.resource(node, PermissionedResolverLib.partHash(coinType)); + if (grant) { + _checkCanGrantRoles(nodeResource, roleBit, msg.sender); + if (roleCount(partResource) == 0) { + emit NamedAddrResource(partResource, toName, coinType); + } + return _grantRoles(partResource, roleBit, account, true); + } else { + _checkCanRevokeRoles(nodeResource, roleBit, msg.sender); + return _revokeRoles(partResource, roleBit, account, true); + } } /// @notice Set ABI data of the associated ENS node. - /// /// @param node The node to update. /// @param contentType The content type of the ABI. - /// @param data The ABI data. - function setABI( - bytes32 node, - uint256 contentType, - bytes calldata data - ) external onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_ABI) { + /// @param value The ABI data. + function setABI(bytes32 node, uint256 contentType, bytes calldata value) + external + onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_ABI) + { if (!_isPowerOf2(contentType)) { revert InvalidContentType(contentType); } - _record(node).abis[contentType] = data; + _record(node).abis[contentType] = value; emit ABIChanged(node, contentType); } /// @notice Set Ethereum mainnet address of the associated ENS node. /// `address(0)` is stored as `new bytes(20)`. - /// /// @param node The node to update. /// @param addr_ The mainnet address. function setAddr(bytes32 node, address addr_) external { @@ -294,71 +411,76 @@ contract PermissionedResolver is } /// @notice Set the contenthash of the associated ENS node. - /// /// @param node The node to update. /// @param hash The contenthash to set. - function setContenthash( - bytes32 node, - bytes calldata hash - ) external onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_CONTENTHASH) { + function setContenthash(bytes32 node, bytes calldata hash) + external + onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_CONTENTHASH) + { _record(node).contenthash = hash; emit ContenthashChanged(node, hash); } + /// @notice Set the data for `key` of the associated ENS node. + /// @param node The node to update. + /// @param key The data key. + /// @param value The data value. + function setData(bytes32 node, string calldata key, bytes calldata value) + external + onlyPartRoles( + node, + PermissionedResolverLib.partHash(key), + PermissionedResolverLib.ROLE_SET_DATA + ) + { + _record(node).datas[key] = value; + emit DataChanged(node, key, key, value); + } + /// @notice Set an interface of the associated ENS node. - /// /// @param node The node to update. /// @param interfaceId The EIP-165 interface ID. /// @param implementer The address of the contract that implements this interface for this node. - function setInterface( - bytes32 node, - bytes4 interfaceId, - address implementer - ) external onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_INTERFACE) { + function setInterface(bytes32 node, bytes4 interfaceId, address implementer) + external + onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_INTERFACE) + { _record(node).interfaces[interfaceId] = implementer; emit InterfaceChanged(node, interfaceId, implementer); } /// @notice Set the SECP256k1 public key associated with an ENS node. - /// /// @param node The node to update. /// @param x The x coordinate of the public key. /// @param y The y coordinate of the public key. - function setPubkey( - bytes32 node, - bytes32 x, - bytes32 y - ) external onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_PUBKEY) { + function setPubkey(bytes32 node, bytes32 x, bytes32 y) + external + onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_PUBKEY) + { _record(node).pubkey = [x, y]; emit PubkeyChanged(node, x, y); } /// @notice Set the name of the associated ENS node. - /// /// @param node The node to update. /// @param primary The primary name. - function setName( - bytes32 node, - string calldata primary - ) external onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_NAME) { + function setName(bytes32 node, string calldata primary) + external + onlyPartRoles(node, 0, PermissionedResolverLib.ROLE_SET_NAME) + { _record(node).name = primary; emit NameChanged(node, primary); } /// @notice Set the text for `key` of the associated ENS node. - /// /// @param node The node to update. /// @param key The text key. /// @param value The text value. - function setText( - bytes32 node, - string calldata key, - string calldata value - ) + function setText(bytes32 node, string calldata key, string calldata value) external onlyPartRoles( node, - PermissionedResolverLib.textPart(key), + PermissionedResolverLib.partHash(key), PermissionedResolverLib.ROLE_SET_TEXT ) { @@ -369,23 +491,31 @@ contract PermissionedResolver is /// @notice Same as `multicall()`. /// @dev The node parameter is accepted for interface compatibility but is not used. /// Permission checking is handled by individual function calls within the multicall. + /// @param {node} Ignored, for interface compatibility. + /// @param calls The calls to make. + /// @return results The results of the calls. function multicallWithNodeCheck( - bytes32, + bytes32 /* node */, bytes[] calldata calls - ) external returns (bytes[] memory) { + ) + external + returns (bytes[] memory) + { return multicall(calls); } /// @inheritdoc IExtendedResolver - function resolve( - bytes calldata fromName, - bytes calldata fromData - ) external view returns (bytes memory) { + function resolve(bytes calldata fromName, bytes calldata fromData) + external + view + returns (bytes memory) + { bytes memory toName = getAlias(fromName); - bytes memory toData = ResolverProfileRewriterLib.replaceNode( - fromData, - NameCoder.namehash(toName.length == 0 ? fromName : toName, 0) // always rewrite node - ); + bytes memory toData = + ResolverProfileRewriterLib.replaceNode( + fromData, + NameCoder.namehash(toName.length == 0 ? fromName : toName, 0) // always rewrite node + ); if (bytes4(toData) == IMulticallable.multicall.selector) { // note: cannot staticcall multicall() because it reverts with first error assembly { @@ -415,25 +545,30 @@ contract PermissionedResolver is } } + /// @inheritdoc IContractNamer + function isContractNamer(address namer) external view returns (bool) { + return hasRootRoles(PermissionedResolverLib.ROLE_CAN_NAME, namer); + } + /// @notice Get the current version. - /// /// @param node The node to check. + /// @return version The current version. function recordVersions(bytes32 node) external view returns (uint64) { - return _storage().versions[node]; + return _versions[node]; } /// @inheritdoc IABIResolver - // solhint-disable-next-line func-name-mixedcase - function ABI( - bytes32 node, - uint256 contentTypes - ) external view returns (uint256 contentType, bytes memory data) { - PermissionedResolverLib.Record storage R = _record(node); + function ABI(bytes32 node, uint256 contentTypes) + external + view + returns (uint256 contentType, bytes memory value) + { + Record storage r = _record(node); for (contentType = 1; contentType > 0 && contentType <= contentTypes; contentType <<= 1) { if ((contentType & contentTypes) != 0) { - data = R.abis[contentType]; - if (data.length > 0) { - return (contentType, data); + value = r.abis[contentType]; + if (value.length > 0) { + return (contentType, value); } } } @@ -450,14 +585,23 @@ contract PermissionedResolver is return _record(node).contenthash; } + /// @inheritdoc IDataResolver + function data(bytes32 node, string calldata key) external view returns (bytes memory) { + return _record(node).datas[key]; + } + /// @inheritdoc IInterfaceResolver - function interfaceImplementer( - bytes32 node, - bytes4 interfaceId - ) external view returns (address implementer) { + function interfaceImplementer(bytes32 node, bytes4 interfaceId) + external + view + returns (address implementer) + { implementer = _record(node).interfaces[interfaceId]; - if (implementer == address(0) && ERC165Checker.supportsInterface(addr(node), interfaceId)) { - implementer = address(this); + if (implementer == address(0)) { + address pointer = addr(node); + if (ERC165Checker.supportsInterface(pointer, interfaceId)) { + implementer = pointer; + } } } @@ -468,9 +612,9 @@ contract PermissionedResolver is /// @inheritdoc IPubkeyResolver function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y) { - PermissionedResolverLib.Record storage R = _record(node); - x = R.pubkey[0]; - y = R.pubkey[1]; + Record storage r = _record(node); + x = r.pubkey[0]; + y = r.pubkey[1]; } /// @inheritdoc ITextResolver @@ -478,8 +622,27 @@ contract PermissionedResolver is return _record(node).texts[key]; } + /// @notice Declares this implementation as an eligible verifiable proxy upgrade target. + /// @dev Upgrade authorization is still enforced by the current implementation during the UUPS + /// upgrade call. + /// @param {previousImplementation} Ignored. + /// @return allowed Always `true` for implementations in this resolver family. + function canUpgradeFrom( + address /* previousImplementation */ + ) + external + pure + virtual + override + returns (bool allowed) + { + return true; + } + /// @notice Perform multiple write operations. /// @dev Reverts with first error. + /// @param calls The calls to make. + /// @return results The results of the calls. function multicall(bytes[] calldata calls) public returns (bytes[] memory results) { results = new bytes[](calls.length); for (uint256 i; i < calls.length; ++i) { @@ -496,19 +659,14 @@ contract PermissionedResolver is /// @notice Set the address for `coinType` of the associated ENS node. /// Reverts `InvalidEVMAddress` if coin type is EVM and not 0 or 20 bytes. - /// /// @param node The node to update. /// @param coinType The coin type. /// @param addressBytes The encoded address. - function setAddr( - bytes32 node, - uint256 coinType, - bytes memory addressBytes - ) + function setAddr(bytes32 node, uint256 coinType, bytes memory addressBytes) public onlyPartRoles( node, - PermissionedResolverLib.addrPart(coinType), + PermissionedResolverLib.partHash(coinType), PermissionedResolverLib.ROLE_SET_ADDR ) { @@ -526,10 +684,10 @@ contract PermissionedResolver is /// @inheritdoc IAddressResolver function addr(bytes32 node, uint256 coinType) public view returns (bytes memory addressBytes) { - PermissionedResolverLib.Record storage R = _record(node); - addressBytes = R.addresses[coinType]; + Record storage r = _record(node); + addressBytes = r.addresses[coinType]; if (addressBytes.length == 0 && ENSIP19.chainFromCoinType(coinType) > 0) { - addressBytes = R.addresses[COIN_TYPE_DEFAULT]; + addressBytes = r.addresses[COIN_TYPE_DEFAULT]; } } @@ -538,94 +696,97 @@ contract PermissionedResolver is return payable(address(bytes20(addr(node, COIN_TYPE_ETH)))); } - /// @notice Determine which name is queried when `fromName` is resolved. - /// - /// @param fromName The source DNS-encoded name. - /// - /// @return toName The destination DNS-encoded name or empty if not aliased. + /// @inheritdoc IPermissionedResolver function getAlias(bytes memory fromName) public view returns (bytes memory toName) { bytes32 prev; for (;;) { bytes memory matchName; (matchName, fromName) = _resolveAlias(fromName); - if (fromName.length == 0) break; // no alias + if (fromName.length == 0) + break; // no alias bytes32 next = keccak256(matchName); - if (next == prev) break; // same alias + if (next == prev) + break; // same alias toName = fromName; prev = next; } } - /// @notice Function is disabled. Use `grant(Name|Text|Addr)Roles()` instead. - function grantRoles( - uint256 resource, - uint256 roleBitmap, - address account - ) public pure override returns (bool) { + /// @notice Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead. + /// @param resource Ignored. + /// @param roleBitmap Ignored. + /// @param account Ignored. + /// @return success Ignored, always reverts. + function grantRoles(uint256 resource, uint256 roleBitmap, address account) + public + pure + override(EnhancedAccessControl, IEnhancedAccessControl) + returns (bool) + { revert EACCannotGrantRoles(resource, roleBitmap, account); } + /// @notice Function is disabled. Use `authorize(Name|Text|Addr)Roles()` instead. + /// @param resource Ignored. + /// @param roleBitmap Ignored. + /// @param account Ignored. + /// @return success Ignored, always reverts. + function revokeRoles(uint256 resource, uint256 roleBitmap, address account) + public + pure + override(EnhancedAccessControl, IEnhancedAccessControl) + returns (bool) + { + revert EACCannotRevokeRoles(resource, roleBitmap, account); + } + //////////////////////////////////////////////////////////////////////// // Internal Functions //////////////////////////////////////////////////////////////////////// /// @dev Allow `ROLE_UPGRADE` to upgrade. - function _authorizeUpgrade( - address newImplementation - ) internal override onlyRootRoles(PermissionedResolverLib.ROLE_UPGRADE) { - // - } - - function _msgSender() - internal - view - virtual - override(HCAContext, HCAContextUpgradeable) - returns (address) - { - return HCAContextUpgradeable._msgSender(); - } - - function _msgData() + function _authorizeUpgrade(address newImplementation) internal - view - virtual - override(Context, ContextUpgradeable) - returns (bytes calldata) + override + onlyRootRoles(PermissionedResolverLib.ROLE_UPGRADE) { - return msg.data; + // } - function _contextSuffixLength() + /// @dev Avoid permission checks during initialization. + function _checkRoles(uint256 resource, uint256 roleBitmap, address account) internal view - virtual - override(Context, ContextUpgradeable) - returns (uint256) + override { - return 0; + if (!_isInitializing()) { + super._checkRoles(resource, roleBitmap, account); + } } /// @dev Apply one round of aliasing. - /// /// @param fromName The source DNS-encoded name. - /// /// @return matchName The alias that matched. /// @return toName The destination DNS-encoded name or empty if no match. - function _resolveAlias( - bytes memory fromName - ) internal view returns (bytes memory matchName, bytes memory toName) { - mapping(bytes32 => bytes) storage A = _storage().aliases; + function _resolveAlias(bytes memory fromName) + internal + view + returns (bytes memory matchName, bytes memory toName) + { uint256 offset; while (offset < fromName.length) { - matchName = A[NameCoder.namehash(fromName, offset)]; + matchName = _aliases[NameCoder.namehash(fromName, offset)]; if (matchName.length > 0) { if (offset > 0) { // rewrite prefix: [x.y].{fromName[offset:]} => [x.y].{matchName} toName = new bytes(offset + matchName.length); assembly { mcopy(add(toName, 32), add(fromName, 32), offset) // copy prefix - mcopy(add(toName, add(32, offset)), add(matchName, 32), mload(matchName)) // copy suffix + mcopy( + add(toName, add(32, offset)), + add(matchName, 32), + mload(matchName) + ) // copy suffix } } else { toName = matchName; @@ -637,19 +798,8 @@ contract PermissionedResolver is } /// @dev Access record storage pointer. - function _record( - bytes32 node - ) internal view returns (PermissionedResolverLib.Record storage R) { - PermissionedResolverLib.Storage storage S = _storage(); - return S.records[node][S.versions[node]]; - } - - /// @dev Access global storage pointer. - function _storage() internal pure returns (PermissionedResolverLib.Storage storage S) { - uint256 slot = PermissionedResolverLib.NAMED_SLOT; - assembly { - S.slot := slot - } + function _record(bytes32 node) internal view returns (Record storage) { + return _records[node][_versions[node]]; } /// @dev Returns true if `x` has a single bit set. diff --git a/contracts/src/resolver/PublicResolverV2.sol b/contracts/src/resolver/PublicResolverV2.sol new file mode 100755 index 000000000..bc5502d47 --- /dev/null +++ b/contracts/src/resolver/PublicResolverV2.sol @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {Multicallable} from "@ens/contracts/resolvers/Multicallable.sol"; +import {ABIResolver} from "@ens/contracts/resolvers/profiles/ABIResolver.sol"; +import {AddrResolver} from "@ens/contracts/resolvers/profiles/AddrResolver.sol"; +import {ContentHashResolver} from "@ens/contracts/resolvers/profiles/ContentHashResolver.sol"; +import {DataResolver} from "@ens/contracts/resolvers/profiles/DataResolver.sol"; +import {DNSResolver} from "@ens/contracts/resolvers/profiles/DNSResolver.sol"; +import {InterfaceResolver} from "@ens/contracts/resolvers/profiles/InterfaceResolver.sol"; +import {NameResolver} from "@ens/contracts/resolvers/profiles/NameResolver.sol"; +import {PubkeyResolver} from "@ens/contracts/resolvers/profiles/PubkeyResolver.sol"; +import {TextResolver} from "@ens/contracts/resolvers/profiles/TextResolver.sol"; +import {INameWrapper} from "@ens/contracts/wrapper/INameWrapper.sol"; +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {LibRegistry} from "../universalResolver/libraries/LibRegistry.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; + +/// @notice PublicResolver that respects the ENSv2 registry. +contract PublicResolverV2 is + ERC165, + Multicallable, + ABIResolver, + AddrResolver, + ContentHashResolver, + DataResolver, + DNSResolver, + InterfaceResolver, + NameResolver, + PubkeyResolver, + TextResolver, + DelegatedContractNamer +{ + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The ENSv1 `NameWrapper` contract. + INameWrapper public immutable NAME_WRAPPER; + + /// @notice The ENSv2 Root Registry contract. + IPermissionedRegistry public immutable ROOT_REGISTRY; + + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// + + /// @dev A mapping of operators. An address that is authorised for an address + /// may make any changes to the name that the owner could, but may not update + /// the set of authorisations. + mapping(address owner => mapping(address operator => bool approved)) internal _operatorApprovals; + + /// @dev A mapping of delegates. A delegate that is authorised by an owner + /// for a name may make changes to the name's resolver, but may not update + /// the set of token approvals. + mapping(address owner => mapping(bytes32 node => mapping(address delegate => bool approved))) internal _tokenApprovals; + + //////////////////////////////////////////////////////////////////////// + // Events + //////////////////////////////////////////////////////////////////////// + + /// @notice An operator is added or removed. + /// @param owner The node owner. + /// @param operator The approved account. + /// @param approved If `true`, approved, otherwise revoked. + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); + + /// @notice A delegate is approved or an approval is revoked. + /// @param owner The node owner. + /// @param node The namehash. + /// @param delegate The approved account. + /// @param approved If `true`, approved, otherwise revoked. + event Approved( + address owner, + bytes32 indexed node, + address indexed delegate, + bool indexed approved + ); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param nameWrapper The ENSv1 `NameWrapper` contract. + /// @param rootRegistry The ENSv2 Root Registry contract. + /// @param contractNamer Delegated contract namer. + constructor( + INameWrapper nameWrapper, + IPermissionedRegistry rootRegistry, + IContractNamer contractNamer + ) + DelegatedContractNamer(contractNamer) + { + NAME_WRAPPER = nameWrapper; + ROOT_REGISTRY = rootRegistry; + } + + /// @inheritdoc AddrResolver + function supportsInterface(bytes4 interfaceId) + public + view + override( + ERC165, + Multicallable, + ABIResolver, + AddrResolver, + ContentHashResolver, + DataResolver, + DNSResolver, + InterfaceResolver, + NameResolver, + PubkeyResolver, + TextResolver, + DelegatedContractNamer + ) + returns (bool) + { + return super.supportsInterface(interfaceId); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Grant or revoke `operator` approval. + /// @param operator The account to approve. + /// @param approved If `true`, approved, otherwise revoked. + function setApprovalForAll(address operator, bool approved) external { + address sender = msg.sender; + require(sender != operator, "ERC1155: setting approval status for self"); + _operatorApprovals[sender][operator] = approved; + emit ApprovalForAll(sender, operator, approved); + } + + /// @notice Grant or revoke `delegate` approval on a specific node. + /// @param node The namehash to approve. + /// @param delegate The account to approve. + /// @param approved If `true`, approved, otherwise revoked. + function approve(bytes32 node, address delegate, bool approved) external { + address sender = msg.sender; + require(sender != delegate, "Setting delegate status for self"); + _tokenApprovals[sender][node][delegate] = approved; + emit Approved(sender, node, delegate, approved); + } + + /// @notice Check if `operator` is approved for all nodes owned by `account`. + /// @param owner The owner account. + /// @param operator The operator account. + /// @return `true` if `operator` is approved. + function isApprovedForAll(address owner, address operator) public view returns (bool) { + return _operatorApprovals[owner][operator]; + } + + /// @notice Check to see if the delegate has been approved by the owner for the node. + /// @param owner The owner account. + /// @param node The namehash to check. + /// @param delegate The delegated account. + /// @return `true` if `operator` is approved. + function isApprovedFor(address owner, bytes32 node, address delegate) + public + view + returns (bool) + { + return _tokenApprovals[owner][node][delegate]; + } + + /// @notice Determine if `operator` is authorized for `node`. + /// @param node The namehash to check. + /// @param operator The account requesting authorization. + /// @return `true` if `node` is authorized. + function canModifyName(bytes32 node, address operator) public view returns (bool) { + bytes memory name = NAME_WRAPPER.names(node); + if (name.length == 0) { + return false; + } + address owner = LibRegistry.findOwner(ROOT_REGISTRY, name, 0); + return + owner == operator || + isApprovedForAll(owner, operator) || + isApprovedFor(owner, node, operator); + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + // solhint-disable private-vars-leading-underscore + /// @dev Determine if the caller is authorized for `node`. + function isAuthorised(bytes32 node) internal view override returns (bool) { + return canModifyName(node, msg.sender); + } +} diff --git a/contracts/src/resolver/interfaces/IPermissionedResolver.sol b/contracts/src/resolver/interfaces/IPermissionedResolver.sol new file mode 100755 index 000000000..1ad87de08 --- /dev/null +++ b/contracts/src/resolver/interfaces/IPermissionedResolver.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {IExtendedResolver} from "@ens/contracts/resolvers/profiles/IExtendedResolver.sol"; + +import {IEnhancedAccessControl} from "../../access-control/interfaces/IEnhancedAccessControl.sol"; + +/// @dev Interface selector: `0x91413117` +interface IPermissionedResolver is IExtendedResolver, IEnhancedAccessControl { + //////////////////////////////////////////////////////////////////////// + // Events + //////////////////////////////////////////////////////////////////////// + + /// @notice An alias was changed. + /// @param indexedFromName The source DNS-encoded name. (indexed bytes, hashed) + /// @param indexedToName The destination DNS-encoded name. (indexed bytes, hashed) + /// @param fromName The source DNS-encoded name. + /// @param toName The destination DNS-encoded name. + event AliasChanged( + bytes indexed indexedFromName, + bytes indexed indexedToName, + bytes fromName, + bytes toName + ); + + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice The resolver profile cannot be answered. + /// @dev Error selector: `0x7b1c461b` + error UnsupportedResolverProfile(bytes4 selector); + + /// @notice The address could not be converted to `address`. + /// @dev Error selector: `0x8d666f60` + error InvalidEVMAddress(bytes addressBytes); + + /// @notice The coin type is not a power of 2. + /// @dev Error selector: `0x5742bb26` + error InvalidContentType(uint256 contentType); + + //////////////////////////////////////////////////////////////////////// + // Functions + //////////////////////////////////////////////////////////////////////// + + /// @notice Initialize the contract. + /// @param admin The resolver owner. + /// @param roleBitmap The roles granted to `admin`. + /// @param setters The setter calldata that avoids permission checks. + function initialize(address admin, uint256 roleBitmap, bytes[] calldata setters) external; + + /// @notice Create an alias from `fromName` to `toName`. + /// @param fromName The source DNS-encoded name. + /// @param toName The destination DNS-encoded name. + function setAlias(bytes calldata fromName, bytes calldata toName) external; + + /// @notice Determine which name is queried when `fromName` is resolved. + /// @param fromName The source DNS-encoded name. + /// @return toName The destination DNS-encoded name or empty if not aliased. + function getAlias(bytes memory fromName) external view returns (bytes memory toName); +} diff --git a/contracts/src/resolver/libraries/PermissionedResolverLib.sol b/contracts/src/resolver/libraries/PermissionedResolverLib.sol index 12a1e0bf8..c30f93264 100644 --- a/contracts/src/resolver/libraries/PermissionedResolverLib.sol +++ b/contracts/src/resolver/libraries/PermissionedResolverLib.sol @@ -1,75 +1,66 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; -/// @notice Storage layout and roles for PermissionedResolver. +/// @dev Roles for PermissionedResolver. library PermissionedResolverLib { - /// @dev Top-level storage layout for `PermissionedResolver`. - /// @param aliases DNS-encoded alias target for internal name rewriting, keyed by node. - /// @param versions Monotonically increasing version counter per node; incrementing - /// invalidates all existing records for the node. - /// @param records The actual resolver records for the current version, keyed by - /// `(node, version)`. - struct Storage { - mapping(bytes32 node => bytes) aliases; - mapping(bytes32 node => uint64) versions; - mapping(bytes32 node => mapping(uint64 version => Record)) records; - } - - /// @dev Holds all resolver record types for a single name version -- contenthash, - /// public key, reverse name, plus mappings for multi-chain addresses, text records, - /// ABIs, and interface implementations. - struct Record { - bytes contenthash; - bytes32[2] pubkey; - string name; - mapping(uint256 coinType => bytes addressBytes) addresses; - mapping(string key => string value) texts; - mapping(uint256 contentType => bytes data) abis; - mapping(bytes4 interfaceId => address implementer) interfaces; - } - - /// @dev Named storage slot for `PermissionedResolver`. - uint256 internal constant NAMED_SLOT = - uint256(keccak256("eth.ens.storage.PermissionedResolver")); - - /// @dev Nybble 0 — authorizes setting multi-chain address records. Root or name. + /// @dev Nybble 0: authorizes setting address records. Root or name. uint256 internal constant ROLE_SET_ADDR = 1 << 0; + /// @dev Nybble 32: authorizes setting ROLE_SET_ADDR. uint256 internal constant ROLE_SET_ADDR_ADMIN = ROLE_SET_ADDR << 128; - /// @dev Nybble 1 — authorizes setting text records. Root or name. + /// @dev Nybble 1: authorizes setting text records. Root or name. uint256 internal constant ROLE_SET_TEXT = 1 << 4; + /// @dev Nybble 33: authorizes setting ROLE_SET_TEXT. uint256 internal constant ROLE_SET_TEXT_ADMIN = ROLE_SET_TEXT << 128; - /// @dev Nybble 2 — authorizes setting the contenthash record. Root or name. + /// @dev Nybble 2: authorizes setting the contenthash record. Root or name. uint256 internal constant ROLE_SET_CONTENTHASH = 1 << 8; + /// @dev Nybble 34: authorizes setting ROLE_SET_CONTENTHASH. uint256 internal constant ROLE_SET_CONTENTHASH_ADMIN = ROLE_SET_CONTENTHASH << 128; - /// @dev Nybble 3 — authorizes setting the public key record. Root or name. + /// @dev Nybble 3: authorizes setting the public key record. Root or name. uint256 internal constant ROLE_SET_PUBKEY = 1 << 12; + /// @dev Nybble 35: authorizes setting ROLE_SET_PUBKEY. uint256 internal constant ROLE_SET_PUBKEY_ADMIN = ROLE_SET_PUBKEY << 128; - /// @dev Nybble 4 — authorizes setting ABI records. Root or name. + /// @dev Nybble 4: authorizes setting ABI records. Root or name. uint256 internal constant ROLE_SET_ABI = 1 << 16; + /// @dev Nybble 36: authorizes setting ROLE_SET_ABI. uint256 internal constant ROLE_SET_ABI_ADMIN = ROLE_SET_ABI << 128; - /// @dev Nybble 5 — authorizes setting interface implementer records. Root or name. + /// @dev Nybble 5: authorizes setting interface implementer records. Root or name. uint256 internal constant ROLE_SET_INTERFACE = 1 << 20; + /// @dev Nybble 37: authorizes setting ROLE_SET_INTERFACE. uint256 internal constant ROLE_SET_INTERFACE_ADMIN = ROLE_SET_INTERFACE << 128; - /// @dev Nybble 6 — authorizes setting the reverse name record. Root or name. + /// @dev Nybble 6: authorizes setting the reverse name record. Root or name. uint256 internal constant ROLE_SET_NAME = 1 << 24; + /// @dev Nybble 38: authorizes setting ROLE_SET_NAME. uint256 internal constant ROLE_SET_NAME_ADMIN = ROLE_SET_NAME << 128; - /// @dev Nybble 7 — authorizes setting alias targets for name rewriting. Root-only. + /// @dev Nybble 7: authorizes setting alias targets for name rewriting. Root-only. uint256 internal constant ROLE_SET_ALIAS = 1 << 28; + /// @dev Nybble 39: authorizes setting ROLE_SET_ALIAS. uint256 internal constant ROLE_SET_ALIAS_ADMIN = ROLE_SET_ALIAS << 128; - /// @dev Nybble 8 — authorizes clearing (version-bumping) all records for a node. Root or name. + /// @dev Nybble 8: authorizes clearing (version-bumping) all records for a node. Root or name. uint256 internal constant ROLE_CLEAR = 1 << 32; + /// @dev Nybble 40: authorizes setting ROLE_CLEAR. uint256 internal constant ROLE_CLEAR_ADMIN = ROLE_CLEAR << 128; - /// @dev Nybble 31 — authorizes UUPS proxy upgrades. Root-only. + /// @dev Nybble 9: authorizes setting data records. Root or name. + uint256 internal constant ROLE_SET_DATA = 1 << 36; + /// @dev Nybble 41: authorizes setting ROLE_SET_DATA. + uint256 internal constant ROLE_SET_DATA_ADMIN = ROLE_SET_DATA << 128; + + /// @dev Nybble 30: authorizes contract naming. Root-only. + uint256 internal constant ROLE_CAN_NAME = 1 << 120; + /// @dev Nybble 63: authorizes setting ROLE_CAN_NAME. + uint256 internal constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128; + + /// @dev Nybble 31: authorizes UUPS proxy upgrades. Root-only. uint256 internal constant ROLE_UPGRADE = 1 << 124; + /// @dev Nybble 63: authorizes setting ROLE_UPGRADE. uint256 internal constant ROLE_UPGRADE_ADMIN = ROLE_UPGRADE << 128; /// @dev Computes `keccak256(node, part)` to create a unique EAC resource ID scoped to both @@ -78,35 +69,30 @@ library PermissionedResolverLib { /// @param part The record-type identifier (e.g. from `addrPart` or `textPart`). /// @return ret The computed resource ID. function resource(bytes32 node, bytes32 part) internal pure returns (uint256 ret) { - assembly { - mstore(0, node) - mstore(32, part) - ret := keccak256(0, 64) + if (node != bytes32(0) || part != bytes32(0)) { + assembly { + mstore(0, node) + mstore(32, part) + ret := keccak256(0, 64) + } + // Equivalent: return uint256(keccak256(abi.encode(node, part))); } - // Equivalent: return uint256(keccak256(abi.encode(node, part))); } - /// @dev Computes a record-type identifier for address records, namespaced by coin type. - /// @param coinType The SLIP-44 coin type. + /// @dev Computes a record-type identifier for uint256-keyed records. + /// @param x The uint256 value. /// @return part The computed record-type identifier. - function addrPart(uint256 coinType) internal pure returns (bytes32 part) { + function partHash(uint256 x) internal pure returns (bytes32 part) { assembly { - mstore8(0, 1) - mstore(1, coinType) - part := keccak256(0, 33) + mstore(0, x) + part := keccak256(0, 32) } - // Equivalent: return keccak256(abi.encodePacked(uint8(1), coinType)); } - /// @dev Computes a record-type identifier for text records, namespaced by key. - /// @param key The text record key. + /// @dev Computes a record-type identifier for string-keyed records. + /// @param x The string value. /// @return part The computed record-type identifier. - function textPart(string memory key) internal pure returns (bytes32 part) { - assembly { - mstore8(0, 2) - mstore(1, keccak256(add(key, 32), mload(key))) - part := keccak256(0, 33) - } - // Equivalent: return keccak256(abi.encodePacked(uint8(2), key)); + function partHash(string memory x) internal pure returns (bytes32) { + return keccak256(bytes(x)); } } diff --git a/contracts/src/resolver/libraries/ResolverProfileRewriterLib.sol b/contracts/src/resolver/libraries/ResolverProfileRewriterLib.sol index c834f792c..7d47e6fea 100755 --- a/contracts/src/resolver/libraries/ResolverProfileRewriterLib.sol +++ b/contracts/src/resolver/libraries/ResolverProfileRewriterLib.sol @@ -2,42 +2,70 @@ pragma solidity >=0.8.13; /// @dev Rewrites the `bytes32 node` parameter in resolver calldata. Resolver functions follow -/// the convention `func(bytes32 node, ...)`, with the node at calldata offset 4. This library -/// replaces that node in a memory copy of the calldata, recursively handling `multicall(bytes[])` -/// (selector `0xac9650d8`) to rewrite the node in every nested call at arbitrary depth. +/// the convention `func(bytes32 node, ...)`, with the node at calldata offset 4. This library +/// replaces that node in a memory copy of the calldata, recursively handling `multicall(bytes[])` +/// (selector `0xac9650d8`) to rewrite the node in every nested call at arbitrary depth. +/// +/// Used by `PermissionedResolver` when resolving aliased names: after determining the alias target, +/// the original calldata must be updated with the new node before forwarding to the actual +/// resolver logic. /// -/// Used by `PermissionedResolver` when resolving aliased names: after determining the alias target, -/// the original calldata must be updated with the new node before forwarding to the actual -/// resolver logic. library ResolverProfileRewriterLib { /// @dev Replace the node in the calldata with a new node. /// Supports `multicall()` to arbitrary depth. /// @param call The calldata for a resolver. /// @param newNode The replacement node. /// @return copy A copy of the calldata with node replaced. - function replaceNode( - bytes calldata call, - bytes32 newNode - ) internal pure returns (bytes memory copy) { + function replaceNode(bytes calldata call, bytes32 newNode) + internal + pure + returns (bytes memory copy) + { + // 0xac9650d8 // selector + // 0000000000000000000000000000000000000000000000000000000000000020 // jump + // 0000000000000000000000000000000000000000000000000000000000000002 // .length @ jump + // 0000000000000000000000000000000000000000000000000000000000000040 // jump[0] + // 00000000000000000000000000000000000000000000000000000000000000a0 // jump[1] + // 0000000000000000000000000000000000000000000000000000000000000024 // [0].length @ jump[0] + // ... + // 0000000000000000000000000000000000000000000000000000000000000024 // [1].length @ jump[1] + // ... copy = call; // make a copy assembly { - function replace(ptr, node) { - switch shr(224, mload(add(ptr, 32))) // call selector + function replace(ptr, bound, node) { + ptr := add(ptr, 36) // skip length + selector + switch shr(224, mload(sub(ptr, 4))) // read selector case 0xac9650d8 { // multicall(bytes[]) - let off := add(ptr, 36) - off := add(off, mload(off)) - let size := shl(5, mload(off)) + let lower := ptr + ptr := add(ptr, mload(ptr)) // follow jump + if lt(ptr, lower) { + leave // underflow + } + let size := shl(5, mload(ptr)) // read word count as size // prettier-ignore - for { } size { size := sub(size, 32) } { - replace(add(add(off, 32), mload(add(off, size))), node) + for { } size { size := sub(size, 32) } { // backwards + lower := add(ptr, 32) + let p := add(lower, mload(add(ptr, size))) // local ptr + if lt(p, lower) { + continue // underflow + } + let b := add(p, mload(p)) // local bound w/room for 1 word + if lt(bound, b) { + b := bound // global bound is smaller + } + replace(p, b, node) } } default { - mstore(add(ptr, 36), node) // replace node + // only bound checks on write + if lt(bound, ptr) { + leave + } + mstore(ptr, node) // replace node } } - replace(copy, newNode) + replace(copy, add(copy, mload(copy)), newNode) // bound w/room for 1 word } } } diff --git a/contracts/src/reverse-registrar/DefaultReverseRegistrarAdapter.sol b/contracts/src/reverse-registrar/DefaultReverseRegistrarAdapter.sol new file mode 100644 index 000000000..576ea7c49 --- /dev/null +++ b/contracts/src/reverse-registrar/DefaultReverseRegistrarAdapter.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { + IDefaultReverseRegistrar +} from "@ens/contracts/reverseRegistrar/IDefaultReverseRegistrar.sol"; + +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; + +import {IContractNamer} from "./interfaces/IContractNamer.sol"; +import {AccountNamerLib} from "./libraries/AccountNamerLib.sol"; + +/// @title Default Reverse Registrar Adapter +/// @notice Forwarder for v1 `default.reverse` registrar updates. +/// @dev The adapter must be configured as a controller on the default reverse registrar. +contract DefaultReverseRegistrarAdapter is DelegatedContractNamer { + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The v1 default reverse registrar for `default.reverse`. + IDefaultReverseRegistrar public immutable DEFAULT_REVERSE_REGISTRAR; + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param defaultReverseRegistrar The v1 default reverse registrar for `default.reverse`. + /// @param contractNamer Delegated contract namer. + constructor(IDefaultReverseRegistrar defaultReverseRegistrar, IContractNamer contractNamer) + DelegatedContractNamer(contractNamer) + { + DEFAULT_REVERSE_REGISTRAR = defaultReverseRegistrar; + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Set account's `default.reverse` primary name. + /// @param account The contract address. + /// @param name The primary name to store. + function setName(address account, string calldata name) external { + AccountNamerLib.requireNamer(account, msg.sender); + DEFAULT_REVERSE_REGISTRAR.setNameForAddr(account, name); + } +} diff --git a/contracts/src/reverse-registrar/L2ReverseRegistrar.sol b/contracts/src/reverse-registrar/L2ReverseRegistrar.sol new file mode 100644 index 000000000..681c42ed3 --- /dev/null +++ b/contracts/src/reverse-registrar/L2ReverseRegistrar.sol @@ -0,0 +1,370 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +import {IUniversalSignatureValidator} from "../utils/interfaces/IUniversalSignatureValidator.sol"; +import {LibISO8601} from "../utils/LibISO8601.sol"; +import {LibString} from "../utils/LibString.sol"; + +import {IContractName} from "./interfaces/IContractName.sol"; +import {IL2ReverseRegistrar} from "./interfaces/IL2ReverseRegistrar.sol"; +import {AccountNamerLib} from "./libraries/AccountNamerLib.sol"; +import {ChainIdsBuilderLib} from "./libraries/ChainIdsBuilderLib.sol"; +import {StandaloneReverseRegistrar} from "./StandaloneReverseRegistrar.sol"; + +/// @title L2 Reverse Registrar +/// @notice A reverse registrar for L2 chains that allows users to set their ENS primary name. +/// @dev Deployed to each L2 chain. Supports signature-based claims for both EOAs and contracts. +contract L2ReverseRegistrar is IL2ReverseRegistrar, ERC165, StandaloneReverseRegistrar { + //////////////////////////////////////////////////////////////////////// + // Constants & Immutables + //////////////////////////////////////////////////////////////////////// + + /// @dev The ERC6492 detection suffix. + bytes32 private constant _ERC6492_DETECTION_SUFFIX = + 0x6492649264926492649264926492649264926492649264926492649264926492; + + /// @dev The universal signature validator for ERC6492 signatures. + IUniversalSignatureValidator private constant _UNIVERSAL_SIG_VALIDATOR = + IUniversalSignatureValidator(0x164af34fAF9879394370C7f09064127C043A35E9); + + /// @notice The chain ID of the chain this contract is deployed to. + /// @dev Derived from the coin type during construction. + uint256 public immutable CHAIN_ID; + + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// + + /// @notice Mapping of addresses to their inception timestamp for replay protection. + /// @dev Only signatures with a signedAt timestamp greater than the stored inception can be used. + mapping(address addr => uint256 inception) public inceptionOf; + + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice Thrown when the signature's signedAt is not after the current inception. + /// @dev Error selector: `0xbdc2d236` + error StaleSignature(uint256 signedAt, uint256 inception); + + /// @notice Thrown when the signature's signedAt timestamp is in the future. + /// @dev Error selector: `0x2c4fde1c` + error SignatureNotValidYet(uint256 signedAt, uint256 currentTime); + + /// @notice Thrown when the signature is invalid. + /// @dev Error selector: `0x8baa579f` + error InvalidSignature(); + + /// @notice Thrown when the chain ID array is not in strictly ascending order. + /// @dev Error selector: `0xea0b14e2` + /// @dev Re-declared here (despite living in`ChainIdsBuilderLib`) because the library + /// reverts via assembly literal and Solidity has no source-level reference to propagate + /// the type into this contract's ABI. `CurrentChainNotFound` doesn't need this anchor — + /// the library reverts it via `revert CurrentChainNotFound(...)` so its type propagates + /// automatically. + error ChainIdsNotAscending(); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @notice Initialises the contract with the chain ID and label for this L2 chain. + /// @param chainId The chain ID of the chain this contract is deployed to. + /// @param label The hex string label for the coin type (used in reverse node computation). + constructor(uint256 chainId, string memory label) StandaloneReverseRegistrar(label) { + CHAIN_ID = chainId; + } + + /// @inheritdoc ERC165 + function supportsInterface(bytes4 interfaceID) + public + view + override(ERC165, StandaloneReverseRegistrar) + returns (bool) + { + return + interfaceID == type(IL2ReverseRegistrar).interfaceId || + super.supportsInterface(interfaceID); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @inheritdoc IL2ReverseRegistrar + function setName(string calldata name) external { + _setName(msg.sender, name); + _advanceInception(msg.sender); + } + + /// @inheritdoc IL2ReverseRegistrar + function setNameForAddr(address addr, string calldata name) external { + AccountNamerLib.requireNamer(addr, msg.sender); + _setName(addr, name); + _advanceInception(addr); + } + + /// @inheritdoc IL2ReverseRegistrar + function setNameForAddrWithSignature(NameClaim calldata claim, bytes calldata signature) + external + { + string memory chainIdsString = ChainIdsBuilderLib.validateAndBuild(claim.chainIds, CHAIN_ID); + + bytes32 message = _createClaimMessageHash(claim, chainIdsString, address(0)); + _validateSignature(signature, claim.addr, message); + _validateAndUpdateInception(claim.addr, claim.signedAt); + + _setName(claim.addr, claim.name); + } + + /// @inheritdoc IL2ReverseRegistrar + function setNameForContractWithSignature( + NameClaim calldata claim, + address owner, + bytes calldata signature + ) + external + { + string memory chainIdsString = ChainIdsBuilderLib.validateAndBuild(claim.chainIds, CHAIN_ID); + + AccountNamerLib.requireNamer(claim.addr, owner); + + bytes32 message = _createClaimMessageHash(claim, chainIdsString, owner); + _validateSignature(signature, owner, message); + _validateAndUpdateInception(claim.addr, claim.signedAt); + + _setName(claim.addr, claim.name); + } + + /// @inheritdoc IL2ReverseRegistrar + function syncName(address addr) external { + _setName(addr, IContractName(addr).contractName()); // reverts if not implemented + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + /// @notice Validates a signature for the given address and message. + /// @dev Supports EOA signatures, ERC1271 (smart contract wallets), and ERC6492 (undeployed wallets). + /// @param signature The signature to validate. + /// @param addr The address that should have signed the message. + /// @param message The message hash that was signed. + function _validateSignature(bytes calldata signature, address addr, bytes32 message) internal { + // ERC6492 check is done internally because UniversalSigValidator is not gas efficient. + // We only want to use UniversalSigValidator for ERC6492 signatures. + if (bytes32(signature[signature.length - 32:signature.length]) == _ERC6492_DETECTION_SUFFIX) { + if (!_UNIVERSAL_SIG_VALIDATOR.isValidSig(addr, message, signature)) + revert InvalidSignature(); + } else { + if (!SignatureChecker.isValidSignatureNow(addr, message, signature)) + revert InvalidSignature(); + } + } + + /// @notice Validates and updates the inception timestamp for replay protection. + /// @dev Reverts if signedAt is not after the current inception or is in the future. + /// @param addr The address to validate and update inception for. + /// @param signedAt The signedAt timestamp from the signature. + function _validateAndUpdateInception(address addr, uint256 signedAt) internal { + uint256 currentInception = inceptionOf[addr]; + + // signedAt must be strictly greater than the current inception + if (signedAt <= currentInception) + revert StaleSignature(signedAt, currentInception); + + // signedAt cannot be in the future + if (signedAt > block.timestamp) + revert SignatureNotValidYet(signedAt, block.timestamp); + + // Update the inception to the new signedAt + inceptionOf[addr] = signedAt; + } + + /// @notice Advances the inception timestamp after an authorized direct name update. + /// @dev The replay fence never moves backward. + /// @param addr The address whose inception should be advanced. + function _advanceInception(address addr) internal { + if (block.timestamp > inceptionOf[addr]) { + inceptionOf[addr] = block.timestamp; + } + } + + /// @dev Creates the EIP-191 message hash for signature-based name claims. + /// + /// For address claims (owner == address(0)): + /// ``` + /// You are setting your ENS primary name to: + /// {name} + /// + /// Address: {address} + /// Chains: {chainList} + /// Signed At: {signedAt} + /// ``` + /// + /// For ownable contract claims (owner != address(0)): + /// ``` + /// You are setting the ENS primary name for a contract you own to: + /// {name} + /// + /// Contract Address: {address} + /// Owner: {owner} + /// Chains: {chainList} + /// Signed At: {signedAt} + /// ``` + /// + /// @param claim The name claim data. + /// @param chainIdsString The pre-validated chain IDs as a display string. + /// @param owner The owner address for ownable claims, or address(0) for address claims. + /// @return digest The EIP-191 signed message hash. + function _createClaimMessageHash( + NameClaim calldata claim, + string memory chainIdsString, + address owner + ) + internal + pure + returns (bytes32 digest) + { + string memory name = claim.name; + string memory addrString = LibString.toChecksumHexString(claim.addr); + string memory signedAtString = LibISO8601.toISO8601(claim.signedAt); + + bool isOwnable = owner != address(0); + string memory ownerString; + if (isOwnable) { + ownerString = LibString.toChecksumHexString(owner); + } + + // Build message in memory as bytes + bytes memory message; + assembly { + // Paris-compatible memory copy helper (replaces mcopy from Cancun) + // Copies in 32-byte chunks; safe here since subsequent writes overwrite any overshoot + function _memcpy(dest, src, len) { + for { + let i := 0 + } lt(i, len) { + i := add(i, 32) + } { + mstore(add(dest, i), mload(add(src, i))) + } + } + + // Get free memory pointer - reserve space for length, then build message + message := mload(0x40) + let ptr := add(message, 32) // Start writing after length slot + + // Header differs based on claim type + switch isOwnable + case 0 { + // "You are setting your ENS primary" (32 bytes) + mstore(ptr, 0x596f75206172652073657474696e6720796f757220454e53207072696d617279) + // " name to:\n" (10 bytes) + mstore( + add(ptr, 32), + 0x206e616d6520746f3a0a00000000000000000000000000000000000000000000 + ) + ptr := add(ptr, 42) + } + default { + // "You are setting the ENS primary " (32 bytes) + mstore(ptr, 0x596f75206172652073657474696e672074686520454e53207072696d61727920) + // "name for a contract you own to:\n" (32 bytes) + mstore( + add(ptr, 32), + 0x6e616d6520666f72206120636f6e747261637420796f75206f776e20746f3a0a + ) + ptr := add(ptr, 64) + } + // Copy name (variable length) + let nameLen := mload(name) + _memcpy(ptr, add(name, 32), nameLen) + ptr := add(ptr, nameLen) + + // Address label differs based on claim type + switch isOwnable + case 0 { + // "\n\nAddress: " (11 bytes) + mstore(ptr, 0x0a0a416464726573733a20000000000000000000000000000000000000000000) + ptr := add(ptr, 11) + } + default { + // "\n\nContract Address: " (20 bytes) + mstore(ptr, 0x0a0a436f6e747261637420416464726573733a20000000000000000000000000) + ptr := add(ptr, 20) + } + // Copy addrString (42 bytes) + _memcpy(ptr, add(addrString, 32), 42) + ptr := add(ptr, 42) + + // Owner section (only for ownable claims) + if isOwnable { + // "\nOwner: " (8 bytes) + mstore(ptr, 0x0a4f776e65723a20000000000000000000000000000000000000000000000000) + ptr := add(ptr, 8) + + // Copy ownerString (42 bytes) + _memcpy(ptr, add(ownerString, 32), 42) + ptr := add(ptr, 42) + } + + // "\nChains: " (9 bytes) + mstore(ptr, 0x0a436861696e733a200000000000000000000000000000000000000000000000) + ptr := add(ptr, 9) + + // Copy chainIdsString (variable length) + let chainLen := mload(chainIdsString) + _memcpy(ptr, add(chainIdsString, 32), chainLen) + ptr := add(ptr, chainLen) + + // "\nSigned At: " (12 bytes) + mstore(ptr, 0x0a5369676e65642041743a200000000000000000000000000000000000000000) + ptr := add(ptr, 12) + + // Copy signedAtString (20 bytes fixed - ISO8601 format) + _memcpy(ptr, add(signedAtString, 32), 20) + ptr := add(ptr, 20) + + // Store final message length and update free memory pointer + mstore(message, sub(ptr, add(message, 32))) + mstore(0x40, ptr) + } + + // Compute EIP-191 signed message hash: keccak256("\x19Ethereum Signed Message:\n" || len || message) + string memory lenString = LibString.toString(message.length); + assembly { + function _memcpy(dest, src, len) { + for { + let i := 0 + } lt(i, len) { + i := add(i, 32) + } { + mstore(add(dest, i), mload(add(src, i))) + } + } + + let messageLen := mload(message) + let lenStringLen := mload(lenString) + + // Build prefixed message at free memory pointer (not updated since only used for hashing) + let ptr := mload(0x40) + + // "\x19Ethereum Signed Message:\n" (26 bytes) + mstore(ptr, 0x19457468657265756d205369676e6564204d6573736167653a0a000000000000) + + // Copy length string (decimal digits of message length) after prefix + _memcpy(add(ptr, 26), add(lenString, 32), lenStringLen) + + // Copy message content after prefix + length string + let messageStart := add(add(ptr, 26), lenStringLen) + _memcpy(messageStart, add(message, 32), messageLen) + + // Compute the final EIP-191 hash + digest := keccak256(ptr, add(add(26, lenStringLen), messageLen)) + } + } +} diff --git a/contracts/src/reverse-registrar/L2ReverseRegistrarWithMigration.sol b/contracts/src/reverse-registrar/L2ReverseRegistrarWithMigration.sol new file mode 100644 index 000000000..23b51bad2 --- /dev/null +++ b/contracts/src/reverse-registrar/L2ReverseRegistrarWithMigration.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.13; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +import {L2ReverseRegistrar} from "./L2ReverseRegistrar.sol"; + +/// @dev Interface selector: `0x4ec3bd23` +interface IL2ReverseRegistrarV1 { + /// @notice Returns the name for an address. + /// @param addr The address to get the name for. + /// @return The name for the address. + function nameForAddr(address addr) external view returns (string memory); +} + + +/// @notice An L2 Reverse Registrar that allows migrating from a prior registrar. +contract L2ReverseRegistrarWithMigration is L2ReverseRegistrar, Ownable { + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The v1 reverse registrar to migrate from + IL2ReverseRegistrarV1 public immutable OLD_L2_REVERSE_REGISTRAR; + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @notice Initialises the contract with the chain ID and label for this L2 chain. + /// @param chainId The chain ID of the chain this contract is deployed to. + /// @param label The hex string label for the coin type (used in reverse node computation). + /// @param owner The owner of the contract. + /// @param oldL2ReverseRegistrar The v1 reverse registrar to migrate from. + constructor( + uint256 chainId, + string memory label, + address owner, + IL2ReverseRegistrarV1 oldL2ReverseRegistrar + ) + L2ReverseRegistrar(chainId, label) + Ownable(owner) + { + OLD_L2_REVERSE_REGISTRAR = oldL2ReverseRegistrar; + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Sets a batch of names for the specified addresses, with values taken + /// from the old reverse registrar. Only callable by the owner. + /// @param addresses The addresses to migrate. + function batchSetName(address[] calldata addresses) external onlyOwner { + for (uint256 i = 0; i < addresses.length; ++i) { + string memory name = OLD_L2_REVERSE_REGISTRAR.nameForAddr(addresses[i]); + + _setName(addresses[i], name); + } + } +} diff --git a/contracts/src/reverse-registrar/README.md b/contracts/src/reverse-registrar/README.md new file mode 100644 index 000000000..cd0714ecf --- /dev/null +++ b/contracts/src/reverse-registrar/README.md @@ -0,0 +1,66 @@ +# L2 Reverse Registrar + +The L2 Reverse Registrar is a combination of a resolver and a reverse registrar that allows the name to be set for a particular reverse node. + +## Setting records + +You can set records using one of the follow functions: + +`setName()` - uses the msg.sender's address and allows you to set a record for that address only + +`setNameForAddr()` - uses the address parameter instead of `msg.sender` and checks if the `msg.sender` is authorized by checking if the contract's owner (via the Ownable pattern) is the msg.sender + +`setNameForAddrWithSignature()` - uses the address parameter instead of `msg.sender` and allows authorisation via a signature + +`setNameForOwnableWithSignature()` - uses the address parameter instead of `msg.sender`. The sender is authorized by checking if the contract's owner (via the Ownable pattern) is the msg.sender, which then checks that the signer has authorized the record on behalf of msg.sender using `ERC1271` (or `ERC6492`) + +## Replay Protection + +Signature-based methods use an **inception timestamp** system for replay protection. Each address has an associated inception timestamp stored onchain. For a signature to be valid: + +1. The signature's `signedAt` timestamp must be **strictly greater than** the current inception for that address +2. The `signedAt` timestamp must not be in the future (i.e., `signedAt <= block.timestamp`) + +When a valid signature is used, the inception is updated to the `signedAt` value. Authorized direct updates via `setName()` or `setNameForAddr()` advance the inception to the current block timestamp. This ensures: +- Each signature can only be used once per chain +- Newer signatures always supersede older ones +- Ordering is guaranteed (signatures with older `signedAt` values become invalid once a newer one is used) + +You can query the current inception for any address using `inceptionOf(address)`. + +## Signatures for setting records + +Signatures are all plaintext, prefixed with `\x19Ethereum Signed Message:\n` as defined in ERC-191. + +### Field definitions + +| Field | Type | Description | +|-------|------|-------------| +| `name` | `string` | The ENS name to set as primary (e.g., `vitalik.eth`). | +| `address` | `address` | The address for which the primary name is being set. EIP-55 checksummed. | +| `owner` | `address` | The address that owns the contract for which the primary name is being set. EIP-55 checksummed. Only applicable for `setNameForOwnableWithSignature`. | +| `chainList` | `string` | Comma-separated list of chain IDs, **must be in strictly ascending order**. | +| `signedAt` | `string` | ISO 8601 UTC datetime when the signature was signed. Must be after the current inception and not in the future. | + +### `setNameForAddrWithSignature` + +``` +You are setting your ENS primary name to: +{name} + +Address: {address} +Chains: {chainList} +Signed At: {signedAt} +``` + +### `setNameForOwnableWithSignature` + +``` +You are setting the ENS primary name for a contract you own to: +{name} + +Contract Address: {address} +Owner: {owner} +Chains: {chainList} +Signed At: {signedAt} +``` diff --git a/contracts/src/reverse-registrar/ReverseRegistrarAdapter.sol b/contracts/src/reverse-registrar/ReverseRegistrarAdapter.sol new file mode 100644 index 000000000..eb30aa691 --- /dev/null +++ b/contracts/src/reverse-registrar/ReverseRegistrarAdapter.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import {IReverseRegistrar} from "@ens/contracts/reverseRegistrar/IReverseRegistrar.sol"; + +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; + +import {IContractNamer} from "./interfaces/IContractNamer.sol"; +import {AccountNamerLib} from "./libraries/AccountNamerLib.sol"; + +/// @title Reverse Registrar Adapter +/// @notice Forwarder for v1 `addr.reverse` registrar updates. +/// @dev The adapter must be configured as a controller on the reverse registrar. +contract ReverseRegistrarAdapter is DelegatedContractNamer { + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The v1 reverse registrar for `addr.reverse`. + IReverseRegistrar public immutable REVERSE_REGISTRAR; + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param reverseRegistrar The v1 reverse registrar for `addr.reverse`. + /// @param contractNamer Delegated contract namer. + constructor(IReverseRegistrar reverseRegistrar, IContractNamer contractNamer) + DelegatedContractNamer(contractNamer) + { + REVERSE_REGISTRAR = reverseRegistrar; + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Claims account's `addr.reverse` node and sets its resolver. + /// @param account The account to claim. + /// @param resolver The resolver to set. + /// @return The ENS node hash for the contract's reverse record. + function claim(address account, address resolver) external returns (bytes32) { + address sender = msg.sender; + AccountNamerLib.requireNamer(account, sender); + return REVERSE_REGISTRAR.claimForAddr(account, sender, resolver); + } +} diff --git a/contracts/src/reverse-registrar/StandaloneReverseRegistrar.sol b/contracts/src/reverse-registrar/StandaloneReverseRegistrar.sol new file mode 100644 index 000000000..d273540a8 --- /dev/null +++ b/contracts/src/reverse-registrar/StandaloneReverseRegistrar.sol @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IExtendedResolver} from "@ens/contracts/resolvers/profiles/IExtendedResolver.sol"; +import {INameResolver} from "@ens/contracts/resolvers/profiles/INameResolver.sol"; +import { + IStandaloneReverseRegistrar +} from "@ens/contracts/reverseRegistrar/IStandaloneReverseRegistrar.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +import {IRegistryEvents} from "../registry/interfaces/IRegistryEvents.sol"; +import {LibString} from "../utils/LibString.sol"; + +/// @dev A standalone reverse registrar, detached from the ENS registry. +abstract contract StandaloneReverseRegistrar is + ERC165, + IStandaloneReverseRegistrar, + IExtendedResolver, + IRegistryEvents, + INameResolver +{ + //////////////////////////////////////////////////////////////////////// + // Constants & Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The namehash of the `reverse` TLD node. + /// @dev Pre-computed: namehash("reverse") = keccak256(abi.encodePacked(bytes32(0), keccak256("reverse"))) + bytes32 internal constant _REVERSE_NODE = + 0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34; + + /// @notice The keccak256 hash of the DNS-encoded parent name. + /// @dev Used for efficient validation in `resolve()` to verify the queried name + /// belongs to this registrar's namespace. + bytes32 internal immutable _SIMPLE_HASHED_PARENT; + + /// @notice The length of the DNS-encoded parent name in bytes. + /// @dev Used in `resolve()` to validate the expected name length. + uint256 internal immutable _PARENT_LENGTH; + + /// @notice The namehash of the parent node for this reverse registrar. + /// @dev Computed as: keccak256(abi.encodePacked(_REVERSE_NODE, keccak256(label))) + /// For example, for Ethereum mainnet with label "60", this would be the namehash of "60.reverse". + bytes32 public immutable PARENT_NODE; + + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// + + /// @notice Mapping from reverse node to the primary ENS name for that address. + /// @dev The node is computed as: keccak256(abi.encodePacked(PARENT_NODE, keccak256(addressString))) + mapping(bytes32 node => string name) internal _names; + + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice Thrown when `resolve()` is called with an unsupported resolver profile. + /// @dev This registrar only supports the `name(bytes32)` selector. + /// @dev Error selector: `0x7b1c461b` + error UnsupportedResolverProfile(bytes4 selector); + + /// @notice Thrown when the queried name is not a valid ENSIP-19 reverse name for this namespace. + /// @dev The name must be exactly 41 + PARENT_LENGTH bytes and match the expected parent suffix. + /// @dev Error selector: `0x5fe9a5df` + error UnreachableName(bytes name); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @dev Computes and stores the parent node and DNS-encoded parent hash for efficient lookups. + /// @param label The string label for the namespace (e.g., "8000000a" for OP Mainnet). + constructor(string memory label) { + // Compute the namehash of "{label}.reverse" + PARENT_NODE = NameCoder.namehash(_REVERSE_NODE, keccak256(bytes(label))); + + // Build the DNS-encoded parent name: {labelLength}{label}{7}reverse{0} + bytes memory parent = + abi.encodePacked(NameCoder.assertLabelSize(label), label, uint8(7), "reverse", uint8(0)); + _SIMPLE_HASHED_PARENT = keccak256(parent); + _PARENT_LENGTH = parent.length; + } + + /// @inheritdoc ERC165 + function supportsInterface(bytes4 interfaceID) + public + view + virtual + override(ERC165) + returns (bool) + { + return + interfaceID == type(IExtendedResolver).interfaceId || + interfaceID == type(INameResolver).interfaceId || + interfaceID == type(IStandaloneReverseRegistrar).interfaceId || + super.supportsInterface(interfaceID); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Returns the primary ENS name for a given reverse node. + /// @inheritdoc INameResolver + /// @param node The reverse node to query. + /// @return The primary ENS name associated with the node, or an empty string if not set. + function name(bytes32 node) external view override returns (string memory) { + return _names[node]; + } + + /// @inheritdoc IStandaloneReverseRegistrar + function nameForAddr(address addr) external view returns (string memory) { + return + _names[NameCoder.namehash(PARENT_NODE, keccak256(bytes(LibString.toAddressString(addr))))]; + } + + /// @notice Resolves a DNS-encoded reverse name to its primary ENS name. + /// @dev Implements ENSIP-10 wildcard resolution for reverse lookups. + /// Only supports the `name(bytes32)` resolver profile. + /// + /// Expected name format: {40-char-hex-address}.{label}.reverse + /// DNS-encoded: {0x28}{40-hex-chars}{labelLen}{label}{0x07}reverse{0x00} + /// + /// @param name_ The DNS-encoded reverse name to resolve. + /// @param data The ABI-encoded function call (must be `name(bytes32)`). + /// @return The ABI-encoded primary ENS name. + function resolve(bytes calldata name_, bytes calldata data) + external + view + override + returns (bytes memory) + { + bytes4 selector = bytes4(data); + + // Only support the name(bytes32) resolver profile + if (selector != INameResolver.name.selector) + revert UnsupportedResolverProfile(selector); + + // Validate name length: 41 bytes for address component + parent suffix + // 41 = 1 byte (length prefix) + 40 bytes (hex address without 0x) + if (name_.length != _PARENT_LENGTH + 41) + revert UnreachableName(name_); + + // Validate the parent suffix matches this registrar's namespace + if (keccak256(name_[41:]) != _SIMPLE_HASHED_PARENT) + revert UnreachableName(name_); + + // Compute the reverse node and return the stored name + bytes32 node = keccak256(abi.encodePacked(PARENT_NODE, keccak256(name_[1:41]))); + return abi.encode(_names[node]); + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + /// @notice Sets the primary ENS name for an address. + /// @dev Computes the reverse node from the address and stores the name. + /// Emits ENSIP-16 events for indexer compatibility. + /// + /// IMPORTANT: Authorisation must be checked by the caller before invoking this function. + /// + /// @param addr The address to set the primary name for. + /// @param name_ The primary ENS name to associate with the address. + function _setName(address addr, string memory name_) internal { + // Convert address to lowercase hex string (without 0x prefix) + string memory label = LibString.toAddressString(addr); + + // Compute the token ID and reverse node + bytes32 labelHash = keccak256(bytes(label)); + uint256 tokenId = uint256(labelHash); + bytes32 node = keccak256(abi.encodePacked(PARENT_NODE, labelHash)); + + // Reverse names never expire + uint64 expiry = type(uint64).max; + + // Store the name + _names[node] = name_; + + // Emit ENSIP-16 events for indexer compatibility + emit LabelRegistered(tokenId, labelHash, label, addr, expiry, msg.sender); + emit ResolverUpdated(tokenId, address(this), msg.sender); + emit NameChanged(node, name_); + } +} diff --git a/contracts/src/reverse-registrar/interfaces/IContractName.sol b/contracts/src/reverse-registrar/interfaces/IContractName.sol new file mode 100755 index 000000000..67ad8ae3b --- /dev/null +++ b/contracts/src/reverse-registrar/interfaces/IContractName.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +/// @dev Interface selector: `0x75d0c0dc` +interface IContractName { + /// @notice The unverified ENS name for this contract, e.g "mycontract.eth". + /// Should not be invoked directly. + /// Must be verified through ENSIP-19. + function contractName() external view returns (string memory); +} diff --git a/contracts/src/reverse-registrar/interfaces/IContractNamer.sol b/contracts/src/reverse-registrar/interfaces/IContractNamer.sol new file mode 100755 index 000000000..0630a62ab --- /dev/null +++ b/contracts/src/reverse-registrar/interfaces/IContractNamer.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +/// @dev Interface selector: `0x6f3ff726` +interface IContractNamer { + /// @notice Determine if an account is authorized to name this contract. + /// Called by reverse registrars. + /// @param namer The address to check. + /// @return `true` if authorized. + function isContractNamer(address namer) external view returns (bool); +} diff --git a/contracts/src/reverse-registrar/interfaces/IL2ReverseRegistrar.sol b/contracts/src/reverse-registrar/interfaces/IL2ReverseRegistrar.sol new file mode 100644 index 000000000..b64554650 --- /dev/null +++ b/contracts/src/reverse-registrar/interfaces/IL2ReverseRegistrar.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +/// @dev Interface selector: `0xd037477f` +interface IL2ReverseRegistrar { + struct NameClaim { + string name; + address addr; + uint256[] chainIds; + uint256 signedAt; + } + + /// @notice Sets the `nameForAddr()` record for the calling account. + /// @param name The name to set. + function setName(string memory name) external; + + /// @notice Sets the `nameForAddr()` record for the addr provided account. + /// @param addr The address to set the name for. + /// @param name The name to set. + function setNameForAddr(address addr, string memory name) external; + + /// @notice Sets the `nameForAddr()` record for the addr provided account using a signature. + /// @param claim The claim to set the name for. + /// @param signature The signature from the addr. + function setNameForAddrWithSignature(NameClaim calldata claim, bytes calldata signature) + external; + + /// @notice Sets the `nameForAddr()` record for the contract provided using a signature. + /// @param claim The claim to set the name for. + /// @param namer The namer of the contract (via `Ownable` or `IContractNamer`). + /// @param signature The signature of an address that will return true on isValidSignature for the owner. + function setNameForContractWithSignature( + NameClaim calldata claim, + address namer, + bytes calldata signature + ) + external; + + /// @notice Set the `nameForAddr()` record for the contract provided using `IContractName`. + /// Callable by anyone. + /// Reverts if not implemented. + /// Does not require `ERC165` support. + /// @param addr The address to set the name for. + function syncName(address addr) external; + + /// @notice Returns the inception timestamp for a given address. + /// @dev Only signatures with a signedAt timestamp greater than the inception can be used. + /// @param addr The address to query. + /// @return The inception timestamp for the address. + function inceptionOf(address addr) external view returns (uint256); +} diff --git a/contracts/src/reverse-registrar/libraries/AccountNamerLib.sol b/contracts/src/reverse-registrar/libraries/AccountNamerLib.sol new file mode 100755 index 000000000..3573ebe99 --- /dev/null +++ b/contracts/src/reverse-registrar/libraries/AccountNamerLib.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +import {IContractNamer} from "../interfaces/IContractNamer.sol"; + +/// @dev Determine if an address is nameable. +library AccountNamerLib { + /// @dev Error selector: `0x0d1b7e4e` + error UnauthorizedNamer(address namer); + + /// @dev Check if an address can be named. + /// @param account The address to name. + /// @param namer The address of the namer. + /// @return canName `true` if `namer` can name `addr`. + function isNamer(address account, address namer) internal view returns (bool canName) { + canName = account == namer; + if (!canName && account.code.length > 0) { + try Ownable(account).owner() returns (address owner) { + canName = owner == namer; + } catch {} + if (!canName) { + try IContractNamer(account).isContractNamer(namer) returns (bool can) { + canName = can; + } catch {} + } + } + } + + /// @dev Ensure `namer` can name `account`. + /// @param account The address to name. + /// @param namer The address of the namer. + function requireNamer(address account, address namer) internal view { + if (!isNamer(account, namer)) { + revert UnauthorizedNamer(namer); + } + } +} diff --git a/contracts/src/reverse-registrar/libraries/ChainIdsBuilderLib.sol b/contracts/src/reverse-registrar/libraries/ChainIdsBuilderLib.sol new file mode 100644 index 000000000..a8b0dbaaa --- /dev/null +++ b/contracts/src/reverse-registrar/libraries/ChainIdsBuilderLib.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +/// @title ChainIdsBuilderLib +/// @notice Validates a strictly-ascending array of chain IDs and builds the +/// comma-separated display string in a single pass with O(n) memory. +/// @dev The naive `string.concat` approach allocates a new copy of the +/// accumulated string on every iteration, resulting in O(n²) total memory. +/// This library pre-allocates a single buffer and writes each chain ID's +/// decimal representation directly into it, keeping memory O(n). +library ChainIdsBuilderLib { + /// @notice Thrown when the chain ID array is not in strictly ascending order. + /// @dev Error selector: `0xea0b14e2` + error ChainIdsNotAscending(); + + /// @notice Thrown when the current chain ID is not included in the array. + /// @dev Error selector: `0x756925c8` + error CurrentChainNotFound(uint256 chainId); + + /// @dev Validates chain IDs are strictly ascending, contain `currentChainId`, + /// and builds the comma-separated display string. + /// @param chainIds Calldata array of chain IDs (must be strictly ascending). + /// @param currentChainId The chain ID that must be present in the array. + /// @return result The comma-separated string, e.g. "1, 10, 8453". + function validateAndBuild(uint256[] calldata chainIds, uint256 currentChainId) + internal + pure + returns (string memory result) + { + uint256 length = chainIds.length; + if (length == 0) + revert CurrentChainNotFound(currentChainId); + + /// @solidity memory-safe-assembly + assembly { + // Grab the free memory pointer; the string will be built in-place. + result := mload(0x40) + let buf := add(result, 32) // data region starts after the 32-byte length slot + let ptr := buf // write cursor + let prev := 0 + let containsCurrent := 0 + + for { + let i := 0 + } lt(i, length) { + i := add(i, 1) + } { + let val := calldataload(add(chainIds.offset, shl(5, i))) + + // --- Validate strictly ascending (skip for the first element) --- + if i { + if iszero(gt(val, prev)) { + // revert ChainIdsNotAscending() + mstore( + 0x00, + 0xea0b14e200000000000000000000000000000000000000000000000000000000 + ) + revert(0x00, 0x04) + } + } + prev := val + // --- Track whether the required chain ID is present --- + if eq(val, currentChainId) { + containsCurrent := 1 + } + + // --- Write ", " separator before every element except the first --- + if i { + mstore8(ptr, 0x2c) // ',' + ptr := add(ptr, 1) + mstore8(ptr, 0x20) // ' ' + ptr := add(ptr, 1) + } + + // --- Write the decimal representation of `val` --- + switch val + case 0 { + mstore8(ptr, 0x30) // '0' + ptr := add(ptr, 1) + } + default { + // Count decimal digits + let digits := 0 + let tmp := val + for {} tmp {} { + digits := add(digits, 1) + tmp := div(tmp, 10) + } + + // Write digits right-to-left into the buffer + let end := add(ptr, digits) + tmp := val + for {} tmp {} { + end := sub(end, 1) + mstore8(end, add(48, mod(tmp, 10))) + tmp := div(tmp, 10) + } + ptr := add(ptr, digits) + } + } + + // Store the final string length and update the free memory pointer. + mstore(result, sub(ptr, buf)) + mstore(0x40, and(add(ptr, 31), not(31))) + + // Revert if the required chain ID was never encountered. + if iszero(containsCurrent) { + // revert CurrentChainNotFound(currentChainId) + mstore(0x00, 0x756925c800000000000000000000000000000000000000000000000000000000) + mstore(0x04, currentChainId) + revert(0x00, 0x24) + } + } + } +} diff --git a/contracts/src/testnet/TestnetV1PremigrationRegistrar.sol b/contracts/src/testnet/TestnetV1PremigrationRegistrar.sol new file mode 100644 index 000000000..3629f7b70 --- /dev/null +++ b/contracts/src/testnet/TestnetV1PremigrationRegistrar.sol @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +import { + BaseRegistrarImplementation +} from "@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol"; +import {IETHRegistrarController} from "@ens/contracts/ethregistrar/IETHRegistrarController.sol"; +import {ENS} from "@ens/contracts/registry/ENS.sol"; +import {Resolver} from "@ens/contracts/resolvers/Resolver.sol"; +import { + IDefaultReverseRegistrar +} from "@ens/contracts/reverseRegistrar/IDefaultReverseRegistrar.sol"; +import {IReverseRegistrar} from "@ens/contracts/reverseRegistrar/IReverseRegistrar.sol"; +import {StringUtils} from "@ens/contracts/utils/StringUtils.sol"; + +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {IRegistry} from "../registry/interfaces/IRegistry.sol"; +import {LibLabel} from "../utils/LibLabel.sol"; + +/// @title TestnetV1PremigrationRegistrar +/// @notice Free testnet-only v1 registration controller that immediately reserves names in ENSv2. +contract TestnetV1PremigrationRegistrar { + using StringUtils for *; + + //////////////////////////////////////////////////////////////////////// + // Constants & Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The bitmask for setting the Ethereum reverse record. + uint8 public constant REVERSE_RECORD_ETHEREUM_BIT = 1; + + /// @notice The bitmask for setting the default reverse record. + uint8 public constant REVERSE_RECORD_DEFAULT_BIT = 2; + + /// @notice The minimum registration duration accepted by the v1 controller. + uint256 public constant MIN_REGISTRATION_DURATION = 28 days; + + /// @notice Bonus added to the v2 reservation expiry so testnet reservations match + /// the migration's continuity-adjusted expiry (v1 grace minus v2 grace) and + /// pass the premigration verifier's expected-expiry check, which expects + /// `v1Expiry + bonusPeriodDays` (default 62 days, i.e. 90 days - 28 days). + uint256 public constant CONTINUITY_BONUS_PERIOD = 90 days - 28 days; + + /// @notice The ENS namehash for `eth`. + bytes32 public constant ETH_NODE = + 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae; + + /// @notice The ENSv1 base registrar used to mint the `.eth` registration. + BaseRegistrarImplementation public immutable BASE; + + /// @notice The ENSv1 registry used when setting resolver records. + ENS public immutable ENS_REGISTRY; + + /// @notice The ENSv1 Ethereum reverse registrar. + IReverseRegistrar public immutable REVERSE_REGISTRAR; + + /// @notice The ENSv1 default reverse registrar. + IDefaultReverseRegistrar public immutable DEFAULT_REVERSE_REGISTRAR; + + /// @notice The ENSv2 `.eth` registry where names are reserved for premigration. + IPermissionedRegistry public immutable ETH_REGISTRY; + + /// @notice The ENSv2 subregistry assigned to premigrated reservations. + IRegistry public immutable PREMIGRATION_REGISTRY; + + /// @notice The ENSv2 resolver assigned to premigrated reservations. + address public immutable PREMIGRATION_RESOLVER; + + //////////////////////////////////////////////////////////////////////// + // Events + //////////////////////////////////////////////////////////////////////// + + /// @notice Emitted when a name is registered. + /// @param label The label of the name. + /// @param labelhash The keccak256 hash of the label. + /// @param owner The owner of the name. + /// @param baseCost The base cost of the name. + /// @param premium The premium cost of the name. + /// @param expires The expiry time of the name. + /// @param referrer The referrer of the registration. + event NameRegistered( + string label, + bytes32 indexed labelhash, + address indexed owner, + uint256 baseCost, + uint256 premium, + uint256 expires, + bytes32 referrer + ); + + //////////////////////////////////////////////////////////////////////// + // Errors + //////////////////////////////////////////////////////////////////////// + + /// @notice Name is not available for v1 registration. + /// @dev Error selector: `0x477707e8` + /// @param name The unavailable label. + error NameNotAvailable(string name); + + /// @notice Registration duration is below the accepted minimum. + /// @dev Error selector: `0x9a71997b` + /// @param duration The supplied duration. + error DurationTooShort(uint256 duration); + + /// @notice Resolver calldata was supplied without a resolver. + /// @dev Error selector: `0xd3f605c4` + error ResolverRequiredWhenDataSupplied(); + + /// @notice A reverse record was requested without a resolver. + /// @dev Error selector: `0x7d4a034a` + error ResolverRequiredForReverseRecord(); + + /// @notice The v1 expiry cannot fit in the ENSv2 registry expiry field. + /// @dev Error selector: `0x544476c3` + /// @param expiry The v1 expiry timestamp. + error ExpiryTooLarge(uint256 expiry); + + /// @notice Refund of accidentally supplied ETH failed. + /// @dev Error selector: `0xaf73b0b2` + /// @param recipient The refund recipient. + /// @param amount The amount that failed to refund. + error RefundFailed(address recipient, uint256 amount); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @notice Initializes the testnet registration controller. + /// @param base_ The ENSv1 base registrar. + /// @param ensRegistry_ The ENSv1 registry. + /// @param reverseRegistrar_ The ENSv1 Ethereum reverse registrar. + /// @param defaultReverseRegistrar_ The ENSv1 default reverse registrar. + /// @param ethRegistry_ The ENSv2 `.eth` registry. + /// @param premigrationRegistry_ The ENSv2 subregistry to assign to reservations. + /// @param premigrationResolver_ The ENSv2 resolver to assign to reservations. + constructor( + BaseRegistrarImplementation base_, + ENS ensRegistry_, + IReverseRegistrar reverseRegistrar_, + IDefaultReverseRegistrar defaultReverseRegistrar_, + IPermissionedRegistry ethRegistry_, + IRegistry premigrationRegistry_, + address premigrationResolver_ + ) + { + BASE = base_; + ENS_REGISTRY = ensRegistry_; + REVERSE_REGISTRAR = reverseRegistrar_; + DEFAULT_REVERSE_REGISTRAR = defaultReverseRegistrar_; + ETH_REGISTRY = ethRegistry_; + PREMIGRATION_REGISTRY = premigrationRegistry_; + PREMIGRATION_RESOLVER = premigrationResolver_; + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Registers a `.eth` label in ENSv1 for free and reserves it in ENSv2. + /// @param registration The v1 controller registration parameters. + function register(IETHRegistrarController.Registration calldata registration) external payable { + bytes32 labelhash = keccak256(bytes(registration.label)); + + if (registration.duration < MIN_REGISTRATION_DURATION) { + revert DurationTooShort(registration.duration); + } + if (!_available(registration.label, labelhash)) { + revert NameNotAvailable(registration.label); + } + if (registration.data.length > 0 && registration.resolver == address(0)) { + revert ResolverRequiredWhenDataSupplied(); + } + if (registration.reverseRecord != 0 && registration.resolver == address(0)) { + revert ResolverRequiredForReverseRecord(); + } + + uint256 expires = _registerV1(registration, labelhash); + _premigrate(registration.label, expires); + + emit NameRegistered( + registration.label, + labelhash, + registration.owner, + 0, + 0, + expires, + registration.referrer + ); + + _refund(); + } + + /// @notice Returns true if the label is valid and available for v1 registration. + /// @param label The label to check. + /// @return True if the label is valid and available, false otherwise. + function available(string calldata label) public view returns (bool) { + return _available(label, keccak256(bytes(label))); + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + /// @dev Registers the name in ENSv1 and applies optional resolver and reverse records. + function _registerV1( + IETHRegistrarController.Registration calldata registration, + bytes32 labelhash + ) + internal + returns (uint256 expires) + { + uint256 tokenId = uint256(labelhash); + if (registration.resolver == address(0)) { + return BASE.register(tokenId, registration.owner, registration.duration); + } + + expires = BASE.register(tokenId, address(this), registration.duration); + bytes32 namehash = keccak256(abi.encodePacked(ETH_NODE, labelhash)); + + // Apply resolver records while this registrar still owns the node, then hand + // ownership to the registrant. A resolver that authorises writes by node owner + // would otherwise reject these calls once ownership has moved. + ENS_REGISTRY.setResolver(namehash, registration.resolver); + if (registration.data.length > 0) { + Resolver(registration.resolver).multicallWithNodeCheck(namehash, registration.data); + } + ENS_REGISTRY.setOwner(namehash, registration.owner); + + BASE.transferFrom(address(this), registration.owner, tokenId); + + // Reverse records are set for the registrant rather than the caller. + string memory name = string.concat(registration.label, ".eth"); + if (registration.reverseRecord & REVERSE_RECORD_ETHEREUM_BIT != 0) { + REVERSE_REGISTRAR.setNameForAddr( + registration.owner, + registration.owner, + registration.resolver, + name + ); + } + if (registration.reverseRecord & REVERSE_RECORD_DEFAULT_BIT != 0) { + DEFAULT_REVERSE_REGISTRAR.setNameForAddr(registration.owner, name); + } + } + + /// @dev Reserves or extends the matching ENSv2 reservation. Every reservation + /// carries the continuity bonus on top of the v1 expiry, matching the migration's + /// expected expiry for premigrated names. + function _premigrate(string calldata label, uint256 v1Expiry) internal { + uint256 reservationExpiry = v1Expiry + CONTINUITY_BONUS_PERIOD; + if (reservationExpiry > type(uint64).max) { + revert ExpiryTooLarge(reservationExpiry); + } + + IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label)); + uint64 expiry = uint64(reservationExpiry); + + if (state.status == IPermissionedRegistry.Status.AVAILABLE) { + ETH_REGISTRY.register( + label, + address(0), + PREMIGRATION_REGISTRY, + PREMIGRATION_RESOLVER, + 0, + expiry + ); + } else if (state.status == IPermissionedRegistry.Status.RESERVED && expiry > state.expiry) { + ETH_REGISTRY.renew(state.tokenId, expiry); + } + } + + /// @dev Refunds ETH because this testnet controller is free. + function _refund() internal { + if (msg.value == 0) + return; + + (bool ok, ) = payable(msg.sender).call{value: msg.value}(""); + if (!ok) { + revert RefundFailed(msg.sender, msg.value); + } + } + + /// @dev Returns true when the label is valid and available in ENSv1. + function _available(string calldata label, bytes32 labelhash) internal view returns (bool) { + return label.strlen() >= 3 && BASE.available(uint256(labelhash)); + } +} diff --git a/contracts/src/universalResolver/UniversalResolverV2.sol b/contracts/src/universalResolver/UniversalResolverV2.sol index 0580c4b1d..3725abfcb 100644 --- a/contracts/src/universalResolver/UniversalResolverV2.sol +++ b/contracts/src/universalResolver/UniversalResolverV2.sol @@ -1,60 +1,107 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; +import {IGatewayProvider} from "@ens/contracts/ccipRead/IGatewayProvider.sol"; import { - AbstractUniversalResolver, - IGatewayProvider + AbstractUniversalResolver } from "@ens/contracts/universalResolver/AbstractUniversalResolver.sol"; -import {LibRegistry, IRegistry} from "./libraries/LibRegistry.sol"; +import {IPermissionedRegistry} from "../registry/interfaces/IPermissionedRegistry.sol"; +import {IRegistry} from "../registry/interfaces/IRegistry.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; +import {DelegatedContractNamer} from "../utils/DelegatedContractNamer.sol"; + +import {IUniversalResolverV2} from "./interfaces/IUniversalResolverV2.sol"; +import {LibRegistry} from "./libraries/LibRegistry.sol"; -/// @notice ENS Universal Resolver that traverses the namechain registry hierarchy to locate +/// @notice Universal Resolver that traverses the namechain registry hierarchy to locate /// resolvers and registries for any DNS-encoded name. -contract UniversalResolverV2 is AbstractUniversalResolver { - IRegistry public immutable ROOT_REGISTRY; +contract UniversalResolverV2 is + AbstractUniversalResolver, + DelegatedContractNamer, + IUniversalResolverV2 +{ + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice The ENSv2 root registry. + IPermissionedRegistry public immutable ROOT_REGISTRY; + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param rootRegistry The root registry. + /// @param batchGatewayProvider The batch gateway provider. + /// @param contractNamer Delegated contract namer. constructor( - IRegistry root, - IGatewayProvider batchGatewayProvider - ) AbstractUniversalResolver(batchGatewayProvider) { - ROOT_REGISTRY = root; + IPermissionedRegistry rootRegistry, + IGatewayProvider batchGatewayProvider, + IContractNamer contractNamer + ) + AbstractUniversalResolver(batchGatewayProvider) + DelegatedContractNamer(contractNamer) + { + ROOT_REGISTRY = rootRegistry; + } + + /// @inheritdoc AbstractUniversalResolver + function supportsInterface(bytes4 interfaceId) + public + view + virtual + override(AbstractUniversalResolver, DelegatedContractNamer) + returns (bool) + { + // note: this is some kind of compiler bug probably due to oz v4/v5 + return + type(IUniversalResolverV2).interfaceId == interfaceId || + AbstractUniversalResolver.supportsInterface(interfaceId) || + DelegatedContractNamer.supportsInterface(interfaceId); } - /// @notice Construct the canonical name for `registry`. - /// - /// @param registry The registry to name. - /// - /// @return The DNS-encoded name or empty if not canonical. + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @inheritdoc IUniversalResolverV2 + function findOwner(bytes calldata name) external view returns (address) { + return LibRegistry.findOwner(ROOT_REGISTRY, name, 0); + } + + /// @inheritdoc IUniversalResolverV2 function findCanonicalName(IRegistry registry) external view returns (bytes memory) { return LibRegistry.findCanonicalName(ROOT_REGISTRY, registry); } - /// @notice Find the canonical registry for `name`. - /// - /// @param name The DNS-encoded name. - /// - /// @return The canonical registry or null if not canonical. + /// @inheritdoc IUniversalResolverV2 function findCanonicalRegistry(bytes calldata name) external view returns (IRegistry) { return LibRegistry.findCanonicalRegistry(ROOT_REGISTRY, name); } - /// @notice Find all registries in the ancestry of `name`. - /// * `findRegistries("") = []` - /// * `findRegistries("eth") = [, ]` - /// * `findRegistries("nick.eth") = [, , ]` - /// * `findRegistries("sub.nick.eth") = [null, , , ]` - /// - /// @param name The DNS-encoded name. - /// - /// @return Array of registries in label-order. + /// @inheritdoc IUniversalResolverV2 + function findExactRegistry(bytes calldata name) external view returns (IRegistry) { + return LibRegistry.findExactRegistry(ROOT_REGISTRY, name, 0); + } + + /// @inheritdoc IUniversalResolverV2 + function findParentRegistry(bytes calldata name) external view returns (IRegistry) { + return LibRegistry.findParentRegistry(ROOT_REGISTRY, name, 0); + } + + /// @inheritdoc IUniversalResolverV2 function findRegistries(bytes calldata name) external view returns (IRegistry[] memory) { return LibRegistry.findRegistries(ROOT_REGISTRY, name, 0); } /// @inheritdoc AbstractUniversalResolver - function findResolver( - bytes memory name - ) public view override returns (address resolver, bytes32 node, uint256 offset) { + function findResolver(bytes memory name) + public + view + override + returns (address resolver, bytes32 node, uint256 offset) + { (, resolver, node, offset) = LibRegistry.findResolver(ROOT_REGISTRY, name, 0); } } diff --git a/contracts/src/universalResolver/UpgradableUniversalResolverProxy.sol b/contracts/src/universalResolver/UpgradableUniversalResolverProxy.sol index ce2fe61b1..0596916fe 100644 --- a/contracts/src/universalResolver/UpgradableUniversalResolverProxy.sol +++ b/contracts/src/universalResolver/UpgradableUniversalResolverProxy.sol @@ -6,18 +6,18 @@ import {BytesUtils} from "@ens/contracts/utils/BytesUtils.sol"; import {StorageSlot} from "@openzeppelin/contracts/utils/StorageSlot.sol"; /// @title UpgradableUniversalResolverProxy -/// @dev A specialized proxy for UniversalResolver that forwards method calls -/// and properly handles CCIP-Read reverts. Admin can upgrade the implementation. +/// @notice A specialized proxy for UniversalResolver that forwards method calls +/// and properly handles CCIP-Read reverts. Admin can upgrade the implementation. contract UpgradableUniversalResolverProxy { //////////////////////////////////////////////////////////////////////// // Constants //////////////////////////////////////////////////////////////////////// - // Storage slot for implementation address (EIP-1967 compatible) + /// @dev Storage slot for implementation address (EIP-1967 compatible) bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - // Storage slot for admin (EIP-1967 compatible) + /// @dev Storage slot for admin (EIP-1967 compatible) bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; @@ -25,10 +25,17 @@ contract UpgradableUniversalResolverProxy { // Events //////////////////////////////////////////////////////////////////////// + /// @notice Event emitted when the implementation is upgraded. + /// @param implementation The new implementation address event Upgraded(address indexed implementation); + /// @notice Event emitted when the admin is changed. + /// @param previousAdmin The previous admin address + /// @param newAdmin The new admin address event AdminChanged(address indexed previousAdmin, address indexed newAdmin); + /// @notice Event emitted when the admin is removed. + /// @param admin The admin address that was removed event AdminRemoved(address indexed admin); //////////////////////////////////////////////////////////////////////// @@ -50,7 +57,8 @@ contract UpgradableUniversalResolverProxy { /// @dev Modifier restricting a function to the admin. modifier onlyAdmin() { - if (msg.sender != _getAdmin()) revert CallerNotAdmin(); + if (msg.sender != _getAdmin()) + revert CallerNotAdmin(); _; } @@ -58,7 +66,8 @@ contract UpgradableUniversalResolverProxy { // Initialization //////////////////////////////////////////////////////////////////////// - /// @dev Initializes the proxy with an implementation and admin. + /// @param admin_ The address of the admin + /// @param implementation_ The address of the implementation constructor(address admin_, address implementation_) { _validateImplementation(implementation_); _setImplementation(implementation_); @@ -69,8 +78,8 @@ contract UpgradableUniversalResolverProxy { // Implementation //////////////////////////////////////////////////////////////////////// - /// @dev Fallback function that handles forwarding calls to the implementation - /// and properly manages CCIP-Read reverts. + /// @notice Fallback function that handles forwarding calls to the implementation + /// and properly manages CCIP-Read reverts. fallback() external { (bool ok, bytes memory v) = _getImplementation().staticcall(msg.data); if (!ok && bytes4(v) == OffchainLookup.selector) { @@ -97,7 +106,7 @@ contract UpgradableUniversalResolverProxy { } } - /// @dev Upgrades to a new implementation. + /// @notice Upgrades to a new implementation. /// @param newImplementation Address of the new implementation function upgradeTo(address newImplementation) external onlyAdmin { _validateImplementation(newImplementation); @@ -105,19 +114,19 @@ contract UpgradableUniversalResolverProxy { emit Upgraded(newImplementation); } - /// @dev Allows admin to revoke their admin rights by setting admin to address(0). + /// @notice Allows admin to revoke their admin rights by setting admin to address(0). function renounceAdmin() external onlyAdmin { - address admin_ = _getAdmin(); + address currentAdmin = _getAdmin(); _setAdmin(address(0)); - emit AdminRemoved(admin_); + emit AdminRemoved(currentAdmin); } - /// @dev Returns the current implementation address. + /// @notice Returns the current implementation address. function implementation() external view returns (address) { return _getImplementation(); } - /// @dev Returns the current admin address. + /// @notice Returns the current admin address. function admin() external view returns (address) { return _getAdmin(); } diff --git a/contracts/src/universalResolver/interfaces/IUniversalResolverV2.sol b/contracts/src/universalResolver/interfaces/IUniversalResolverV2.sol new file mode 100755 index 000000000..9c5148740 --- /dev/null +++ b/contracts/src/universalResolver/interfaces/IUniversalResolverV2.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IRegistry} from "../../registry/interfaces/IRegistry.sol"; + +/// @notice Interface for ENSv2-specific UniversalResolver helper functions. +/// @dev Interface selector: `0xf99a5e06` +interface IUniversalResolverV2 { + /// @notice Find the owner for `name`. + /// @param name The DNS-encoded name. + /// @return The owner address or null if unowned or not found. + function findOwner(bytes calldata name) external view returns (address); + + /// @notice Construct the canonical name for `registry`. + /// @param registry The registry to name. + /// @return The DNS-encoded name or empty if not canonical. + function findCanonicalName(IRegistry registry) external view returns (bytes memory); + + /// @notice Find the canonical registry for `name`. + /// @param name The DNS-encoded name. + /// @return The canonical registry or null if not canonical. + function findCanonicalRegistry(bytes calldata name) external view returns (IRegistry); + + /// @notice Find the exact registry for `name`. + /// @param name The DNS-encoded name. + /// @return The registry or null if not found. + function findExactRegistry(bytes calldata name) external view returns (IRegistry); + + /// @notice Find the parent registry for `name`. + /// @param name The DNS-encoded name. + /// @return The parent registry or null if not found. + function findParentRegistry(bytes calldata name) external view returns (IRegistry); + + /// @notice Find all registries in the ancestry of `name`. + /// * `findRegistries("") = []` + /// * `findRegistries("eth") = [, ]` + /// * `findRegistries("nick.eth") = [, , ]` + /// * `findRegistries("sub.nick.eth") = [null, , , ]` + /// + /// @param name The DNS-encoded name. + /// @return Array of registries in label-order. + function findRegistries(bytes calldata name) external view returns (IRegistry[] memory); +} diff --git a/contracts/src/universalResolver/libraries/LibRegistry.sol b/contracts/src/universalResolver/libraries/LibRegistry.sol index d6427d141..0179bb6cf 100644 --- a/contracts/src/universalResolver/libraries/LibRegistry.sol +++ b/contracts/src/universalResolver/libraries/LibRegistry.sol @@ -2,27 +2,23 @@ pragma solidity >=0.8.24; import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {IOwnedRegistry} from "../../registry/interfaces/IOwnedRegistry.sol"; import {IRegistry} from "../../registry/interfaces/IRegistry.sol"; /// @dev Recursive traversal helpers for the namechain registry tree — resolver lookup, registry /// discovery, canonical name construction, and ancestry enumeration. library LibRegistry { /// @dev Find the resolver address for `name[offset:]`. - /// /// @param rootRegistry The root ENS registry. /// @param name The DNS-encoded name to search. /// @param offset The offset into `name` to begin the search. - /// /// @return exactRegistry The exact registry or null if not exact. /// @return resolver The resolver or null if not found. /// @return node The namehash of `name[offset:]`. /// @return resolverOffset The offset into `name` corresponding to `resolver`. - function findResolver( - IRegistry rootRegistry, - bytes memory name, - uint256 offset - ) + function findResolver(IRegistry rootRegistry, bytes memory name, uint256 offset) internal view returns (IRegistry exactRegistry, address resolver, bytes32 node, uint256 resolverOffset) @@ -48,58 +44,34 @@ library LibRegistry { node = NameCoder.namehash(node, labelHash); // update namehash } - /// @notice Find (registry, resolver) for `name[offset:]` starting from - /// (parentRegistry, parentResolver) for `name[:parentOffset]`. - /// + /// @dev Find the owner for `name[offset:]`. + /// @param rootRegistry The root ENS registry. /// @param name The DNS-encoded name to search. - /// @param offset The offset into `name` to begin the search. - /// @param parentOffset The offset into `name` to use parent values. - /// @param parentRegistry The registry at `name[length:]`. - /// @param parentResolver The resolver at `name[length:]`. - /// - /// @return registry The exact registry or null if not exact. - /// @return resolver The resolver or null if not found. - function findResolverFromParent( - bytes memory name, - uint256 offset, - uint256 parentOffset, - IRegistry parentRegistry, - address parentResolver - ) internal view returns (IRegistry registry, address resolver) { - if (offset > parentOffset) { - revert NameCoder.DNSDecodingFailed(name); - } else if (offset == parentOffset) { - return (parentRegistry, parentResolver); - } else { - string memory label; - (label, offset) = NameCoder.extractLabel(name, offset); - (registry, resolver) = findResolverFromParent( - name, - offset, - parentOffset, - parentRegistry, - parentResolver - ); - if (address(registry) != address(0)) { - address res = registry.getResolver(label); - if (res != address(0)) { - resolver = res; - } - registry = registry.getSubregistry(label); - } + /// @return owner The owner address or null if unowned or not found. + function findOwner(IRegistry rootRegistry, bytes memory name, uint256 offset) + internal + view + returns (address owner) + { + IRegistry registry = findParentRegistry(rootRegistry, name, offset); + if ( + address(registry) != address(0) && + ERC165Checker.supportsInterface(address(registry), type(IOwnedRegistry).interfaceId) + ) { + (string memory label, ) = NameCoder.extractLabel(name, offset); + owner = IOwnedRegistry(address(registry)).findOwner(label); } } - /// @notice Construct the canonical name for `registry`. - /// + /// @dev Construct the canonical name for `registry`. /// @param rootRegistry The root ENS registry. /// @param registry The registry to name. - /// /// @return name The DNS-encoded name or empty if not canonical. - function findCanonicalName( - IRegistry rootRegistry, - IRegistry registry - ) internal view returns (bytes memory name) { + function findCanonicalName(IRegistry rootRegistry, IRegistry registry) + internal + view + returns (bytes memory name) + { if (address(registry) == address(0)) { return ""; } @@ -120,36 +92,33 @@ library LibRegistry { } } - /// @notice Find the registry for `name` and return it iff it is canonical for that name. - /// + /// @dev Find the registry for `name` and return it iff it is canonical for that name. /// @param rootRegistry The root ENS registry. /// @param name The DNS-encoded name. - /// /// @return The canonical registry or null if not canonical. - function findCanonicalRegistry( - IRegistry rootRegistry, - bytes memory name - ) internal view returns (IRegistry) { + function findCanonicalRegistry(IRegistry rootRegistry, bytes memory name) + internal + view + returns (IRegistry) + { IRegistry registry = LibRegistry.findExactRegistry(rootRegistry, name, 0); return address(registry) != address(0) && - keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) == - keccak256(name) - ? registry - : IRegistry(address(0)); + keccak256(bytes(LibRegistry.findCanonicalName(rootRegistry, registry))) == + keccak256(name) + ? registry + : IRegistry(address(0)); } - /// @notice Find the exact registry for `name[offset:]`. - /// + /// @dev Find the exact registry for `name[offset:]`. /// @param rootRegistry The root ENS registry. /// @param name The DNS-encoded name to search. - /// /// @return exactRegistry The exact registry or null if not found. - function findExactRegistry( - IRegistry rootRegistry, - bytes memory name, - uint256 offset - ) internal view returns (IRegistry exactRegistry) { + function findExactRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset) + internal + view + returns (IRegistry exactRegistry) + { (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset); if (labelHash == bytes32(0)) { return rootRegistry; @@ -161,35 +130,31 @@ library LibRegistry { } } - /// @notice Find the parent registry for `name[offset:]`. - /// + /// @dev Find the parent registry for `name[offset:]`. /// @param rootRegistry The root ENS registry. /// @param name The DNS-encoded name to search. - /// /// @return parentRegistry The parent registry or null if not found. - function findParentRegistry( - IRegistry rootRegistry, - bytes memory name, - uint256 offset - ) internal view returns (IRegistry parentRegistry) { + function findParentRegistry(IRegistry rootRegistry, bytes memory name, uint256 offset) + internal + view + returns (IRegistry parentRegistry) + { (bytes32 labelHash, uint256 next) = NameCoder.readLabel(name, offset); if (labelHash != bytes32(0)) { parentRegistry = findExactRegistry(rootRegistry, name, next); } } - /// @notice Find all registries in the ancestry of `name`. - /// + /// @dev Find all registries in the ancestry of `name`. /// @param rootRegistry The root ENS registry. /// @param name The DNS-encoded name. /// @param offset The offset into `name` to begin the search. - /// /// @return registries Array of registries in label-order. - function findRegistries( - IRegistry rootRegistry, - bytes memory name, - uint256 offset - ) internal view returns (IRegistry[] memory registries) { + function findRegistries(IRegistry rootRegistry, bytes memory name, uint256 offset) + internal + view + returns (IRegistry[] memory registries) + { registries = new IRegistry[](1 + NameCoder.countLabels(name, offset)); registries[registries.length - 1] = rootRegistry; _findRegistries(name, offset, registries, 0); @@ -201,7 +166,11 @@ library LibRegistry { uint256 offset, IRegistry[] memory registries, uint256 index - ) private view returns (IRegistry registry) { + ) + private + view + returns (IRegistry registry) + { (string memory label, uint256 nextOffset) = NameCoder.extractLabel(name, offset); if (bytes(label).length == 0) { return registries[registries.length - 1]; diff --git a/contracts/src/utils/ContractNamer.sol b/contracts/src/utils/ContractNamer.sol new file mode 100755 index 000000000..42e546b28 --- /dev/null +++ b/contracts/src/utils/ContractNamer.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import { + OwnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; + +/// @notice Shared `IContractNamer` instance. +contract ContractNamer is ERC165, OwnableUpgradeable, UUPSUpgradeable, IContractNamer { + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + constructor() { + _disableInitializers(); + } + + /// @notice Initialize the contract. + /// @param owner_ The contract owner. + function initialize(address owner_) external initializer { + __Ownable_init(owner_); + } + + /// @inheritdoc ERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return + interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @inheritdoc IContractNamer + function isContractNamer(address namer) external view returns (bool) { + return owner() == namer; + } + + /// @dev Allow owner to upgrade. + function _authorizeUpgrade(address) internal override onlyOwner {} +} diff --git a/contracts/src/utils/DelegatedContractNamer.sol b/contracts/src/utils/DelegatedContractNamer.sol new file mode 100755 index 000000000..17bcd61f0 --- /dev/null +++ b/contracts/src/utils/DelegatedContractNamer.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; + +/// @dev Mixin for delegated contract naming. +abstract contract DelegatedContractNamer is ERC165, IContractNamer { + //////////////////////////////////////////////////////////////////////// + // Immutables + //////////////////////////////////////////////////////////////////////// + + /// @notice Delegated contract namer. + IContractNamer public immutable CONTRACT_NAMER; + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param contractNamer Delegated contract namer. + constructor(IContractNamer contractNamer) { + CONTRACT_NAMER = contractNamer; + } + + /// @inheritdoc ERC165 + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return + interfaceId == type(IContractNamer).interfaceId || super.supportsInterface(interfaceId); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @inheritdoc IContractNamer + function isContractNamer(address namer) external view returns (bool) { + return CONTRACT_NAMER.isContractNamer(namer); + } +} diff --git a/contracts/src/utils/LabelStore.sol b/contracts/src/utils/LabelStore.sol new file mode 100755 index 000000000..d535d3102 --- /dev/null +++ b/contracts/src/utils/LabelStore.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; + +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; + +import {DelegatedContractNamer} from "./DelegatedContractNamer.sol"; +import {ILabelStore} from "./interfaces/ILabelStore.sol"; +import {LibLabel} from "./LibLabel.sol"; + +/// @notice Shared label database. +contract LabelStore is DelegatedContractNamer, ILabelStore { + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// + + /// @dev The truncated labelhash to label mapping. + mapping(uint256 storageId => string label) internal _labels; + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param contractNamer Delegated contract namer. + constructor(IContractNamer contractNamer) DelegatedContractNamer(contractNamer) {} + + /// @inheritdoc DelegatedContractNamer + function supportsInterface(bytes4 interfaceId) public view override returns (bool) { + return interfaceId == type(ILabelStore).interfaceId || super.supportsInterface(interfaceId); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @inheritdoc ILabelStore + function setLabel(string calldata label) external { + NameCoder.assertLabelSize(label); + uint256 labelId = LibLabel.id(label); + uint256 storageId = _storageId(labelId); + if (bytes(_labels[storageId]).length == 0) { + _labels[storageId] = label; + emit Label(bytes32(labelId), label); + } + } + + /// @inheritdoc ILabelStore + function getLabel(uint256 anyId) public view returns (string memory) { + return _labels[_storageId(anyId)]; + } + + //////////////////////////////////////////////////////////////////////// + // Internal Functions + //////////////////////////////////////////////////////////////////////// + + /// @dev Convert `anyId` to `storageId`. + function _storageId(uint256 anyId) internal pure returns (uint256) { + return LibLabel.withVersion(anyId, 0); + } +} diff --git a/contracts/src/utils/LibISO8601.sol b/contracts/src/utils/LibISO8601.sol new file mode 100644 index 000000000..74a8421ad --- /dev/null +++ b/contracts/src/utils/LibISO8601.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +/// @dev Library for converting uint256 timestamps to ISO 8601 strings. +library LibISO8601 { + /// @dev The timestamp is out of range. + /// @dev Error selector: `0x09064f83` + error TimestampOutOfRange(uint256 timestamp); + + /// @dev Converts a timestamp to an ISO 8601 string. + function toISO8601(uint256 ts) internal pure returns (string memory result) { + if (ts >= 253402300800) + revert TimestampOutOfRange(ts); + + assembly { + // Allocate memory + result := mload(0x40) + mstore(0x40, add(result, 0x40)) + mstore(result, 20) + + // Variable reuse strategy to avoid stack-too-deep: + // a: totalDays -> qday -> qjul -> yday -> bump -> month + // b: secs -> second + // c: cent -> year + // d: N -> M -> hour + // day: keeps day value + // minute: keeps minute value + // e: digit extraction helper + + // Split timestamp + let a := div(ts, 86400) + let b := sub(ts, mul(a, 86400)) + + // Howard Hinnant date algorithm / Ben Joffe fast date algorithm + // https://howardhinnant.github.io/date_algorithms.html / https://www.benjoffe.com/fast-date + a := add(a, 719468) + a := add(shl(2, a), 3) + let c := div(a, 146097) + a := add(sub(a, and(c, not(3))), shl(2, c)) + c := div(a, 1461) + a := shr(2, mod(a, 1461)) + let d := add(mul(a, 2141), 197913) + let day := add(div(and(d, 0xffff), 2141), 1) + d := shr(16, d) + a := gt(a, 305) + c := add(c, a) + a := sub(d, mul(a, 12)) + + // Time + d := div(b, 3600) + b := sub(b, mul(d, 3600)) + let minute := div(b, 60) + b := sub(b, mul(minute, 60)) + + // Year YYYY (extract digits from least to most significant) + let e := sub(c, mul(div(c, 10), 10)) + mstore8(add(result, 35), add(48, e)) + c := div(c, 10) + e := sub(c, mul(div(c, 10), 10)) + mstore8(add(result, 34), add(48, e)) + c := div(c, 10) + e := sub(c, mul(div(c, 10), 10)) + mstore8(add(result, 33), add(48, e)) + mstore8(add(result, 32), add(48, div(c, 10))) + mstore8(add(result, 36), 0x2d) + + // Month MM (1-12): gt is cheaper than div + e := gt(a, 9) + mstore8(add(result, 37), add(48, e)) + mstore8(add(result, 38), add(48, sub(a, mul(e, 10)))) + mstore8(add(result, 39), 0x2d) + + // Day DD (1-31) + e := div(day, 10) + mstore8(add(result, 40), add(48, e)) + mstore8(add(result, 41), add(48, sub(day, mul(e, 10)))) + mstore8(add(result, 42), 0x54) + + // Hour HH (0-23) + e := div(d, 10) + mstore8(add(result, 43), add(48, e)) + mstore8(add(result, 44), add(48, sub(d, mul(e, 10)))) + mstore8(add(result, 45), 0x3a) + + // Minute MM (0-59) + e := div(minute, 10) + mstore8(add(result, 46), add(48, e)) + mstore8(add(result, 47), add(48, sub(minute, mul(e, 10)))) + mstore8(add(result, 48), 0x3a) + + // Second SS (0-59) + e := div(b, 10) + mstore8(add(result, 49), add(48, e)) + mstore8(add(result, 50), add(48, sub(b, mul(e, 10)))) + mstore8(add(result, 51), 0x5a) + } + } +} diff --git a/contracts/src/utils/LibLabel.sol b/contracts/src/utils/LibLabel.sol index 3a9095266..0d1f0185a 100755 --- a/contracts/src/utils/LibLabel.sol +++ b/contracts/src/utils/LibLabel.sol @@ -3,12 +3,12 @@ pragma solidity >=0.8.13; /// @dev Utilities for computing labelhash-based token IDs and applying version suffixes. library LibLabel { - /// @notice Compute `labelhash(label)`. + /// @dev Compute `labelhash(label)`. function id(string memory label) internal pure returns (uint256) { return uint256(keccak256(bytes(label))); } - /// @notice Replace the lower 32-bits of `anyId` with `versionId`. + /// @dev Replace the lower 32-bits of `anyId` with `versionId`. /// @param anyId The labelhash, token ID, or resource. /// @param versionId The version ID. /// @return The versioned ID. diff --git a/contracts/src/utils/LibMem.sol b/contracts/src/utils/LibMem.sol index 4133bc821..954f967b2 100755 --- a/contracts/src/utils/LibMem.sol +++ b/contracts/src/utils/LibMem.sol @@ -1,14 +1,14 @@ -//SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT pragma solidity >=0.8.25; // solhint-disable no-inline-assembly /// @dev Low-level memory helpers for copying, pointer conversion, and word loading. library LibMem { - bool public constant REMAPPED = true; + /// @dev If true, LibMem uses mcopy. + bool internal constant REMAPPED = true; /// @dev Copy `mem[src:src+len]` to `mem[dst:dst+len]`. - /// /// @param src The source memory offset. /// @param dst The destination memory offset. /// @param len The number of bytes to copy. @@ -19,9 +19,7 @@ library LibMem { } /// @dev Convert bytes to a memory offset. - /// /// @param v The bytes to convert. - /// /// @return ret The corresponding memory offset. function ptr(bytes memory v) internal pure returns (uint256 ret) { assembly { @@ -30,9 +28,7 @@ library LibMem { } /// @dev Read word at memory offset. - /// /// @param src The memory offset. - /// /// @return ret The read word. function load(uint256 src) internal pure returns (uint256 ret) { assembly { diff --git a/contracts/src/utils/LibString.sol b/contracts/src/utils/LibString.sol new file mode 100644 index 000000000..b240b1f0a --- /dev/null +++ b/contracts/src/utils/LibString.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +/// @title LibString +/// @notice Gas-efficient string conversion utilities for Ethereum addresses and numbers. +/// @dev All functions use inline assembly for optimal gas efficiency. +library LibString { + //////////////////////////////////////////////////////////////////////// + // Address to String Conversions + //////////////////////////////////////////////////////////////////////// + + /// @dev Converts an address to its lowercase hex string representation (without 0x prefix). + /// + /// Uses inline assembly for gas efficiency. + /// Produces exactly 40 hex characters. + /// + /// @param value The address to convert. + /// @return result The lowercase hex string (40 bytes, no 0x prefix). + function toAddressString(address value) internal pure returns (string memory result) { + /// @solidity memory-safe-assembly + assembly { + // Allocate memory for result string + result := mload(0x40) + mstore(0x40, add(result, 0x60)) // 32 (length slot) + 40 (data) padded to 64 bytes + mstore(result, 40) // Store string length (40 hex chars) + + // Hex lookup table: "0123456789abcdef" left-aligned in a bytes32 + let table := 0x3031323334353637383961626364656600000000000000000000000000000000 + + let o := add(result, 32) // Pointer to string data (after length slot) + let v := shl(96, value) // Left-align 160-bit address in 256-bit word + + // Process 1 byte (2 nibbles) per iteration → 20 iterations for 40 hex chars + for { + let i := 0 + } lt(i, 20) { + i := add(i, 1) + } { + let b := byte(i, v) // Extract i-th byte from left + let pos := shl(1, i) // Output position = i * 2 + mstore8(add(o, pos), byte(shr(4, b), table)) // High nibble → ASCII + mstore8(add(o, add(pos, 1)), byte(and(b, 0xf), table)) // Low nibble → ASCII + } + } + } + + /// @dev Converts an address to its EIP-55 checksummed hex string. + /// + /// Uses toAddressString for lowercase conversion, then applies EIP-55 checksum. + /// Produces "0x" + 40 hex characters. + /// + /// @param addr The address to convert. + /// @return result The checksummed hex string (42 bytes). + function toChecksumHexString(address addr) internal pure returns (string memory result) { + // Get lowercase hex without prefix (40 chars) + string memory lowercase = toAddressString(addr); + + assembly { + result := mload(0x40) + mstore(0x40, add(result, 0x60)) // 32 (length) + 42 (data) = 74, round up to 96 + mstore(result, 42) // Set string length + + let ptr := add(result, 32) + // Write "0x" prefix + mstore8(ptr, 0x30) // '0' + mstore8(add(ptr, 1), 0x78) // 'x' + + let hexPtr := add(ptr, 2) + let srcPtr := add(lowercase, 32) + + // Copy 40 bytes from lowercase string to result + mstore(hexPtr, mload(srcPtr)) + mstore(add(hexPtr, 32), mload(add(srcPtr, 32))) + + // Hash the 40 lowercase hex chars for checksum + let hashVal := keccak256(hexPtr, 40) + + // Apply checksum: uppercase letters where hash nibble >= 8 + for { + let i := 0 + } lt(i, 40) { + i := add(i, 1) + } { + let charPos := add(hexPtr, i) + let char := byte(0, mload(charPos)) + // If char is a-f (97-102) and hash nibble >= 8, uppercase it (xor with 0x20) + // Hash nibble at position i: shift right by (252 - i*4) and mask + if and(gt(char, 96), gt(and(shr(sub(252, shl(2, i)), hashVal), 0xf), 7)) { + mstore8(charPos, xor(char, 0x20)) + } + } + } + } + + //////////////////////////////////////////////////////////////////////// + // Number to String Conversions + //////////////////////////////////////////////////////////////////////// + + /// @dev Converts a uint256 to its ASCII decimal string representation. + /// @param value The value to convert. + /// @return result The decimal string. + function toString(uint256 value) internal pure returns (string memory result) { + assembly { + result := mload(0x40) + + switch value + case 0 { + mstore(0x40, add(result, 0x40)) // 32 (length slot) + 1 (data) = 33, round to 64 + mstore(result, 1) // length = 1 + mstore8(add(result, 32), 0x30) // '0' + } + default { + // Count digits: `for {} temp {}` is Yul idiom for `while (temp != 0)` + let temp := value + let digits := 0 + for {} temp {} { + digits := add(digits, 1) + temp := div(temp, 10) + } + + // Set length and update free memory pointer (rounded to 32-byte boundary) + mstore(result, digits) + mstore(0x40, add(result, and(add(add(32, digits), 31), not(31)))) + + // Write digits from right to left: `for {} temp {}` is Yul idiom for `while (temp != 0)` + let ptr := add(add(result, 32), digits) + temp := value + for {} temp {} { + ptr := sub(ptr, 1) + mstore8(ptr, add(48, mod(temp, 10))) // 48 = ASCII '0' + temp := div(temp, 10) + } + } + } + } +} diff --git a/contracts/src/utils/PermissionedAddressSet.sol b/contracts/src/utils/PermissionedAddressSet.sol new file mode 100755 index 000000000..8f9117055 --- /dev/null +++ b/contracts/src/utils/PermissionedAddressSet.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {EnhancedAccessControl} from "../access-control/EnhancedAccessControl.sol"; +import {IContractNamer} from "../reverse-registrar/interfaces/IContractNamer.sol"; + +import {IAddressSet} from "./interfaces/IAddressSet.sol"; + +/// @dev Nybble 0: authorizes modifying the set. Root only. +uint256 constant ROLE_APPROVE = 1 << 0; + +/// @dev Nybble 32: authorizes setting `ROLE_APPROVE`. +uint256 constant ROLE_APPROVE_ADMIN = ROLE_APPROVE << 128; + +/// @dev Nybble 1: authorizes contract naming. Root only. +uint256 constant ROLE_CAN_NAME = 1 << 4; + +/// @dev Nybble 33: authorizes setting `ROLE_CAN_NAME`. +uint256 constant ROLE_CAN_NAME_ADMIN = ROLE_CAN_NAME << 128; + +/// @dev Default root roles assigned at construction. +uint256 constant DEFAULT_ROLE_BITMAP = + ROLE_APPROVE | ROLE_APPROVE_ADMIN | ROLE_CAN_NAME | ROLE_CAN_NAME_ADMIN; + +/// @notice An arbitrary set of addresses managed by EAC. +contract PermissionedAddressSet is EnhancedAccessControl, IAddressSet, IContractNamer { + //////////////////////////////////////////////////////////////////////// + // Storage + //////////////////////////////////////////////////////////////////////// + + /// @dev Mapping that determines members of the set. + mapping(address addr => bool approved) internal _approved; + + //////////////////////////////////////////////////////////////////////// + // Events + //////////////////////////////////////////////////////////////////////// + + /// @notice Inclusion of a member of the set has changed. + /// @param addr The address. + /// @param approved If `true`, added, otherwise removed. + /// @param sender The sender of the change. + event ApprovalChanged(address indexed addr, bool approved, address indexed sender); + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @param rootAccount Account granted root roles. + constructor(address rootAccount) { + _grantRoles(ROOT_RESOURCE, DEFAULT_ROLE_BITMAP, rootAccount, false); + } + + /// @inheritdoc EnhancedAccessControl + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return + interfaceId == type(IAddressSet).interfaceId || + interfaceId == type(IContractNamer).interfaceId || + super.supportsInterface(interfaceId); + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Add or remove a member from the set. + /// @param addr The address to approve. + /// @param approved If `true`, added, otherwise removed. + function approve(address addr, bool approved) external onlyRootRoles(ROLE_APPROVE) { + require(_approved[addr] != approved); + _approved[addr] = approved; + emit ApprovalChanged(addr, approved, msg.sender); + } + + /// @inheritdoc IAddressSet + function includes(address addr) external view returns (bool) { + return _approved[addr]; + } + + /// @inheritdoc IContractNamer + function isContractNamer(address namer) external view returns (bool) { + return hasRootRoles(ROLE_CAN_NAME, namer); + } +} diff --git a/contracts/src/utils/WrappedErrorLib.sol b/contracts/src/utils/WrappedErrorLib.sol index 17ffa6efd..504fba902 100755 --- a/contracts/src/utils/WrappedErrorLib.sol +++ b/contracts/src/utils/WrappedErrorLib.sol @@ -7,12 +7,11 @@ import {HexUtils} from "@ens/contracts/utils/HexUtils.sol"; /// Uses hex to embed arbitrary data and avoid invalid unicode. library WrappedErrorLib { /// @dev Error selector for `Error(string)`. - bytes4 public constant ERROR_STRING_SELECTOR = 0x08c379a0; + bytes4 internal constant ERROR_STRING_SELECTOR = 0x08c379a0; /// @dev The detectable human-readable error prefix. - bytes16 public constant WRAPPED_ERROR_PREFIX = "WrappedError:0x"; - // Alternative: unicode"❌WrappedErr:0x"; - // Alternative: unicode"❌WrappedError:"; + /// Must be exactly 16 bytes. + bytes16 internal constant WRAPPED_ERROR_PREFIX = "WrappedError::0x"; /// @dev Wrap an error and then revert. function wrapAndRevert(bytes memory err) internal pure { @@ -38,9 +37,7 @@ library WrappedErrorLib { /// @dev Unwrap a typed error from `Error(string)`. /// Does nothing if detection and extracton fails. - /// /// @param err The error data to unwrap. - /// /// @return The unwrapped error data, or unmodified if not wrapped. function unwrap(bytes memory err) internal pure returns (bytes memory) { if (bytes4(err) == ERROR_STRING_SELECTOR) { diff --git a/contracts/src/utils/interfaces/IAddressSet.sol b/contracts/src/utils/interfaces/IAddressSet.sol new file mode 100755 index 000000000..df8b02030 --- /dev/null +++ b/contracts/src/utils/interfaces/IAddressSet.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +/// @dev Interface selector: `0x1aedefda` +interface IAddressSet { + /// @notice Check if `addr` is included in the set. + /// @param addr The address to check. + /// @return `true` if included. + function includes(address addr) external view returns (bool); +} diff --git a/contracts/src/utils/interfaces/ILabelStore.sol b/contracts/src/utils/interfaces/ILabelStore.sol new file mode 100755 index 000000000..61aa11dcd --- /dev/null +++ b/contracts/src/utils/interfaces/ILabelStore.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +/// @notice Interface for a shared label database. +/// @dev Interface selector: `0x0d48fe93` +interface ILabelStore { + /// @notice A label was recorded. + /// @param labelHash The hash of `label`. + /// @param label The recorded label. + event Label(bytes32 indexed labelHash, string label); + + /// @notice Ensure `label` can be inverted from `anyId`. + /// @param label The label. + function setLabel(string calldata label) external; + + /// @notice Invert `anyId` to the corresponding label. + /// @param anyId The truncated labelhash. + /// @return The label or null if unknown. + function getLabel(uint256 anyId) external view returns (string memory); +} diff --git a/contracts/src/utils/interfaces/IUniversalSignatureValidator.sol b/contracts/src/utils/interfaces/IUniversalSignatureValidator.sol new file mode 100644 index 000000000..76039ebcb --- /dev/null +++ b/contracts/src/utils/interfaces/IUniversalSignatureValidator.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +/// @dev Interface selector: `0x98ef1ed8` +interface IUniversalSignatureValidator { + /// @notice Validates a signature. + /// @param signer The signer of the signature. + /// @param hash The hash of the message that was signed. + /// @param signature The signature to validate. + /// @return isValid Whether the signature is valid. + function isValidSig(address signer, bytes32 hash, bytes calldata signature) + external + returns (bool); +} diff --git a/contracts/test/DOSNameService.t.sol b/contracts/test/DOSNameService.t.sol deleted file mode 100644 index dfe9931a8..000000000 --- a/contracts/test/DOSNameService.t.sol +++ /dev/null @@ -1,369 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import "forge-std/Test.sol"; - -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; -import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; -import {IRegistryMetadata} from "~src/registry/interfaces/IRegistryMetadata.sol"; -import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; - -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; -import {SimpleRegistryMetadata} from "~src/registry/SimpleRegistryMetadata.sol"; -import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; - -import {StandardRentPriceOracle, DiscountPoint, PaymentRatio} from "~src/registrar/StandardRentPriceOracle.sol"; -import {DOSRegistrar} from "~src/registrar/DOSRegistrar.sol"; -import {IDOSRegistrar} from "~src/registrar/interfaces/IDOSRegistrar.sol"; -import {IRentPriceOracle} from "~src/registrar/interfaces/IRentPriceOracle.sol"; - -import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; -import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; -import {LibLabel} from "~src/utils/LibLabel.sol"; - -/// @dev Simple mock WDOS token for testing (real WDOS is a WARP precompile at 0x1111...1111). -contract MockWDOS is ERC20 { - constructor() ERC20("Wrapped DOS", "WDOS") {} - - function mint(address to, uint256 amount) external { - _mint(to, amount); - } -} - -/// @notice Integration tests for the DOS Name Service stack. -contract DOSNameServiceTest is Test { - // ---- ERC1155 Receiver (required because deployer = this contract) ---- - function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) { - return this.onERC1155Received.selector; - } - - function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) external pure returns (bytes4) { - return this.onERC1155BatchReceived.selector; - } - - function supportsInterface(bytes4 interfaceId) external pure returns (bool) { - return interfaceId == 0x01ffc9a7 || interfaceId == 0x4e2312e0; - } - - // ---- Contracts ---- - MockHCAFactoryBasic hcaFactory; - SimpleRegistryMetadata metadata; - PermissionedRegistry root; - PermissionedRegistry dosTLD; - PermissionedRegistry reverseReg; - StandardRentPriceOracle priceOracle; - DOSRegistrar registrar; - MockWDOS wdos; - - // ---- Actors ---- - address deployer; - address user; - bytes32 constant SECRET = keccak256("my-secret"); - uint64 constant DURATION = 365 days; // 1 year - uint64 constant MAX_EXPIRY = type(uint64).max; - - // ---- Deploy params (mirror DeployDOS.s.sol) ---- - uint64 constant MIN_COMMITMENT_AGE = 60; - uint64 constant MAX_COMMITMENT_AGE = 86400; - uint64 constant MIN_REGISTER_DURATION = 2419200; // 28 days - - function setUp() public { - // Warp to a reasonable timestamp so commitment checks work - // (default block.timestamp=1 causes 0 + MAX_COMMITMENT_AGE > 1 to be true for any empty slot) - vm.warp(100_000); - - deployer = address(this); - user = makeAddr("user"); - - // 1. MockWDOS - wdos = new MockWDOS(); - - // 2. HCAFactory - hcaFactory = new MockHCAFactoryBasic(); - - // 3. SimpleRegistryMetadata - metadata = new SimpleRegistryMetadata(IHCAFactoryBasic(address(hcaFactory))); - - // 4. RootRegistry - root = new PermissionedRegistry( - IHCAFactoryBasic(address(hcaFactory)), - IRegistryMetadata(address(metadata)), - deployer, - EACBaseRolesLib.ALL_ROLES - ); - - // 5. DOSTLDRegistry - dosTLD = new PermissionedRegistry( - IHCAFactoryBasic(address(hcaFactory)), - IRegistryMetadata(address(metadata)), - deployer, - EACBaseRolesLib.ALL_ROLES - ); - - // Register "dos" TLD in root - root.register("dos", deployer, IRegistry(address(dosTLD)), address(0), 0, MAX_EXPIRY); - - // 6. ReverseRegistry - reverseReg = new PermissionedRegistry( - IHCAFactoryBasic(address(hcaFactory)), - IRegistryMetadata(address(metadata)), - deployer, - EACBaseRolesLib.ALL_ROLES - ); - root.register("reverse", deployer, IRegistry(address(reverseReg)), address(0), 0, MAX_EXPIRY); - - // 7. StandardRentPriceOracle - uint256[] memory baseRatePerCp = new uint256[](3); - baseRatePerCp[0] = 3_170_979_198; // 1-char: ~100 DOS/year - baseRatePerCp[1] = 1_585_489_599; // 2-char: ~50 DOS/year - baseRatePerCp[2] = 317_097_919; // 3+ char: ~10 DOS/year - - DiscountPoint[] memory discountPoints = new DiscountPoint[](0); - - PaymentRatio[] memory paymentRatios = new PaymentRatio[](1); - paymentRatios[0] = PaymentRatio({token: IERC20(address(wdos)), numer: 1, denom: 1}); - - priceOracle = new StandardRentPriceOracle( - deployer, - IPermissionedRegistry(address(dosTLD)), - baseRatePerCp, - discountPoints, - 0, // premiumPriceInitial - 0, // premiumHalvingPeriod - 0, // premiumPeriod - paymentRatios - ); - - // 8. DOSRegistrar - registrar = new DOSRegistrar( - IPermissionedRegistry(address(dosTLD)), - IHCAFactoryBasic(address(hcaFactory)), - deployer, // beneficiary - MIN_COMMITMENT_AGE, - MAX_COMMITMENT_AGE, - MIN_REGISTER_DURATION, - IRentPriceOracle(address(priceOracle)) - ); - - // Grant ROLE_REGISTRAR | ROLE_RENEW to DOSRegistrar on dosTLD - dosTLD.grantRootRoles( - RegistryRolesLib.ROLE_REGISTRAR | RegistryRolesLib.ROLE_RENEW, - address(registrar) - ); - - // Fund user with WDOS - wdos.mint(user, 10_000 ether); - } - - // ----------------------------------------------------------------------- - // Helpers - // ----------------------------------------------------------------------- - - /// @dev Full commit-reveal registration helper. - function _registerName(string memory label, address owner_, bytes32 secret_, uint64 duration_) internal returns (uint256 tokenId) { - bytes32 commitment = registrar.makeCommitment( - label, owner_, secret_, IRegistry(address(0)), address(0), duration_, bytes32(0) - ); - - vm.prank(owner_); - registrar.commit(commitment); - - vm.warp(block.timestamp + MIN_COMMITMENT_AGE + 1); - - // Approve registrar to spend WDOS - vm.prank(owner_); - wdos.approve(address(registrar), type(uint256).max); - - vm.prank(owner_); - tokenId = registrar.register( - label, owner_, secret_, IRegistry(address(0)), address(0), duration_, IERC20(address(wdos)), bytes32(0) - ); - } - - // ----------------------------------------------------------------------- - // Tests - // ----------------------------------------------------------------------- - - /// @notice Verify all contracts deployed correctly, root has "dos" TLD registered. - function test_deploymentSetup() public view { - // HCAFactory exists - assertTrue(address(hcaFactory) != address(0), "hcaFactory not deployed"); - - // Root, dosTLD, reverseReg exist - assertTrue(address(root) != address(0), "root not deployed"); - assertTrue(address(dosTLD) != address(0), "dosTLD not deployed"); - assertTrue(address(reverseReg) != address(0), "reverseReg not deployed"); - - // "dos" TLD is registered in root (not AVAILABLE) - IPermissionedRegistry.Status dosStatus = root.getStatus(LibLabel.id("dos")); - assertTrue(dosStatus != IPermissionedRegistry.Status.AVAILABLE, "dos TLD not registered"); - - // "reverse" is registered in root - IPermissionedRegistry.Status reverseStatus = root.getStatus(LibLabel.id("reverse")); - assertTrue(reverseStatus != IPermissionedRegistry.Status.AVAILABLE, "reverse not registered"); - - // Registrar points to dosTLD - assertEq(address(registrar.REGISTRY()), address(dosTLD), "registrar registry mismatch"); - - // PriceOracle is set - assertEq(address(registrar.rentPriceOracle()), address(priceOracle), "oracle mismatch"); - - // Commitment age params - assertEq(registrar.MIN_COMMITMENT_AGE(), MIN_COMMITMENT_AGE, "minCommitmentAge mismatch"); - assertEq(registrar.MAX_COMMITMENT_AGE(), MAX_COMMITMENT_AGE, "maxCommitmentAge mismatch"); - assertEq(registrar.MIN_REGISTER_DURATION(), MIN_REGISTER_DURATION, "minRegisterDuration mismatch"); - - // WDOS is a valid payment token - assertTrue(priceOracle.isPaymentToken(IERC20(address(wdos))), "WDOS not payment token"); - } - - /// @notice Full commit-reveal flow: commit -> wait -> register a ".dos" name. - function test_registerDosName() public { - string memory label = "testname"; - uint256 tokenId = _registerName(label, user, SECRET, DURATION); - - // Verify name is registered (not available) - assertFalse(registrar.isAvailable(label), "name should not be available after registration"); - - // Verify state in dosTLD registry - IPermissionedRegistry.State memory state = dosTLD.getState(LibLabel.id(label)); - assertTrue(state.status == IPermissionedRegistry.Status.REGISTERED, "status should be REGISTERED"); - assertEq(state.latestOwner, user, "owner should be user"); - assertTrue(state.tokenId > 0, "tokenId should be nonzero"); - assertEq(state.tokenId, tokenId, "tokenId mismatch"); - } - - /// @notice Verify price oracle returns correct prices for 3/4/5 char names. - function test_pricingByLength() public view { - // baseRatePerCp: [0]=1-char, [1]=2-char, [2]=3+ char - // For 3+ char names, rate = 317_097_919 per second - // For 1 char, rate = 3_170_979_198 - // For 2 char, rate = 1_585_489_599 - - // 1-char name "a" => uses baseRatePerCp[0] - uint256 rate1 = priceOracle.baseRate("a"); - assertEq(rate1, 3_170_979_198, "1-char rate incorrect"); - - // 2-char name "ab" => uses baseRatePerCp[1] - uint256 rate2 = priceOracle.baseRate("ab"); - assertEq(rate2, 1_585_489_599, "2-char rate incorrect"); - - // 3-char name "abc" => uses baseRatePerCp[2] - uint256 rate3 = priceOracle.baseRate("abc"); - assertEq(rate3, 317_097_919, "3-char rate incorrect"); - - // 4-char name "abcd" => also uses baseRatePerCp[2] (last entry) - uint256 rate4 = priceOracle.baseRate("abcd"); - assertEq(rate4, 317_097_919, "4-char rate incorrect"); - - // 5-char name "abcde" => also uses baseRatePerCp[2] - uint256 rate5 = priceOracle.baseRate("abcde"); - assertEq(rate5, 317_097_919, "5-char rate incorrect"); - - // Verify actual rent prices differ by name length (1 year duration) - (uint256 base3, ) = priceOracle.rentPrice("abc", address(0), DURATION, IERC20(address(wdos))); - (uint256 base1, ) = priceOracle.rentPrice("a", address(0), DURATION, IERC20(address(wdos))); - assertTrue(base1 > base3, "1-char should cost more than 3-char"); - } - - /// @notice Register then renew a name. - function test_renewDosName() public { - string memory label = "renewable"; - _registerName(label, user, SECRET, DURATION); - - // Get state before renewal - IPermissionedRegistry.State memory stateBefore = dosTLD.getState(LibLabel.id(label)); - uint64 expiryBefore = stateBefore.expiry; - - // Compute renewal price - uint64 renewDuration = 365 days; - (uint256 renewBase, ) = priceOracle.rentPrice(label, user, renewDuration, IERC20(address(wdos))); - assertTrue(renewBase > 0, "renewal price should be > 0"); - - // Approve and renew - vm.prank(user); - wdos.approve(address(registrar), type(uint256).max); - - vm.prank(user); - registrar.renew(label, renewDuration, IERC20(address(wdos)), bytes32(0)); - - // Verify expiry extended - IPermissionedRegistry.State memory stateAfter = dosTLD.getState(LibLabel.id(label)); - assertEq(stateAfter.expiry, expiryBefore + renewDuration, "expiry should be extended by renewDuration"); - } - - /// @notice Cannot register the same name twice. - function test_revertOnDuplicateRegistration() public { - string memory label = "unique"; - _registerName(label, user, SECRET, DURATION); - - // Try to register the same name again with a new commitment - bytes32 secret2 = keccak256("another-secret"); - bytes32 commitment = registrar.makeCommitment( - label, user, secret2, IRegistry(address(0)), address(0), DURATION, bytes32(0) - ); - - vm.prank(user); - registrar.commit(commitment); - - vm.warp(block.timestamp + MIN_COMMITMENT_AGE + 1); - - vm.prank(user); - wdos.approve(address(registrar), type(uint256).max); - - vm.prank(user); - vm.expectRevert(abi.encodeWithSelector(IDOSRegistrar.NameNotAvailable.selector, label)); - registrar.register( - label, user, secret2, IRegistry(address(0)), address(0), DURATION, IERC20(address(wdos)), bytes32(0) - ); - } - - /// @notice Commitment expires after maxCommitmentAge. - function test_revertOnExpiredCommitment() public { - string memory label = "expired"; - bytes32 commitment = registrar.makeCommitment( - label, user, SECRET, IRegistry(address(0)), address(0), DURATION, bytes32(0) - ); - - vm.prank(user); - registrar.commit(commitment); - - // Warp past maxCommitmentAge - vm.warp(block.timestamp + MAX_COMMITMENT_AGE + 1); - - vm.prank(user); - wdos.approve(address(registrar), type(uint256).max); - - vm.prank(user); - vm.expectRevert(); // CommitmentTooOld - registrar.register( - label, user, SECRET, IRegistry(address(0)), address(0), DURATION, IERC20(address(wdos)), bytes32(0) - ); - } - - /// @notice Cannot register before minCommitmentAge. - function test_revertOnEarlyRegistration() public { - string memory label = "tooearly"; - bytes32 commitment = registrar.makeCommitment( - label, user, SECRET, IRegistry(address(0)), address(0), DURATION, bytes32(0) - ); - - vm.prank(user); - registrar.commit(commitment); - - // Only warp 30 seconds (less than minCommitmentAge=60) - vm.warp(block.timestamp + 30); - - vm.prank(user); - wdos.approve(address(registrar), type(uint256).max); - - vm.prank(user); - vm.expectRevert(); // CommitmentTooNew - registrar.register( - label, user, SECRET, IRegistry(address(0)), address(0), DURATION, IERC20(address(wdos)), bytes32(0) - ); - } -} diff --git a/contracts/test/StandardRegistrar.sol b/contracts/test/StandardRegistrar.sol new file mode 100644 index 000000000..0d04add18 --- /dev/null +++ b/contracts/test/StandardRegistrar.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {PaymentRatio, DiscountPoint} from "~src/registrar/StandardRentPriceOracle.sol"; +import {MockERC20} from "~test/mocks/MockERC20.sol"; + +library StandardRegistrar { + uint64 internal constant SEC_PER_YEAR = 365 * 1 days; // 31536000 + + uint64 internal constant MIN_COMMITMENT_AGE = 60; // 1 minute + uint64 internal constant MAX_COMMITMENT_AGE = 1 days; + + uint64 internal constant MIN_REGISTER_DURATION = 28 days; + + uint64 internal constant GRACE_PERIOD_V1 = 90 days; + uint64 internal constant GRACE_PERIOD_V2 = 28 days; + uint64 internal constant BONUS_PERIOD = + 1 + GRACE_PERIOD_V1 - GRACE_PERIOD_V2; + + uint8 internal constant PRICE_DECIMALS = 12; + uint256 internal constant PRICE_SCALE = 10 ** PRICE_DECIMALS; + + uint256 internal constant PREMIUM_PRICE_INITIAL = 100_000_000 * PRICE_SCALE; + uint64 internal constant PREMIUM_HALVING_PERIOD = 1 days; + uint64 internal constant PREMIUM_PERIOD = 21 days; + + // ┌───┬────┬───────────┬────────┐ + // │ │ cp │ rate │ yearly │ + // ├───┼────┼───────────┼────────┤ + // │ 0 │ 5 │ 253679n │ 8.00 │ + // │ 1 │ 4 │ 5073567n │ 160.00 │ + // │ 2 │ 3 │ 20294267n │ 640.00 │ + // └───┴────┴───────────┴────────┘ + + uint256 internal constant RATE_1CP = 0; + uint256 internal constant RATE_2CP = 0; + uint256 internal constant RATE_3CP = + (640 * PRICE_SCALE + SEC_PER_YEAR - 1) / SEC_PER_YEAR; // round up + uint256 internal constant RATE_4CP = + (160 * PRICE_SCALE + SEC_PER_YEAR - 1) / SEC_PER_YEAR; + uint256 internal constant RATE_5CP = + (8 * PRICE_SCALE + SEC_PER_YEAR - 1) / SEC_PER_YEAR; + + function getBaseRates() internal pure returns (uint256[] memory rates) { + rates = new uint256[](5); + rates[0] = RATE_1CP; + rates[1] = RATE_2CP; + rates[2] = RATE_3CP; + rates[3] = RATE_4CP; + rates[4] = RATE_5CP; + } + + // ┌────┬─────────┬──────────┬────────┬────────┬────────┬─────────┬────────┬──────────┐ + // │ │ years │ discount │ 5cp/yr │ 5cp │ 4cp/yr │ 4cp │ 3cp/yr │ 3cp │ + // ├────┼─────────┼──────────┼────────┼────────┼────────┼─────────┼────────┼──────────┤ + // │ 0 │ <1.00 │ 0.00% │ 8.00 │ 8.00 │ 160.00 │ 160.00 │ 640.00 │ 640.00 │ + // │ 1 │ <2.00 │ 0.00% │ 8.00 │ 16.00 │ 160.00 │ 320.00 │ 640.00 │ 1280.00 │ + // │ 2 │ <3.00 │ 12.50% │ 7.00 │ 21.00 │ 140.00 │ 420.00 │ 560.00 │ 1680.00 │ + // │ 3 │ <4.00 │ 31.25% │ 5.50 │ 22.00 │ 110.00 │ 440.00 │ 440.00 │ 1760.00 │ + // │ 4 │ <5.00 │ 31.25% │ 5.50 │ 27.50 │ 110.00 │ 550.00 │ 440.00 │ 2200.00 │ + // │ 5 │ <6.00 │ 31.25% │ 5.50 │ 33.00 │ 110.00 │ 660.00 │ 440.00 │ 2640.00 │ + // │ 6 │ <7.00 │ 43.75% │ 4.50 │ 31.50 │ 90.00 │ 630.00 │ 360.00 │ 2520.00 │ + // │ 7 │ <8.00 │ 43.75% │ 4.50 │ 36.00 │ 90.00 │ 720.00 │ 360.00 │ 2880.00 │ + // │ 8 │ <9.00 │ 43.75% │ 4.50 │ 40.50 │ 90.00 │ 810.00 │ 360.00 │ 3240.00 │ + // │ 9 │ <10.00 │ 43.75% │ 4.50 │ 45.00 │ 90.00 │ 900.00 │ 360.00 │ 3600.00 │ + // │ 10 │ <25.00 │ 43.75% │ 4.50 │ 112.50 │ 90.00 │ 2250.00 │ 360.00 │ 9000.00 │ + // │ 11 │ <100.00 │ 43.75% │ 4.50 │ 450.00 │ 90.00 │ 9000.00 │ 360.00 │ 36000.00 │ + // └────┴─────────┴──────────┴────────┴────────┴────────┴─────────┴────────┴──────────┘ + + function getDiscountPoints() internal pure returns (DiscountPoint[] memory v) { + v = new DiscountPoint[](3); + v[0] = DiscountPoint(SEC_PER_YEAR * 2, _discountNumer(7, 8)); //// 1 - 14/16 = 12.50% + v[1] = DiscountPoint(SEC_PER_YEAR * 3, _discountNumer(11, 16)); // 1 - 11/16 = 31.25% + v[2] = DiscountPoint(SEC_PER_YEAR * 6, _discountNumer(9, 16)); /// 1 - 9/16 = 43.75% + } + + uint128 internal constant DISCOUNT_DENOMINATOR = 1e38; // Floor[Log10[2^128-1] == 38 + + function _discountNumer(uint256 numer, uint256 denom) private pure returns (uint128) { + require(numer < denom, "discountNumer"); + return uint128((DISCOUNT_DENOMINATOR * numer + denom - 1) / denom); // round up + } + + function ratioFromStable(MockERC20 token) internal view returns (PaymentRatio memory) { + uint8 d = token.decimals(); + if (d > PRICE_DECIMALS) { + return PaymentRatio(token, uint128(10) ** (d - PRICE_DECIMALS), 1); + } else { + return PaymentRatio(token, 1, uint128(10) ** (PRICE_DECIMALS - d)); + } + } +} diff --git a/contracts/test/e2e/devnet.test.ts b/contracts/test/e2e/devnet.test.ts index 29ec1c2c9..ade73b4cc 100644 --- a/contracts/test/e2e/devnet.test.ts +++ b/contracts/test/e2e/devnet.test.ts @@ -1,5 +1,4 @@ -import { beforeAll, describe, expect, it } from "bun:test"; -import { toHex } from "viem"; +import { describe, expect, it } from "bun:test"; import { expectVar } from "../utils/expectVar.js"; describe("Devnet", () => { @@ -8,53 +7,46 @@ describe("Devnet", () => { setupEnv({ resetOnEach: true }); it("sync", async () => { - await env.deployment.client.mine({ blocks: 1, interval: 10 }); // advance chain - const block0 = await env.getBlock(); + await env.client.mine({ blocks: 1, interval: 10 }); // advance chain + const block0 = await env.client.getBlock(); const t = await env.sync(); - const block1 = await env.getBlock(); + const block1 = await env.client.getBlock(); expect(block1.timestamp).toBeGreaterThanOrEqual(block0.timestamp); expectVar({ t }).toStrictEqual(block1.timestamp); }); it("warp", async () => { const warpSec = 60; - const block0 = await env.getBlock(); + const block0 = await env.client.getBlock(); const t = await env.sync({ warpSec }); // time warp - const block1 = await env.getBlock(); + const block1 = await env.client.getBlock(); expect(block1.timestamp - block0.timestamp).toBeGreaterThanOrEqual(warpSec); expect(block1.timestamp).toBeGreaterThanOrEqual(t); expectVar({ t }).toBeGreaterThanOrEqual(Math.floor(Date.now() / 1000)); }); it("saveState", async () => { - const gateways = - await env.deployment.contracts.BatchGatewayProvider.read.gateways(); - await env.deployment.contracts.BatchGatewayProvider.write.setGateways( - [[]], - { - account: env.namedAccounts.owner, - }, - ); + const gateways = await env.shared.BatchGatewayProvider.read.gateways(); + await env.shared.BatchGatewayProvider.write.setGateways([[]], { + account: env.namedAccounts.owner, + }); expect( - env.deployment.contracts.BatchGatewayProvider.read.gateways(), + env.shared.BatchGatewayProvider.read.gateways(), ).resolves.toStrictEqual([]); await resetInitialState(); expect( - env.deployment.contracts.BatchGatewayProvider.read.gateways(), + env.shared.BatchGatewayProvider.read.gateways(), ).resolves.toStrictEqual(gateways); }); it(`computeVerifiableProxyAddress`, async () => { const account = env.namedAccounts.deployer; const salt = 1234n; - const contract = await env.deployment.deployPermissionedResolver({ + const contract = await env.deployPermissionedResolver({ account, salt, }); - const address = await env.deployment.computeVerifiableProxyAddress({ - deployer: account.address, - salt, - }); + const address = env.computeVerifiableProxyAddress(account.address, salt); expect(address).toStrictEqual(contract.address); }); }); diff --git a/contracts/test/e2e/migration.test.ts b/contracts/test/e2e/migration.test.ts new file mode 100755 index 000000000..ca58d3259 --- /dev/null +++ b/contracts/test/e2e/migration.test.ts @@ -0,0 +1,893 @@ +import { describe, it } from "bun:test"; +import { + type AbiParameterToPrimitiveType, + type Account, + type Address, + encodeAbiParameters, + type Hex, + namehash, + zeroAddress, +} from "viem"; +import { + STATUS, + MAX_EXPIRY, + FUSES, + PREMIGRATION_BONUS_PERIOD, + SEC_PER_YEAR, + GRACE_PERIOD_V2, +} from "../../script/deploy-constants.js"; +import { migrationDataComponents } from "../../script/migration.js"; +import { expect, expectVar } from "../utils/expectVar.js"; +import { + COIN_TYPE_ETH, + dnsEncodeName, + getLabelAt, + getParentName, + idFromLabel, +} from "../utils/utils.js"; +import { + bundleCalls, + type KnownProfile, + makeResolutions, +} from "../utils/resolutions.js"; + +// see: LibMigration.sol +type MigrationData = AbiParameterToPrimitiveType<{ + type: "tuple"; + components: typeof migrationDataComponents; +}>; + +const anotherAddress = "0x8000000000000000000000000000000000000001"; +const defaultProfile = { + addresses: [{ coinType: COIN_TYPE_ETH, value: anotherAddress }], + texts: [{ key: "url", value: "https://ens.domains" }], + contenthash: { value: "0x12345678" }, +} as const satisfies Partial; + +describe("Migration", () => { + const { env, setupEnv } = process.env.TEST_GLOBALS!; + + setupEnv({ + resetOnEach: true, + async initialize() { + // hack: add controller so we can register() directly + // v1.7.0: BaseRegistrar is now owned by RegistrarSecurityController + await env.v1.RegistrarSecurityController.write.addRegistrarController( + [env.namedAccounts.deployer.address], + { account: env.namedAccounts.owner }, + ); + // assumes fallback resolver set during deployment + // see: deploy/00_ENSV2Resolver.ts + }, + }); + + async function ensurePremigration(label: string) { + const tokenId = idFromLabel(label); + const expiry = await env.v1.BaseRegistrar.read.nameExpires([tokenId]); + await env.v2.ETHRegistry.write.register([ + label, + zeroAddress, // owner (must be null) + zeroAddress, // registry + env.v2.ENSV1Resolver.address, // fallback resolver + 0n, // roleBitmap (must be null) + expiry + PREMIGRATION_BONUS_PERIOD, + ]); + } + + type MigrateArgs = { + target: Address; + sender?: Account; + rawData?: Hex; + data?: Partial; + }; + + abstract class TokenV1 { + constructor( + readonly name: string, + readonly account: Account, + ) {} + get namehash() { + return namehash(this.name); + } + get label() { + return getLabelAt(this.name); + } + abstract get tokenId(): bigint; + abstract setResolver(address: Address): Promise; + abstract migrate(args?: MigrateArgs): Promise; + async makeData(data: Partial = {}): Promise { + const resolver = await env.v1.ENSRegistry.read.resolver([this.namehash]); + return { + label: this.label, + owner: this.account.address, + subregistry: zeroAddress, + resolver, + ...data, + }; + } + async setupPublicResolver() { + await this.setResolver(env.v1.PublicResolver.address); + await env.v1.PublicResolver.write.multicall( + [ + makeResolutions({ name: this.name, ...defaultProfile }).map( + (x) => x.write, + ), + ], + { account: this.account }, + ); + } + async checkMigrated({ + owner = this.account.address, + }: { + owner?: Address; + } = {}) { + const parentRegistry = await env.findPermissionedRegistry( + getParentName(this.name), + ); + const { status, latestOwner } = await parentRegistry.read.getState([ + idFromLabel(this.label), + ]); + expectVar({ status }).toStrictEqual(STATUS.REGISTERED); + expectVar({ latestOwner }).toEqualAddress(owner); + } + async checkResolution() { + const bundle = bundleCalls( + makeResolutions({ name: this.name, ...defaultProfile }), + ); + const [answer1] = await env.v1.UniversalResolver.read.resolve([ + dnsEncodeName(this.name), + bundle.call, + ]); + bundle.expect(answer1); + const [answer2] = await env.v2.UniversalResolver.read.resolve([ + dnsEncodeName(this.name), + bundle.call, + ]); + bundle.expect(answer2); + } + } + + class UnwrappedToken extends TokenV1 { + override get tokenId() { + return idFromLabel(this.label); + } + override async setResolver(address: Address) { + await env.v1.ENSRegistry.write.setResolver([this.namehash, address], { + account: this.account, + }); + } + override async migrate(args: Partial = {}) { + return env.waitFor( + env.v1.BaseRegistrar.write.safeTransferFrom( + [ + this.account.address, + args.target ?? env.v2.UnlockedMigrationController.address, + this.tokenId, + args.rawData ?? encodeMigrationData(await this.makeData(args.data)), + ], + { account: args.sender ?? this.account }, + ), + ); + } + async wrap(fuses: number = FUSES.CAN_DO_EVERYTHING) { + const { name, account, tokenId, label } = this; + await env.v1.BaseRegistrar.write.safeTransferFrom( + [ + account.address, + env.v1.NameWrapper.address, + tokenId, + encodeAbiParameters( + // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/NameWrapper.sol#L789-L794 + [ + { name: "label", type: "string" }, + { name: "owner", type: "address" }, + { name: "fuses", type: "uint16" }, + { name: "resolver", type: "address" }, + ], + [label, account.address, fuses, zeroAddress], + ), + ], + { account }, + ); + return new WrappedToken(name, account); + } + async renewV1(duration: bigint) { + const { label, account } = this; + const amount = await env.v2.ETHRenewerV1.read.getRenewPrice([ + label, + duration, + env.erc20.MockUSDC.address, + ]); + await env.erc20.MockUSDC.write.mint([account.address, amount]); + await env.erc20.MockUSDC.write.approve( + [env.v2.ETHRenewerV1.address, amount], + { account }, + ); + await env.v2.ETHRenewerV1.write.renew( + [label, duration, env.erc20.MockUSDC.address, namehash("referrer")], + { account }, + ); + } + } + + class WrappedToken extends TokenV1 { + override get tokenId() { + return BigInt(this.namehash); + } + override async setResolver(address: Address) { + await env.v1.NameWrapper.write.setResolver([this.namehash, address], { + account: this.account, + }); + } + async createChild({ + label = "sub", + fuses = FUSES.CAN_DO_EVERYTHING, + account = this.account, + expiry = MAX_EXPIRY, + }: { + label?: string; + fuses?: number; + account?: Account; + expiry?: bigint; + } = {}) { + await env.v1.NameWrapper.write.setSubnodeOwner( + [this.namehash, label, account.address, fuses, expiry], + { account: this.account }, + ); + return new WrappedToken(`${label}.${this.name}`, account); + } + burnFuses(fuses: number) { + return env.v1.NameWrapper.write.setFuses([this.namehash, fuses], { + account: this.account, + }); + } + override async migrate(args: MigrateArgs) { + return env.waitFor( + env.v1.NameWrapper.write.safeTransferFrom( + [ + this.account.address, + args.target, + this.tokenId, + 1n, + args.rawData ?? encodeMigrationData(await this.makeData(args.data)), + ], + { account: args.sender ?? this.account }, + ), + ); + } + wrapperRegistry(account = this.account) { + return env.findWrapperRegistry(this.name, account); + } + } + + type BaseRegistrarArgs = { + label?: string; + account?: Account; + duration?: bigint; + premigrate?: boolean; + }; + + async function registerUnwrapped({ + label = "test", + account = env.namedAccounts.user, + duration = 86400n, + premigrate = true, + }: BaseRegistrarArgs = {}) { + await env.v1.BaseRegistrar.write.register([ + idFromLabel(label), + account.address, + duration, + ]); + if (premigrate) { + await ensurePremigration(label); + } + return new UnwrappedToken(`${label}.eth`, account); + } + + async function registerWrapped( + args: BaseRegistrarArgs & { + fuses?: number; + } = {}, + ) { + const unwrapped = await registerUnwrapped(args); + return unwrapped.wrap(args.fuses); + } + + function encodeMigrationData(v: MigrationData | MigrationData[]): Hex { + if (Array.isArray(v)) { + return encodeAbiParameters( + [{ type: "tuple[]", components: migrationDataComponents }], + [v], + ); + } else { + return encodeAbiParameters( + [{ type: "tuple", components: migrationDataComponents }], + [v], + ); + } + } + + describe("helpers", () => { + it("registerUnwrapped()", async () => { + await registerUnwrapped(); + }); + it("registerWrapped()", async () => { + await registerWrapped(); + }); + it("createChild()", async () => { + const wrapped = await registerWrapped(); + await wrapped.createChild(); + }); + it("wrapperRegistry", async () => { + const v = [await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP })]; + for (let i = 0; i < 5; ++i) { + v.push( + await v[v.length - 1].createChild({ + fuses: FUSES.PARENT_CANNOT_CONTROL | FUSES.CANNOT_UNWRAP, + }), + ); + } + let target = env.v2.LockedMigrationController.address; + for (const x of v) { + await x.migrate({ target }); + target = x.wrapperRegistry().address; + } + for (const x of v) { + const registry = await env.v2.UniversalResolver.read.findExactRegistry([ + dnsEncodeName(x.name), + ]); + expectVar({ registry }).toEqualAddress(x.wrapperRegistry().address); + } + }); + it("ensurePremigration()", async () => { + const unwrapped = await registerUnwrapped(); + const status = await env.v2.ETHRegistry.read.getStatus([ + unwrapped.tokenId, + ]); + expectVar({ status }).toStrictEqual(STATUS.RESERVED); + }); + it("ensurePremigration() of empty name", async () => { + expect(registerUnwrapped({ label: "" })).rejects.toThrow("LabelIsEmpty"); + }); + it("ensurePremigration() of long name", async () => { + expect(registerUnwrapped({ label: "a".repeat(256) })).rejects.toThrow( + "LabelIsTooLong", + ); + }); + }); + + describe("premigration", () => { + // these should never happen + it("empty name", async () => { + const unwrapped = await registerUnwrapped({ + label: "", + premigrate: false, + }); + // not LabelIsEmpty() because MIN_DATA_SIZE assumes label.length > 0 + expect(unwrapped.migrate()).rejects.toThrow("InvalidData"); + }); + + it("long name", async () => { + const unwrapped = await registerUnwrapped({ + label: "a".repeat(256), + premigrate: false, + }); + expect(unwrapped.migrate()).rejects.toThrow("LabelIsTooLong"); + }); + + it("not reserved", async () => { + const unwrapped = await registerUnwrapped({ + premigrate: false, + }); + expect(unwrapped.migrate()).rejects.toThrow( + "EACUnauthorizedAccountRoles", + ); + }); + }); + + describe("postlaunch", () => { + it("renew", async () => { + const unwrapped = await registerUnwrapped(); + const expiry0 = await env.v1.BaseRegistrar.read.nameExpires([ + unwrapped.tokenId, + ]); + await env.activateV2(); + await unwrapped.renewV1(SEC_PER_YEAR); + const expiry1 = await env.v1.BaseRegistrar.read.nameExpires([ + unwrapped.tokenId, + ]); + expectVar({ expiry1 }).toStrictEqual(expiry0 + SEC_PER_YEAR); + }); + + it("renew in grace", async () => { + const unwrapped = await registerUnwrapped(); + const expiry0 = await env.v1.BaseRegistrar.read.nameExpires([ + unwrapped.tokenId, + ]); + await env.activateV2(); + await env.client.setNextBlockTimestamp({ timestamp: expiry0 }); + await env.client.mine({ blocks: 1 }); + await expect( + env.v1.BaseRegistrar.read.ownerOf([unwrapped.tokenId]), + ).rejects.toThrow(); // unowned + await expect( + env.v1.BaseRegistrar.read.available([unwrapped.tokenId]), + ).resolves.toStrictEqual(false); // not available + await unwrapped.renewV1(SEC_PER_YEAR); + const expiry1 = await env.v1.BaseRegistrar.read.nameExpires([ + unwrapped.tokenId, + ]); + expectVar({ expiry1 }).toStrictEqual(expiry0 + SEC_PER_YEAR); + }); + + it("renew after grace", async () => { + const unwrapped = await registerUnwrapped(); + const expiry0 = await env.v1.BaseRegistrar.read.nameExpires([ + unwrapped.tokenId, + ]); + await env.activateV2(); + await env.client.setNextBlockTimestamp({ + timestamp: expiry0 + PREMIGRATION_BONUS_PERIOD + GRACE_PERIOD_V2, + }); + await env.client.mine({ blocks: 1 }); + await expect( + env.v1.BaseRegistrar.read.available([unwrapped.tokenId]), + ).resolves.toStrictEqual(true); // available + await expect(unwrapped.renewV1(SEC_PER_YEAR)).rejects.toThrow( + "NameNotRenewable", + ); + }); + + it("syncWrapper", async () => { + const unlocked = await registerWrapped(); + await env.activateV2(); + await env.v2.ETHRenewerV1.write.syncWrapper([[unlocked.label]]); + }); + }); + + describe("unwrapped", () => { + it("migrate", async () => { + const unwrapped = await registerUnwrapped(); + await unwrapped.setupPublicResolver(); + await unwrapped.checkResolution(); + await unwrapped.migrate(); + await unwrapped.checkMigrated(); + await unwrapped.checkResolution(); + }); + + it("migrate with approval", async () => { + const unwrapped = await registerUnwrapped(); + const { user2 } = env.namedAccounts; + await env.v1.BaseRegistrar.write.setApprovalForAll( + [user2.address, true], + { account: unwrapped.account }, + ); + await unwrapped.migrate({ sender: user2 }); + await unwrapped.checkMigrated(); + }); + + it("new owner", async () => { + const unwrapped = await registerUnwrapped(); + const { user2 } = env.namedAccounts; + await unwrapped.migrate({ + data: { owner: user2.address }, + }); + await unwrapped.checkMigrated({ owner: user2.address }); + }); + + it("new resolver", async () => { + const unwrapped = await registerUnwrapped(); + await unwrapped.setupPublicResolver(); + await unwrapped.checkResolution(); + const { resolver } = env.namedAccounts.user; + await unwrapped.migrate({ + data: { resolver: resolver.address }, + }); + await unwrapped.checkMigrated(); + await resolver.write.multicall([ + makeResolutions({ name: unwrapped.name, ...defaultProfile }).map( + (x) => x.write, + ), + ]); + await unwrapped.checkResolution(); + }); + + it("custom subregistry", async () => { + const unwrapped = await registerUnwrapped(); + await unwrapped.migrate({ data: { subregistry: anotherAddress } }); + await unwrapped.checkMigrated(); + const subregistry = await env.v2.ETHRegistry.read.getSubregistry([ + unwrapped.label, + ]); + expectVar({ subregistry }).toEqualAddress(anotherAddress); + }); + + it("invalid owner", async () => { + const unwrapped = await registerUnwrapped(); + expect( + unwrapped.migrate({ data: { owner: zeroAddress } }), // wrong + ).rejects.toThrow("InvalidOwner"); + }); + + it("invalid receiver", async () => { + const unwrapped = await registerUnwrapped(); + expect( + unwrapped.migrate({ data: { owner: env.v2.ETHRegistry.address } }), // not IERC1155Receiver + ).rejects.toThrow("ERC1155InvalidReceiver"); + }); + + it("wrong controller", async () => { + const unwrapped = await registerUnwrapped(); + expect( + unwrapped.migrate({ target: env.v2.LockedMigrationController.address }), // wrong + ).rejects.toThrow("ERC721: transfer to non ERC721Receiver implementer"); + }); + + it("invalid data", async () => { + const unwrapped = await registerUnwrapped(); + expect( + unwrapped.migrate({ rawData: "0x1234" }), // wrong + ).rejects.toThrow("InvalidData"); + }); + + it("wrong label", async () => { + const unwrapped = await registerUnwrapped(); + expect( + unwrapped.migrate({ data: { label: unwrapped.label + "2" } }), // wrong + ).rejects.toThrow("NameDataMismatch"); + }); + }); + + describe("unlocked", () => { + it("migrate", async () => { + const unlocked = await registerWrapped(); + await unlocked.setupPublicResolver(); + await unlocked.checkResolution(); + await unlocked.migrate({ + target: env.v2.UnlockedMigrationController.address, + }); + await unlocked.checkMigrated(); + await unlocked.checkResolution(); + }); + + it("invalid owner", async () => { + const unlocked = await registerWrapped(); + expect( + unlocked.migrate({ + target: env.v2.UnlockedMigrationController.address, + data: { owner: zeroAddress }, // wrong + }), + ).rejects.toThrow("InvalidOwner"); + }); + + it("invalid receiver", async () => { + const unlocked = await registerUnwrapped(); + expect( + unlocked.migrate({ + target: env.v2.UnlockedMigrationController.address, + data: { owner: env.v2.ETHRegistry.address }, // not IERC1155Receiver + }), + ).rejects.toThrow("ERC1155InvalidReceiver"); + }); + + it("wrong controller", async () => { + const unlocked = await registerWrapped(); + expect( + unlocked.migrate({ target: env.v2.LockedMigrationController.address }), // wrong + ).rejects.toThrow("NameNotLocked"); + }); + + it("invalid data", async () => { + const unlocked = await registerWrapped(); + expect( + unlocked.migrate({ + target: env.v2.UnlockedMigrationController.address, + rawData: "0x1234", // wrong + }), + ).rejects.toThrow("InvalidData"); + }); + + it("wrong label", async () => { + const unlocked = await registerWrapped(); + expect( + unlocked.migrate({ + target: env.v2.UnlockedMigrationController.address, + data: { label: unlocked.label + "2" }, // wrong + }), + ).rejects.toThrow("NameDataMismatch"); + }); + }); + + describe("locked", () => { + it("migrate", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + await locked.setupPublicResolver(); + await locked.checkResolution(); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + }); + await locked.checkMigrated(); + await locked.checkResolution(); + }); + + async function testLockedResolver(whitelisted: boolean) { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + await locked.setupPublicResolver(); + await locked.burnFuses(FUSES.CANNOT_SET_RESOLVER); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + data: { resolver: anotherAddress }, + }); + await locked.checkMigrated(); + const resolver = await env.v2.ETHRegistry.read.getResolver([ + locked.label, + ]); + expectVar({ resolver }).toEqualAddress( + whitelisted + ? env.v2.PublicResolver.address + : env.v1.PublicResolver.address, + ); + } + + it("locked resolver", async () => { + await env.v2.PublicResolverSet.write.approve( + [env.v1.PublicResolver.address, false], // remove from set + { account: env.namedAccounts.owner }, + ); + await testLockedResolver(false); + }); + + it("locked resolver (wrapper-aware)", async () => { + await testLockedResolver(true); + }); + + it("locked transfer", async () => { + const locked = await registerWrapped({ + fuses: FUSES.CANNOT_UNWRAP | FUSES.CANNOT_TRANSFER, + }); + expect( + locked.migrate({ + target: env.v2.LockedMigrationController.address, + }), + ).rejects.toThrow("OperationProhibited"); + }); + + it("locked fuses", async () => { + const locked = await registerWrapped({ + fuses: FUSES.CANNOT_UNWRAP | FUSES.CANNOT_BURN_FUSES, + }); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + }); + await locked.checkMigrated(); + }); + + it("migrate locked child", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + const lockedChild = await locked.createChild({ + fuses: FUSES.PARENT_CANNOT_CONTROL | FUSES.CANNOT_UNWRAP, + }); + await lockedChild.setupPublicResolver(); + await lockedChild.checkResolution(); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + }); + const lockedRegistry = locked.wrapperRegistry(); + await lockedChild.migrate({ + target: lockedRegistry.address, + }); + await lockedChild.checkMigrated(); + await lockedChild.checkResolution(); + }); + + it("migrate detached child", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + const detachedChild = await locked.createChild({ + fuses: FUSES.PARENT_CANNOT_CONTROL, + }); + await detachedChild.setupPublicResolver(); + await detachedChild.checkResolution(); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + }); + const lockedRegistry = locked.wrapperRegistry(); + await detachedChild.migrate({ + target: lockedRegistry.address, + }); + await detachedChild.checkMigrated(); + await detachedChild.checkResolution(); + }); + + it("unmigrated locked child", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + const lockedChild = await locked.createChild({ + fuses: FUSES.PARENT_CANNOT_CONTROL | FUSES.CANNOT_UNWRAP, + }); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + }); + const lockedRegistry = locked.wrapperRegistry(); + + // name has fallback resolver + const resolver = await lockedRegistry.read.getResolver([ + lockedChild.label, + ]); + expectVar({ resolver }).toEqualAddress(env.v2.ENSV1Resolver.address); + + // name cannot be registered + expect( + lockedRegistry.write.register([ + lockedChild.label, + lockedChild.account.address, + zeroAddress, + zeroAddress, + 0n, + MAX_EXPIRY, + ]), + ).rejects.toThrow("NameRequiresMigration"); + }); + + it("unmigrated detached child", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + const detachedChild = await locked.createChild({ + fuses: FUSES.PARENT_CANNOT_CONTROL, + }); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + }); + const lockedRegistry = locked.wrapperRegistry(); + + // name has fallback resolver + const resolver = await lockedRegistry.read.getResolver([ + detachedChild.label, + ]); + expectVar({ resolver }).toEqualAddress(env.v2.ENSV1Resolver.address); + + // name cannot be registered + expect( + lockedRegistry.write.register([ + detachedChild.label, + detachedChild.account.address, + zeroAddress, + zeroAddress, + 0n, + MAX_EXPIRY, + ]), + ).rejects.toThrow("NameRequiresMigration"); + }); + + it("unmigrated unlocked child", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + const unlockedChild = await locked.createChild(); + await unlockedChild.setupPublicResolver(); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + }); + const lockedRegistry = locked.wrapperRegistry(); + + // name cannot be migrated + expect( + unlockedChild.migrate({ target: lockedRegistry.address }), + ).rejects.toThrow("NameNotLocked"); + + // name has null resolver + const resolver = await lockedRegistry.read.getResolver([ + unlockedChild.label, + ]); + expectVar({ resolver }).toEqualAddress(zeroAddress); + + // name can be clobbered + await lockedRegistry.write.register([ + unlockedChild.label, + unlockedChild.account.address, + zeroAddress, + zeroAddress, + 0n, + MAX_EXPIRY, + ]); + }); + + it("can extend expiry", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + const lockedChild = await locked.createChild({ + account: env.namedAccounts.user2, + fuses: + FUSES.PARENT_CANNOT_CONTROL | + FUSES.CANNOT_UNWRAP | + FUSES.CAN_EXTEND_EXPIRY, + }); + await locked.migrate({ + target: env.v2.LockedMigrationController.address, + }); + const lockedRegistry = locked.wrapperRegistry(); + await lockedChild.migrate({ + target: lockedRegistry.address, + }); + const state = await lockedRegistry.read.getState([ + idFromLabel(lockedChild.label), + ]); + await lockedRegistry.write.renew([state.tokenId, state.expiry + 1n], { + account: lockedChild.account, + }); + }); + + it("invalid owner", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + expect( + locked.migrate({ + target: env.v2.LockedMigrationController.address, + data: { owner: zeroAddress }, // wrong + }), + ).rejects.toThrow("InvalidOwner"); + }); + + it("invalid receiver", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + expect( + locked.migrate({ + target: env.v2.LockedMigrationController.address, + data: { owner: env.v2.ETHRegistry.address }, // not IERC1155Receiver + }), + ).rejects.toThrow("ERC1155InvalidReceiver"); + }); + + it("wrong controller", async () => { + const locked1 = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + const lockedChild = await locked1.createChild({ + fuses: FUSES.PARENT_CANNOT_CONTROL | FUSES.CANNOT_UNWRAP, + }); + const locked2 = await registerWrapped({ + label: locked1.label + "2", + fuses: FUSES.CANNOT_UNWRAP, + }); + await locked2.migrate({ + target: env.v2.LockedMigrationController.address, + }); + const locked2Registry = locked2.wrapperRegistry(); + + // 2LD => UnlockedMigrationController + expect( + locked1.migrate({ + target: env.v2.UnlockedMigrationController.address, + }), + ).rejects.toThrow("NameIsLocked"); + + // 3LD => LockedMigrationController + expect( + lockedChild.migrate({ + target: env.v2.LockedMigrationController.address, + }), + ).rejects.toThrow("NameDataMismatch"); + + // 2LD => WrapperRegistry + expect( + locked1.migrate({ target: locked2Registry.address }), + ).rejects.toThrow("NameDataMismatch"); + + // 3LD => wrong WrapperRegistry + expect( + lockedChild.migrate({ target: locked2Registry.address }), + ).rejects.toThrow("NameDataMismatch"); + }); + + it("invalid data", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + expect( + locked.migrate({ + target: env.v2.LockedMigrationController.address, + rawData: "0x1234", // wrong + }), + ).rejects.toThrow("InvalidData"); + }); + + it("wrong label", async () => { + const locked = await registerWrapped({ fuses: FUSES.CANNOT_UNWRAP }); + expect( + locked.migrate({ + target: env.v2.LockedMigrationController.address, + data: { label: locked.label + "2" }, // wrong + }), + ).rejects.toThrow("NameDataMismatch"); + }); + }); +}); diff --git a/contracts/test/e2e/phasedMigration.test.ts b/contracts/test/e2e/phasedMigration.test.ts new file mode 100644 index 000000000..382b99ba0 --- /dev/null +++ b/contracts/test/e2e/phasedMigration.test.ts @@ -0,0 +1,428 @@ +import { afterEach, describe, expect, it } from "bun:test"; +import { createServer } from "node:net"; +import { + existsSync, + mkdtempSync, + readFileSync, + rmSync, + unlinkSync, + writeFileSync, +} from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { + type Account, + type Address, + encodeAbiParameters, + getContract, + namehash, + zeroAddress, + zeroHash, +} from "viem"; +import { Artifact_ETHRegistrarController } from "generated/artifacts/ETHRegistrarController.js"; +import { ROLES, STATUS } from "../../script/deploy-constants.js"; +import { migrationDataComponents } from "../../script/migration.js"; +import { main as preMigrationMain } from "../../script/preMigration.js"; +import { + buildMainArgs, + createCSVFile, + verifyV2State, +} from "../utils/mockPreMigration.js"; +import { idFromLabel } from "../utils/utils.js"; + +const ONE_YEAR_SECONDS = 365n * 24n * 60n * 60n; +const MIN_V2_REGISTRATION_SECONDS = 28n * 24n * 60n * 60n; +const REGISTRAR_ROLES = ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW; + +describe("Phased migration rehearsal", () => { + const { env, setupEnv } = process.env.TEST_GLOBALS!; + const csvFilePath = join(process.cwd(), "test-phased-migration.csv"); + const cleanupFiles = [ + csvFilePath, + "preMigration-checkpoint.json", + "preMigration-errors.log", + "preMigration.log", + ]; + + setupEnv({ + resetOnEach: true, + async initialize() { + await enableV1Controller(ethRegistrarControllerAddress()); + await enableV1Controller(env.v1.NameWrapper.address); + + const v2RegistrarEnabled = await env.v2.ETHRegistry.read.hasRootRoles([ + REGISTRAR_ROLES, + env.v2.ETHRegistrar.address, + ]); + if (v2RegistrarEnabled) { + await env.v2.ETHRegistry.write.revokeRootRoles([ + REGISTRAR_ROLES, + env.v2.ETHRegistrar.address, + ]); + } + }, + }); + + afterEach(() => { + for (const file of cleanupFiles) { + if (existsSync(file)) { + try { + unlinkSync(file); + } catch {} + } + } + }); + + it("runs the migration phases on the local devnet snapshot", async () => { + const { user } = env.namedAccounts; + const initialLabel = "phaseoldok"; + const firstMigrationLabel = "phasemigrateone"; + const remainingMigrationLabel = "phasemigratetwo"; + + await registerViaV1Controller(initialLabel, user); + await registerViaV1Controller(firstMigrationLabel, user); + await registerViaV1Controller(remainingMigrationLabel, user); + + const initialOwner = await env.v1.BaseRegistrar.read.ownerOf([ + idFromLabel(initialLabel), + ]); + expect(initialOwner.toLowerCase()).toBe(user.address.toLowerCase()); + + createCSVFile(csvFilePath, [firstMigrationLabel, remainingMigrationLabel]); + await preMigrationMain( + buildMainArgs(env, csvFilePath, { + limit: 1, + batchSize: 1, + }), + ); + + let firstState = await verifyV2State(env, firstMigrationLabel); + let remainingState = await verifyV2State(env, remainingMigrationLabel); + expect(firstState.status).toBe(STATUS.RESERVED); + expect(remainingState.status).toBe(STATUS.AVAILABLE); + + await disableV1Registrars(); + + await expect( + env.v1.BaseRegistrar.read.controllers([ethRegistrarControllerAddress()]), + ).resolves.toBe(false); + await expect( + env.v1.BaseRegistrar.read.controllers([env.v1.NameWrapper.address]), + ).resolves.toBe(false); + // v1 BaseRegistrar rejects register() from a removed controller with a + // bare require (no reason string), so only the reverted call is matchable. + await expect( + registerViaV1Controller("phaseoldblocked", user), + ).rejects.toThrow('The contract function "register" reverted'); + + await preMigrationMain( + buildMainArgs(env, csvFilePath, { + continue: true, + batchSize: 1, + }), + ); + + firstState = await verifyV2State(env, firstMigrationLabel); + remainingState = await verifyV2State(env, remainingMigrationLabel); + expect(firstState.status).toBe(STATUS.RESERVED); + expect(remainingState.status).toBe(STATUS.RESERVED); + + await migrateUnwrappedV1Name(firstMigrationLabel, user); + + const migratedState = await verifyV2State(env, firstMigrationLabel); + expect(migratedState.status).toBe(STATUS.REGISTERED); + expect(migratedState.latestOwner.toLowerCase()).toBe( + user.address.toLowerCase(), + ); + + const registrarEnabledBefore = await env.v2.ETHRegistry.read.hasRootRoles([ + REGISTRAR_ROLES, + env.v2.ETHRegistrar.address, + ]); + expect(registrarEnabledBefore).toBe(false); + // ETHRegistrar lacks REGISTRAR/RENEW root roles on the registry, so the + // registry rejects the registration with + // EACUnauthorizedAccountRoles(uint256,uint256,address). The registrar's + // deployment ABI cannot decode the registry's error, so viem surfaces the + // raw selector (0x4b27a133); match either form. + await expect( + registerViaV2Registrar("phasev2blocked", user), + ).rejects.toThrow(/EACUnauthorizedAccountRoles|0x4b27a133/); + + await env.v2.ETHRegistry.write.grantRootRoles([ + REGISTRAR_ROLES, + env.v2.ETHRegistrar.address, + ]); + + const registrarEnabledAfter = await env.v2.ETHRegistry.read.hasRootRoles([ + REGISTRAR_ROLES, + env.v2.ETHRegistrar.address, + ]); + expect(registrarEnabledAfter).toBe(true); + + // The name is RESERVED from premigration, so the registrar refuses it. + await expect( + registerViaV2Registrar(remainingMigrationLabel, user), + ).rejects.toThrow("NameNotAvailable"); + + await registerViaV2Registrar("phasev2works", user); + const v2RegisteredState = await verifyV2State(env, "phasev2works"); + expect(v2RegisteredState.status).toBe(STATUS.REGISTERED); + expect(v2RegisteredState.latestOwner.toLowerCase()).toBe( + user.address.toLowerCase(), + ); + }, 30_000); + + function ethRegistrarControllerAddress(): Address { + return env.rocketh.deployments["ETHRegistrarController"].address; + } + + function ethRegistrarController(account: Account) { + return env.patchContractWrite( + getContract({ + abi: Artifact_ETHRegistrarController.abi, + address: ethRegistrarControllerAddress(), + client: env.createClient(account), + }), + ) as any; + } + + async function enableV1Controller(address: Address) { + const enabled = await env.v1.BaseRegistrar.read.controllers([address]); + if (enabled) return; + await env.v1.RegistrarSecurityController.write.addRegistrarController( + [address], + { account: env.namedAccounts.owner }, + ); + } + + async function disableV1Registrars() { + const controllerAddresses = [ + ethRegistrarControllerAddress(), + env.v1.NameWrapper.address, + ]; + for (const address of controllerAddresses) { + const enabled = await env.v1.BaseRegistrar.read.controllers([address]); + if (!enabled) continue; + await env.v1.RegistrarSecurityController.write.removeRegistrarController( + [address], + { account: env.namedAccounts.owner }, + ); + } + } + + async function registerViaV1Controller(label: string, account: Account) { + const controller = ethRegistrarController(account); + const registration = { + label, + owner: account.address, + duration: ONE_YEAR_SECONDS, + secret: zeroHash, + resolver: zeroAddress, + data: [], + reverseRecord: 0, + referrer: zeroHash, + }; + const commitment = await controller.read.makeCommitment([registration]); + await controller.write.commit([commitment], { account }); + const minCommitmentAge = await controller.read.minCommitmentAge(); + await env.sync({ warpSec: Number(minCommitmentAge) + 1 }); + + const price = await controller.read.rentPrice([label, ONE_YEAR_SECONDS]); + await controller.write.register([registration], { + account, + value: price.base + price.premium, + }); + } + + async function migrateUnwrappedV1Name(label: string, account: Account) { + const resolver = await env.v1.ENSRegistry.read.resolver([ + namehash(`${label}.eth`), + ]); + const data = encodeAbiParameters( + [{ type: "tuple", components: migrationDataComponents }], + [ + { + label, + owner: account.address, + subregistry: zeroAddress, + resolver, + }, + ], + ); + await env.v1.BaseRegistrar.write.safeTransferFrom( + [ + account.address, + env.v2.UnlockedMigrationController.address, + idFromLabel(label), + data, + ], + { account }, + ); + } + + async function registerViaV2Registrar(label: string, account: Account) { + const duration = MIN_V2_REGISTRATION_SECONDS; + const resolver = zeroAddress; + const subregistry = zeroAddress; + const referrer = zeroHash; + const secret = zeroHash; + const paymentToken = env.erc20.MockUSDC.address; + + const commitment = await env.v2.ETHRegistrar.read.makeCommitment([ + label, + account.address, + secret, + subregistry, + resolver, + duration, + referrer, + ]); + await env.v2.ETHRegistrar.write.commit([commitment], { account }); + await env.sync({ warpSec: 61 }); + + const [base, premium] = await env.v2.ETHRegistrar.read.getRegisterPrice([ + label, + duration, + paymentToken, + ]); + await env.erc20.MockUSDC.write.mint([account.address, base + premium], { + account, + }); + await env.erc20.MockUSDC.write.approve( + [env.v2.ETHRegistrar.address, base + premium], + { account }, + ); + await env.v2.ETHRegistrar.write.register( + [ + label, + account.address, + secret, + subregistry, + resolver, + duration, + paymentToken, + referrer, + ], + { account }, + ); + } +}); + +const sepoliaRpcUrl = loadEnvValue("SEPOLIA_RPC_URL"); +const runSepoliaFork = + process.env.RUN_SEPOLIA_FORK_MIGRATION_TEST === "1" && Boolean(sepoliaRpcUrl); +const describeSepoliaFork = runSepoliaFork ? describe : describe.skip; + +describeSepoliaFork("Sepolia Anvil fork migration rehearsal", () => { + it("runs the migration phases against a direct Sepolia fork", async () => { + const workDir = mkdtempSync(join(tmpdir(), "enschain-sepolia-fork-")); + const csvFile = join(workDir, "registrations.csv"); + writeFileSync( + csvFile, + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate\n", + ); + const port = await getFreePort(); + + try { + const proc = Bun.spawn( + [ + "bun", + "script/migration.ts", + "fork", + "full", + "--network", + "sepolia", + "--rpc-url", + sepoliaRpcUrl!, + "--chain-id", + "11155111", + "--port", + String(port), + "--csv-file", + csvFile, + "--work-dir", + workDir, + "--initial-limit", + "1", + ], + { + cwd: process.cwd(), + env: { + ...stringEnv(process.env), + SEPOLIA_RPC_URL: sepoliaRpcUrl!, + }, + stdout: "pipe", + stderr: "pipe", + }, + ); + const [stdout, stderr, exitCode] = await Promise.all([ + new Response(proc.stdout).text(), + new Response(proc.stderr).text(), + proc.exited, + ]); + const output = `${stdout}\n${stderr}`; + if (exitCode !== 0) { + throw new Error( + `Sepolia fork rehearsal failed:\n${output.slice(-12_000)}`, + ); + } + + expect(output).toContain( + "phase 1: deploy v2 contracts against official Sepolia v1 references", + ); + expect(output).toContain( + "v1 registration succeeded before registrar disablement", + ); + expect(output).toContain( + "v1 registration rejected after registrar disablement", + ); + expect(output).toContain("smoke migration registered"); + expect(output).toContain( + "v2 registrar rejected registration before enablement", + ); + expect(output).toContain( + "v2 registrar rejected pre-migrated reserved name after enablement", + ); + expect(output).toContain("v2 registrar registered"); + } finally { + rmSync(workDir, { recursive: true, force: true }); + } + }, 300_000); +}); + +function loadEnvValue(name: string): string | undefined { + if (process.env[name]) return process.env[name]; + const envFile = join(process.cwd(), ".env"); + if (!existsSync(envFile)) return undefined; + for (const line of readFileSync(envFile, "utf-8").split(/\r?\n/)) { + const match = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)=(.*)\s*$/); + if (!match || match[1] !== name) continue; + return match[2].replace(/^["']|["']$/g, ""); + } + return undefined; +} + +function stringEnv(env: NodeJS.ProcessEnv): Record { + return Object.fromEntries( + Object.entries(env).filter( + (entry): entry is [string, string] => typeof entry[1] === "string", + ), + ); +} + +async function getFreePort(): Promise { + const server = createServer(); + await new Promise((resolve, reject) => { + server.once("error", reject); + server.listen(0, "127.0.0.1", () => resolve()); + }); + const address = server.address(); + await new Promise((resolve, reject) => { + server.close((error) => (error ? reject(error) : resolve())); + }); + if (!address || typeof address === "string") { + throw new Error("failed to allocate a free local port"); + } + return address.port; +} diff --git a/contracts/test/e2e/preMigration.test.ts b/contracts/test/e2e/preMigration.test.ts new file mode 100644 index 000000000..603532a8f --- /dev/null +++ b/contracts/test/e2e/preMigration.test.ts @@ -0,0 +1,1322 @@ +import { afterEach, describe, expect, it, setDefaultTimeout } from "bun:test"; +setDefaultTimeout(60_000); + +import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { setTimeout } from "node:timers/promises"; +import { + createPublicClient, + createWalletClient, + http, + publicActions, + zeroAddress, +} from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { mainnet } from "viem/chains"; +import { STATUS, MAX_EXPIRY } from "../../script/deploy-constants.js"; +import { + main, + verifyNameOnV1, + batchVerifyRegistrations, + InvalidLabelNameError, + CSVFormatError, + isValidLabel, +} from "../../script/preMigration.js"; +import { + setupBaseRegistrarController, + registerV1Name, + renewV1Name, + createCSVFile, + buildMainArgs, + verifyV2State, +} from "../utils/mockPreMigration.js"; +import { + createTestCheckpoint, + deleteTestCheckpoint, + readTestCheckpoint, + writeTestCheckpoint, +} from "../utils/preMigrationTestUtils.js"; + +const ONE_YEAR_SECONDS = 365 * 24 * 60 * 60; + +describe("PreMigration", () => { + const { env, setupEnv } = process.env.TEST_GLOBALS!; + + const csvFilePath = join(tmpdir(), "test-premigration.csv"); + const cleanupFiles = [ + csvFilePath, + "preMigration-checkpoint.json", + "preMigration-errors.log", + "preMigration.log", + ]; + + setupEnv({ + resetOnEach: true, + async initialize() { + await setupBaseRegistrarController(env); + }, + }); + + afterEach(() => { + delete process.env.PREMIGRATION_PRIVATE_KEY; + for (const file of cleanupFiles) { + if (existsSync(file)) { + try { + unlinkSync(file); + } catch {} + } + } + }); + + async function expectMainToExitWithCsvError( + args: string[], + expectedFragments: string[], + ): Promise { + const originalExit = process.exit; + let exitCode: number | undefined; + process.exit = ((code?: number) => { + exitCode = code; + throw new Error(`process.exit(${code})`); + }) as never; + + let returnedNormally = false; + try { + await main(args); + returnedNormally = true; + } catch (e: any) { + if (e.message !== "process.exit(1)") { + throw e; + } + } finally { + process.exit = originalExit; + } + + if (returnedNormally) { + throw new Error("expected main() to exit with code 1 but it returned"); + } + expect(exitCode).toBe(1); + + const log = readFileSync("preMigration-errors.log", "utf-8"); + expect(log).toContain("CSVFormatError"); + for (const fragment of expectedFragments) { + expect(log).toContain(fragment); + } + } + + // ─── Core reservation flow ───────────────────────────────────────── + + it("reserves names from v1 on v2", async () => { + const labels = ["testname1", "testname2", "testname3"]; + const { user } = env.namedAccounts; + + const expiries: bigint[] = []; + for (const label of labels) { + const expiry = await registerV1Name( + env, + label, + user.address, + ONE_YEAR_SECONDS, + ); + expiries.push(expiry); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + for (let i = 0; i < labels.length; i++) { + const state = await verifyV2State(env, labels[i]); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.latestOwner).toBe(zeroAddress); + expect(state.expiry).toBe(expiries[i]); + } + }); + + it("reserves v1-grace-period names even when v2 expiry would already be in the past", async () => { + const label = "expiredname"; + const { user } = env.namedAccounts; + + const v1Expiry = await registerV1Name(env, label, user.address, 1); + await setTimeout(2000); + + createCSVFile(csvFilePath, [label]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + // Past expiry on a reservation is allowed by the contract; getState + // still reports AVAILABLE because _constructStatus treats expired + // entries as such. + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.AVAILABLE); + expect(state.expiry).toBe(v1Expiry); + + const checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(1); + expect(checkpoint!.failureCount).toBe(0); + }); + + it("reserves names that are expired but within v1 grace period", async () => { + const label = "graceperiodname"; + const { user } = env.namedAccounts; + + const v1Expiry = await registerV1Name(env, label, user.address, 1); + await setTimeout(2000); + + createCSVFile(csvFilePath, [label]); + const bonusPeriodDays = 62; + const args = buildMainArgs(env, csvFilePath, { bonusPeriodDays }); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.expiry).toBe(v1Expiry + BigInt(bonusPeriodDays) * 86400n); + }); + + it("handles already-reserved names (same expiry)", async () => { + const labels = ["alreadyres1", "alreadyres2"]; + const { user } = env.namedAccounts; + + for (const label of labels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const statesBefore = await Promise.all( + labels.map((l) => verifyV2State(env, l)), + ); + + deleteTestCheckpoint(); + await main(args); + + for (let i = 0; i < labels.length; i++) { + const stateAfter = await verifyV2State(env, labels[i]); + expect(stateAfter.status).toBe(STATUS.RESERVED); + expect(stateAfter.expiry).toBe(statesBefore[i].expiry); + } + }); + + it("renews already-reserved names with newer expiry", async () => { + const label = "renewtest"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + createCSVFile(csvFilePath, [label]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const stateBefore = await verifyV2State(env, label); + expect(stateBefore.status).toBe(STATUS.RESERVED); + + await renewV1Name(env, label, ONE_YEAR_SECONDS); + + deleteTestCheckpoint(); + const args2 = buildMainArgs(env, csvFilePath); + await main(args2); + + const stateAfter = await verifyV2State(env, label); + expect(stateAfter.status).toBe(STATUS.RESERVED); + expect(stateAfter.expiry).toBeGreaterThan(stateBefore.expiry); + }); + + it("dry run does not create on-chain state", async () => { + const label = "dryruntest"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + createCSVFile(csvFilePath, [label]); + const args = buildMainArgs(env, csvFilePath, { dryRun: true }); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.AVAILABLE); + }); + + it("limit parameter restricts processing", async () => { + const labels = ["limitname1", "limitname2", "limitname3"]; + const { user } = env.namedAccounts; + + for (const label of labels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath, { limit: 2 }); + await main(args); + + const state1 = await verifyV2State(env, labels[0]); + const state2 = await verifyV2State(env, labels[1]); + const state3 = await verifyV2State(env, labels[2]); + + expect(state1.status).toBe(STATUS.RESERVED); + expect(state2.status).toBe(STATUS.RESERVED); + expect(state3.status).toBe(STATUS.AVAILABLE); + }); + + it("adds expiry buffer to short v1 expiries", async () => { + const label = "soonexpire"; + const { user } = env.namedAccounts; + + const fiveDays = 5 * 24 * 60 * 60; + const v1Expiry = await registerV1Name( + env, + label, + user.address, + fiveDays, + ); + + createCSVFile(csvFilePath, [label]); + const bonusPeriodDays = 90; + const args = buildMainArgs(env, csvFilePath, { bonusPeriodDays }); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.expiry).toBe(v1Expiry + BigInt(bonusPeriodDays) * 86400n); + }); + + it("adds expiry buffer to long v1 expiries", async () => { + const label = "longexpire"; + const { user } = env.namedAccounts; + + const v1Expiry = await registerV1Name( + env, + label, + user.address, + ONE_YEAR_SECONDS, + ); + + createCSVFile(csvFilePath, [label]); + const bonusPeriodDays = 90; + const args = buildMainArgs(env, csvFilePath, { bonusPeriodDays }); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.expiry).toBe(v1Expiry + BigInt(bonusPeriodDays) * 86400n); + }); + + it("handles checkpoint resumption", async () => { + const labels = ["checkpoint1", "checkpoint2", "checkpoint3"]; + const { user } = env.namedAccounts; + + for (const label of labels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + createCSVFile(csvFilePath, labels); + + const args1 = buildMainArgs(env, csvFilePath, { limit: 1 }); + await main(args1); + + const state1After = await verifyV2State(env, labels[0]); + expect(state1After.status).toBe(STATUS.RESERVED); + + const args2 = buildMainArgs(env, csvFilePath, { + continue: true, + }); + await main(args2); + + for (const label of labels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + } + }); + + it("handles already-REGISTERED names gracefully", async () => { + const registeredLabel = "alreadyregistered"; + const normalLabel = "normalreserve"; + const { user, deployer } = env.namedAccounts; + + await registerV1Name(env, registeredLabel, user.address, ONE_YEAR_SECONDS); + await registerV1Name(env, normalLabel, user.address, ONE_YEAR_SECONDS); + + await env.v2.ETHRegistry.write.register([ + registeredLabel, + deployer.address, + zeroAddress, + zeroAddress, + 0n, + MAX_EXPIRY, + ]); + + const registeredState = await verifyV2State(env, registeredLabel); + expect(registeredState.status).toBe(STATUS.REGISTERED); + + createCSVFile(csvFilePath, [registeredLabel, normalLabel]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const regStateAfter = await verifyV2State(env, registeredLabel); + expect(regStateAfter.status).toBe(STATUS.REGISTERED); + + const normalState = await verifyV2State(env, normalLabel); + expect(normalState.status).toBe(STATUS.RESERVED); + }); + + // ─── Private key env var support ─────────────────────────────────── + + it("accepts private key from PREMIGRATION_PRIVATE_KEY env var", async () => { + const label = "envkeytest"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + createCSVFile(csvFilePath, [label]); + const args = buildMainArgs(env, csvFilePath, { useEnvVarForPrivateKey: true }); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + }); + + it("CLI --private-key overrides env var", async () => { + const label = "clioverride"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + process.env.PREMIGRATION_PRIVATE_KEY = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; + + createCSVFile(csvFilePath, [label]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + }); + + it("exits with error when no private key is provided", async () => { + const label = "nokey"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + createCSVFile(csvFilePath, [label]); + const args = buildMainArgs(env, csvFilePath, { omitPrivateKey: true }); + + const originalExit = process.exit; + let exitCode: number | undefined; + process.exit = ((code?: number) => { + exitCode = code; + throw new Error(`process.exit(${code})`); + }) as never; + + try { + await main(args); + } catch (e: any) { + expect(e.message).toBe("process.exit(1)"); + } finally { + process.exit = originalExit; + } + + expect(exitCode).toBe(1); + }); + + // ─── Multicall batching ──────────────────────────────────────────── + + it("correctly verifies a batch of names via multicall", async () => { + const labels = ["multi1", "multi2", "multi3", "multi4", "multi5"]; + const { user } = env.namedAccounts; + + const expiries: bigint[] = []; + for (const label of labels) { + const expiry = await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + expiries.push(expiry); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + for (let i = 0; i < labels.length; i++) { + const state = await verifyV2State(env, labels[i]); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.expiry).toBe(expiries[i]); + } + }); + + it("handles mixed registered/expired/valid names in single multicall batch", async () => { + const validLabel = "mixedvalid"; + const expiredLabel = "mixedexpired"; + const neverRegisteredLabel = "mixednever"; + const { user } = env.namedAccounts; + + await registerV1Name(env, validLabel, user.address, ONE_YEAR_SECONDS); + + await registerV1Name(env, expiredLabel, user.address, 1); + await setTimeout(2000); + + createCSVFile(csvFilePath, [validLabel, expiredLabel, neverRegisteredLabel]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const validState = await verifyV2State(env, validLabel); + expect(validState.status).toBe(STATUS.RESERVED); + + const expiredState = await verifyV2State(env, expiredLabel); + expect(expiredState.status).toBe(STATUS.AVAILABLE); + + const neverState = await verifyV2State(env, neverRegisteredLabel); + expect(neverState.status).toBe(STATUS.AVAILABLE); + }); + + it("batchVerifyRegistrations returns correct v1/v2 state for each name", async () => { + const validLabel = "bvvalid"; + const expiredLabel = "bvexpired"; + const registeredLabel = "bvregistered"; + const neverLabel = "bvnever"; + const { user, deployer } = env.namedAccounts; + + const validExpiry = await registerV1Name(env, validLabel, user.address, ONE_YEAR_SECONDS); + await registerV1Name(env, expiredLabel, user.address, 1); + await registerV1Name(env, registeredLabel, user.address, ONE_YEAR_SECONDS); + await setTimeout(2000); + + await env.v2.ETHRegistry.write.register([ + registeredLabel, + deployer.address, + zeroAddress, + zeroAddress, + 0n, + MAX_EXPIRY, + ]); + + const rpcUrl = `http://${env.hostPort}`; + const client = createWalletClient({ + account: privateKeyToAccount("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"), + chain: mainnet, + transport: http(rpcUrl, { retryCount: 0, timeout: 30000 }), + }).extend(publicActions); + + const mainnetClient = createPublicClient({ + chain: mainnet, + transport: http(rpcUrl, { retryCount: 0, timeout: 30000 }), + }); + + const registryAbi = [...env.v2.ETHRegistry.abi]; + const registrations = [ + { labelName: validLabel, lineNumber: 1 }, + { labelName: expiredLabel, lineNumber: 2 }, + { labelName: registeredLabel, lineNumber: 3 }, + { labelName: neverLabel, lineNumber: 4 }, + ]; + + const results = await batchVerifyRegistrations( + registrations, + client, + mainnetClient, + env.v2.ETHRegistry.address, + registryAbi, + env.v1.BaseRegistrar.address, + ); + + expect(results.length).toBe(4); + + expect(results[0].v2Status).toBe(STATUS.AVAILABLE); + expect(results[0].v1IsClaimable).toBe(true); + expect(results[0].v1Expiry).toBe(validExpiry); + + // Just-expired name is still within v1's 90-day grace, so claimable. + expect(results[1].v2Status).toBe(STATUS.AVAILABLE); + expect(results[1].v1IsClaimable).toBe(true); + + expect(results[2].v2Status).toBe(STATUS.REGISTERED); + expect(results[2].v1IsClaimable).toBe(true); + + expect(results[3].v2Status).toBe(STATUS.AVAILABLE); + expect(results[3].v1IsClaimable).toBe(false); + expect(results[3].v1Expiry).toBe(0n); + }); + + // ─── Batch sizing ────────────────────────────────────────────────── + + it("processes names across multiple batches with batchSize=1", async () => { + const labels = ["batch1a", "batch1b", "batch1c"]; + const { user } = env.namedAccounts; + + for (const label of labels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath, { batchSize: 1 }); + await main(args); + + for (const label of labels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + } + }); + + it("processes names across multiple batches with batchSize=2", async () => { + const labels = ["batch2a", "batch2b", "batch2c", "batch2d", "batch2e"]; + const { user } = env.namedAccounts; + + const expiries: bigint[] = []; + for (const label of labels) { + const expiry = await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + expiries.push(expiry); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath, { batchSize: 2 }); + await main(args); + + for (let i = 0; i < labels.length; i++) { + const state = await verifyV2State(env, labels[i]); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.expiry).toBe(expiries[i]); + } + + const checkpoint = readTestCheckpoint(); + expect(checkpoint).not.toBeNull(); + expect(checkpoint!.successCount).toBe(5); + expect(checkpoint!.failureCount).toBe(0); + }); + + // ─── Gas estimation (exercises estimateAndSplitBatch path) ───────── + + it("handles a larger batch of 10 names through gas estimation", async () => { + const labels = Array.from({ length: 10 }, (_, i) => `gasest${i}`); + const { user } = env.namedAccounts; + + const expiries: bigint[] = []; + for (const label of labels) { + const expiry = await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + expiries.push(expiry); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + for (let i = 0; i < labels.length; i++) { + const state = await verifyV2State(env, labels[i]); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.expiry).toBe(expiries[i]); + } + + const checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(10); + expect(checkpoint!.failureCount).toBe(0); + }); + + it("handles batch of names with long labels (higher calldata cost)", async () => { + const labels = [ + "a".repeat(63), + "b".repeat(63), + "c".repeat(63), + ]; + const { user } = env.namedAccounts; + + const expiries: bigint[] = []; + for (const label of labels) { + const expiry = await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + expiries.push(expiry); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + for (let i = 0; i < labels.length; i++) { + const state = await verifyV2State(env, labels[i]); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.expiry).toBe(expiries[i]); + } + }); + + // ─── Checkpoint tracking ─────────────────────────────────────────── + + it("checkpoint correctly tracks success, skip, and failure counts", async () => { + const validLabel = "cptvalid"; + const expiredLabel = "cptexpired"; + const neverLabel = "cptnever"; + const { user } = env.namedAccounts; + + await registerV1Name(env, validLabel, user.address, ONE_YEAR_SECONDS); + await registerV1Name(env, expiredLabel, user.address, 1); + await setTimeout(2000); + + createCSVFile(csvFilePath, [validLabel, expiredLabel, neverLabel]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const checkpoint = readTestCheckpoint(); + expect(checkpoint).not.toBeNull(); + expect(checkpoint!.successCount).toBe(2); + expect(checkpoint!.skippedCount).toBe(1); + expect(checkpoint!.failureCount).toBe(0); + expect(checkpoint!.totalProcessed).toBe(3); + }); + + it("checkpoint tracks failures for already-registered names", async () => { + const registeredLabel = "cptregfail"; + const validLabel = "cptregvalid"; + const { user, deployer } = env.namedAccounts; + + await registerV1Name(env, registeredLabel, user.address, ONE_YEAR_SECONDS); + await registerV1Name(env, validLabel, user.address, ONE_YEAR_SECONDS); + + await env.v2.ETHRegistry.write.register([ + registeredLabel, + deployer.address, + zeroAddress, + zeroAddress, + 0n, + MAX_EXPIRY, + ]); + + createCSVFile(csvFilePath, [registeredLabel, validLabel]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const checkpoint = readTestCheckpoint(); + expect(checkpoint).not.toBeNull(); + expect(checkpoint!.successCount).toBe(1); + expect(checkpoint!.failureCount).toBe(1); + }); + + it("checkpoint tracks renewed count separately", async () => { + const label = "cptrenewal"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + createCSVFile(csvFilePath, [label]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const checkpointBefore = readTestCheckpoint(); + expect(checkpointBefore!.successCount).toBe(1); + expect(checkpointBefore!.renewedCount).toBe(0); + + await renewV1Name(env, label, ONE_YEAR_SECONDS); + + deleteTestCheckpoint(); + await main(args); + + const checkpointAfter = readTestCheckpoint(); + expect(checkpointAfter!.renewedCount).toBe(1); + expect(checkpointAfter!.successCount).toBe(0); + }); + + // ─── Invalid label handling ──────────────────────────────────────── + + it("fails fast on empty labelName cell", async () => { + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,validfirst,,`, + ",,,,,,,,", + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await expectMainToExitWithCsvError(args, [ + `${csvFilePath}:3`, + `empty "labelName"`, + ]); + }); + + it("accepts the 6-column exporter header (label alias)", async () => { + const label = "exporterfmt"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + const csvContent = [ + "name,label,labelhash,registrant,expiryDate,registrationDate", + `,${label},,,,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + }); + + it("fails fast when header has no labelName or label column", async () => { + const csvContent = [ + "node,name,owner", + "n,foo,0x00", + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await expectMainToExitWithCsvError(args, [ + `${csvFilePath}:1`, + `no "labelName" or "label" column`, + "Found columns: [node, name, owner]", + ]); + }); + + it("fails fast when a row's column count differs from the header", async () => { + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,validlbl,,`, + `,,,,short,row`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await expectMainToExitWithCsvError(args, [ + `${csvFilePath}:3`, + "6 columns but header declared 9", + ]); + }); + + it("fails fast on unbalanced quotes in a data row", async () => { + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,"unterminated,,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await expectMainToExitWithCsvError(args, [ + `${csvFilePath}:2`, + "unbalanced quotes", + ]); + }); + + it("tolerates a trailing blank line at end of file", async () => { + const label = "trailblank"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + const csvContent = + [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,${label},,`, + "", + "", + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + }); + + it("tolerates a UTF-8 BOM on the header line", async () => { + const label = "bomlabel"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + const csvContent = + "" + + [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,${label},,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + }); + + it("prefers labelName over label when both columns are present", async () => { + const winning = "winnerlbl"; + const losing = "loserlbl"; + const { user } = env.namedAccounts; + + await registerV1Name(env, winning, user.address, ONE_YEAR_SECONDS); + + const csvContent = [ + "label,labelName,extra", + `${losing},${winning},x`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const winnerState = await verifyV2State(env, winning); + expect(winnerState.status).toBe(STATUS.RESERVED); + + const loserState = await verifyV2State(env, losing); + expect(loserState.status).toBe(STATUS.AVAILABLE); + }); + + it("fails fast on a blank line in the middle of the file", async () => { + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,first,,`, + ``, + `,,,,,,second,,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await expectMainToExitWithCsvError(args, [ + `${csvFilePath}:3`, + "is blank", + ]); + }); + + it("skips labels exceeding 255 bytes and encoded labelhashes in CSV", async () => { + const validLabel = "validlabel2"; + const { user } = env.namedAccounts; + + await registerV1Name(env, validLabel, user.address, ONE_YEAR_SECONDS); + + const longLabel = "a".repeat(256); + const encodedLabel = `[${"a".repeat(64)}]`; + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,${validLabel},,`, + `,,,,,,${longLabel},,`, + `,,,,,,${encodedLabel},,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const state = await verifyV2State(env, validLabel); + expect(state.status).toBe(STATUS.RESERVED); + + const checkpoint = readTestCheckpoint(); + expect(checkpoint).not.toBeNull(); + expect(checkpoint!.successCount).toBe(1); + expect(checkpoint!.invalidLabelCount).toBe(2); + }); + + // ─── Edge cases ──────────────────────────────────────────────────── + + it("handles empty CSV file gracefully", async () => { + writeFileSync(csvFilePath, "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate\n"); + + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const checkpoint = readTestCheckpoint(); + expect(checkpoint).toBeNull(); + }); + + it("handles single name CSV", async () => { + const label = "singlename"; + const { user } = env.namedAccounts; + + const expiry = await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + createCSVFile(csvFilePath, [label]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + expect(state.expiry).toBe(expiry); + }); + + it("processes names with limit + continue across multiple runs", async () => { + const labels = ["lc1", "lc2", "lc3", "lc4", "lc5"]; + const { user } = env.namedAccounts; + + for (const label of labels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + createCSVFile(csvFilePath, labels); + + const args1 = buildMainArgs(env, csvFilePath, { limit: 2 }); + await main(args1); + + let checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(2); + + const args2 = buildMainArgs(env, csvFilePath, { continue: true, limit: 2 }); + await main(args2); + + checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(4); + + const args3 = buildMainArgs(env, csvFilePath, { continue: true }); + await main(args3); + + checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(5); + + for (const label of labels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + } + }); + + it("--limit N does not validate a wrong-column-count row at position N+1", async () => { + const validLabels = ["lcap1", "lcap2"]; + const { user } = env.namedAccounts; + + for (const label of validLabels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,${validLabels[0]},,`, + `,,,,,,${validLabels[1]},,`, + `,,,short,row`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath, { limit: 2 }); + await main(args); + + for (const label of validLabels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + } + + const checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(2); + }); + + it("--limit N does not validate an unbalanced-quotes row at position N+1", async () => { + const validLabels = ["lqcap1", "lqcap2"]; + const { user } = env.namedAccounts; + + for (const label of validLabels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,${validLabels[0]},,`, + `,,,,,,${validLabels[1]},,`, + `,,,,,,"unterminated,,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath, { limit: 2 }); + await main(args); + + for (const label of validLabels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + } + + const checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(2); + }); + + it("--dry-run --limit N tolerates malformed rows beyond the cap", async () => { + const validLabels = ["dryc1", "dryc2"]; + const { user } = env.namedAccounts; + + for (const label of validLabels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,${validLabels[0]},,`, + `,,,,,,${validLabels[1]},,`, + `,,,short,row`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath, { limit: 2, dryRun: true }); + await main(args); + + for (const label of validLabels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.AVAILABLE); + } + + const checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(2); + }); + + it("--continue does not validate a wrong-column-count row before the resume point", async () => { + const label = "resumecols"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + writeTestCheckpoint( + createTestCheckpoint({ + lastProcessedLineNumber: 0, + totalProcessed: 1, + totalExpected: 1, + successCount: 1, + }), + ); + + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,short,row`, + `,,,,,,${label},,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath, { continue: true }); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + }); + + it("--continue does not validate an unbalanced-quotes row before the resume point", async () => { + const label = "resumequotes"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + writeTestCheckpoint( + createTestCheckpoint({ + lastProcessedLineNumber: 0, + totalProcessed: 1, + totalExpected: 1, + successCount: 1, + }), + ); + + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + `,,,,,,"unterminated,,`, + `,,,,,,${label},,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath, { continue: true }); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + }); + + it("--continue tolerates a blank line in the pre-resume range", async () => { + const label = "resumeblank"; + const { user } = env.namedAccounts; + + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + + writeTestCheckpoint( + createTestCheckpoint({ + lastProcessedLineNumber: 0, + totalProcessed: 1, + totalExpected: 1, + successCount: 1, + }), + ); + + const csvContent = [ + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate", + "", + `,,,,,,already,,`, + `,,,,,,${label},,`, + ].join("\n"); + writeFileSync(csvFilePath, csvContent); + + const args = buildMainArgs(env, csvFilePath, { continue: true }); + await main(args); + + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + }); + + it("dry run with batch size 1 does not create state", async () => { + const labels = ["dryb1", "dryb2", "dryb3"]; + const { user } = env.namedAccounts; + + for (const label of labels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath, { dryRun: true, batchSize: 1 }); + await main(args); + + for (const label of labels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.AVAILABLE); + } + }); + + it("mixed batch: some expired, some valid, some never registered — with small batches", async () => { + const validLabels = ["mxs1", "mxs3", "mxs5"]; + const expiredLabels = ["mxs2", "mxs4"]; + const neverLabel = "mxs6"; + const allLabels = ["mxs1", "mxs2", "mxs3", "mxs4", "mxs5", "mxs6"]; + const { user } = env.namedAccounts; + + for (const label of validLabels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + for (const label of expiredLabels) { + await registerV1Name(env, label, user.address, 1); + } + await setTimeout(2000); + + createCSVFile(csvFilePath, allLabels); + const args = buildMainArgs(env, csvFilePath, { batchSize: 2 }); + await main(args); + + for (const label of validLabels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + } + for (const label of [...expiredLabels, neverLabel]) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.AVAILABLE); + } + + const checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(5); + expect(checkpoint!.skippedCount).toBe(1); + expect(checkpoint!.failureCount).toBe(0); + }); + + it("multiple registered names in batch are all counted as failures", async () => { + const registeredLabels = ["mreg1", "mreg2"]; + const validLabel = "mregvalid"; + const { user, deployer } = env.namedAccounts; + + for (const label of [...registeredLabels, validLabel]) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + for (const label of registeredLabels) { + await env.v2.ETHRegistry.write.register([ + label, + deployer.address, + zeroAddress, + zeroAddress, + 0n, + MAX_EXPIRY, + ]); + } + + createCSVFile(csvFilePath, [...registeredLabels, validLabel]); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const checkpoint = readTestCheckpoint(); + expect(checkpoint!.successCount).toBe(1); + expect(checkpoint!.failureCount).toBe(2); + }); + + it("re-running same batch after successful reservation uses renewal path", async () => { + const labels = ["rerun1", "rerun2"]; + const { user } = env.namedAccounts; + + for (const label of labels) { + await registerV1Name(env, label, user.address, ONE_YEAR_SECONDS); + } + + createCSVFile(csvFilePath, labels); + const args = buildMainArgs(env, csvFilePath); + await main(args); + + const checkpoint1 = readTestCheckpoint(); + expect(checkpoint1!.successCount).toBe(2); + expect(checkpoint1!.renewedCount).toBe(0); + + deleteTestCheckpoint(); + await main(args); + + const checkpoint2 = readTestCheckpoint(); + expect(checkpoint2!.successCount).toBe(0); + expect(checkpoint2!.renewedCount).toBe(2); + + for (const label of labels) { + const state = await verifyV2State(env, label); + expect(state.status).toBe(STATUS.RESERVED); + } + }); +}); + +describe("PreMigration - Live Mainnet v1 Verification", () => { + const mainnetClient = createPublicClient({ + chain: mainnet, + transport: http(process.env.MAINNET_RPC_URL, { + retryCount: 2, + timeout: 15_000, + }), + }); + + // The two cases below read live mainnet state through the configured RPC + // (defaulting to a public endpoint), so they depend on external availability + // and rate limits. They are opt-in to keep CI independent of those; set a + // reliable MAINNET_RPC_URL when enabling. + const itLiveMainnet = + process.env.RUN_LIVE_MAINNET_TESTS === "1" ? it : it.skip; + + itLiveMainnet( + "verifies well-known names are registered on v1 mainnet", + async () => { + const wellKnownNames = ["nick", "vitalik"]; + + for (const name of wellKnownNames) { + const result = await verifyNameOnV1(name, mainnetClient); + expect(result.isRegistered).toBe(true); + expect(result.expiry).toBeGreaterThan( + BigInt(Math.floor(Date.now() / 1000)), + ); + } + }, + ); + + itLiveMainnet( + "verifies a non-existent name returns not-registered on v1 mainnet", + async () => { + const nonExistentName = + "thisisaverylongnamethatwillneverberegistered12345678"; + const result = await verifyNameOnV1(nonExistentName, mainnetClient); + expect(result.isRegistered).toBe(false); + }, + ); + + it("throws InvalidLabelNameError for empty label", async () => { + try { + await verifyNameOnV1("", mainnetClient); + expect.unreachable("should have thrown"); + } catch (e) { + expect(e).toBeInstanceOf(InvalidLabelNameError); + } + }); + + it("throws InvalidLabelNameError for whitespace-only label", async () => { + try { + await verifyNameOnV1(" ", mainnetClient); + expect.unreachable("should have thrown"); + } catch (e) { + expect(e).toBeInstanceOf(InvalidLabelNameError); + } + }); + + it("throws InvalidLabelNameError for label exceeding 255 bytes", async () => { + const longLabel = "a".repeat(256); + try { + await verifyNameOnV1(longLabel, mainnetClient); + expect.unreachable("should have thrown"); + } catch (e) { + expect(e).toBeInstanceOf(InvalidLabelNameError); + } + }); + + it("throws InvalidLabelNameError for encoded labelhash", async () => { + const encodedLabel = `[${"a".repeat(64)}]`; + try { + await verifyNameOnV1(encodedLabel, mainnetClient); + expect.unreachable("should have thrown"); + } catch (e) { + expect(e).toBeInstanceOf(InvalidLabelNameError); + } + }); +}); diff --git a/contracts/test/e2e/prepareMigration.test.ts b/contracts/test/e2e/prepareMigration.test.ts new file mode 100644 index 000000000..453145852 --- /dev/null +++ b/contracts/test/e2e/prepareMigration.test.ts @@ -0,0 +1,178 @@ +import { describe, expect, it, setDefaultTimeout } from "bun:test"; +setDefaultTimeout(60_000); + +import { toHex, type Address } from "viem"; +import { ROLES } from "../../script/deploy-constants.js"; +import { main } from "../../script/prepareMigration.js"; +import { revertPrePrepareMigrationRoles } from "../utils/mockPrepareMigration.js"; + +const ROLE_REGISTRAR = ROLES.REGISTRY.REGISTRAR; +const ROLE_REGISTRAR_ADMIN = ROLES.ADMIN.REGISTRY.REGISTRAR; +const ROLE_REGISTER_RESERVED = ROLES.REGISTRY.REGISTER_RESERVED; +const ROLE_REGISTER_RESERVED_ADMIN = ROLES.ADMIN.REGISTRY.REGISTER_RESERVED; +const ROLE_RENEW = ROLES.REGISTRY.RENEW; +const ROLE_RENEW_ADMIN = ROLES.ADMIN.REGISTRY.RENEW; + +describe("PrepareMigration", () => { + const { env, setupEnv } = process.env.TEST_GLOBALS!; + + setupEnv({ + resetOnEach: true, + async initialize() { + await revertPrePrepareMigrationRoles(env); + }, + }); + + function getAddresses() { + return { + rpcUrl: `http://${env.hostPort}`, + registry: env.v2.ETHRegistry.address, + batchRegistrar: env.rocketh.get("BatchRegistrar").address as Address, + ethRegistrar: env.v2.ETHRegistrar.address, + unlocked: env.v2.UnlockedMigrationController.address, + locked: env.v2.LockedMigrationController.address, + }; + } + + function buildArgs( + addrs: ReturnType, + overrides: { privateKey?: string; execute?: boolean } = {}, + ): string[] { + const args = [ + "node", + "prepareMigration", + "--rpc-url", + addrs.rpcUrl, + "--registry", + addrs.registry, + "--batch-registrar", + addrs.batchRegistrar, + "--eth-registrar", + addrs.ethRegistrar, + "--unlocked-migration-controller", + addrs.unlocked, + "--locked-migration-controller", + addrs.locked, + ]; + const pk = + overrides.privateKey ?? + toHex(env.namedAccounts.deployer.getHdKey().privateKey!); + if (pk) args.push("--private-key", pk); + if (overrides.execute) args.push("--execute"); + return args; + } + + async function readRoles(account: Address): Promise { + return (await env.v2.ETHRegistry.read.roles([0n, account])) as bigint; + } + + it("devnet starts in pre-prepareMigration state", async () => { + const addrs = getAddresses(); + + expect((await readRoles(addrs.batchRegistrar)) & ROLE_REGISTRAR).toBe( + ROLE_REGISTRAR, + ); + expect((await readRoles(addrs.ethRegistrar)) & ROLE_REGISTRAR).toBe(0n); + expect((await readRoles(addrs.unlocked)) & ROLE_REGISTER_RESERVED).toBe(0n); + expect((await readRoles(addrs.locked)) & ROLE_REGISTER_RESERVED).toBe(0n); + }); + + it("dry run does not mutate on-chain role state", async () => { + const addrs = getAddresses(); + + const before = { + batch: await readRoles(addrs.batchRegistrar), + eth: await readRoles(addrs.ethRegistrar), + unlocked: await readRoles(addrs.unlocked), + locked: await readRoles(addrs.locked), + }; + + await main(buildArgs(addrs)); + + expect(await readRoles(addrs.batchRegistrar)).toBe(before.batch); + expect(await readRoles(addrs.ethRegistrar)).toBe(before.eth); + expect(await readRoles(addrs.unlocked)).toBe(before.unlocked); + expect(await readRoles(addrs.locked)).toBe(before.locked); + }); + + it("execute strips all migration-relevant roles from BatchRegistrar and hands them to the live targets", async () => { + const addrs = getAddresses(); + + const batchBefore = await readRoles(addrs.batchRegistrar); + expect(batchBefore & ROLE_REGISTRAR).toBe(ROLE_REGISTRAR); + expect(batchBefore & ROLE_RENEW).toBe(ROLE_RENEW); + + await main(buildArgs(addrs, { execute: true })); + + const batchAfter = await readRoles(addrs.batchRegistrar); + expect(batchAfter & ROLE_REGISTRAR).toBe(0n); + expect(batchAfter & ROLE_REGISTRAR_ADMIN).toBe(0n); + expect(batchAfter & ROLE_REGISTER_RESERVED).toBe(0n); + expect(batchAfter & ROLE_REGISTER_RESERVED_ADMIN).toBe(0n); + expect(batchAfter & ROLE_RENEW).toBe(0n); + expect(batchAfter & ROLE_RENEW_ADMIN).toBe(0n); + + const ethAfter = await readRoles(addrs.ethRegistrar); + expect(ethAfter & ROLE_REGISTRAR).toBe(ROLE_REGISTRAR); + expect(ethAfter & ROLE_RENEW).toBe(ROLE_RENEW); + expect((await readRoles(addrs.unlocked)) & ROLE_REGISTER_RESERVED).toBe( + ROLE_REGISTER_RESERVED, + ); + expect((await readRoles(addrs.locked)) & ROLE_REGISTER_RESERVED).toBe( + ROLE_REGISTER_RESERVED, + ); + }); + + it("execute fully decommissions BatchRegistrar (no roles remain)", async () => { + const addrs = getAddresses(); + const batchBefore = await readRoles(addrs.batchRegistrar); + expect(batchBefore & ROLE_RENEW).toBe(ROLE_RENEW); + + await main(buildArgs(addrs, { execute: true })); + + expect(await readRoles(addrs.batchRegistrar)).toBe(0n); + }); + + it("is idempotent on repeated execute", async () => { + const addrs = getAddresses(); + + await main(buildArgs(addrs, { execute: true })); + const snapshot = { + batch: await readRoles(addrs.batchRegistrar), + eth: await readRoles(addrs.ethRegistrar), + unlocked: await readRoles(addrs.unlocked), + locked: await readRoles(addrs.locked), + }; + + await main(buildArgs(addrs, { execute: true })); + + expect(await readRoles(addrs.batchRegistrar)).toBe(snapshot.batch); + expect(await readRoles(addrs.ethRegistrar)).toBe(snapshot.eth); + expect(await readRoles(addrs.unlocked)).toBe(snapshot.unlocked); + expect(await readRoles(addrs.locked)).toBe(snapshot.locked); + }); + + it("aborts when signer lacks required admin roles", async () => { + const addrs = getAddresses(); + // "owner" account is funded but has CAN_NAME for root on ETHRegistry + const { owner } = env.namedAccounts; + const privateKey = toHex(owner.getHdKey().privateKey!); + expect(await readRoles(owner.address)).toBe(ROLES.REGISTRY.CAN_NAME); + + await expect( + main(buildArgs(addrs, { privateKey, execute: true })), + ).rejects.toThrow(/admin roles/); + + // state untouched + expect((await readRoles(addrs.batchRegistrar)) & ROLE_REGISTRAR).toBe( + ROLE_REGISTRAR, + ); + }); + + it("rejects --execute without --private-key", async () => { + const addrs = getAddresses(); + await expect( + main(buildArgs(addrs, { privateKey: "", execute: true })), + ).rejects.toThrow(/--execute requires --private-key/); + }); +}); diff --git a/contracts/test/e2e/resolve.test.ts b/contracts/test/e2e/resolve.test.ts index cdfa43423..a8703a3e4 100755 --- a/contracts/test/e2e/resolve.test.ts +++ b/contracts/test/e2e/resolve.test.ts @@ -1,17 +1,26 @@ import { describe, it } from "bun:test"; -import { type Address, getAddress, namehash, zeroAddress } from "viem"; +import type { Address } from "viem"; -import { MAX_EXPIRY } from "../../script/deploy-constants.js"; import { expectVar } from "../utils/expectVar.js"; import { bundleCalls, - COIN_TYPE_DEFAULT, - COIN_TYPE_ETH, - getReverseName, type KnownProfile, makeResolutions, } from "../utils/resolutions.js"; -import { dnsEncodeName } from "../utils/utils.js"; +import { + coinTypeFromChain, + COIN_TYPE_DEFAULT, + COIN_TYPE_ETH, + dnsEncodeName, + getReverseNamespace, +} from "../utils/utils.js"; + +const COIN_TYPE_OPTIMISM = coinTypeFromChain(10); + +// Some DNS cases resolve real third-party domains through the live +// dnssec-oracle.ens.domains CCIP gateway, so they depend on external DNS state +// and gateway availability. They are opt-in to keep CI independent of those. +const itLiveDns = process.env.RUN_LIVE_DNS_TESTS === "1" ? it : it.skip; describe("Resolve", () => { const { env, setupEnv } = process.env.TEST_GLOBALS!; @@ -20,43 +29,46 @@ describe("Resolve", () => { async function expectResolve(kp: KnownProfile) { const bundle = bundleCalls(makeResolutions(kp)); - const [answer] = - await env.deployment.contracts.UniversalResolverV2.read.resolve([ - dnsEncodeName(kp.name), - bundle.call, - ]); + const [answer] = await env.v2.UniversalResolver.read.resolve([ + dnsEncodeName(kp.name), + bundle.call, + ]); bundle.expect(answer); } describe("Protocol", () => { - async function named(name: string, fn: () => Address) { + function expectNamed(name: string, fn: () => Address) { it(name, async () => { - const [resolver] = - await env.deployment.contracts.UniversalResolverV2.read.findResolver([ - dnsEncodeName(name), - ]); - expectVar({ resolver }).toStrictEqual(getAddress(fn())); // toEqualAddress + const [resolver] = await env.v2.UniversalResolver.read.findResolver([ + dnsEncodeName(name), + ]); + expectVar({ resolver }).toEqualAddress(fn()); }); } - named( - "reverse", - () => env.deployment.contracts.DefaultReverseResolver.address, + expectNamed("reverse", () => env.v2.ENSV1Resolver.address); + expectNamed( + getReverseNamespace(COIN_TYPE_ETH), + () => env.v2.ENSV1Resolver.address, + ); + expectNamed( + getReverseNamespace(COIN_TYPE_DEFAULT), + () => env.v2.ENSV1Resolver.address, ); - named( - "addr.reverse", - () => env.deployment.contracts.ETHReverseResolver.address, + expectNamed( + getReverseNamespace(COIN_TYPE_OPTIMISM), + () => env.v2.ENSV1Resolver.address, ); }); - describe("L1", () => { + describe("DNS", () => { it("dnstxt.ens.eth + addr() => DNSTXTResolver", () => expectResolve({ name: "dnstxt.ens.eth", addresses: [ { coinType: COIN_TYPE_ETH, - value: env.deployment.contracts.DNSTXTResolver.address, + value: env.v2.DNSTXTResolver.address, }, ], })); @@ -67,117 +79,12 @@ describe("Resolve", () => { addresses: [ { coinType: COIN_TYPE_ETH, - value: env.deployment.contracts.DNSAliasResolver.address, + value: env.v2.DNSAliasResolver.address, }, ], })); - }); - - describe("Reverse", () => { - describe("addr.reverse", () => { - const label = "user"; - const name = `${label}.eth`; - - it("addr.reverse", async () => { - const { deployer, owner: account } = env.namedAccounts; - - // setup addr(default) - const resolver = await env.deployment.deployPermissionedResolver({ - account, - }); - await resolver.write.setAddr([ - namehash(name), - COIN_TYPE_ETH, - account.address, - ]); - // hack: create name - await env.deployment.contracts.ETHRegistry.write.register( - [ - label, - account.address, - zeroAddress, - resolver.address, - 0n, - MAX_EXPIRY, - ], - { account: deployer }, - ); - // setup name() - await env.deployment.contracts.ETHReverseRegistrar.write.setName( - [name], - { - account, - }, - ); - await expectResolve({ - name: getReverseName(account.address), - primary: { value: name }, - }); - await expectResolve({ - name, - addresses: [{ coinType: COIN_TYPE_ETH, value: account.address }], - }); - const [primary] = - await env.deployment.contracts.UniversalResolverV2.read.reverse([ - account.address, - COIN_TYPE_ETH, - ]); - expectVar({ primary }).toStrictEqual(name); - }); - - it("default.reverse", async () => { - const { deployer, owner: account } = env.namedAccounts; - - // setup addr(default) - const resolver = await env.deployment.deployPermissionedResolver({ - account, - }); - await resolver.write.setAddr([ - namehash(name), - COIN_TYPE_DEFAULT, - account.address, - ]); - // hack: create name - await env.deployment.contracts.ETHRegistry.write.register( - [ - label, - account.address, - zeroAddress, - resolver.address, - 0n, - MAX_EXPIRY, - ], - { account: deployer }, - ); - // setup name() - await env.deployment.contracts.DefaultReverseRegistrar.write.setName( - [name], - { - account, - }, - ); - - await expectResolve({ - name: getReverseName(account.address, COIN_TYPE_DEFAULT), - primary: { value: name }, - }); - await expectResolve({ - name, - addresses: [{ coinType: COIN_TYPE_ETH, value: account.address }], - }); - const [primary] = - await env.deployment.contracts.UniversalResolverV2.read.reverse([ - account.address, - COIN_TYPE_ETH, - ]); - expectVar({ primary }).toStrictEqual(name); - }); - }); - }); - - describe("DNS", () => { - it("onchain txt: taytems.xyz", () => + itLiveDns("onchain txt: taytems.xyz", () => // Uses real DNS TXT record for taytems.xyz expectResolve({ name: "taytems.xyz", @@ -187,9 +94,10 @@ describe("Resolve", () => { value: "0x8e8Db5CcEF88cca9d624701Db544989C996E3216", }, ], - })); + }), + ); - it("onchain txt: dnstxt.raffy.xyz", () => + itLiveDns("onchain txt: dnstxt.raffy.xyz", () => // `dnstxt.ens.eth t[avatar]=https://raffy.xyz/ens.jpg a[e0]=0x51050ec063d393217B436747617aD1C2285Aeeee` expectResolve({ name: "dnstxt.raffy.xyz", @@ -200,18 +108,20 @@ describe("Resolve", () => { }, ], texts: [{ key: "avatar", value: "https://raffy.xyz/ens.jpg" }], - })); + }), + ); - it("alias rewrite: dnsalias[.raffy.xyz] => dnsalias[.ens.eth]", () => + itLiveDns("alias rewrite: dnsalias[.raffy.xyz] => dnsalias[.ens.eth]", () => // `dnsalias.ens.eth raffy.xyz ens.eth` expectResolve({ name: "dnsalias.raffy.xyz", addresses: [ { coinType: COIN_TYPE_ETH, - value: env.deployment.contracts.DNSAliasResolver.address, + value: env.v2.DNSAliasResolver.address, }, ], - })); + }), + ); }); }); diff --git a/contracts/test/e2e/runPreMigrationCommandSigner.test.ts b/contracts/test/e2e/runPreMigrationCommandSigner.test.ts new file mode 100644 index 000000000..8e4f9411e --- /dev/null +++ b/contracts/test/e2e/runPreMigrationCommandSigner.test.ts @@ -0,0 +1,97 @@ +import { afterEach, beforeEach, describe, expect, it } from "bun:test"; +import { privateKeyToAccount } from "viem/accounts"; +import { runPreMigrationCommand } from "../../script/migration.js"; + +// The BatchRegistrar owner that fork/clean-testnet runs impersonate. The env +// deployer key below does NOT control it. +const OWNER_KEY = + "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"; +const ownerAccount = privateKeyToAccount(OWNER_KEY); + +const DEPLOYER_KEY = + "0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba"; +const deployerAccount = privateKeyToAccount(DEPLOYER_KEY); + +let capturedArgs: string[] | null = null; + +async function capturePreMigrationArgs(args: string[]) { + capturedArgs = args; +} + +function flagValue(args: string[], flag: string): string | undefined { + const i = args.indexOf(flag); + return i === -1 ? undefined : args[i + 1]; +} + +const baseOpts = { + rpcUrl: "http://127.0.0.1:8545", + network: "mainnet" as const, + registry: "0x0000000000000000000000000000000000000001" as const, + batchRegistrar: "0x0000000000000000000000000000000000000002" as const, + v1Resolver: "0x0000000000000000000000000000000000000003" as const, + v1BaseRegistrar: "0x0000000000000000000000000000000000000004" as const, + csvFile: "names.csv", +}; + +describe("runPreMigrationCommand signer resolution", () => { + const savedEnv = { + PREMIGRATION_PRIVATE_KEY: process.env.PREMIGRATION_PRIVATE_KEY, + BATCH_REGISTRAR_OWNER_KEY: process.env.BATCH_REGISTRAR_OWNER_KEY, + DEPLOYER_KEY: process.env.DEPLOYER_KEY, + }; + + beforeEach(() => { + capturedArgs = null; + delete process.env.PREMIGRATION_PRIVATE_KEY; + delete process.env.BATCH_REGISTRAR_OWNER_KEY; + process.env.DEPLOYER_KEY = DEPLOYER_KEY; + }); + + afterEach(() => { + for (const [key, value] of Object.entries(savedEnv)) { + if (value === undefined) delete process.env[key]; + else process.env[key] = value; + } + }); + + it("drops the non-matching env fallback when an impersonated account is supplied", async () => { + await runPreMigrationCommand( + { ...baseOpts, account: ownerAccount.address }, + false, + capturePreMigrationArgs, + ); + expect(capturedArgs).not.toBeNull(); + expect(flagValue(capturedArgs!, "--account")).toBe(ownerAccount.address); + expect(capturedArgs).not.toContain("--private-key"); + }); + + it("keeps the env fallback when it controls the supplied account", async () => { + await runPreMigrationCommand( + { ...baseOpts, account: deployerAccount.address }, + false, + capturePreMigrationArgs, + ); + expect(flagValue(capturedArgs!, "--private-key")).toBe(DEPLOYER_KEY); + expect(flagValue(capturedArgs!, "--account")).toBe(deployerAccount.address); + }); + + it("uses the env fallback when no account is supplied", async () => { + await runPreMigrationCommand( + { ...baseOpts }, + false, + capturePreMigrationArgs, + ); + expect(flagValue(capturedArgs!, "--private-key")).toBe(DEPLOYER_KEY); + expect(capturedArgs).not.toContain("--account"); + }); + + it("an explicit private key always wins over the impersonated account", async () => { + await runPreMigrationCommand( + { ...baseOpts, privateKey: OWNER_KEY, account: ownerAccount.address }, + false, + capturePreMigrationArgs, + ); + expect(flagValue(capturedArgs!, "--private-key")).toBe(OWNER_KEY); + expect(flagValue(capturedArgs!, "--account")).toBe(ownerAccount.address); + }); +}); diff --git a/contracts/test/e2e/test-setup.ts b/contracts/test/e2e/test-setup.ts index f04688111..7d156d424 100644 --- a/contracts/test/e2e/test-setup.ts +++ b/contracts/test/e2e/test-setup.ts @@ -1,5 +1,6 @@ // Global test setup -import { afterAll, beforeAll, beforeEach } from "bun:test"; +import { afterAll, beforeAll, beforeEach, expect } from "bun:test"; +import { isAddress, isAddressEqual, type Address } from "viem"; import { type DevnetEnvironment, type StateSnapshot, @@ -22,9 +23,24 @@ declare global { } } +expect.extend({ + // bug: bun custom maters don't relay `message` + toEqualAddress(actual, expected: Address) { + const pass = + typeof actual === "string" && + isAddress(actual) && + isAddressEqual(actual, expected); + return { + pass, + message: () => + `expected ${this.utils.printReceived(actual)}${pass ? " not " : " "}to equal address ${this.utils.printExpected(expected)}`, + }; + }, +}); + const t0 = Date.now(); -const env = await setupDevnet(); +const env = await setupDevnet({ procLog: false, chainId: 1 }); // save the initial state const resetInitialState = await env.saveState(); diff --git a/contracts/test/fixtures/MigrationControllerFixture.sol b/contracts/test/fixtures/MigrationControllerFixture.sol new file mode 100755 index 000000000..24b12c7da --- /dev/null +++ b/contracts/test/fixtures/MigrationControllerFixture.sol @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; + +import {Graveyard} from "~src/migration/Graveyard.sol"; +import {ENSV1Resolver} from "~src/resolver/ENSV1Resolver.sol"; +import {ENSV2Resolver} from "~src/resolver/ENSV2Resolver.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {LibMigration} from "~src/migration/libraries/LibMigration.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {V1Fixture} from "~test/fixtures/V1Fixture.sol"; +import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; +import {StandardRegistrar} from "~test/StandardRegistrar.sol"; + +// forge test test/unit/migration/UnlockedMigrationController.t.sol -vv +// forge test test/unit/migration/LockedMigrationController.t.sol -vv + +// [initial gas analysis] +// * Unwrapped: 160300 +// * Unlocked: 179367 +// * Locked: 658489 (~500k for VerifiedFactory => WrapperRegistry) + +// [after graveyard] +// * Unwrapped: 193011 (+32K) +// * Unlocked: 183292 (+4K) +// * Locked: 665863 (+7K) + +/// @dev Reusable testing fixture for migration. +contract MigrationControllerFixture is V1Fixture, V2Fixture { + ENSV1Resolver ensV1Resolver; + ENSV2Resolver ensV2Resolver; + Graveyard graveyard; + MockERC721 dummy721; + MockERC1155 dummy1155; + + string testLabel = "test"; + address testResolver = makeAddr("resolver"); + IRegistry testRegistry = IRegistry(makeAddr("registry")); + address premigrationController = makeAddr("premigrationController"); + uint64 premigrationBonusPeriod = StandardRegistrar.BONUS_PERIOD; + + address actor = makeAddr("actor"); + address friend = makeAddr("friend"); + + function deployMigrationControllerFixture() public { + deployV1Fixture(); + deployV2Fixture(); + + ethRegistry.grantRootRoles( + RegistryRolesLib.ROLE_REGISTRAR | RegistryRolesLib.ROLE_RENEW, + premigrationController + ); + + ensV1Resolver = new ENSV1Resolver(batchGatewayProvider, contractNamer, registryV1); + ensV2Resolver = new ENSV2Resolver( + batchGatewayProvider, + contractNamer, + rootRegistry, + address(0) + ); + + graveyard = new Graveyard(nameWrapper, contractNamer); + + baseRegistrar.setResolver(address(ensV2Resolver)); + baseRegistrar.addController(address(graveyard)); + + dummy721 = new MockERC721(); + dummy1155 = new MockERC1155(); + } + + /// @dev Ensure premigration has occurred. + function registerUnwrapped(string memory label) + public + override + returns (bytes memory name, uint256 tokenId) + { + (name, tokenId) = super.registerUnwrapped(label); + if (address(premigrationController) != address(0)) { + vm.prank(premigrationController); + ethRegistry.register( + label, + address(0), // reserve + IRegistry(address(0)), + address(ensV1Resolver), // fallback + 0, + uint64(baseRegistrar.nameExpires(tokenId)) + premigrationBonusPeriod + ); + } + } + + /// @dev Check resolver and fallback logic. + function checkResolution(bytes memory name, address resolverV1, address resolverV2) public view { + assertEq(findResolverV1(name), resolverV1, "findResolverV1"); + assertEq(findResolverV2(name), resolverV2, "findResolverV2"); + if (resolverV2 == address(ensV1Resolver)) { + (address r, ) = ensV1Resolver.getResolver(name); + assertEq(r, resolverV1, "compositeV1"); + } else if (resolverV1 == address(ensV2Resolver)) { + (address r, ) = ensV2Resolver.getResolver(name); + assertEq(r, resolverV2, "compositeV2"); + assertEq(registryV1.resolver(NameCoder.namehash(name, 0)), address(0), "resolverV1"); + } + } + + function _label(uint256 i) internal view returns (string memory) { + return string.concat(testLabel, vm.toString(i)); + } + + function _soon() internal view returns (uint64) { + return uint64(block.timestamp + 1000); + } + + function _unlockedData(bytes memory name) internal view returns (LibMigration.Data memory) { + return + LibMigration.Data({label: NameCoder.firstLabel(name), owner: testOwner, subregistry: testRegistry, resolver: testResolver}); + } + + function _lockedData(bytes memory name) internal view returns (LibMigration.Data memory) { + return + LibMigration.Data({ + label: NameCoder.firstLabel(name), + owner: nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), + subregistry: IRegistry(address(0)), // ignored by LockedMigrationController + resolver: testResolver + }); + } +} + + +contract MockERC721 is ERC721 { + uint256 _id; + constructor() ERC721("", "") {} + function mint(address to) external returns (uint256) { + _mint(to, _id); + return _id++; + } +} + + +contract MockERC1155 is ERC1155 { + uint256 _id; + constructor() ERC1155("") {} + function mint(address to) external returns (uint256) { + _mint(to, _id, 1, ""); + return _id++; + } +} diff --git a/contracts/test/fixtures/StandardRentPriceOracleFixture.sol b/contracts/test/fixtures/StandardRentPriceOracleFixture.sol new file mode 100755 index 000000000..ef9a8eec2 --- /dev/null +++ b/contracts/test/fixtures/StandardRentPriceOracleFixture.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file + +import {Test} from "forge-std/Test.sol"; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import {StandardRentPriceOracle, PaymentRatio} from "~src/registrar/StandardRentPriceOracle.sol"; +import { + MockERC20, + MockERC20Blacklist, + MockERC20VoidReturn, + MockERC20FalseReturn +} from "~test/mocks/MockERC20.sol"; +import {StandardRegistrar} from "~test/StandardRegistrar.sol"; + +/// @dev Reusable testing fixture for StandardRentPriceOracle. +contract StandardRentPriceOracleFixture is Test { + StandardRentPriceOracle rentPriceOracle; + + MockERC20 tokenUSDC; + MockERC20 tokenDAI; + MockERC20 tokenIdentity; + MockERC20Blacklist tokenBlack; + MockERC20VoidReturn tokenVoid; + MockERC20FalseReturn tokenFalse; + + MockERC20[] paymentTokens; + + address beneficiary = makeAddr("beneficiary"); + IERC20 invalidPaymentToken = IERC20(makeAddr("invalidPaymentToken")); + + function deployStandardRentPriceOracleFixture() public { + tokenUSDC = new MockERC20("USDC", 6); + tokenDAI = new MockERC20("DAI", 18); + tokenIdentity = new MockERC20("Identity", StandardRegistrar.PRICE_DECIMALS); + tokenBlack = new MockERC20Blacklist(); + tokenVoid = new MockERC20VoidReturn(); + tokenFalse = new MockERC20FalseReturn(); + + paymentTokens = new MockERC20[](6); + paymentTokens[0] = tokenUSDC; + paymentTokens[1] = tokenDAI; + paymentTokens[2] = tokenIdentity; + paymentTokens[3] = tokenBlack; + paymentTokens[4] = tokenVoid; + paymentTokens[5] = tokenFalse; + + PaymentRatio[] memory paymentRatios = new PaymentRatio[](paymentTokens.length); + for (uint256 i; i < paymentTokens.length; ++i) { + paymentRatios[i] = StandardRegistrar.ratioFromStable(paymentTokens[i]); + } + rentPriceOracle = new StandardRentPriceOracle( + address(this), + StandardRegistrar.getBaseRates(), + StandardRegistrar.getDiscountPoints(), + StandardRegistrar.DISCOUNT_DENOMINATOR, + StandardRegistrar.PREMIUM_PRICE_INITIAL, + StandardRegistrar.PREMIUM_HALVING_PERIOD, + StandardRegistrar.PREMIUM_PERIOD, + paymentRatios + ); + + // give beneficiary non-zero balance + for (uint256 i; i < paymentTokens.length; ++i) { + paymentTokens[i].mint(beneficiary, 1); + } + } + + function setupPaymentTokens(address owner, address approved) internal { + for (uint256 i; i < paymentTokens.length; ++i) { + MockERC20 token = paymentTokens[i]; + token.mint(owner, 1e9 * 10 ** token.decimals()); + } + vm.startPrank(owner); + for (uint256 i; i < paymentTokens.length; ++i) { + paymentTokens[i].approve(approved, type(uint256).max); + } + vm.stopPrank(); + } + + function randomPaymentToken() internal view returns (MockERC20) { + return vm.randomBool() ? tokenUSDC : tokenDAI; + } +} diff --git a/contracts/test/fixtures/V1Fixture.sol b/contracts/test/fixtures/V1Fixture.sol index 070d05388..2a39b4292 100755 --- a/contracts/test/fixtures/V1Fixture.sol +++ b/contracts/test/fixtures/V1Fixture.sol @@ -5,34 +5,49 @@ import {Test} from "forge-std/Test.sol"; import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; - import {ENSRegistry, ENS} from "@ens/contracts/registry/ENSRegistry.sol"; import { BaseRegistrarImplementation } from "@ens/contracts/ethregistrar/BaseRegistrarImplementation.sol"; -import {NameWrapper, IMetadataService} from "@ens/contracts/wrapper/NameWrapper.sol"; +import {NameWrapper, INameWrapper, IMetadataService} from "@ens/contracts/wrapper/NameWrapper.sol"; import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import {RegistryUtils} from "@ens/contracts/universalResolver/RegistryUtils.sol"; /// @dev Reusable testing fixture for ENSv1. contract V1Fixture is Test, ERC721Holder, ERC1155Holder { - ENS ensV1; - BaseRegistrarImplementation ethRegistrarV1; + enum StatusV1 { + REGISTERED, + GRACE, + AVAILABLE + } + + ENS registryV1; + BaseRegistrarImplementation baseRegistrar; NameWrapper nameWrapper; + MockWrappedETHRegistrarController wrappedController; - address user = makeAddr("user"); - address ensV1Controller = makeAddr("ensV1Controller"); + uint64 gracePeriodV1; + address testOwner = makeAddr("ownerV1"); + uint64 testDuration = 1 days; + address ethControllerV1 = makeAddr("ethControllerV1"); function deployV1Fixture() public { - ensV1 = new ENSRegistry(); - ethRegistrarV1 = new BaseRegistrarImplementation(ensV1, NameCoder.ETH_NODE); - ethRegistrarV1.addController(ensV1Controller); - _claimNodes(NameCoder.encode("eth"), 0, address(ethRegistrarV1)); + registryV1 = new ENSRegistry(); + baseRegistrar = new BaseRegistrarImplementation(registryV1, NameCoder.ETH_NODE); + baseRegistrar.addController(ethControllerV1); + gracePeriodV1 = uint64(baseRegistrar.GRACE_PERIOD()) + 1; // see: BaseRegistrarImplementation.available() + _claimNodes(NameCoder.encode("eth"), 0, address(baseRegistrar)); _claimNodes(NameCoder.encode("addr.reverse"), 0, address(this)); // see: fake ReverseClaimer - nameWrapper = new NameWrapper(ensV1, ethRegistrarV1, IMetadataService(address(0))); - nameWrapper.setController(ensV1Controller, true); - ethRegistrarV1.addController(address(nameWrapper)); - vm.warp(ethRegistrarV1.GRACE_PERIOD() + 1); // avoid timestamp issues + nameWrapper = new NameWrapper(registryV1, baseRegistrar, IMetadataService(address(0))); + wrappedController = new MockWrappedETHRegistrarController(nameWrapper); + nameWrapper.setController(ethControllerV1, true); + nameWrapper.setController(address(wrappedController), true); + baseRegistrar.addController(address(nameWrapper)); + + uint256 t = gracePeriodV1; + if (block.timestamp < t) { + vm.warp(t); // avoid timestamp issues + } } // fake ReverseClaimer @@ -45,68 +60,108 @@ contract V1Fixture is Test, ERC721Holder, ERC1155Holder { if (labelHash != bytes32(0)) { _claimNodes(name, nextOffset, owner); // claim if leaf or unset - if (offset == 0 || ensV1.owner(NameCoder.namehash(name, offset)) == address(0)) { + if (offset == 0 || registryV1.owner(NameCoder.namehash(name, offset)) == address(0)) { bytes32 parentNode = NameCoder.namehash(name, nextOffset); - vm.prank(ensV1.owner(parentNode)); - ensV1.setSubnodeOwner(parentNode, labelHash, owner); + vm.prank(registryV1.owner(parentNode)); + registryV1.setSubnodeOwner(parentNode, labelHash, owner); } } } - function registerUnwrapped( - string memory label - ) public returns (bytes memory name, uint256 tokenId) { + function registerUnwrapped(string memory label) + public + virtual + returns (bytes memory name, uint256 tokenId) + { name = NameCoder.ethName(label); + address registrant = _determineRegistrant(); tokenId = uint256(keccak256(bytes(label))); - vm.prank(ensV1Controller); - ethRegistrarV1.register(tokenId, user, 1 days); // test duration + vm.prank(ethControllerV1); + baseRegistrar.register(tokenId, registrant, testDuration); } - function registerWrappedETH2LD( - string memory label, - uint32 ownerFuses - ) public virtual returns (bytes memory name) { + function registerWrappedETH2LD(string memory label, uint32 ownerFuses) + public + returns (bytes memory name) + { + address wrappedOwner = _determineRegistrant(); uint256 tokenId; (name, tokenId) = registerUnwrapped(label); - address owner = ethRegistrarV1.ownerOf(tokenId); - vm.startPrank(owner); - ethRegistrarV1.setApprovalForAll(address(nameWrapper), true); - nameWrapper.wrapETH2LD(label, owner, uint16(ownerFuses), address(0)); - vm.stopPrank(); + address owner = baseRegistrar.ownerOf(tokenId); + vm.prank(owner); + baseRegistrar.safeTransferFrom( + owner, + address(nameWrapper), + tokenId, + abi.encode( + label, // label + wrappedOwner, + uint16(ownerFuses), // fuses + address(0) // resolver + ) + ); } - function createWrappedChild( - bytes memory parentName, - string memory label, - uint32 fuses - ) public returns (bytes memory name) { + function createWrappedChild(bytes memory parentName, string memory label, uint32 fuses) + public + returns (bytes memory name) + { + address wrappedOwner = _determineRegistrant(); bytes32 parentNode = NameCoder.namehash(parentName, 0); (address owner, , uint64 expiry) = nameWrapper.getData(uint256(parentNode)); - name = NameCoder.addLabel(parentName, label); vm.prank(owner); - nameWrapper.setSubnodeOwner(parentNode, label, owner, fuses, expiry); + nameWrapper.setSubnodeOwner(parentNode, label, wrappedOwner, fuses, expiry); + name = NameCoder.addLabel(parentName, label); } - function createWrappedName( - string memory domain, - uint32 fuses - ) public returns (bytes memory name) { + function createWrappedName(string memory domain, uint32 fuses) + public + returns (bytes memory name) + { name = NameCoder.encode(domain); - _claimNodes(name, 0, user); + address registrant = _determineRegistrant(); + _claimNodes(name, 0, registrant); (bytes32 labelHash, uint256 offset) = NameCoder.readLabel(name, 0); bytes32 parentNode = NameCoder.namehash(name, offset); - vm.startPrank(user); - ensV1.setApprovalForAll(address(nameWrapper), true); - nameWrapper.wrap(name, user, address(0)); + vm.prank(registrant); + registryV1.setApprovalForAll(address(nameWrapper), true); + vm.prank(registrant); + nameWrapper.wrap(name, registrant, address(0)); if (fuses != 0) { - // this might need to be setChildFuses() - bytes32 node = NameCoder.namehash(parentNode, labelHash); - nameWrapper.setFuses(node, uint16(fuses)); + vm.prank(registrant); + nameWrapper.setFuses(NameCoder.namehash(parentNode, labelHash), uint16(fuses)); + } + } + + function getStatusV1(uint256 tokenId) public view returns (StatusV1) { + try baseRegistrar.ownerOf(tokenId) { + return StatusV1.REGISTERED; + } catch { + return baseRegistrar.available(tokenId) ? StatusV1.AVAILABLE : StatusV1.GRACE; } - vm.stopPrank(); } function findResolverV1(bytes memory name) public view returns (address resolver) { - (resolver, , ) = RegistryUtils.findResolver(ensV1, name, 0); + (resolver, , ) = RegistryUtils.findResolver(registryV1, name, 0); + } + + function _determineRegistrant() internal view returns (address registrant) { + registrant = msg.sender; + if (registrant == DEFAULT_SENDER) { + registrant = testOwner; + } + } +} + + +// https://github.com/ensdomains/ens-contracts/blob/staging/deployments/mainnet/WrappedETHRegistrarController.json +contract MockWrappedETHRegistrarController { + INameWrapper internal immutable NAME_WRAPPER; + constructor(INameWrapper nameWrapper) { + NAME_WRAPPER = nameWrapper; + } + function renew(string calldata label, uint256 duration) external payable { + require(duration == 0); + NAME_WRAPPER.renew(uint256(keccak256(bytes(label))), duration); } } diff --git a/contracts/test/fixtures/V1Fixture.t.sol b/contracts/test/fixtures/V1Fixture.t.sol index e4dbc4fbf..c1bceb834 100755 --- a/contracts/test/fixtures/V1Fixture.t.sol +++ b/contracts/test/fixtures/V1Fixture.t.sol @@ -3,8 +3,10 @@ pragma solidity >=0.8.13; import { PARENT_CANNOT_CONTROL, + CANNOT_SET_RESOLVER, CANNOT_UNWRAP, CANNOT_BURN_FUSES, + CANNOT_APPROVE, LabelTooShort, LabelTooLong } from "@ens/contracts/wrapper/NameWrapper.sol"; @@ -13,6 +15,8 @@ import {V1Fixture, NameCoder} from "./V1Fixture.sol"; // TODO: add more NameWrapper quirks and invariant tests. contract V1FixtureTest is V1Fixture { + address friend = makeAddr("friend"); + function setUp() external { deployV1Fixture(); } @@ -23,64 +27,94 @@ contract V1FixtureTest is V1Fixture { function test_registerUnwrapped() external { (, uint256 tokenId) = registerUnwrapped("test"); - assertEq(ethRegistrarV1.ownerOf(tokenId), user, "owner"); + assertEq(baseRegistrar.ownerOf(tokenId), testOwner, "owner"); + } + + function test_registerUnwrapped_pranked() external { + vm.prank(friend); + (, uint256 tokenId) = this.registerUnwrapped("test"); + assertEq(baseRegistrar.ownerOf(tokenId), friend, "owner"); } function test_registerWrappedETH2LD() external { bytes memory name = registerWrappedETH2LD("test", 0); - assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), user, "owner"); + assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), testOwner, "owner"); + } + + function test_registerWrappedETH2LD_pranked() external { + vm.prank(friend); + bytes memory name = this.registerWrappedETH2LD("test", 0); + assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), friend, "owner"); } function test_registerWrappedETH3LD() external { bytes memory parentName = registerWrappedETH2LD("test", 0); bytes memory name = createWrappedChild(parentName, "sub", 0); - assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), user, "owner"); + assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), testOwner, "owner"); + } + + function test_registerWrappedETH3LD_pranked() external { + bytes memory parentName = registerWrappedETH2LD("test", 0); + vm.prank(friend); + bytes memory name = this.createWrappedChild(parentName, "sub", 0); + assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), friend, "owner"); } function test_registerWrappedDNS2LD() external { bytes memory name = createWrappedName("ens.domains", 0); - assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), user, "owner"); + assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), testOwner, "owner"); } function test_registerWrappedDNS3LD() external { bytes memory parentName = createWrappedName("ens.domains", 0); bytes memory name = createWrappedChild(parentName, "sub", 0); - assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), user, "owner"); + assertEq(nameWrapper.ownerOf(uint256(NameCoder.namehash(name, 0))), testOwner, "owner"); } function test_findResolverV1_unwrapped() external { (bytes memory name, ) = registerUnwrapped("test"); assertEq(findResolverV1(name), address(0), "before"); - vm.prank(user); - ensV1.setResolver(NameCoder.namehash(name, 0), address(1)); + vm.prank(testOwner); + registryV1.setResolver(NameCoder.namehash(name, 0), address(1)); assertEq(findResolverV1(name), address(1), "after"); } function test_findResolverV1_wrapped() external { bytes memory name = createWrappedName("a.b.c", 0); assertEq(findResolverV1(name), address(0), "before"); - vm.prank(user); + vm.prank(testOwner); nameWrapper.setResolver(NameCoder.namehash(name, 0), address(1)); assertEq(findResolverV1(name), address(1), "after"); } + function test_getStatusV1_lifecycle() external { + (, uint256 tokenId) = registerUnwrapped("test"); + assertEq(uint256(getStatusV1(tokenId)), uint8(StatusV1.REGISTERED), "REGISTERED"); + vm.warp(baseRegistrar.nameExpires(tokenId)); + assertEq(uint256(getStatusV1(tokenId)), uint8(StatusV1.GRACE), "GRACE:start"); + vm.warp(baseRegistrar.nameExpires(tokenId) + gracePeriodV1 - 1); + assertEq(uint256(getStatusV1(tokenId)), uint8(StatusV1.GRACE), "GRACE:end"); + vm.warp(baseRegistrar.nameExpires(tokenId) + gracePeriodV1); + assertEq(uint256(getStatusV1(tokenId)), uint8(StatusV1.AVAILABLE), "AVAILABLE"); + } + //////////////////////////////////////////////////////////////////////// // NameWrapper Quirks //////////////////////////////////////////////////////////////////////// function test_nameWrapper_wrapRootReverts() external { - vm.expectRevert(abi.encodeWithSignature("Error(string)", "readLabel: Index out of bounds")); + vm.expectRevert("readLabel: Index out of bounds"); nameWrapper.wrap(hex"00", address(1), address(0)); } function test_nameWrapper_labelTooShort() external { bytes memory name = registerWrappedETH2LD("test", 0); vm.expectRevert(abi.encodeWithSelector(LabelTooShort.selector)); - vm.prank(user); + vm.prank(testOwner); nameWrapper.setSubnodeOwner( NameCoder.namehash(name, 0), "", - user, + testOwner, 0, uint64(block.timestamp + 1 days) ); @@ -90,11 +124,11 @@ contract V1FixtureTest is V1Fixture { bytes memory name = registerWrappedETH2LD("test", 0); string memory label = new string(256); vm.expectRevert(abi.encodeWithSelector(LabelTooLong.selector, label)); - vm.prank(user); + vm.prank(testOwner); nameWrapper.setSubnodeOwner( NameCoder.namehash(name, 0), label, - user, + testOwner, 0, uint64(block.timestamp + 1 days) ); @@ -102,11 +136,32 @@ contract V1FixtureTest is V1Fixture { function test_nameWrapper_expiryForETH2LDIncludesGrace() external { bytes memory name = registerWrappedETH2LD("test", 0); - uint256 unwrappedExpiry = ethRegistrarV1.nameExpires( - uint256(keccak256(bytes(NameCoder.firstLabel(name)))) - ); + uint256 unwrappedExpiry = + baseRegistrar.nameExpires(uint256(keccak256(bytes(NameCoder.firstLabel(name))))); (, , uint256 wrappedExpiry) = nameWrapper.getData(uint256(NameCoder.namehash(name, 0))); - assertEq(unwrappedExpiry + ethRegistrarV1.GRACE_PERIOD(), wrappedExpiry); + assertEq(unwrappedExpiry + baseRegistrar.GRACE_PERIOD(), wrappedExpiry); + } + + function test_nameWrapper_gracePeriod() external { + bytes memory name = registerWrappedETH2LD("test", CANNOT_UNWRAP); + uint256 tokenId = uint256(keccak256(bytes(NameCoder.firstLabel(name)))); + uint256 unwrappedExpiry = baseRegistrar.nameExpires(tokenId); + bytes32 node = NameCoder.namehash(name, 0); + uint64[3] memory ts = [0, gracePeriodV1 >> 1, gracePeriodV1 - 1]; // start, middle, before-end + for (uint256 i; i < ts.length; ++i) { + vm.warp(unwrappedExpiry + ts[i]); + (address owner, uint32 fuses, ) = nameWrapper.getData(uint256(node)); + assertFalse(baseRegistrar.available(tokenId), "grace:available"); + assertEq(owner, testOwner, "grace:owner"); + assertTrue((fuses & CANNOT_UNWRAP) != 0, "grace:fuses"); + } + { + vm.warp(unwrappedExpiry + gracePeriodV1); // after-end + (address owner, uint32 fuses, ) = nameWrapper.getData(uint256(node)); + assertTrue(baseRegistrar.available(tokenId), "after:available"); + assertEq(owner, address(0), "after:owner"); + assertEq(fuses, 0, "after:fuses"); + } } function test_nameWrapper_CANNOT_UNWRAP_requires_PARENT_CANNOT_CONTROL() external { @@ -120,20 +175,24 @@ contract V1FixtureTest is V1Fixture { function test_nameWrapper_PARENT_CANNOT_CONTROL_via_setFuses() external { bytes memory name = registerWrappedETH2LD("test", 0); (bytes32 labelhash, ) = NameCoder.readLabel(name, 0); - vm.startPrank(user); + vm.prank(testOwner); nameWrapper.setFuses(NameCoder.namehash(name, 0), uint16(PARENT_CANNOT_CONTROL)); - nameWrapper.unwrapETH2LD(labelhash, user, user); - vm.stopPrank(); + vm.prank(testOwner); + nameWrapper.unwrapETH2LD(labelhash, testOwner, testOwner); } function test_nameWrapper_PARENT_CANNOT_CONTROL_via_wrap() external { bytes memory parentName = registerWrappedETH2LD("test", CANNOT_UNWRAP); bytes memory name = createWrappedChild(parentName, "sub", PARENT_CANNOT_CONTROL); (bytes32 labelhash, ) = NameCoder.readLabel(name, 0); - vm.startPrank(user); - nameWrapper.setFuses(NameCoder.namehash(name, 0), uint16(PARENT_CANNOT_CONTROL)); - nameWrapper.unwrap(NameCoder.namehash(parentName, 0), labelhash, user); - vm.stopPrank(); + vm.prank(testOwner); + nameWrapper.unwrap(NameCoder.namehash(parentName, 0), labelhash, testOwner); + } + + function test_nameWrapper_PARENT_CANNOT_CONTROL_withoutParent() external { + bytes memory parentName = registerWrappedETH2LD("test", 0); + vm.expectRevert(); + this.createWrappedChild(parentName, "sub", PARENT_CANNOT_CONTROL); } function test_nameWrapper_CANNOT_BURN_FUSES_via_wrap() external { @@ -142,21 +201,18 @@ contract V1FixtureTest is V1Fixture { function test_nameWrapper_CANNOT_BURN_FUSES_via_setFuses() external { bytes memory name = registerWrappedETH2LD("test", CANNOT_UNWRAP); - vm.prank(user); + vm.prank(testOwner); nameWrapper.setFuses(NameCoder.namehash(name, 0), uint16(CANNOT_BURN_FUSES)); } function test_nameWrapper_CANNOT_BURN_FUSES_via_setChildFuses() external { bytes memory parentName = registerWrappedETH2LD("test", CANNOT_UNWRAP); - bytes memory name = createWrappedChild( - parentName, - "sub", - CANNOT_UNWRAP | PARENT_CANNOT_CONTROL - ); + bytes memory name = + createWrappedChild(parentName, "sub", CANNOT_UNWRAP | PARENT_CANNOT_CONTROL); // setChildFuses() does not allow fuse changes if PCC // _setFuses() requires CU + PCC if child fuses as burned vm.expectRevert(); - vm.prank(user); + vm.prank(testOwner); nameWrapper.setChildFuses( NameCoder.namehash(parentName, 0), keccak256(bytes(NameCoder.firstLabel(name))), @@ -165,8 +221,53 @@ contract V1FixtureTest is V1Fixture { ); } - function test_ethRegistrarV1_ownerOf_unregisteredReverts() external { + function test_nameWrapper_CANNOT_SET_RESOLVER_requires_CANNOT_UNWRAP() external { + vm.expectRevert(); + this.registerWrappedETH2LD("test", CANNOT_SET_RESOLVER); + this.registerWrappedETH2LD("test", CANNOT_SET_RESOLVER | CANNOT_UNWRAP); + } + + function test_nameWrapper_CANNOT_APPROVE_requires_CANNOT_UNWRAP() external { + vm.expectRevert(); + this.registerWrappedETH2LD("test", CANNOT_APPROVE); + this.registerWrappedETH2LD("test", CANNOT_APPROVE | CANNOT_UNWRAP); + } + + function test_nameWrapper_approveBug() external { + bytes memory name = registerWrappedETH2LD("test", 0); + bytes32 node = NameCoder.namehash(name, 0); + vm.prank(testOwner); + nameWrapper.approve(friend, uint256(node)); + // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/wrapper/ERC1155Fuse.sol#L146-L149 + vm.prank(friend); + vm.expectRevert("ERC1155: caller is not owner nor approved"); + nameWrapper.safeTransferFrom(testOwner, friend, uint256(node), 1, ""); + } + + //////////////////////////////////////////////////////////////////////// + // BaseRegistrar Quirks + //////////////////////////////////////////////////////////////////////// + + function test_baseRegistrar_gracePeriod() external { + (, uint256 tokenId) = registerUnwrapped("test"); + uint256 expiry = baseRegistrar.nameExpires(tokenId); + uint64[3] memory ts = [0, gracePeriodV1 >> 1, gracePeriodV1 - 1]; + for (uint256 i; i < ts.length; ++i) { + vm.warp(expiry + ts[i]); + assertFalse(baseRegistrar.available(tokenId), "grace:available"); + vm.expectRevert(); + baseRegistrar.ownerOf(tokenId); + } + { + vm.warp(expiry + gracePeriodV1); // after-end + assertTrue(baseRegistrar.available(tokenId), "after:available"); + vm.expectRevert(); + baseRegistrar.ownerOf(tokenId); + } + } + + function test_baseRegistrar_ownerOf_unregisteredReverts() external { vm.expectRevert(); - ethRegistrarV1.ownerOf(0); + baseRegistrar.ownerOf(0); } } diff --git a/contracts/test/fixtures/V2Fixture.sol b/contracts/test/fixtures/V2Fixture.sol index 6a8facf9c..7f9540c39 100755 --- a/contracts/test/fixtures/V2Fixture.sol +++ b/contracts/test/fixtures/V2Fixture.sol @@ -4,66 +4,103 @@ pragma solidity >=0.8.13; import {Test} from "forge-std/Test.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; - import {GatewayProvider} from "@ens/contracts/ccipRead/GatewayProvider.sol"; -import {VerifiableFactory, UUPSProxy} from "@ensdomains/verifiable-factory/VerifiableFactory.sol"; +import {CloneProxyBytecode} from "@ensdomains/verifiable-factory/CloneProxyBytecode.sol"; +import {VerifiableFactory} from "@ensdomains/verifiable-factory/VerifiableFactory.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; -import {BaseUriRegistryMetadata} from "~src/registry/BaseUriRegistryMetadata.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; import {UserRegistry} from "~src/registry/UserRegistry.sol"; +import {ContractNamer} from "~src/utils/ContractNamer.sol"; +import {LabelStore} from "~src/utils/LabelStore.sol"; import {UniversalResolverV2} from "~src/universalResolver/UniversalResolverV2.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; /// @dev Reusable testing fixture for ENSv2 with a basic ".eth" deployment. contract V2Fixture is Test, ERC1155Holder { + ContractNamer contractNamer; VerifiableFactory verifiableFactory; - MockHCAFactoryBasic hcaFactory; - BaseUriRegistryMetadata metadata; + LabelStore labelStore; UserRegistry userRegistryImpl; PermissionedRegistry rootRegistry; PermissionedRegistry ethRegistry; GatewayProvider batchGatewayProvider; UniversalResolverV2 universalResolver; + /// @dev Role bitmaps matching README Static Deployment Permissions. + function _rootRegistryRootRoles() internal pure returns (uint256) { + return + RegistryRolesLib.ROLE_REGISTRAR | + RegistryRolesLib.ROLE_REGISTRAR_ADMIN | + RegistryRolesLib.ROLE_REGISTER_RESERVED | + RegistryRolesLib.ROLE_REGISTER_RESERVED_ADMIN | + RegistryRolesLib.ROLE_SET_PARENT | + RegistryRolesLib.ROLE_SET_PARENT_ADMIN | + RegistryRolesLib.ROLE_RENEW | + RegistryRolesLib.ROLE_RENEW_ADMIN | + RegistryRolesLib.ROLE_CAN_NAME | + RegistryRolesLib.ROLE_CAN_NAME_ADMIN; + } + + function _ethRegistryRootRoles() internal pure returns (uint256) { + return + RegistryRolesLib.ROLE_REGISTRAR_ADMIN | + RegistryRolesLib.ROLE_REGISTER_RESERVED_ADMIN | + RegistryRolesLib.ROLE_SET_PARENT | + RegistryRolesLib.ROLE_SET_PARENT_ADMIN | + RegistryRolesLib.ROLE_RENEW_ADMIN | + RegistryRolesLib.ROLE_CAN_NAME | + RegistryRolesLib.ROLE_CAN_NAME_ADMIN; + } + + function _ethTokenRoles() internal pure returns (uint256) { + return + RegistryRolesLib.ROLE_SET_SUBREGISTRY | + RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN | + RegistryRolesLib.ROLE_SET_RESOLVER | + RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN; + } + function deployV2Fixture() public { - verifiableFactory = new VerifiableFactory(); - hcaFactory = new MockHCAFactoryBasic(); - metadata = new BaseUriRegistryMetadata(hcaFactory); - userRegistryImpl = new UserRegistry(hcaFactory, metadata); - rootRegistry = new PermissionedRegistry( - hcaFactory, - metadata, - address(this), - EACBaseRolesLib.ALL_ROLES - ); - ethRegistry = new PermissionedRegistry( - hcaFactory, - metadata, - address(this), - EACBaseRolesLib.ALL_ROLES + contractNamer = ContractNamer( + address( + new ERC1967Proxy( + address(new ContractNamer()), + abi.encodeCall(ContractNamer.initialize, (address(this))) + ) + ) ); + verifiableFactory = new VerifiableFactory(); + labelStore = new LabelStore(contractNamer); + userRegistryImpl = new UserRegistry(labelStore, address(this)); + rootRegistry = new PermissionedRegistry(labelStore, address(this), _rootRegistryRootRoles()); + ethRegistry = new PermissionedRegistry(labelStore, address(this), _ethRegistryRootRoles()); rootRegistry.register( "eth", address(this), ethRegistry, address(0), - EACBaseRolesLib.ALL_ROLES, + _ethTokenRoles(), type(uint64).max ); + ethRegistry.setParent(rootRegistry, "eth"); + ethRegistry.grantRootRoles(RegistryRolesLib.ROLE_REGISTRAR, address(this)); batchGatewayProvider = new GatewayProvider(address(this), new string[](0)); - universalResolver = new UniversalResolverV2(rootRegistry, batchGatewayProvider); + universalResolver = new UniversalResolverV2( + rootRegistry, + batchGatewayProvider, + contractNamer + ); } function findResolverV2(bytes memory name) public view returns (address resolver) { (resolver, , ) = universalResolver.findResolver(name); } - function deployUserRegistry( - address owner, - uint256 roleBitmap, - uint256 salt - ) public returns (UserRegistry) { + function deployUserRegistry(address owner, uint256 roleBitmap, uint256 salt) + public + returns (UserRegistry) + { return UserRegistry( verifiableFactory.deployProxy( @@ -74,21 +111,14 @@ contract V2Fixture is Test, ERC1155Holder { ); } - function _computeVerifiableFactoryAddress( - address deployer, - uint256 salt - ) internal view returns (address) { + function _computeVerifiableFactoryAddress(address deployer, uint256 salt) + internal + view + returns (address) + { bytes32 outerSalt = keccak256(abi.encode(deployer, salt)); - return - vm.computeCreate2Address( - outerSalt, - keccak256( - abi.encodePacked( - type(UUPSProxy).creationCode, - abi.encode(verifiableFactory, outerSalt) - ) - ), - address(verifiableFactory) - ); + bytes memory bytecode = + CloneProxyBytecode.creationCode(verifiableFactory.proxyLogic(), outerSalt); + return vm.computeCreate2Address(outerSalt, keccak256(bytecode), address(verifiableFactory)); } } diff --git a/contracts/test/fixtures/V2Fixture.t.sol b/contracts/test/fixtures/V2Fixture.t.sol index 9990a32f8..3e6353ce1 100755 --- a/contracts/test/fixtures/V2Fixture.t.sol +++ b/contracts/test/fixtures/V2Fixture.t.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; +import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; -import {V2Fixture, UserRegistry, EACBaseRolesLib} from "./V2Fixture.sol"; +import {V2Fixture, UserRegistry} from "./V2Fixture.sol"; contract V2FixtureTest is V2Fixture { address user = makeAddr("user"); @@ -13,9 +14,8 @@ contract V2FixtureTest is V2Fixture { } function test_deployUserRegistry(uint256 salt) external { - UserRegistry registry = UserRegistry( - deployUserRegistry(user, EACBaseRolesLib.ALL_ROLES, salt) - ); + UserRegistry registry = + UserRegistry(deployUserRegistry(user, EACBaseRolesLib.ALL_ROLES, salt)); assertTrue(registry.supportsInterface(type(IPermissionedRegistry).interfaceId)); } diff --git a/contracts/test/integration/DOSNameService.t.sol b/contracts/test/integration/DOSNameService.t.sol new file mode 100644 index 000000000..696e47750 --- /dev/null +++ b/contracts/test/integration/DOSNameService.t.sol @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IAddressResolver} from "@ens/contracts/resolvers/profiles/IAddressResolver.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; + +import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; +import {DOSRegistrar} from "~src/registrar/DOSRegistrar.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {LibLabel} from "~src/utils/LibLabel.sol"; +import {L2ReverseRegistrar} from "~src/reverse-registrar/L2ReverseRegistrar.sol"; +import {PermissionedResolver} from "~src/resolver/PermissionedResolver.sol"; +import {MockERC20} from "~test/mocks/MockERC20.sol"; +import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; +import {StandardRentPriceOracleFixture} from "~test/fixtures/StandardRentPriceOracleFixture.sol"; +import {StandardRegistrar} from "~test/StandardRegistrar.sol"; + +import {DeployDOS} from "../../script/foundry/DeployDOS.s.sol"; + +/// @notice Integration coverage for the DOS Chain ENSv2 deployment profile. +contract DOSNameServiceTest is V2Fixture, StandardRentPriceOracleFixture { + uint256 internal constant DOS_CHAIN_ID = 3939; + uint256 internal constant DOS_COIN_TYPE = (1 << 31) | DOS_CHAIN_ID; + string internal constant DOS_REVERSE_LABEL = "80000f63"; + + PermissionedRegistry internal dosRegistry; + DOSRegistrar internal dosRegistrar; + L2ReverseRegistrar internal reverseRegistrar; + + address internal registrant = makeAddr("registrant"); + bytes32 internal secret = keccak256("dos-secret"); + + function setUp() external { + deployV2Fixture(); + deployStandardRentPriceOracleFixture(); + + dosRegistry = new PermissionedRegistry(labelStore, address(this), _ethRegistryRootRoles()); + rootRegistry.register( + "dos", + address(this), + dosRegistry, + address(0), + _ethTokenRoles(), + type(uint64).max + ); + dosRegistry.setParent(rootRegistry, "dos"); + + dosRegistrar = new DOSRegistrar( + address(this), + dosRegistry, + beneficiary, + rentPriceOracle, + StandardRegistrar.GRACE_PERIOD_V2, + StandardRegistrar.MIN_COMMITMENT_AGE, + StandardRegistrar.MAX_COMMITMENT_AGE, + StandardRegistrar.MIN_REGISTER_DURATION + ); + dosRegistry.grantRootRoles( + RegistryRolesLib.ROLE_REGISTRAR | RegistryRolesLib.ROLE_RENEW, + address(dosRegistrar) + ); + + setupPaymentTokens(registrant, address(dosRegistrar)); + reverseRegistrar = new L2ReverseRegistrar(DOS_CHAIN_ID, DOS_REVERSE_LABEL); + + uint64 initialTimestamp = dosRegistrar.GRACE_PERIOD() + 1; + if (block.timestamp < initialTimestamp) { + vm.warp(initialTimestamp); + } + } + + function test_registersDosAsCanonicalTld() external view { + assertEq(address(dosRegistrar.ETH_REGISTRY()), address(dosRegistry)); + assertEq( + uint8(rootRegistry.getStatus(LibLabel.id("dos"))), + uint8(IPermissionedRegistry.Status.REGISTERED) + ); + (IRegistry parent, string memory label) = dosRegistry.getParent(); + assertEq(address(parent), address(rootRegistry)); + assertEq(label, "dos"); + } + + function test_registersAndRenewsDosName() external { + string memory label = "alice"; + uint64 duration = StandardRegistrar.MIN_REGISTER_DURATION; + MockERC20 paymentToken = tokenUSDC; + uint256 tokenId = _register(label, duration, paymentToken); + + IPermissionedRegistry.State memory state = dosRegistry.getState(LibLabel.id(label)); + assertEq(state.tokenId, tokenId); + assertEq(state.latestOwner, registrant); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.REGISTERED)); + assertEq(labelStore.getLabel(tokenId), label); + + uint64 expiry = state.expiry; + vm.prank(registrant); + dosRegistrar.renew(label, duration, IERC20(paymentToken), bytes32(0)); + assertEq(dosRegistry.getExpiry(tokenId), expiry + duration); + } + + function test_setsPrimaryDosNameForDosChain() external { + assertEq(reverseRegistrar.CHAIN_ID(), DOS_CHAIN_ID); + assertEq(DOS_COIN_TYPE, 0x80000f63); + + vm.prank(registrant); + reverseRegistrar.setName("alice.dos"); + + assertEq(reverseRegistrar.nameForAddr(registrant), "alice.dos"); + } + + function test_deploymentProfileWiresDosContracts() external { + DeployDOS deployer = new DeployDOS(); + DeployDOS.Deployment memory deployment = + deployer.deploy(address(deployer), beneficiary, IERC20(tokenIdentity), DOS_CHAIN_ID); + + assertEq(address(deployment.dosRegistrar.ETH_REGISTRY()), address(deployment.dosRegistry)); + assertEq(deployment.reverseRegistrar.CHAIN_ID(), DOS_CHAIN_ID); + assertEq( + uint8(deployment.rootRegistry.getStatus(LibLabel.id("dos"))), + uint8(IPermissionedRegistry.Status.REGISTERED) + ); + (uint128 numer, uint128 denom) = + deployment.priceOracle.getPaymentTokenRatio(IERC20(tokenIdentity)); + assertEq(numer, 1); + assertEq(denom, 1); + assertTrue(address(deployment.verifiableFactory) != address(0)); + } + + function test_deploymentRejectsPaymentTokenBelowPriceScale() external { + DeployDOS deployer = new DeployDOS(); + MockERC20 lowDecimalToken = new MockERC20("Low decimals", 6); + + vm.expectRevert( + abi.encodeWithSelector(DeployDOS.PaymentTokenDecimalsTooLow.selector, uint8(6)) + ); + deployer.deploy(address(deployer), beneficiary, IERC20(lowDecimalToken), DOS_CHAIN_ID); + } + + function test_deploymentRejectsPaymentTokenAboveRatioCapacity() external { + DeployDOS deployer = new DeployDOS(); + MockERC20 highDecimalToken = new MockERC20("High decimals", 51); + + vm.expectRevert( + abi.encodeWithSelector(DeployDOS.PaymentTokenDecimalsTooHigh.selector, uint8(51)) + ); + deployer.deploy(address(deployer), beneficiary, IERC20(highDecimalToken), DOS_CHAIN_ID); + } + + function test_deploymentConvertsEighteenDecimalPaymentToken() external { + DeployDOS deployer = new DeployDOS(); + DeployDOS.Deployment memory deployment = + deployer.deploy(address(deployer), beneficiary, IERC20(tokenDAI), DOS_CHAIN_ID); + + (uint128 numer, uint128 denom) = + deployment.priceOracle.getPaymentTokenRatio(IERC20(tokenDAI)); + assertEq(numer, 1e6); + assertEq(denom, 1); + } + + function test_deploymentSupportsForwardAndReverseResolution() external { + DeployDOS deployer = new DeployDOS(); + DeployDOS.Deployment memory deployment = + deployer.deploy(address(deployer), beneficiary, IERC20(tokenIdentity), DOS_CHAIN_ID); + + bytes[] memory setters = new bytes[](0); + vm.prank(registrant); + PermissionedResolver resolver = + PermissionedResolver( + deployment.verifiableFactory.deployProxy( + address(deployment.permissionedResolverImplementation), + 1, + abi.encodeCall( + PermissionedResolver.initialize, + (registrant, EACBaseRolesLib.ALL_ROLES, setters) + ) + ) + ); + + tokenIdentity.mint(registrant, 1_000_000e12); + vm.prank(registrant); + tokenIdentity.approve(address(deployment.dosRegistrar), type(uint256).max); + + string memory label = "resolved"; + uint64 duration = StandardRegistrar.MIN_REGISTER_DURATION; + bytes32 commitment = + deployment.dosRegistrar.makeCommitment( + label, + registrant, + secret, + IRegistry(address(0)), + address(resolver), + duration, + bytes32(0) + ); + vm.prank(registrant); + deployment.dosRegistrar.commit(commitment); + vm.warp(block.timestamp + deployment.dosRegistrar.MIN_COMMITMENT_AGE()); + vm.prank(registrant); + deployment.dosRegistrar.register( + label, + registrant, + secret, + IRegistry(address(0)), + address(resolver), + duration, + IERC20(tokenIdentity), + bytes32(0) + ); + + bytes memory dnsName = NameCoder.encode("resolved.dos"); + bytes32 node = NameCoder.namehash(dnsName, 0); + vm.prank(registrant); + resolver.setAddr(node, DOS_COIN_TYPE, abi.encodePacked(registrant)); + vm.prank(registrant); + deployment.reverseRegistrar.setName("resolved.dos"); + + (bytes memory forwardResult, address forwardResolver) = + deployment.universalResolver.resolve( + dnsName, + abi.encodeCall(IAddressResolver.addr, (node, DOS_COIN_TYPE)) + ); + assertEq(abi.decode(forwardResult, (bytes)), abi.encodePacked(registrant)); + assertEq(forwardResolver, address(resolver)); + + (string memory primary, address resolvedBy, address reverseResolvedBy) = + deployment.universalResolver.reverse(abi.encodePacked(registrant), DOS_COIN_TYPE); + assertEq(primary, "resolved.dos"); + assertEq(resolvedBy, address(resolver)); + assertEq(reverseResolvedBy, address(deployment.reverseRegistrar)); + } + + function _register(string memory label, uint64 duration, MockERC20 paymentToken) + internal + returns (uint256 tokenId) + { + bytes32 commitment = + dosRegistrar.makeCommitment( + label, + registrant, + secret, + IRegistry(address(0)), + address(0), + duration, + bytes32(0) + ); + + vm.prank(registrant); + dosRegistrar.commit(commitment); + vm.warp(block.timestamp + dosRegistrar.MIN_COMMITMENT_AGE()); + + vm.prank(registrant); + tokenId = dosRegistrar.register( + label, + registrant, + secret, + IRegistry(address(0)), + address(0), + duration, + IERC20(paymentToken), + bytes32(0) + ); + } +} diff --git a/contracts/test/integration/ENSV1Resolver.test.ts b/contracts/test/integration/ENSV1Resolver.test.ts index 56a11f471..577334a66 100644 --- a/contracts/test/integration/ENSV1Resolver.test.ts +++ b/contracts/test/integration/ENSV1Resolver.test.ts @@ -3,13 +3,12 @@ import hre from "hardhat"; import { describe, expect, it } from "vitest"; import { - COIN_TYPE_ETH, type KnownProfile, bundleCalls, makeResolutions, } from "../utils/resolutions.js"; import { shouldSupportFeatures } from "../utils/supportsFeatures.js"; -import { dnsEncodeName } from "../utils/utils.js"; +import { dnsEncodeName, COIN_TYPE_ETH } from "../utils/utils.js"; import { deployV1Fixture } from "./fixtures/deployV1Fixture.js"; import { deployV2Fixture } from "./fixtures/deployV2Fixture.js"; import { expectVar } from "../utils/expectVar.js"; @@ -17,13 +16,14 @@ import { expectVar } from "../utils/expectVar.js"; const network = await hre.network.connect(); async function fixture() { - const mainnetV1 = await deployV1Fixture(network, true); - const mainnetV2 = await deployV2Fixture(network, true); + const v1 = await deployV1Fixture(network, true); + const v2 = await deployV2Fixture(network, true); const ensV1Resolver = await network.viem.deployContract("ENSV1Resolver", [ - mainnetV1.ensRegistry.address, - mainnetV1.batchGatewayProvider.address, + v1.batchGatewayProvider.address, + v2.contractNamer.address, + v1.ensRegistry.address, ]); - return { mainnetV1, mainnetV2, ensV1Resolver }; + return { v1, v2, ensV1Resolver }; } describe("ENSV1Resolver", () => { @@ -35,6 +35,7 @@ describe("ENSV1Resolver", () => { "IERC7996", "IExtendedResolver", "ICompositeResolver", + "IContractNamer", ], }); @@ -46,21 +47,12 @@ describe("ENSV1Resolver", () => { }, }); - it("requiresOffchain", async () => { - const F = await network.networkHelpers.loadFixture(fixture); - expect( - F.ensV1Resolver.read.requiresOffchain([dnsEncodeName("any.eth")]), - ).resolves.toStrictEqual(false); - }); - - it("getResolver", async () => { - const F = await network.networkHelpers.loadFixture(fixture); - expect( - F.ensV1Resolver.read.requiresOffchain([dnsEncodeName("any.eth")]), - ).resolves.toStrictEqual(false); - }); - - for (const name of ["test.eth", "sub.test.eth"]) { + for (const name of [ + "test.eth", + "sub.test.eth", + "abc.sub.test.eth", + "test.xyz", + ]) { it(name, async () => { const F = await network.networkHelpers.loadFixture(fixture); const kp: KnownProfile = { @@ -75,21 +67,29 @@ describe("ENSV1Resolver", () => { contenthash: { value: "0xabcdef" }, }; const res = bundleCalls(makeResolutions(kp)); - await F.mainnetV1.setupName({ name }); - await F.mainnetV2.setupName({ + await F.v1.setupName({ name }); + await F.v2.setupName({ name, resolverAddress: F.ensV1Resolver.address, }); - await F.mainnetV1.publicResolver.write.multicall([ + await F.v1.publicResolver.write.multicall([ res.resolutions.map((x) => x.write), ]); - const [answer, resolver] = - await F.mainnetV2.universalResolver.read.resolve([ + { + const [answer, resolver] = await F.v2.universalResolver.read.resolve([ dnsEncodeName(kp.name), res.call, ]); - expectVar({ resolver }).toEqualAddress(F.ensV1Resolver.address); - res.expect(answer); + expectVar({ resolver }).toEqualAddress(F.ensV1Resolver.address); + res.expect(answer); + } + { + const [resolver, offchain] = await F.ensV1Resolver.read.getResolver([ + dnsEncodeName(name), + ]); + expectVar({ resolver }).toEqualAddress(F.v1.publicResolver.address); + expectVar({ offchain }).toStrictEqual(false); + } }); } }); diff --git a/contracts/test/integration/ENSV2Resolver.test.ts b/contracts/test/integration/ENSV2Resolver.test.ts index af56b28b3..45fde64ef 100755 --- a/contracts/test/integration/ENSV2Resolver.test.ts +++ b/contracts/test/integration/ENSV2Resolver.test.ts @@ -1,15 +1,14 @@ import { shouldSupportInterfaces } from "@ensdomains/hardhat-chai-matchers-viem/behaviour"; import hre from "hardhat"; -import { describe, expect, it } from "vitest"; +import { describe, it } from "vitest"; import { - COIN_TYPE_ETH, type KnownProfile, bundleCalls, makeResolutions, } from "../utils/resolutions.js"; import { shouldSupportFeatures } from "../utils/supportsFeatures.js"; -import { dnsEncodeName } from "../utils/utils.js"; +import { dnsEncodeName, idFromLabel, COIN_TYPE_ETH } from "../utils/utils.js"; import { deployV1Fixture } from "./fixtures/deployV1Fixture.js"; import { deployV2Fixture } from "./fixtures/deployV2Fixture.js"; import { expectVar } from "../utils/expectVar.js"; @@ -17,13 +16,21 @@ import { expectVar } from "../utils/expectVar.js"; const network = await hre.network.connect(); async function fixture() { - const mainnetV1 = await deployV1Fixture(network, true); - const mainnetV2 = await deployV2Fixture(network, true); + const v1 = await deployV1Fixture(network, true); + const v2 = await deployV2Fixture(network, true); + const ethResolver = v1.ownedResolver.address; const ensV2Resolver = await network.viem.deployContract("ENSV2Resolver", [ - mainnetV2.rootRegistry.address, - mainnetV2.batchGatewayProvider.address, + v2.batchGatewayProvider.address, + v2.contractNamer.address, + v2.rootRegistry.address, + ethResolver, ]); - return { mainnetV1, mainnetV2, ensV2Resolver }; + // setup fallback resolver + await v1.setupName({ + name: "eth", + resolverAddress: ensV2Resolver.address, + }); + return { v1, v2, ensV2Resolver, ethResolver }; } describe("ENSV2Resolver", () => { @@ -35,6 +42,7 @@ describe("ENSV2Resolver", () => { "IERC7996", "IExtendedResolver", "ICompositeResolver", + "IContractNamer", ], }); @@ -46,23 +54,47 @@ describe("ENSV2Resolver", () => { }, }); - it("requiresOffchain", async () => { - const F = await network.networkHelpers.loadFixture(fixture); - expect( - F.ensV2Resolver.read.requiresOffchain([dnsEncodeName("any.eth")]), - ).resolves.toStrictEqual(false); - }); - - it("getResolver", async () => { + it("eth override", async () => { const F = await network.networkHelpers.loadFixture(fixture); - expect( - F.ensV2Resolver.read.requiresOffchain([dnsEncodeName("any.eth")]), - ).resolves.toStrictEqual(false); + // setup invalid resolver in v2 + await F.v2.rootRegistry.write.setResolver([ + idFromLabel("eth"), + "0x1111111111111111111111111111111111111111", + ]); + // resolve in v1 + { + const res = bundleCalls( + makeResolutions({ + name: "eth", + addresses: [ + { + coinType: COIN_TYPE_ETH, + value: F.v1.baseRegistrar.address, + }, + ], + }), + ); + const [answer, resolver] = await F.v1.universalResolver.read.resolve([ + dnsEncodeName("eth"), + res.call, + ]); + expectVar({ resolver }).toEqualAddress(F.ensV2Resolver.address); + res.expect(answer); + } + // check getResolver + { + const [resolver, offchain] = await F.ensV2Resolver.read.getResolver([ + dnsEncodeName("eth"), + ]); + expectVar({ resolver }).toEqualAddress(F.ethResolver); + expectVar({ offchain }).toStrictEqual(false); + } }); - for (const name of ["test.eth", "sub.test.eth"]) { + for (const name of ["test.eth", "sub.test.eth", "abc.sub.test.eth"]) { it(name, async () => { const F = await network.networkHelpers.loadFixture(fixture); + // setup profile in v2 const kp: KnownProfile = { name, addresses: [ @@ -75,23 +107,29 @@ describe("ENSV2Resolver", () => { contenthash: { value: "0xabcdef" }, }; const res = bundleCalls(makeResolutions(kp)); - const myResolver = await F.mainnetV2.deployPermissionedResolver(); - await F.mainnetV1.setupName({ - name, - resolverAddress: F.ensV2Resolver.address, - }); - await F.mainnetV2.setupName({ + const myResolver = await F.v2.deployPermissionedResolver(); + await F.v2.setupName({ name, resolverAddress: myResolver.address, }); await myResolver.write.multicall([res.resolutions.map((x) => x.write)]); - const [answer, resolver] = - await F.mainnetV1.universalResolver.read.resolve([ + // resolve in v1 + { + const [answer, resolver] = await F.v1.universalResolver.read.resolve([ dnsEncodeName(kp.name), res.call, ]); - expectVar({ resolver }).toEqualAddress(F.ensV2Resolver.address); - res.expect(answer); + expectVar({ resolver }).toEqualAddress(F.ensV2Resolver.address); + res.expect(answer); + } + // check getResolver + { + const [resolver, offchain] = await F.ensV2Resolver.read.getResolver([ + dnsEncodeName(name), + ]); + expectVar({ resolver }).toEqualAddress(myResolver.address); + expectVar({ offchain }).toStrictEqual(false); + } }); } }); diff --git a/contracts/test/integration/common/LibISO8601.test.ts b/contracts/test/integration/common/LibISO8601.test.ts new file mode 100644 index 000000000..bb4616273 --- /dev/null +++ b/contracts/test/integration/common/LibISO8601.test.ts @@ -0,0 +1,411 @@ +import hre from 'hardhat' +import { describe, expect, it, test } from 'vitest' + +const connection = await hre.network.connect() + +async function fixture() { + return connection.viem.deployContract('MockLibISO8601Implementer') +} + +const loadFixture = async () => connection.networkHelpers.loadFixture(fixture) + +function timestampToISO8601(timestamp: bigint): string { + const date = new Date(Number(timestamp) * 1000) + return date.toISOString().replace('.000Z', 'Z') +} + +function dateToTimestamp(isoString: string): bigint { + return BigInt(Math.floor(new Date(isoString).getTime() / 1000)) +} + +// ========================================================================= +// All Input → Output Tests +// ========================================================================= +const testCases = [ + [ + 'Unix Epoch and Basic Tests', + [ + ['1970-01-01T00:00:00Z', 'Unix epoch'], + ['1970-01-01T00:00:01Z', 'One second after epoch'], + ['1970-01-01T00:01:00Z', 'One minute after epoch'], + ['1970-01-01T01:00:00Z', 'One hour after epoch'], + ['1970-01-02T00:00:00Z', 'One day after epoch'], + ], + ], + [ + 'Time Component Tests', + [ + ['1970-01-02T00:00:00Z', 'Midnight'], + ['1970-01-01T12:00:00Z', 'Noon'], + ['1970-01-01T23:59:59Z', 'End of day'], + ['1970-01-01T01:23:45Z', '01:23:45'], + ['1970-01-01T09:08:07Z', '09:08:07 - single digit padding'], + ['1970-01-01T10:11:12Z', '10:11:12 - double digits'], + ], + ], + [ + 'Year Transition Tests', + [ + ['1970-12-31T23:59:59Z', 'End of 1970'], + ['1971-01-01T00:00:00Z', 'Start of 1971'], + ['2000-01-01T00:00:00Z', 'Y2K'], + ['1999-12-31T23:59:59Z', 'End of 1999'], + ], + ], + [ + 'Leap Year Tests', + [ + ['2000-02-29T00:00:00Z', 'Feb 29, 2000 - leap year divisible by 400'], + ['2000-02-28T00:00:00Z', 'Feb 28, 2000'], + ['2000-03-01T00:00:00Z', 'Mar 1, 2000 - day after Feb 29 in leap year'], + ['2004-02-29T00:00:00Z', 'Feb 29, 2004 - leap year divisible by 4'], + ['2024-02-29T00:00:00Z', 'Feb 29, 2024 - leap year'], + ['2001-02-28T00:00:00Z', 'Feb 28, 2001 - non-leap year'], + [ + '2001-03-01T00:00:00Z', + 'Mar 1, 2001 - day after Feb 28 in non-leap year', + ], + ['2100-02-28T00:00:00Z', 'Feb 28, 2100 - century year non-leap'], + [ + '2100-03-01T00:00:00Z', + 'Mar 1, 2100 - day after Feb 28 in non-leap century year', + ], + ], + ], + [ + 'Month Boundary Tests', + [ + ['1970-01-31T00:00:00Z', 'Jan 31 - 31-day month'], + ['1970-02-01T00:00:00Z', 'Feb 1'], + ['1970-02-28T00:00:00Z', 'Feb 28, 1970 - non-leap year'], + ['1970-03-01T00:00:00Z', 'Mar 1, 1970 - after Feb 28 in non-leap year'], + ['1970-04-30T00:00:00Z', 'Apr 30 - 30-day month'], + ['1970-05-01T00:00:00Z', 'May 1'], + ['1970-06-30T00:00:00Z', 'Jun 30 - 30-day month'], + ['1970-07-31T00:00:00Z', 'Jul 31 - 31-day month'], + ['1970-08-31T00:00:00Z', 'Aug 31 - 31-day month'], + ['1970-09-30T00:00:00Z', 'Sep 30 - 30-day month'], + ['1970-10-31T00:00:00Z', 'Oct 31 - 31-day month'], + ['1970-11-30T00:00:00Z', 'Nov 30 - 30-day month'], + ['1970-12-31T00:00:00Z', 'Dec 31 - 31-day month end of year'], + ], + ], + [ + 'Padding Tests', + [ + ['1970-09-05T00:00:00Z', 'Month 09 padded with zero'], + ['1970-11-15T00:00:00Z', 'Month 11 - double digit'], + ['1970-01-05T00:00:00Z', 'Day 05 padded with zero'], + ['1970-01-25T00:00:00Z', 'Day 25 - double digit'], + ['1970-01-01T05:00:00Z', 'Hour 05 padded with zero'], + ['1970-01-01T00:07:00Z', 'Minute 07 padded with zero'], + ['1970-01-01T00:00:03Z', 'Second 03 padded with zero'], + ], + ], + [ + 'Known Timestamps from Real-World Events', + [ + ['2009-01-03T18:15:05Z', 'Bitcoin genesis block'], + ['2015-07-30T15:26:13Z', 'Ethereum genesis block'], + ['2022-09-15T06:42:42Z', 'Ethereum Merge'], + ], + ], + [ + 'Far Future Dates', + [ + ['2038-01-19T03:14:07Z', 'Y2038 - max signed 32-bit timestamp'], + ['2038-01-19T03:14:08Z', 'One second after Y2038'], + ['2100-01-01T00:00:00Z', 'Year 2100'], + ['3000-01-01T00:00:00Z', 'Year 3000'], + ['9999-12-31T23:59:59Z', 'End of year 9999'], + ], + ], + [ + 'All Months of 2023', + [ + ['2023-01-01T00:00:00Z', 'January'], + ['2023-02-01T00:00:00Z', 'February'], + ['2023-03-01T00:00:00Z', 'March'], + ['2023-04-01T00:00:00Z', 'April'], + ['2023-05-01T00:00:00Z', 'May'], + ['2023-06-01T00:00:00Z', 'June'], + ['2023-07-01T00:00:00Z', 'July'], + ['2023-08-01T00:00:00Z', 'August'], + ['2023-09-01T00:00:00Z', 'September'], + ['2023-10-01T00:00:00Z', 'October'], + ['2023-11-01T00:00:00Z', 'November'], + ['2023-12-01T00:00:00Z', 'December'], + ], + ], + [ + 'Edge Cases', + [ + ['1987-11-22T13:37:42Z', 'All components non-zero'], + ['1970-01-01T01:02:03Z', 'All single digit time components padded'], + ], + ], + [ + 'Sequential Days', + [ + ['1970-01-01T00:00:00Z', 'Day 1'], + ['1970-01-02T00:00:00Z', 'Day 2'], + ['1970-01-03T00:00:00Z', 'Day 3'], + ['1970-01-04T00:00:00Z', 'Day 4'], + ['1970-01-05T00:00:00Z', 'Day 5'], + ['1970-01-06T00:00:00Z', 'Day 6'], + ['1970-01-07T00:00:00Z', 'Day 7'], + ], + ], + [ + 'Leap Year Boundary Tests', + [ + ['2020-02-28T00:00:00Z', 'Feb 28, 2020 (leap year)'], + ['2020-02-29T00:00:00Z', 'Feb 29, 2020 (leap year)'], + ['2020-03-01T00:00:00Z', 'Mar 1, 2020 (leap year)'], + ['2019-02-28T00:00:00Z', 'Feb 28, 2019 (non-leap year)'], + ['2019-03-01T00:00:00Z', 'Mar 1, 2019 (non-leap year)'], + ], + ], + // Add to testCases array: + [ + 'Additional Edge Cases', + [ + // Year 2400 - century year that IS a leap year (divisible by 400) + ['2400-02-29T00:00:00Z', 'Feb 29, 2400 - century leap year'], + [ + '2400-03-01T00:00:00Z', + 'Mar 1, 2400 - after Feb 29 in century leap year', + ], + + // Era boundary around year 2000 (algorithm's internal epoch is March 1, 2000) + ['2000-02-29T23:59:59Z', 'Last second of Feb 29, 2000 (era boundary)'], + ['2000-03-01T00:00:00Z', 'March 1, 2000 - algorithm epoch'], + + // Exact midnight transitions + ['2020-02-29T23:59:59Z', 'Last second of Feb 29, 2020 leap year'], + ['2020-03-01T00:00:00Z', 'First second of Mar 1, 2020'], + ['2019-02-28T23:59:59Z', 'Last second of Feb 28, 2019 non-leap year'], + + // Year 2400 era boundary + ['2399-12-31T23:59:59Z', 'End of era 5'], + ['2400-01-01T00:00:00Z', 'Start of era 6'], + + // Another century non-leap year for variety + ['2200-02-28T00:00:00Z', 'Feb 28, 2200 - century non-leap'], + [ + '2200-03-01T00:00:00Z', + 'Mar 1, 2200 - after Feb 28 in non-leap century', + ], + ['2300-02-28T23:59:59Z', 'Last second of Feb 28, 2300'], + ], + ], + + [ + 'Boundary Timestamp Values', + [ + // Maximum representable timestamp + ['9999-12-31T23:59:59Z', 'Maximum 4-digit year timestamp'], + // One second before various boundaries + ['1999-12-31T23:59:59Z', 'One second before Y2K'], + ['2099-12-31T23:59:59Z', 'One second before 2100'], + ], + ], +] satisfies [string, [string, string][]][] + +describe('LibISO8601', () => { + describe.each(testCases)('%s', (_, cases) => { + test.each(cases)('$1', async (expected) => { + const contract = await loadFixture() + const timestamp = dateToTimestamp(expected) + const result = await contract.read.toISO8601([timestamp]) + expect(result).toBe(expected) + }) + }) + + describe('Overflow Behavior', () => { + it('should revert for timestamp of year 10000', async () => { + const contract = await loadFixture() + // 253402300800n = 10000-01-01T00:00:00Z + await expect(contract.read.toISO8601([253402300800n])) + .toBeRevertedWithCustomError('TimestampOutOfRange') + .withArgs([253402300800n]) + }) + it('should revert for timestamp of year 10000 + 1 second', async () => { + const contract = await loadFixture() + await expect(contract.read.toISO8601([253402300801n])) + .toBeRevertedWithCustomError('TimestampOutOfRange') + .withArgs([253402300801n]) + }) + }) + + describe('String Format Verification', () => { + it('output length is always 20 characters', async () => { + const contract = await loadFixture() + + let result = await contract.read.toISO8601([0n]) + expect(result.length).toBe(20) + + const timestamp = dateToTimestamp('9999-12-31T23:59:59Z') + result = await contract.read.toISO8601([timestamp]) + expect(result.length).toBe(20) + }) + + it('format structure is correct', async () => { + const contract = await loadFixture() + const result = await contract.read.toISO8601([0n]) + + expect(result[4]).toBe('-') + expect(result[7]).toBe('-') + expect(result[10]).toBe('T') + expect(result[13]).toBe(':') + expect(result[16]).toBe(':') + expect(result[19]).toBe('Z') + }) + + it('all digit positions are numeric', async () => { + const contract = await loadFixture() + const timestamp = dateToTimestamp('2009-02-13T23:31:30Z') + const result = await contract.read.toISO8601([timestamp]) + + const isDigit = (c: string) => c >= '0' && c <= '9' + const digitPositions = [0, 1, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18] + for (const pos of digitPositions) { + expect(isDigit(result[pos])).toBe(true) + } + }) + }) + + describe('Fuzz/Bulk Tests', () => { + test('100k random timestamps', async () => { + const contract = await loadFixture() + + const ITERATIONS = 100_000 + const BATCH_SIZE = 500 + const MAX_TIMESTAMP = 253402300799n + + let seed = 12345n + const nextRandom = (): bigint => { + seed = (seed * 1103515245n + 12345n) % 2n ** 31n + return seed + } + const randomTimestamp = (): bigint => nextRandom() % (MAX_TIMESTAMP + 1n) + + const errors: Array<{ + timestamp: bigint + solidity: string + javascript: string + }> = [] + + for (let batch = 0; batch < ITERATIONS / BATCH_SIZE; batch++) { + const timestamps = Array.from({ length: BATCH_SIZE }, randomTimestamp) + const results = await contract.read.toISO8601_batch([timestamps]) + + for (let i = 0; i < results.length; i++) { + const jsResult = timestampToISO8601(timestamps[i]) + if (results[i] !== jsResult) { + errors.push({ + timestamp: timestamps[i], + solidity: results[i], + javascript: jsResult, + }) + } + } + + if ((batch + 1) % 20 === 0) { + console.log( + ` Progress: ${( + (batch + 1) * + BATCH_SIZE + ).toLocaleString()} / ${ITERATIONS.toLocaleString()}`, + ) + } + } + + if (errors.length > 0) { + console.error(`\nFound ${errors.length} mismatches:`) + for (const err of errors.slice(0, 10)) { + console.error( + ` Timestamp ${err.timestamp}: Solidity="${err.solidity}" vs JS="${err.javascript}"`, + ) + } + throw new Error( + `Fuzz test failed: ${errors.length} mismatches found out of ${ITERATIONS} tests`, + ) + } + + console.log(`\n✓ All ${ITERATIONS.toLocaleString()} fuzz tests passed!`) + }, 60_000) + + test('daily exhaustive from 1970-01-01 to 2970-01-01', async () => { + const contract = await loadFixture() + + const SECONDS_PER_DAY = 86400n + const START_TIMESTAMP = 0n + const END_TIMESTAMP = dateToTimestamp('2970-01-01T00:00:00Z') + const BATCH_SIZE = 500 + + const errors: Array<{ + timestamp: bigint + solidity: string + javascript: string + }> = [] + + let currentTimestamp = START_TIMESTAMP + let dayCount = 0 + const totalDays = Number( + (END_TIMESTAMP - START_TIMESTAMP) / SECONDS_PER_DAY, + ) + + console.log( + `\nTesting ${totalDays.toLocaleString()} days (1000 years)...`, + ) + + while (currentTimestamp <= END_TIMESTAMP) { + const timestamps: bigint[] = [] + for ( + let i = 0; + i < BATCH_SIZE && currentTimestamp <= END_TIMESTAMP; + i++ + ) { + timestamps.push(currentTimestamp) + currentTimestamp += SECONDS_PER_DAY + dayCount++ + } + + const results = await contract.read.toISO8601_batch([timestamps]) + + for (let i = 0; i < results.length; i++) { + const jsResult = timestampToISO8601(timestamps[i]) + if (results[i] !== jsResult) { + errors.push({ + timestamp: timestamps[i], + solidity: results[i], + javascript: jsResult, + }) + } + } + + if (dayCount % 50000 < BATCH_SIZE) { + const percent = ((dayCount / totalDays) * 100).toFixed(1) + console.log( + ` Progress: ${dayCount.toLocaleString()} / ${totalDays.toLocaleString()} days (${percent}%)`, + ) + } + } + + if (errors.length > 0) { + console.error(`\nFound ${errors.length} mismatches:`) + for (const err of errors.slice(0, 10)) { + console.error( + ` Timestamp ${err.timestamp}: Solidity="${err.solidity}" vs JS="${err.javascript}"`, + ) + } + throw new Error( + `Daily exhaustive test failed: ${errors.length} mismatches found out of ${dayCount} days`, + ) + } + + console.log(`\n✓ All ${dayCount.toLocaleString()} daily tests passed!`) + }, 300_000) + }) +}) diff --git a/contracts/test/integration/dns/DNSTLDResolver.mainnet.test.ts b/contracts/test/integration/dns/DNSTLDResolver.mainnet.test.ts index f4a10a06e..31112b4c9 100755 --- a/contracts/test/integration/dns/DNSTLDResolver.mainnet.test.ts +++ b/contracts/test/integration/dns/DNSTLDResolver.mainnet.test.ts @@ -19,7 +19,7 @@ if (url) { async function fixture() { await chain.networkHelpers.mine(); // https://github.com/NomicFoundation/hardhat/issues/5511#issuecomment-2288072104 - const mainnetV2 = await deployV2Fixture(chain, true); // CCIP on UR + const v2 = await deployV2Fixture(chain, true); // CCIP on UR const ensRegistry = await chain.viem.getContractAt( "ENSRegistry", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", @@ -35,29 +35,30 @@ if (url) { const oracleGatewayProvider = await chain.viem.deployContract( "GatewayProvider", [ - mainnetV2.walletClient.account.address, + v2.walletClient.account.address, [await dnsTLDResolverV1.read.gatewayURL()], ], ); const dnsTLDResolver = await chain.viem.deployContract("DNSTLDResolver", [ ensRegistry.address, dnsTLDResolverV1.address, - mainnetV2.rootRegistry.address, + v2.rootRegistry.address, DNSSEC.address, oracleGatewayProvider.address, - mainnetV2.batchGatewayProvider.address, + v2.batchGatewayProvider.address, + v2.contractNamer.address, ]); for (const name of ["dnsname.ens.eth"]) { - await mainnetV2.setupName({ + await v2.setupName({ name, resolverAddress: await ensRegistry.read.resolver([namehash(name)]), }); } return { + v2, ensRegistry, dnsTLDResolverV1, DNSSEC, - mainnetV2, dnsTLDResolver, }; } @@ -68,16 +69,15 @@ if (url) { for (const kp of KNOWN_DNS) { it(kp.name, { timeout }, async () => { const F = await chain.networkHelpers.loadFixture(fixture); - await F.mainnetV2.setupName({ + await F.v2.setupName({ name: getLabelAt(kp.name, -1), resolverAddress: F.dnsTLDResolverV1.address, }); const bundle = bundleCalls(makeResolutions(kp)); - const [answer, resolver] = - await F.mainnetV2.universalResolver.read.resolve([ - dnsEncodeName(kp.name), - bundle.call, - ]); + const [answer, resolver] = await F.v2.universalResolver.read.resolve([ + dnsEncodeName(kp.name), + bundle.call, + ]); expectVar({ resolver }).toEqualAddress(F.dnsTLDResolverV1.address); bundle.expect(answer); }); @@ -87,16 +87,15 @@ if (url) { for (const kp of KNOWN_DNS) { it(kp.name, { timeout }, async () => { const F = await chain.networkHelpers.loadFixture(fixture); - await F.mainnetV2.setupName({ + await F.v2.setupName({ name: getLabelAt(kp.name, -1), resolverAddress: F.dnsTLDResolver.address, }); const bundle = bundleCalls(makeResolutions(kp)); - const [answer, resolver] = - await F.mainnetV2.universalResolver.read.resolve([ - dnsEncodeName(kp.name), - bundle.call, - ]); + const [answer, resolver] = await F.v2.universalResolver.read.resolve([ + dnsEncodeName(kp.name), + bundle.call, + ]); expectVar({ resolver }).toEqualAddress(F.dnsTLDResolver.address); bundle.expect(answer); }); diff --git a/contracts/test/integration/dns/DNSTLDResolver.test.ts b/contracts/test/integration/dns/DNSTLDResolver.test.ts index 34497e486..eb06dece5 100644 --- a/contracts/test/integration/dns/DNSTLDResolver.test.ts +++ b/contracts/test/integration/dns/DNSTLDResolver.test.ts @@ -13,26 +13,27 @@ import { describe, expect, it } from "vitest"; import { expectVar } from "../../utils/expectVar.js"; import { - type KnownProfile, bundleCalls, - COIN_TYPE_DEFAULT, - COIN_TYPE_ETH, + type KnownProfile, makeResolutions, -} from "../../utils/resolutions.ts"; +} from "../../utils/resolutions.js"; import { shouldSupportFeatures } from "../../utils/supportsFeatures.js"; -import { dnsEncodeName } from "../../utils/utils.js"; +import { + dnsEncodeName, + COIN_TYPE_DEFAULT, + COIN_TYPE_ETH, +} from "../../utils/utils.js"; import { deployV1Fixture } from "../fixtures/deployV1Fixture.js"; import { deployV2Fixture } from "../fixtures/deployV2Fixture.js"; -import { deployArtifact } from "../fixtures/deployArtifact.js"; import { encodeRRs, makeTXT } from "./rr.js"; import { FEATURES } from "../../../lib/ens-contracts/test/utils/features.js"; const network = await hre.network.connect(); const dnsTXTResolverName = "dnstxt.ens.eth"; -const extendedDNSResolverName = "dnsname.ens.eth"; const dummyBytes4 = "0x12345678"; const testAddress = "0x8000000000000000000000000000000000000001"; +const testData = "0xabcdef"; const testURL = "https://ens.domains"; const basicProfile: KnownProfile = { name: "test.com", @@ -44,56 +45,53 @@ const dnsOracleGateway = 'data:application/json,{"data":"0x0000000000000000000000000000000000000000000000000000000000000000"}'; async function fixture() { - const mainnetV1 = await deployV1Fixture(network); - const mainnetV2 = await deployV2Fixture(network, true); // CCIP on UR + const v1 = await deployV1Fixture(network); + const v2 = await deployV2Fixture(network, true); // CCIP on UR const ssResolver = await network.viem.deployContract( "DummyShapeshiftResolver", ); const mockDNSSEC = await network.viem.deployContract("MockDNSSEC"); const dnsTLDResolverV1 = await network.viem.deployContract( "OffchainDNSResolver", - [mainnetV1.ensRegistry.address, mockDNSSEC.address, dnsOracleGateway], + [v1.ensRegistry.address, mockDNSSEC.address, dnsOracleGateway], ); const oracleGatewayProvider = await network.viem.deployContract( "GatewayProvider", - [mainnetV2.walletClient.account.address, [dnsOracleGateway]], + [v2.walletClient.account.address, [dnsOracleGateway]], ); - const myResolver = await mainnetV2.deployPermissionedResolver(); + const myResolver = await v2.deployPermissionedResolver(); const dnsTLDResolver = await network.viem.deployContract("DNSTLDResolver", [ - mainnetV1.ensRegistry.address, + v1.ensRegistry.address, dnsTLDResolverV1.address, - mainnetV2.rootRegistry.address, + v2.rootRegistry.address, mockDNSSEC.address, oracleGatewayProvider.address, - mainnetV2.batchGatewayProvider.address, + v2.batchGatewayProvider.address, + v2.contractNamer.address, ]); - await mainnetV1.setupName({ + await v1.setupName({ name: "com", resolverAddress: dnsTLDResolverV1.address, }); - await mainnetV2.setupName({ + await v2.setupName({ name: "com", resolverAddress: dnsTLDResolver.address, }); - const dnsTXTResolver = await network.viem.deployContract("DNSTXTResolver"); + const dnsTXTResolver = await network.viem.deployContract("DNSTXTResolver", [ + v2.contractNamer.address, + ]); await setupNamedResolver(dnsTXTResolverName, dnsTXTResolver.address); const dnsAliasResolver = await network.viem.deployContract( "DNSAliasResolver", - [mainnetV2.rootRegistry.address, mainnetV2.batchGatewayProvider.address], - ); - const extendedDNSResolverAddress = await deployArtifact( - mainnetV2.walletClient, - { - file: new URL( - "./ExtendedDNSResolver_53f64de872aad627467a34836be1e2b63713a438.json", - import.meta.url, - ), - }, + [ + v2.rootRegistry.address, + v2.batchGatewayProvider.address, + v2.contractNamer.address, + ], ); - await setupNamedResolver(extendedDNSResolverName, extendedDNSResolverAddress); return { - mainnetV1, - mainnetV2, + v1, + v2, ssResolver, mockDNSSEC, dnsTLDResolverV1, @@ -102,7 +100,6 @@ async function fixture() { dnsTLDResolver, dnsTXTResolver, dnsAliasResolver, - extendedDNSResolverAddress, expectTXT, expectGasless, expectResolution, @@ -120,7 +117,7 @@ async function fixture() { gasless = false, ) { const bundle = bundleCalls(makeResolutions(kp)); - const [answer, resolver] = await mainnetV2.universalResolver.read.resolve([ + const [answer, resolver] = await v2.universalResolver.read.resolve([ dnsEncodeName(kp.name), bundle.call, ]); @@ -131,19 +128,16 @@ async function fixture() { bundle.call, ]); expectVar({ directAnswer }).toStrictEqual(answer); - await expect( - dnsTLDResolver.read.requiresOffchain([dnsEncodeName(kp.name)]), - ).resolves.toStrictEqual(gasless); await expect( dnsTLDResolver.read.getResolver([dnsEncodeName(kp.name)]), ).resolves.toStrictEqual([getAddress(resolverAddress), gasless]); } async function setupNamedResolver(name: string, resolver: Address) { - await mainnetV2.setupName({ + await v2.setupName({ name, resolverAddress: myResolver.address, }); - await myResolver.write.setAddr([namehash(name), COIN_TYPE_ETH, resolver]); + await myResolver.write.setAddr([namehash(name), resolver]); } } @@ -245,16 +239,16 @@ describe("DNSTLDResolver", () => { describe("still registered on V1", () => { testProfiles("immediate", (kp) => async () => { const F = await network.networkHelpers.loadFixture(fixture); - await F.mainnetV1.setupName(kp); + await F.v1.setupName(kp); for (const res of makeResolutions(kp)) { - await F.mainnetV1.publicResolver.write.multicall([[res.write]]); + await F.v1.publicResolver.write.multicall([[res.write]]); } - await F.expectResolution(kp, F.mainnetV1.publicResolver.address); + await F.expectResolution(kp, F.v1.publicResolver.address); }); testProfiles("onchain extended", (kp) => async () => { const F = await network.networkHelpers.loadFixture(fixture); - await F.mainnetV1.setupName({ + await F.v1.setupName({ name: kp.name, resolverAddress: F.ssResolver.address, }); @@ -267,7 +261,7 @@ describe("DNSTLDResolver", () => { testProfiles("offchain extended", (kp) => async () => { const F = await network.networkHelpers.loadFixture(fixture); - await F.mainnetV1.setupName({ + await F.v1.setupName({ name: kp.name, resolverAddress: F.ssResolver.address, }); @@ -283,54 +277,25 @@ describe("DNSTLDResolver", () => { it("imported on V2", async () => { const F = await network.networkHelpers.loadFixture(fixture); const bundle = bundleCalls(makeResolutions(basicProfile)); - await F.mainnetV2.setupName({ + await F.v2.setupName({ name: basicProfile.name, resolverAddress: F.myResolver.address, }); await F.myResolver.write.multicall([ bundle.resolutions.map((x) => x.write), ]); - const [answer, resolverAddress] = - await F.mainnetV2.universalResolver.read.resolve([ - dnsEncodeName(basicProfile.name), - bundle.call, - ]); + const [answer, resolverAddress] = await F.v2.universalResolver.read.resolve( + [dnsEncodeName(basicProfile.name), bundle.call], + ); expectVar({ resolverAddress }).toEqualAddress(F.myResolver.address); bundle.expect(answer); }); - describe("ExtendedDNSResolver (original deployment)", () => { - // this ensures MockDNSSEC is working as expected - it("addr(60)", async () => { - const F = await network.networkHelpers.loadFixture(fixture); - await F.mockDNSSEC.write.setResponse([ - encodeRRs([ - makeTXT( - basicProfile.name, - `ENS1 ${extendedDNSResolverName} ${testAddress}`, - ), - ]), - ]); - await F.expectGasless( - { - name: basicProfile.name, - addresses: [ - { - coinType: COIN_TYPE_ETH, - value: testAddress, - }, - ], - }, - F.extendedDNSResolverAddress, - ); - }); - }); - describe("DNSSEC", () => { it("no ENS1", async () => { const F = await network.networkHelpers.loadFixture(fixture); await expect( - F.mainnetV2.universalResolver.read.resolve([ + F.v2.universalResolver.read.resolve([ dnsEncodeName(basicProfile.name), dummyBytes4, ]), @@ -394,7 +359,7 @@ describe("DNSTLDResolver", () => { const anotherAddress = "0x1234567812345678123456781234567812345678"; const x = `0x${"a".repeat(64)}` as const; const y = `0x${"b".repeat(64)}` as const; - const context = `a[60]=${testAddress} a[e0]=${anotherAddress} t[url]='${testURL}' c=${contenthash} xy=${concat([x, y])}`; + const context = `a[60]=${testAddress} a[e0]=${anotherAddress} t[url]='${testURL}' d[abc]=${testData} c=${contenthash} xy=${concat([x, y])}`; const encodedRRs = encodeRRs([ makeTXT(basicProfile.name, `ENS1 ${dnsTXTResolverName} ${context}`), ]); @@ -403,7 +368,7 @@ describe("DNSTLDResolver", () => { const F = await network.networkHelpers.loadFixture(fixture); await F.mockDNSSEC.write.setResponse([encodedRRs]); await expect( - F.mainnetV2.universalResolver.read.resolve([ + F.v2.universalResolver.read.resolve([ dnsEncodeName(basicProfile.name), dummyBytes4, ]), @@ -412,36 +377,37 @@ describe("DNSTLDResolver", () => { .withArgs([dummyBytes4]); }); - it("invalid hex", async () => { - const F = await network.networkHelpers.loadFixture(fixture); - const invalidHex = "!@#$"; - await F.mockDNSSEC.write.setResponse([ - encodeRRs([ - makeTXT( - basicProfile.name, - `ENS1 ${dnsTXTResolverName} a[60]=${invalidHex}`, - ), - ]), - ]); - const [res] = makeResolutions({ - name: basicProfile.name, - addresses: [{ coinType: COIN_TYPE_ETH, value: testAddress }], - }); - await expect( - F.mainnetV2.universalResolver.read.resolve([ - dnsEncodeName(basicProfile.name), - res.call, - ]), - ) - .toBeRevertedWithCustomError("ResolverError") - .withArgs([ - encodeErrorResult({ - abi: F.dnsTXTResolver.abi, - errorName: "InvalidHexData", - args: [stringToHex(invalidHex)], - }), + for (const invalidHex of ["0", "00", "0x0", "!@#$"]) { + it(`invalid hex: ${invalidHex}`, async () => { + const F = await network.networkHelpers.loadFixture(fixture); + await F.mockDNSSEC.write.setResponse([ + encodeRRs([ + makeTXT( + basicProfile.name, + `ENS1 ${dnsTXTResolverName} a[60]=${invalidHex}`, + ), + ]), ]); - }); + const [res] = makeResolutions({ + name: basicProfile.name, + addresses: [{ coinType: COIN_TYPE_ETH, value: testAddress }], + }); + await expect( + F.v2.universalResolver.read.resolve([ + dnsEncodeName(basicProfile.name), + res.call, + ]), + ) + .toBeRevertedWithCustomError("ResolverError") + .withArgs([ + encodeErrorResult({ + abi: F.dnsTXTResolver.abi, + errorName: "InvalidHexData", + args: [stringToHex(invalidHex)], + }), + ]); + }); + } it("invalid length: address", async () => { const F = await network.networkHelpers.loadFixture(fixture); @@ -458,7 +424,7 @@ describe("DNSTLDResolver", () => { addresses: [{ coinType: COIN_TYPE_ETH, value: testAddress }], }); await expect( - F.mainnetV2.universalResolver.read.resolve([ + F.v2.universalResolver.read.resolve([ dnsEncodeName(basicProfile.name), res.call, ]), @@ -488,7 +454,7 @@ describe("DNSTLDResolver", () => { pubkey: { x, y }, }); await expect( - F.mainnetV2.universalResolver.read.resolve([ + F.v2.universalResolver.read.resolve([ dnsEncodeName(basicProfile.name), res.call, ]), @@ -503,6 +469,22 @@ describe("DNSTLDResolver", () => { ]); }); + it("og: just addr(60)", async () => { + const F = await network.networkHelpers.loadFixture(fixture); + const name = "og.com"; + await F.mockDNSSEC.write.setResponse([ + encodeRRs([makeTXT(name, `ENS1 ${dnsTXTResolverName} ${testAddress}`)]), + ]); + await F.expectTXT({ + name, + addresses: [ + { coinType: COIN_TYPE_ETH, value: testAddress }, + { coinType: COIN_TYPE_DEFAULT, value: "0x" }, + { coinType: 0n, value: "0x" }, + ], + }); + }); + it("addr()", async () => { const F = await network.networkHelpers.loadFixture(fixture); await F.mockDNSSEC.write.setResponse([encodedRRs]); @@ -533,7 +515,7 @@ describe("DNSTLDResolver", () => { }); }); - it("text(url)", async () => { + it("text()", async () => { const F = await network.networkHelpers.loadFixture(fixture); await F.mockDNSSEC.write.setResponse([encodedRRs]); await F.expectTXT({ @@ -542,6 +524,33 @@ describe("DNSTLDResolver", () => { }); }); + it("text() w/[-key", async () => { + const F = await network.networkHelpers.loadFixture(fixture); + const key = "a[b[c]]"; + const value = "123"; + await F.mockDNSSEC.write.setResponse([ + encodeRRs([ + makeTXT( + basicProfile.name, + `ENS1 ${dnsTXTResolverName} t[${key}]=${value}`, + ), + ]), + ]); + await F.expectTXT({ + name: basicProfile.name, + texts: [{ key, value }], + }); + }); + + it("data()", async () => { + const F = await network.networkHelpers.loadFixture(fixture); + await F.mockDNSSEC.write.setResponse([encodedRRs]); + await F.expectTXT({ + name: basicProfile.name, + datas: [{ key: "abc", value: testData }], + }); + }); + it("contenthash()", async () => { const F = await network.networkHelpers.loadFixture(fixture); await F.mockDNSSEC.write.setResponse([encodedRRs]); @@ -598,7 +607,7 @@ describe("DNSTLDResolver", () => { function parseContext(name: string, context: string) { const pos = context.indexOf(" "); - if (pos == -1) return context; + if (pos === -1) return context; return name.replace( new RegExp(`(^|\.)${context.slice(0, pos)}$`), (_, x) => x + context.slice(pos + 1), @@ -618,8 +627,9 @@ describe("DNSTLDResolver", () => { name: newName, addresses: [{ coinType: COIN_TYPE_ETH, value: testAddress }], texts: [{ key: "url", value: testURL }], + datas: [{ key: "abc", value: testData }], } as const satisfies KnownProfile; - await F.mainnetV2.setupName({ + await F.v2.setupName({ name: newName, resolverAddress: F.ssResolver.address, }); diff --git a/contracts/test/integration/dns/ExtendedDNSResolver_53f64de872aad627467a34836be1e2b63713a438.json b/contracts/test/integration/dns/ExtendedDNSResolver_53f64de872aad627467a34836be1e2b63713a438.json deleted file mode 100755 index c24a5cc29..000000000 --- a/contracts/test/integration/dns/ExtendedDNSResolver_53f64de872aad627467a34836be1e2b63713a438.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "origin": { - "deployment": "https://github.com/ensdomains/ens-contracts/blob/53f64de872aad627467a34836be1e2b63713a438/deployments/mainnet/ExtendedDNSResolver.json", - "explorer": "https://etherscan.io/address/0x238A8F792dFA6033814B18618aD4100654aeef01#code" - }, - "address": "0x238A8F792dFA6033814B18618aD4100654aeef01", - "abi": [ - { - "inputs": [], - "name": "InvalidAddressFormat", - "type": "error" - }, - { - "inputs": [], - "name": "NotImplemented", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "context", - "type": "bytes" - } - ], - "name": "resolve", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "transactionHash": "0x49894a0ebf1294f19adad02ff24b181f50073c00cc19dac085c43b9de1363650", - "receipt": { - "to": null, - "from": "0x0904Dac3347eA47d208F3Fd67402D039a3b99859", - "contractAddress": "0x238A8F792dFA6033814B18618aD4100654aeef01", - "transactionIndex": 23, - "gasUsed": "422726", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x478d0a21285cee90daa3c2144252894733be7877f9f94ef110aa576cd1c9b715", - "transactionHash": "0x49894a0ebf1294f19adad02ff24b181f50073c00cc19dac085c43b9de1363650", - "logs": [], - "blockNumber": 19020789, - "cumulativeGasUsed": "3404020", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "dd9e022689821cffaeb04b9ddbda87ae", - "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"InvalidAddressFormat\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotImplemented\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"resolve\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/resolvers/profiles/ExtendedDNSResolver.sol\":\"ExtendedDNSResolver\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1200},\"remappings\":[]},\"sources\":{\"@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\"},\"contracts/resolvers/profiles/ExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"../../resolvers/profiles/IExtendedDNSResolver.sol\\\";\\nimport \\\"../../resolvers/profiles/IAddressResolver.sol\\\";\\nimport \\\"../../resolvers/profiles/IAddrResolver.sol\\\";\\nimport \\\"../../utils/HexUtils.sol\\\";\\n\\ncontract ExtendedDNSResolver is IExtendedDNSResolver, IERC165 {\\n using HexUtils for *;\\n\\n uint256 private constant COIN_TYPE_ETH = 60;\\n\\n error NotImplemented();\\n error InvalidAddressFormat();\\n\\n function supportsInterface(\\n bytes4 interfaceId\\n ) external view virtual override returns (bool) {\\n return interfaceId == type(IExtendedDNSResolver).interfaceId;\\n }\\n\\n function resolve(\\n bytes calldata /* name */,\\n bytes calldata data,\\n bytes calldata context\\n ) external pure override returns (bytes memory) {\\n bytes4 selector = bytes4(data);\\n if (\\n selector == IAddrResolver.addr.selector ||\\n selector == IAddressResolver.addr.selector\\n ) {\\n if (selector == IAddressResolver.addr.selector) {\\n (, uint256 coinType) = abi.decode(data[4:], (bytes32, uint256));\\n if (coinType != COIN_TYPE_ETH) return abi.encode(\\\"\\\");\\n }\\n (address record, bool valid) = context.hexToAddress(\\n 2,\\n context.length\\n );\\n if (!valid) revert InvalidAddressFormat();\\n return abi.encode(record);\\n }\\n revert NotImplemented();\\n }\\n}\\n\",\"keccak256\":\"0xe49059d038b1e57513359d5fc05f44e7697bd0d1ccb5a979173e2cac429756ed\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IAddrResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/**\\n * Interface for the legacy (ETH-only) addr function.\\n */\\ninterface IAddrResolver {\\n event AddrChanged(bytes32 indexed node, address a);\\n\\n /**\\n * Returns the address associated with an ENS node.\\n * @param node The ENS node to query.\\n * @return The associated address.\\n */\\n function addr(bytes32 node) external view returns (address payable);\\n}\\n\",\"keccak256\":\"0x2ad7f2fc60ebe0f93745fe70247f6a854f66af732483fda2a3c5e055614445e8\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IAddressResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.4;\\n\\n/**\\n * Interface for the new (multicoin) addr function.\\n */\\ninterface IAddressResolver {\\n event AddressChanged(\\n bytes32 indexed node,\\n uint256 coinType,\\n bytes newAddress\\n );\\n\\n function addr(\\n bytes32 node,\\n uint256 coinType\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x411447c1e90c51e09702815a85ec725ffbbe37cf96e8cc4d2a8bd4ad8a59d73e\",\"license\":\"MIT\"},\"contracts/resolvers/profiles/IExtendedDNSResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IExtendedDNSResolver {\\n function resolve(\\n bytes memory name,\\n bytes memory data,\\n bytes memory context\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x541f8799c34ff9e7035d09f06ae0f0f8a16b6065e9b60a15670b957321630f72\",\"license\":\"MIT\"},\"contracts/utils/HexUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\nlibrary HexUtils {\\n /**\\n * @dev Attempts to parse bytes32 from a hex string\\n * @param str The string to parse\\n * @param idx The offset to start parsing at\\n * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\\n */\\n function hexStringToBytes32(\\n bytes memory str,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal pure returns (bytes32 r, bool valid) {\\n uint256 hexLength = lastIdx - idx;\\n if ((hexLength != 64 && hexLength != 40) || hexLength % 2 == 1) {\\n revert(\\\"Invalid string length\\\");\\n }\\n valid = true;\\n assembly {\\n // check that the index to read to is not past the end of the string\\n if gt(lastIdx, mload(str)) {\\n revert(0, 0)\\n }\\n\\n function getHex(c) -> ascii {\\n // chars 48-57: 0-9\\n if and(gt(c, 47), lt(c, 58)) {\\n ascii := sub(c, 48)\\n leave\\n }\\n // chars 65-70: A-F\\n if and(gt(c, 64), lt(c, 71)) {\\n ascii := add(sub(c, 65), 10)\\n leave\\n }\\n // chars 97-102: a-f\\n if and(gt(c, 96), lt(c, 103)) {\\n ascii := add(sub(c, 97), 10)\\n leave\\n }\\n // invalid char\\n ascii := 0xff\\n }\\n\\n let ptr := add(str, 32)\\n for {\\n let i := idx\\n } lt(i, lastIdx) {\\n i := add(i, 2)\\n } {\\n let byte1 := getHex(byte(0, mload(add(ptr, i))))\\n let byte2 := getHex(byte(0, mload(add(ptr, add(i, 1)))))\\n // if either byte is invalid, set invalid and break loop\\n if or(eq(byte1, 0xff), eq(byte2, 0xff)) {\\n valid := false\\n break\\n }\\n let combined := or(shl(4, byte1), byte2)\\n r := or(shl(8, r), combined)\\n }\\n }\\n }\\n\\n /**\\n * @dev Attempts to parse an address from a hex string\\n * @param str The string to parse\\n * @param idx The offset to start parsing at\\n * @param lastIdx The (exclusive) last index in `str` to consider. Use `str.length` to scan the whole string.\\n */\\n function hexToAddress(\\n bytes memory str,\\n uint256 idx,\\n uint256 lastIdx\\n ) internal pure returns (address, bool) {\\n if (lastIdx - idx < 40) return (address(0x0), false);\\n (bytes32 r, bool valid) = hexStringToBytes32(str, idx, lastIdx);\\n return (address(uint160(uint256(r))), valid);\\n }\\n}\\n\",\"keccak256\":\"0x4a8a9c72d6f3effb80b310faa6dc273e7adbc3b949df9c7a42e290e5b13519f3\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506106ba806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806301ffc9a71461003b5780638ef98a7e1461008d575b600080fd5b61007861004936600461045d565b6001600160e01b0319167f8ef98a7e000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b6100a061009b3660046104d7565b6100ad565b6040516100849190610571565b606060006100bb85876105bf565b90506001600160e01b031981167f3b3b57de00000000000000000000000000000000000000000000000000000000148061011e57506001600160e01b031981167ff1cb7e0600000000000000000000000000000000000000000000000000000000145b15610271577f0e3481fa000000000000000000000000000000000000000000000000000000006001600160e01b03198216016101b0576000610163866004818a6105ef565b8101906101709190610619565b915050603c81146101ae5760405160200161019690602080825260009082015260400190565b604051602081830303815290604052925050506102a3565b505b6000806101fc60028787905088888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102ad9050565b9150915080610237576040517fc9e47ee500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff841660208201520160405160208183030381529060405293505050506102a3565b6040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9695505050505050565b60008060286102bc858561063b565b10156102cd575060009050806102e3565b6000806102db8787876102eb565b909450925050505b935093915050565b600080806102f9858561063b565b90508060401415801561030d575080602814155b80610322575061031e600282610662565b6001145b1561038d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c696420737472696e67206c656e6774680000000000000000000000604482015260640160405180910390fd5b60019150855184111561039f57600080fd5b6103f0565b6000603a8210602f831116156103bc5750602f190190565b604782106040831116156103d257506036190190565b606782106060831116156103e857506056190190565b5060ff919050565b60208601855b858110156104525761040d8183015160001a6103a4565b61041f6001830184015160001a6103a4565b60ff811460ff8314171561043857600095505050610452565b60049190911b1760089590951b94909417936002016103f6565b505050935093915050565b60006020828403121561046f57600080fd5b81356001600160e01b03198116811461048757600080fd5b9392505050565b60008083601f8401126104a057600080fd5b50813567ffffffffffffffff8111156104b857600080fd5b6020830191508360208285010111156104d057600080fd5b9250929050565b600080600080600080606087890312156104f057600080fd5b863567ffffffffffffffff8082111561050857600080fd5b6105148a838b0161048e565b9098509650602089013591508082111561052d57600080fd5b6105398a838b0161048e565b9096509450604089013591508082111561055257600080fd5b5061055f89828a0161048e565b979a9699509497509295939492505050565b600060208083528351808285015260005b8181101561059e57858101830151858201604001528201610582565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160e01b031981358181169160048510156105e75780818660040360031b1b83161692505b505092915050565b600080858511156105ff57600080fd5b8386111561060c57600080fd5b5050820193919092039150565b6000806040838503121561062c57600080fd5b50508035926020909101359150565b8181038181111561065c57634e487b7160e01b600052601160045260246000fd5b92915050565b60008261067f57634e487b7160e01b600052601260045260246000fd5b50069056fea264697066735822122048092a531a20e262efce54779239b612bcaff145bb48f1dae6c4641143e50c4164736f6c63430008110033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806301ffc9a71461003b5780638ef98a7e1461008d575b600080fd5b61007861004936600461045d565b6001600160e01b0319167f8ef98a7e000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b6100a061009b3660046104d7565b6100ad565b6040516100849190610571565b606060006100bb85876105bf565b90506001600160e01b031981167f3b3b57de00000000000000000000000000000000000000000000000000000000148061011e57506001600160e01b031981167ff1cb7e0600000000000000000000000000000000000000000000000000000000145b15610271577f0e3481fa000000000000000000000000000000000000000000000000000000006001600160e01b03198216016101b0576000610163866004818a6105ef565b8101906101709190610619565b915050603c81146101ae5760405160200161019690602080825260009082015260400190565b604051602081830303815290604052925050506102a3565b505b6000806101fc60028787905088888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294939250506102ad9050565b9150915080610237576040517fc9e47ee500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff841660208201520160405160208183030381529060405293505050506102a3565b6040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9695505050505050565b60008060286102bc858561063b565b10156102cd575060009050806102e3565b6000806102db8787876102eb565b909450925050505b935093915050565b600080806102f9858561063b565b90508060401415801561030d575080602814155b80610322575061031e600282610662565b6001145b1561038d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f496e76616c696420737472696e67206c656e6774680000000000000000000000604482015260640160405180910390fd5b60019150855184111561039f57600080fd5b6103f0565b6000603a8210602f831116156103bc5750602f190190565b604782106040831116156103d257506036190190565b606782106060831116156103e857506056190190565b5060ff919050565b60208601855b858110156104525761040d8183015160001a6103a4565b61041f6001830184015160001a6103a4565b60ff811460ff8314171561043857600095505050610452565b60049190911b1760089590951b94909417936002016103f6565b505050935093915050565b60006020828403121561046f57600080fd5b81356001600160e01b03198116811461048757600080fd5b9392505050565b60008083601f8401126104a057600080fd5b50813567ffffffffffffffff8111156104b857600080fd5b6020830191508360208285010111156104d057600080fd5b9250929050565b600080600080600080606087890312156104f057600080fd5b863567ffffffffffffffff8082111561050857600080fd5b6105148a838b0161048e565b9098509650602089013591508082111561052d57600080fd5b6105398a838b0161048e565b9096509450604089013591508082111561055257600080fd5b5061055f89828a0161048e565b979a9699509497509295939492505050565b600060208083528351808285015260005b8181101561059e57858101830151858201604001528201610582565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160e01b031981358181169160048510156105e75780818660040360031b1b83161692505b505092915050565b600080858511156105ff57600080fd5b8386111561060c57600080fd5b5050820193919092039150565b6000806040838503121561062c57600080fd5b50508035926020909101359150565b8181038181111561065c57634e487b7160e01b600052601160045260246000fd5b92915050565b60008261067f57634e487b7160e01b600052601260045260246000fd5b50069056fea264697066735822122048092a531a20e262efce54779239b612bcaff145bb48f1dae6c4641143e50c4164736f6c63430008110033", - "devdoc": { - "kind": "dev", - "methods": { - "supportsInterface(bytes4)": { - "details": "Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created. This function call must use less than 30 000 gas." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} diff --git a/contracts/test/integration/dns/mainnet.ts b/contracts/test/integration/dns/mainnet.ts index 7377af1aa..00326e47d 100644 --- a/contracts/test/integration/dns/mainnet.ts +++ b/contracts/test/integration/dns/mainnet.ts @@ -1,4 +1,5 @@ -import { COIN_TYPE_ETH, type KnownProfile } from "../../utils/resolutions.js"; +import type { KnownProfile } from "../../utils/resolutions.js"; +import { COIN_TYPE_ETH } from "../../utils/utils.js"; export const KNOWN_DNS: KnownProfile[] = [ { diff --git a/contracts/test/integration/fixtures/deployUniversalSigValidator.ts b/contracts/test/integration/fixtures/deployUniversalSigValidator.ts new file mode 100644 index 000000000..d4d120435 --- /dev/null +++ b/contracts/test/integration/fixtures/deployUniversalSigValidator.ts @@ -0,0 +1,56 @@ +import type { NetworkConnection } from 'hardhat/types/network' + +const ddpSigner = '0x3fab184622dc19b6109349b94811493bf2a45362' +const ddpAddress = '0x4e59b44847b379578588920ca78fbf26c0b4956c' + +export async function deployUniversalSigValidator( + network: NetworkConnection, +) { + const testClient = await network.viem.getTestClient() + const publicClient = await network.viem.getPublicClient() + const [walletClient] = await network.viem.getWalletClients() + + // Get the expected address - either hardcoded or calculated + const expectedAddress = '0x164af34fAF9879394370C7f09064127C043A35E9' + + // deploy deterministic deployer proxy + await testClient.setBalance({ + address: ddpSigner, + value: 10n ** 16n, + }) + const ddpBytecode = await publicClient.getBytecode({ + address: ddpAddress, + }) + if (!ddpBytecode) { + const deterministicDeployerDeployHash = + await publicClient.sendRawTransaction({ + serializedTransaction: + '0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222', + }) + await publicClient.waitForTransactionReceipt({ + hash: deterministicDeployerDeployHash, + }) + } + + // Check if USV is already deployed at the calculated address + const usvCurrentBytecode = await publicClient.getCode({ + address: expectedAddress, + }) + if (!usvCurrentBytecode) { + const universalSigValidatorDeployHash = await walletClient.sendTransaction({ + to: ddpAddress, + // something in config is causing a different deployment with bytecode, i assume metadata related + // replaced with hardcoded bytecode for now + data: '0x00000000000000000000000000000000000000000000000000000000000000006080604052348015600f57600080fd5b50610d488061001f6000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806316d43401146100465780638f0684301461006d57806398ef1ed814610080575b600080fd5b61005961005436600461085e565b610093565b604051901515815260200160405180910390f35b61005961007b3660046108d2565b6105f8565b61005961008e3660046108d2565b61068e565b600073ffffffffffffffffffffffffffffffffffffffff86163b6060826020861080159061010157507f649264926492649264926492649264926492649264926492649264926492649287876100ea60208261092e565b6100f6928a929061096e565b6100ff91610998565b145b90508015610200576000606088828961011b60208261092e565b926101289392919061096e565b8101906101359190610acf565b9550909250905060008590036101f9576000808373ffffffffffffffffffffffffffffffffffffffff168360405161016d9190610b6e565b6000604051808303816000865af19150503d80600081146101aa576040519150601f19603f3d011682016040523d82523d6000602084013e6101af565b606091505b5091509150816101f657806040517f9d0d6e2d0000000000000000000000000000000000000000000000000000000081526004016101ed9190610bd4565b60405180910390fd5b50505b505061023a565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b80806102465750600083115b156103d3576040517f1626ba7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a1690631626ba7e9061029f908b908690600401610bee565b602060405180830381865afa9250505080156102f6575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526102f391810190610c07565b60015b61035e573d808015610324576040519150601f19603f3d011682016040523d82523d6000602084013e610329565b606091505b50806040517f6f2a95990000000000000000000000000000000000000000000000000000000081526004016101ed9190610bd4565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f1626ba7e0000000000000000000000000000000000000000000000000000000014841580156103ae5750825b80156103b8575086155b156103c757806000526001601ffd5b94506105ef9350505050565b60418614610463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5369676e617475726556616c696461746f72237265636f7665725369676e657260448201527f3a20696e76616c6964207369676e6174757265206c656e67746800000000000060648201526084016101ed565b6000610472602082898b61096e565b61047b91610998565b9050600061048d604060208a8c61096e565b61049691610998565b90506000898960408181106104ad576104ad610c49565b919091013560f81c915050601b81148015906104cd57508060ff16601c14155b1561055a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5369676e617475726556616c696461746f723a20696e76616c6964207369676e60448201527f617475726520762076616c75650000000000000000000000000000000000000060648201526084016101ed565b6040805160008152602081018083528d905260ff831691810191909152606081018490526080810183905273ffffffffffffffffffffffffffffffffffffffff8d169060019060a0016020604051602081039080840390855afa1580156105c5573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff161496505050505050505b95945050505050565b6040517f16d4340100000000000000000000000000000000000000000000000000000000815260009030906316d4340190610640908890889088908890600190600401610c78565b6020604051808303816000875af115801561065f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106839190610cf5565b90505b949350505050565b6040517f16d4340100000000000000000000000000000000000000000000000000000000815260009030906316d43401906106d59088908890889088908890600401610c78565b6020604051808303816000875af192505050801561072e575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261072b91810190610cf5565b60015b6107db573d80801561075c576040519150601f19603f3d011682016040523d82523d6000602084013e610761565b606091505b50805160018190036107d4578160008151811061078057610780610c49565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f0100000000000000000000000000000000000000000000000000000000000000149250610686915050565b8060208301fd5b9050610686565b73ffffffffffffffffffffffffffffffffffffffff8116811461080457600080fd5b50565b60008083601f84011261081957600080fd5b50813567ffffffffffffffff81111561083157600080fd5b60208301915083602082850101111561084957600080fd5b9250929050565b801515811461080457600080fd5b60008060008060006080868803121561087657600080fd5b8535610881816107e2565b945060208601359350604086013567ffffffffffffffff8111156108a457600080fd5b6108b088828901610807565b90945092505060608601356108c481610850565b809150509295509295909350565b600080600080606085870312156108e857600080fd5b84356108f3816107e2565b935060208501359250604085013567ffffffffffffffff81111561091657600080fd5b61092287828801610807565b95989497509550505050565b81810381811115610968577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b6000808585111561097e57600080fd5b8386111561098b57600080fd5b5050820193919092039150565b80356020831015610968577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610a1457600080fd5b813567ffffffffffffffff811115610a2e57610a2e6109d4565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff82111715610a9a57610a9a6109d4565b604052818152838201602001851015610ab257600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215610ae457600080fd5b8335610aef816107e2565b9250602084013567ffffffffffffffff811115610b0b57600080fd5b610b1786828701610a03565b925050604084013567ffffffffffffffff811115610b3457600080fd5b610b4086828701610a03565b9150509250925092565b60005b83811015610b65578181015183820152602001610b4d565b50506000910152565b60008251610b80818460208701610b4a565b9190910192915050565b60008151808452610ba2816020860160208601610b4a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610be76020830184610b8a565b9392505050565b8281526040602082015260006106866040830184610b8a565b600060208284031215610c1957600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114610be757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015260806040820152826080820152828460a0830137600060a08483010152600060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116830101905082151560608301529695505050505050565b600060208284031215610d0757600080fd5b8151610be78161085056fea2646970667358221220fa1669652244780c8dcf7823a819ca1aa2abb64af0cf4d7adedb2339d4e907d964736f6c634300081a0033', + }) + await publicClient.waitForTransactionReceipt({ + hash: universalSigValidatorDeployHash, + }) + console.log(`UniversalSigValidator deployed at: ${expectedAddress}`) + } + + const usvActualBytecode = await publicClient.getBytecode({ + address: expectedAddress, + }) + if (!usvActualBytecode) throw new Error('UniversalSigValidator not deployed') +} diff --git a/contracts/test/integration/fixtures/deployV1Fixture.ts b/contracts/test/integration/fixtures/deployV1Fixture.ts index 21c86d679..b79d7b939 100755 --- a/contracts/test/integration/fixtures/deployV1Fixture.ts +++ b/contracts/test/integration/fixtures/deployV1Fixture.ts @@ -8,7 +8,10 @@ import { zeroAddress, } from "viem"; import { splitName } from "../../utils/utils.js"; -import { LOCAL_BATCH_GATEWAY_URL } from "../../../script/deploy-constants.js"; +import { + LOCAL_BATCH_GATEWAY_URL, + MAX_EXPIRY, +} from "../../../script/deploy-constants.js"; export async function deployV1Fixture( network: NetworkConnection, @@ -19,7 +22,7 @@ export async function deployV1Fixture( }); const [walletClient] = await network.viem.getWalletClients(); const ensRegistry = await network.viem.deployContract("ENSRegistry"); - const ethRegistrar = await network.viem.deployContract( + const baseRegistrar = await network.viem.deployContract( "BaseRegistrarImplementation", [ensRegistry.address, namehash("eth")], ); @@ -57,23 +60,24 @@ export async function deployV1Fixture( ], { client: { public: publicClient } }, ); - await ethRegistrar.write.addController([walletClient.account.address]); + await baseRegistrar.write.addController([walletClient.account.address]); + const ownedResolver = await network.viem.deployContract("OwnedResolver"); await ensRegistry.write.setSubnodeRecord([ namehash(""), labelhash("eth"), walletClient.account.address, - zeroAddress, + ownedResolver.address, 0n, ]); - await publicResolver.write.setAddr([namehash("eth"), ethRegistrar.address]); + await ownedResolver.write.setAddr([namehash("eth"), baseRegistrar.address]); await ensRegistry.write.setSubnodeOwner([ namehash(""), labelhash("eth"), - ethRegistrar.address, + baseRegistrar.address, ]); const nameWrapper = await network.viem.deployContract("NameWrapper", [ ensRegistry.address, - ethRegistrar.address, + baseRegistrar.address, zeroAddress, // IMetadataService ]); return { @@ -82,8 +86,9 @@ export async function deployV1Fixture( walletClient, ensRegistry, reverseRegistrar, - ethRegistrar, + baseRegistrar, publicResolver, + ownedResolver, batchGatewayProvider, universalResolver, nameWrapper, @@ -104,10 +109,10 @@ export async function deployV1Fixture( const labels = splitName(name); let i = labels.length; if (name.endsWith(".eth")) { - await ethRegistrar.write.register([ + await baseRegistrar.write.register([ BigInt(labelhash(labels[(i -= 2)])), account.address, - (1n << 64n) - 1n, + MAX_EXPIRY, ]); } while (i > 0) { diff --git a/contracts/test/integration/fixtures/deployV2Fixture.ts b/contracts/test/integration/fixtures/deployV2Fixture.ts index 40e1321d8..669c63e7f 100644 --- a/contracts/test/integration/fixtures/deployV2Fixture.ts +++ b/contracts/test/integration/fixtures/deployV2Fixture.ts @@ -1,14 +1,14 @@ import type { NetworkConnection } from "hardhat/types/network"; -import { type Address, zeroAddress } from "viem"; +import { type Address, encodeFunctionData, type Hex, zeroAddress } from "viem"; import { + DEPLOYMENT_ROLES, LOCAL_BATCH_GATEWAY_URL, + MAX_EXPIRY, ROLES, } from "../../../script/deploy-constants.js"; import { splitName, idFromLabel } from "../../utils/utils.js"; import { deployVerifiableProxy } from "./deployVerifiableProxy.js"; -export const MAX_EXPIRY = (1n << 64n) - 1n; - export async function deployV2Fixture( network: NetworkConnection, enableCcipRead = false, @@ -17,14 +17,37 @@ export async function deployV2Fixture( ccipRead: enableCcipRead ? undefined : false, }); const [walletClient] = await network.viem.getWalletClients(); - const hcaFactory = await network.viem.deployContract("MockHCAFactoryBasic"); + const contractNamerImpl = await network.viem.deployContract("ContractNamer"); + const contractNamerProxy = await network.viem.deployContract("ERC1967Proxy", [ + contractNamerImpl.address, + encodeFunctionData({ + abi: contractNamerImpl.abi, + functionName: "initialize", + args: [walletClient.account.address], + }), + ]); + const contractNamer = await network.viem.getContractAt( + "ContractNamer", + contractNamerProxy.address, + ); + const labelStore = await network.viem.deployContract("LabelStore", [ + contractNamer.address, + ]); const rootRegistry = await network.viem.deployContract( "PermissionedRegistry", - [hcaFactory.address, zeroAddress, walletClient.account.address, ROLES.ALL], + [ + labelStore.address, + walletClient.account.address, + DEPLOYMENT_ROLES.ROOT_REGISTRY_ROOT, + ], ); const ethRegistry = await network.viem.deployContract( "PermissionedRegistry", - [hcaFactory.address, zeroAddress, walletClient.account.address, ROLES.ALL], + [ + labelStore.address, + walletClient.account.address, + DEPLOYMENT_ROLES.ETH_REGISTRY_ROOT, + ], ); const batchGatewayProvider = await network.viem.deployContract( "GatewayProvider", @@ -32,7 +55,7 @@ export async function deployV2Fixture( ); const universalResolver = await network.viem.deployContract( "UniversalResolverV2", - [rootRegistry.address, batchGatewayProvider.address], + [rootRegistry.address, batchGatewayProvider.address, contractNamer.address], { client: { public: publicClient } }, ); await rootRegistry.write.register([ @@ -40,20 +63,28 @@ export async function deployV2Fixture( walletClient.account.address, ethRegistry.address, zeroAddress, - ROLES.ALL, + DEPLOYMENT_ROLES.ETH_TOKEN, MAX_EXPIRY, ]); + await ethRegistry.write.setParent([rootRegistry.address, "eth"]); + + // Grant REGISTRAR so setupName can register subdomains under .eth + await ethRegistry.write.grantRootRoles([ + ROLES.REGISTRY.REGISTRAR, + walletClient.account.address, + ]); const verifiableFactory = await network.viem.deployContract("VerifiableFactory"); const PermissionedResolverImpl = await network.viem.deployContract( "PermissionedResolver", - [hcaFactory.address], + [contractNamer.address], ); return { network, publicClient, walletClient, - hcaFactory, + contractNamer, + labelStore, rootRegistry, ethRegistry, batchGatewayProvider, @@ -64,10 +95,12 @@ export async function deployV2Fixture( async function deployPermissionedResolver({ owner = walletClient.account.address, roles = ROLES.ALL, + setters = [], salt = idFromLabel(new Date().toISOString()), }: { owner?: Address; roles?: bigint; + setters?: Hex[]; salt?: bigint; } = {}) { return deployVerifiableProxy({ @@ -76,20 +109,18 @@ export async function deployV2Fixture( implAddress: PermissionedResolverImpl.address, abi: PermissionedResolverImpl.abi, functionName: "initialize", - args: [walletClient.account.address, roles], + args: [walletClient.account.address, roles, setters], salt, }); } // creates registries up to the parent name // if exact, exactRegistry is setup - // if no resolverAddress, dedicatedResolver is deployed async function setupName({ name, owner = walletClient.account.address, expiry = MAX_EXPIRY, roles = ROLES.ALL, resolverAddress, - metadataAddress = zeroAddress, exact, }: { name: string; @@ -97,7 +128,6 @@ export async function deployV2Fixture( expiry?: bigint; roles?: bigint; resolverAddress?: Address; - metadataAddress?: Address; exact?: exact_; }) { const labels = splitName(name); @@ -115,12 +145,7 @@ export async function deployV2Fixture( // registry does not exist, create it const registry = await network.viem.deployContract( "PermissionedRegistry", - [ - hcaFactory.address, - metadataAddress, - walletClient.account.address, - roles, - ], + [labelStore.address, walletClient.account.address, roles], ); registryAddress = registry.address; if (exists) { diff --git a/contracts/test/integration/fixtures/deployVerifiableProxy.ts b/contracts/test/integration/fixtures/deployVerifiableProxy.ts index 21fb73451..48061be1e 100755 --- a/contracts/test/integration/fixtures/deployVerifiableProxy.ts +++ b/contracts/test/integration/fixtures/deployVerifiableProxy.ts @@ -8,7 +8,6 @@ import { encodeFunctionData, getContract, getContractAddress, - type Hex, keccak256, parseAbi, parseEventLogs, @@ -75,14 +74,14 @@ export async function deployVerifiableProxy< }); } -export async function computeVerifiableProxyAddress({ +export function computeVerifiableProxyAddress({ factoryAddress, - bytecode, + proxyLogic, deployer, salt, }: { factoryAddress: Address; - bytecode: Hex; + proxyLogic: Address; deployer: Address; salt: bigint; }) { @@ -92,14 +91,14 @@ export async function computeVerifiableProxyAddress({ [deployer, salt], ), ); + const bytecode = concat([ + "0x3d604d80600a3d3981f3363d3d373d3d3d363d73", + proxyLogic, + "0x5af43d82803e903d91602b57fd5bf3", + outerSalt, + ]); return getContractAddress({ - bytecode: concat([ - bytecode, - encodeAbiParameters( - [{ type: "address" }, { type: "bytes32" }], - [factoryAddress, outerSalt], - ), - ]), + bytecode, from: factoryAddress, opcode: "CREATE2", salt: outerSalt, diff --git a/contracts/test/integration/l2/L2ReverseRegistrar.test.ts b/contracts/test/integration/l2/L2ReverseRegistrar.test.ts new file mode 100644 index 000000000..ae46c402a --- /dev/null +++ b/contracts/test/integration/l2/L2ReverseRegistrar.test.ts @@ -0,0 +1,1786 @@ +import { shouldSupportInterfaces } from "@ensdomains/hardhat-chai-matchers-viem/behaviour"; +import hre from "hardhat"; +import { + decodeFunctionResult, + encodeFunctionData, + getAddress, + namehash, + serializeErc6492Signature, + type Address, +} from "viem"; +import { optimism } from "viem/chains"; +import { describe, expect, it } from "vitest"; +import { dnsEncodeName } from "../../utils/utils.ts"; +import { deployUniversalSigValidator } from "../fixtures/deployUniversalSigValidator.ts"; + +const connection = await hre.network.connect(); + +// Chain ID for Optimism - used to construct coin type +const OPTIMISM_CHAIN_ID = BigInt(optimism.id); +// Coin type format: 0x80000000 | chainId (see ENSIP-11) +const COIN_TYPE = 0x80000000n | OPTIMISM_CHAIN_ID; +// Label is the hex representation of the coin type +const COIN_TYPE_LABEL = COIN_TYPE.toString(16); +// `8000000a.reverse` +const PARENT_NAMESPACE = `${COIN_TYPE_LABEL}.reverse`; + +/** + * Converts a Unix timestamp to ISO 8601 format (matching LibISO8601.sol) + * Format: YYYY-MM-DDTHH:MM:SSZ + */ +function timestampToISO8601(timestamp: bigint): string { + const date = new Date(Number(timestamp) * 1000); + return date.toISOString().replace(".000Z", "Z"); +} + +/** + * Creates the plaintext message for setNameForAddrWithSignature + * This must match the format in L2ReverseRegistrar._createClaimMessageHash (owner == address(0)) + */ +function createNameForAddrMessage({ + name, + address, + chainIds, + signedAt, +}: { + name: string; + address: Address; + chainIds: bigint[]; + signedAt: bigint; +}): string { + const chainIdsString = chainIds.map((id) => id.toString()).join(", "); + const signedAtString = timestampToISO8601(signedAt); + + return `You are setting your ENS primary name to: +${name} + +Address: ${getAddress(address)} +Chains: ${chainIdsString} +Signed At: ${signedAtString}`; +} + +/** + * Creates the plaintext message for setNameForContractWithSignature + * This must match the format in L2ReverseRegistrar._createClaimMessageHash (owner != address(0)) + */ +function createNameForOwnableMessage({ + name, + contractAddress, + owner, + chainIds, + signedAt, +}: { + name: string; + contractAddress: Address; + owner: Address; + chainIds: bigint[]; + signedAt: bigint; +}): string { + const chainIdsString = chainIds.map((id) => id.toString()).join(", "); + const signedAtString = timestampToISO8601(signedAt); + + return `You are setting the ENS primary name for a contract you own to: +${name} + +Contract Address: ${getAddress(contractAddress)} +Owner: ${getAddress(owner)} +Chains: ${chainIdsString} +Signed At: ${signedAtString}`; +} + +async function fixture() { + const accounts = await connection.viem + .getWalletClients() + .then((clients) => clients.map((c) => c.account)); + + await deployUniversalSigValidator(connection); + + const l2ReverseRegistrar = await connection.viem.deployContract( + // Use fully qualified name to ensure the correct contract is deployed + "src/reverse-registrar/L2ReverseRegistrar.sol:L2ReverseRegistrar", + [OPTIMISM_CHAIN_ID, COIN_TYPE_LABEL], + ); + const mockSmartContractAccount = await connection.viem.deployContract( + "MockSmartContractWallet", + [accounts[0].address], + ); + const mockOwnableSca = await connection.viem.deployContract("MockOwnable", [ + mockSmartContractAccount.address, + ]); + const mockErc6492WalletFactory = await connection.viem.deployContract( + "MockERC6492WalletFactory", + ); + const mockOwnableEoa = await connection.viem.deployContract("MockOwnable", [ + accounts[0].address, + ]); + + /** + * Helper function to get the name for an address + * Since v2 uses name(bytes32 node) instead of nameForAddr(address) + */ + async function getNameForAddr(addr: Address): Promise { + const node = namehash(`${addr.slice(2).toLowerCase()}.${PARENT_NAMESPACE}`); + return l2ReverseRegistrar.read.name([node]); + } + + return { + l2ReverseRegistrar, + mockSmartContractAccount, + mockErc6492WalletFactory, + mockOwnableSca, + mockOwnableEoa, + accounts, + getNameForAddr, + }; +} + +const loadFixture = async () => connection.networkHelpers.loadFixture(fixture); + +describe("L2ReverseRegistrar", () => { + shouldSupportInterfaces({ + contract: () => + loadFixture().then(({ l2ReverseRegistrar }) => l2ReverseRegistrar), + interfaces: [ + "src/reverse-registrar/interfaces/IL2ReverseRegistrar.sol:IL2ReverseRegistrar", + "IExtendedResolver", + "INameResolver", + "IERC165", + ], + }); + + it("should deploy the contract", async () => { + const { l2ReverseRegistrar } = await loadFixture(); + + expect(l2ReverseRegistrar.address).not.toBeUndefined(); + }); + + it("should have correct CHAIN_ID set", async () => { + const { l2ReverseRegistrar } = await loadFixture(); + + const chainId = await l2ReverseRegistrar.read.CHAIN_ID(); + expect(chainId).toStrictEqual(OPTIMISM_CHAIN_ID); + }); + + describe("setName", () => { + async function setNameFixture() { + const initial = await loadFixture(); + + const name = "myname.eth"; + + return { + ...initial, + name, + }; + } + + it("should set the name record for the calling account", async () => { + const { l2ReverseRegistrar, name, accounts, getNameForAddr } = + await connection.networkHelpers.loadFixture(setNameFixture); + + await l2ReverseRegistrar.write.setName([name]); + + await expect(getNameForAddr(accounts[0].address)).resolves.toStrictEqual( + name, + ); + }); + + it("event NameChanged is emitted", async () => { + const { l2ReverseRegistrar, name } = + await connection.networkHelpers.loadFixture(setNameFixture); + + await expect(l2ReverseRegistrar.write.setName([name])).toEmitEvent( + "NameChanged", + ); + }); + + it("can update the name record", async () => { + const { l2ReverseRegistrar, name, accounts, getNameForAddr } = + await connection.networkHelpers.loadFixture(setNameFixture); + + await l2ReverseRegistrar.write.setName([name]); + const newName = "newname.eth"; + await l2ReverseRegistrar.write.setName([newName]); + + await expect(getNameForAddr(accounts[0].address)).resolves.toStrictEqual( + newName, + ); + }); + + it("can set the name to an empty string", async () => { + const { l2ReverseRegistrar, name, accounts, getNameForAddr } = + await connection.networkHelpers.loadFixture(setNameFixture); + + await l2ReverseRegistrar.write.setName([name]); + await l2ReverseRegistrar.write.setName([""]); + + await expect(getNameForAddr(accounts[0].address)).resolves.toStrictEqual( + "", + ); + }); + }); + + describe("setNameForAddr", () => { + async function setNameForAddrFixture() { + const initial = await loadFixture(); + + const name = "myname.eth"; + + return { + ...initial, + name, + }; + } + + it("should set the name record for a contract the caller owns", async () => { + const { l2ReverseRegistrar, name, mockOwnableEoa, getNameForAddr } = + await connection.networkHelpers.loadFixture(setNameForAddrFixture); + + await l2ReverseRegistrar.write.setNameForAddr([ + mockOwnableEoa.address, + name, + ]); + + await expect( + getNameForAddr(mockOwnableEoa.address), + ).resolves.toStrictEqual(name); + }); + + it("event NameChanged is emitted", async () => { + const { l2ReverseRegistrar, name, mockOwnableEoa } = + await connection.networkHelpers.loadFixture(setNameForAddrFixture); + + await expect( + l2ReverseRegistrar.write.setNameForAddr([mockOwnableEoa.address, name]), + ).toEmitEvent("NameChanged"); + }); + + it("caller can set their own name", async () => { + const { l2ReverseRegistrar, name, accounts, getNameForAddr } = + await connection.networkHelpers.loadFixture(setNameForAddrFixture); + + await l2ReverseRegistrar.write.setNameForAddr([ + accounts[0].address, + name, + ]); + + await expect(getNameForAddr(accounts[0].address)).resolves.toStrictEqual( + name, + ); + }); + + it("reverts if the caller is not the owner of the target address", async () => { + const { l2ReverseRegistrar, name, accounts, mockOwnableEoa } = + await connection.networkHelpers.loadFixture(setNameForAddrFixture); + + await expect( + l2ReverseRegistrar.write.setNameForAddr( + [mockOwnableEoa.address, name], + { account: accounts[1] }, + ), + ) + .toBeRevertedWithCustomError("UnauthorizedNamer") + .withArgs([getAddress(accounts[1].address)]); + }); + + it("reverts if caller tries to set name for another EOA", async () => { + const { l2ReverseRegistrar, name, accounts } = + await connection.networkHelpers.loadFixture(setNameForAddrFixture); + + await expect( + l2ReverseRegistrar.write.setNameForAddr([accounts[1].address, name]), + ) + .toBeRevertedWithCustomError("UnauthorizedNamer") + .withArgs([getAddress(accounts[0].address)]); + }); + + it("reverts if caller is not owner of the target contract (via Ownable)", async () => { + const { l2ReverseRegistrar, name, accounts, mockOwnableSca } = + await connection.networkHelpers.loadFixture(setNameForAddrFixture); + + // mockOwnableSca is owned by mockSmartContractAccount, not accounts[0] + await expect( + l2ReverseRegistrar.write.setNameForAddr([mockOwnableSca.address, name]), + ) + .toBeRevertedWithCustomError("UnauthorizedNamer") + .withArgs([getAddress(accounts[0].address)]); + }); + }); + + describe("setNameForAddrWithSignature", () => { + async function setNameForAddrWithSignatureFixture() { + const initial = await loadFixture(); + const { l2ReverseRegistrar, accounts } = initial; + + const name = "myname.eth"; + + const publicClient = await connection.viem.getPublicClient(); + const blockTimestamp = await publicClient + .getBlock() + .then((b) => b.timestamp); + const signedAt = blockTimestamp; + + const [walletClient] = await connection.viem.getWalletClients(); + + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + return { + ...initial, + message, + name, + signedAt, + signature, + walletClient, + }; + } + + it("allows an account to sign a message to allow a relayer to claim the address", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + signature, + accounts, + getNameForAddr, + } = await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const claim = { + name, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ).not.toBeReverted(); + + await expect(getNameForAddr(accounts[0].address)).resolves.toStrictEqual( + name, + ); + }); + + it("event NameChanged is emitted", async () => { + const { l2ReverseRegistrar, name, signedAt, signature, accounts } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const claim = { + name, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ).toEmitEvent("NameChanged"); + }); + + it("allows SCA signatures (ERC1271)", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockSmartContractAccount, + walletClient, + getNameForAddr, + } = await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const message = createNameForAddrMessage({ + name, + address: mockSmartContractAccount.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockSmartContractAccount.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ).toEmitEvent("NameChanged"); + + await expect( + getNameForAddr(mockSmartContractAccount.address), + ).resolves.toStrictEqual(name); + }); + + it("allows undeployed SCA signatures (ERC6492)", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockErc6492WalletFactory, + walletClient, + getNameForAddr, + } = await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const predictedAddress = + await mockErc6492WalletFactory.read.predictAddress([ + accounts[0].address, + ]); + + const message = createNameForAddrMessage({ + name, + address: predictedAddress, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const wrappedSignature = serializeErc6492Signature({ + address: mockErc6492WalletFactory.address, + data: encodeFunctionData({ + abi: mockErc6492WalletFactory.abi, + functionName: "createWallet", + args: [accounts[0].address], + }), + signature, + }); + + const claim = { + name, + addr: predictedAddress, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, wrappedSignature], + { account: accounts[1] }, + ), + ).toEmitEvent("NameChanged"); + + await expect(getNameForAddr(predictedAddress)).resolves.toStrictEqual( + name, + ); + }); + + it("reverts if signature parameters do not match", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + // Sign with different name + const message = createNameForAddrMessage({ + name: "different.eth", + address: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, // Original name + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ).toBeRevertedWithCustomError("InvalidSignature"); + }); + + it("reverts if signedAt is in the future", async () => { + const { l2ReverseRegistrar, name, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const publicClient = await connection.viem.getPublicClient(); + const blockTimestamp = await publicClient + .getBlock() + .then((b) => b.timestamp); + const futureTime = blockTimestamp + 3600n; // 1 hour in the future + + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt: futureTime, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt: futureTime, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ).toBeRevertedWithCustomError("SignatureNotValidYet"); + }); + + it("reverts if signedAt is not after inception", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + walletClient, + signature, + } = await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + // First, use the signature to establish an inception + const claim1 = { + name, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim1, signature], + { account: accounts[1] }, + ); + + // Try to use a signature with the same signedAt (should fail) + const newName = "newname.eth"; + const message2 = createNameForAddrMessage({ + name: newName, + address: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature2 = await walletClient.signMessage({ + message: message2, + }); + + const claim2 = { + name: newName, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim2, signature2], + { account: accounts[1] }, + ), + ).toBeRevertedWithCustomError("StaleSignature"); + }); + + it("allows multiple chain IDs in array (must be ascending)", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + walletClient, + getNameForAddr, + } = await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const chainIds = [1n, OPTIMISM_CHAIN_ID, 8453n, 42161n]; // ETH (1), Optimism (10), Base (8453), Arbitrum (42161) - ascending order + + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[0].address, + chainIds, + signedAt, + }; + + await l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ); + + await expect(getNameForAddr(accounts[0].address)).resolves.toStrictEqual( + name, + ); + }); + + it("allows large chain ID array with approx. linear gas scaling", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const getClaimAndSig = async (length: number) => { + const chainIds = Array.from({ length }, (_, i) => BigInt(i) + 1n); + if (length === 1) chainIds[0] = OPTIMISM_CHAIN_ID; + + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[0].address, + chainIds, + signedAt, + }; + + return [claim, signature] as const; + }; + + const amounts = [1, 25, 50, 100, 200, 400, 800, 1600]; + const gasUseds = await Promise.all( + amounts.map(async (length) => { + const [claim, signature] = await getClaimAndSig(length); + const gas = + await l2ReverseRegistrar.estimateGas.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ); + return { gas, gasPerEach: Number((gas - 99_650n) / BigInt(length)) }; + }), + ); + + for (let i = 1; i < gasUseds.length; i++) { + expect(gasUseds[i].gasPerEach).toBeLessThan( + gasUseds[i - 1].gasPerEach * 1.15, + ); + } + }); + + it("reverts if chain IDs are not in ascending order", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const chainIds = [1n, 42161n, OPTIMISM_CHAIN_ID, 8453n]; // Not ascending: 1, 42161, 10, 8453 + + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[0].address, + chainIds, + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ).toBeRevertedWithCustomError("ChainIdsNotAscending"); + }); + + it("reverts if chain IDs contain duplicates", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const chainIds = [1n, OPTIMISM_CHAIN_ID, OPTIMISM_CHAIN_ID, 42161n]; // Duplicate: 10 appears twice + + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[0].address, + chainIds, + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ).toBeRevertedWithCustomError("ChainIdsNotAscending"); + }); + + it("reverts if current chain ID is not in array", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const chainIds = [1n, 8453n, 42161n]; // ETH, Base, Arbitrum - ascending order, NO Optimism + + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[0].address, + chainIds, + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ) + .toBeRevertedWithCustomError("CurrentChainNotFound") + .withArgs([OPTIMISM_CHAIN_ID]); + }); + + it("reverts if chain ID array is empty", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const chainIds: bigint[] = []; + + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[0].address, + chainIds, + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ) + .toBeRevertedWithCustomError("CurrentChainNotFound") + .withArgs([OPTIMISM_CHAIN_ID]); + }); + + it("reverts if the same signature is used twice (replay protection)", async () => { + const { l2ReverseRegistrar, name, signedAt, signature, accounts } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const claim = { + name, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + // First call should succeed + await l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ); + + // Second call with same signature should fail (signedAt not after inception) + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ), + ).toBeRevertedWithCustomError("StaleSignature"); + }); + + it("allows newer signatures with later signedAt for same address", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + walletClient, + getNameForAddr, + } = await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + // First signature + const message1 = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature1 = await walletClient.signMessage({ + message: message1, + }); + + const claim1 = { + name, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim1, signature1], + { account: accounts[1] }, + ), + ).not.toBeReverted(); + + // Mine a block to advance time + await connection.networkHelpers.mine(1); + const publicClient = await connection.viem.getPublicClient(); + const newBlockTimestamp = await publicClient + .getBlock() + .then((b) => b.timestamp); + + // Second signature with newer signedAt should work + const newName = "updated.eth"; + const message2 = createNameForAddrMessage({ + name: newName, + address: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt: newBlockTimestamp, + }); + + const signature2 = await walletClient.signMessage({ + message: message2, + }); + + const claim2 = { + name: newName, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt: newBlockTimestamp, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim2, signature2], + { account: accounts[1] }, + ), + ).not.toBeReverted(); + + await expect(getNameForAddr(accounts[0].address)).resolves.toStrictEqual( + newName, + ); + }); + + it("reverts if signed by wrong account", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + const [, secondWalletClient] = await connection.viem.getWalletClients(); + + // Sign with account[1] but claim is for account[0] + const message = createNameForAddrMessage({ + name, + address: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await secondWalletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[2] }, + ), + ).toBeRevertedWithCustomError("InvalidSignature"); + }); + + it("updates and returns inception correctly", async () => { + const { l2ReverseRegistrar, name, signedAt, signature, accounts } = + await connection.networkHelpers.loadFixture( + setNameForAddrWithSignatureFixture, + ); + + // Check initial inception is 0 + const initialInception = await l2ReverseRegistrar.read.inceptionOf([ + accounts[0].address, + ]); + expect(initialInception).toStrictEqual(0n); + + const claim = { + name, + addr: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await l2ReverseRegistrar.write.setNameForAddrWithSignature( + [claim, signature], + { account: accounts[1] }, + ); + + // Check inception is updated + const updatedInception = await l2ReverseRegistrar.read.inceptionOf([ + accounts[0].address, + ]); + expect(updatedInception).toStrictEqual(signedAt); + }); + }); + + describe("setNameForContractWithSignature", () => { + async function setNameForContractWithSignatureFixture() { + const initial = await loadFixture(); + const { l2ReverseRegistrar } = initial; + + const name = "ownable.eth"; + + const publicClient = await connection.viem.getPublicClient(); + const blockTimestamp = await publicClient + .getBlock() + .then((b) => b.timestamp); + const signedAt = blockTimestamp; + + const [walletClient] = await connection.viem.getWalletClients(); + + return { + ...initial, + name, + signedAt, + walletClient, + }; + } + + it("allows an EOA to sign a message to claim the address of a contract it owns via Ownable", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + getNameForAddr, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ).toEmitEvent("NameChanged"); + + await expect( + getNameForAddr(mockOwnableEoa.address), + ).resolves.toStrictEqual(name); + }); + + it("allows an SCA to sign a message to claim the address of a contract it owns via Ownable", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableSca, + mockSmartContractAccount, + walletClient, + getNameForAddr, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableSca.address, + owner: mockSmartContractAccount.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableSca.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, mockSmartContractAccount.address, signature], + { account: accounts[9] }, + ), + ).toEmitEvent("NameChanged"); + + await expect( + getNameForAddr(mockOwnableSca.address), + ).resolves.toStrictEqual(name); + }); + + it("reverts if the owner address is not the owner of the contract", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, mockOwnableEoa } = + await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const [, secondWalletClient] = await connection.viem.getWalletClients(); + + // Sign with accounts[1] and claim they own mockOwnableEoa + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[1].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await secondWalletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[1].address, signature], + { account: accounts[9] }, + ), + ) + .toBeRevertedWithCustomError("UnauthorizedNamer") + .withArgs([getAddress(accounts[1].address)]); + }); + + it("reverts if the target address is not a contract (is an EOA)", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + // Try to claim for EOA account[2] saying account[0] owns it + const message = createNameForOwnableMessage({ + name, + contractAddress: accounts[2].address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: accounts[2].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ) + .toBeRevertedWithCustomError("UnauthorizedNamer") + .withArgs([getAddress(accounts[0].address)]); + }); + + it("reverts if the target address does not implement Ownable", async () => { + const { l2ReverseRegistrar, name, signedAt, accounts, walletClient } = + await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + // L2ReverseRegistrar itself does not implement Ownable + const message = createNameForOwnableMessage({ + name, + contractAddress: l2ReverseRegistrar.address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: l2ReverseRegistrar.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ) + .toBeRevertedWithCustomError("UnauthorizedNamer") + .withArgs([getAddress(accounts[0].address)]); + }); + + it("reverts if the signature is invalid", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + // Sign with different signedAt + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt: signedAt - 100n, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, // Original signedAt + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ).toBeRevertedWithCustomError("InvalidSignature"); + }); + + it("reverts if signedAt is in the future", async () => { + const { + l2ReverseRegistrar, + name, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const publicClient = await connection.viem.getPublicClient(); + const blockTimestamp = await publicClient + .getBlock() + .then((b) => b.timestamp); + const futureTime = blockTimestamp + 3600n; // 1 hour in the future + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt: futureTime, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt: futureTime, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ).toBeRevertedWithCustomError("SignatureNotValidYet"); + }); + + it("reverts if signedAt is not after inception", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + // First call should succeed + await l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ); + + // Try to use a signature with the same signedAt (should fail) + const newName = "newname.eth"; + const message2 = createNameForOwnableMessage({ + name: newName, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature2 = await walletClient.signMessage({ + message: message2, + }); + + const claim2 = { + name: newName, + addr: mockOwnableEoa.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim2, accounts[0].address, signature2], + { account: accounts[9] }, + ), + ).toBeRevertedWithCustomError("StaleSignature"); + }); + + it("allows multiple chain IDs in array (must be ascending)", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + getNameForAddr, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const chainIds = [1n, OPTIMISM_CHAIN_ID, 8453n, 42161n]; // Ascending order + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds, + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ).toEmitEvent("NameChanged"); + + await expect( + getNameForAddr(mockOwnableEoa.address), + ).resolves.toStrictEqual(name); + }); + + it("allows large chain ID array with approx. linear gas scaling", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const getClaimAndSig = async (length: number) => { + const chainIds = Array.from({ length }, (_, i) => BigInt(i) + 1n); + if (length === 1) chainIds[0] = OPTIMISM_CHAIN_ID; + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds, + signedAt, + }; + + return [claim, signature] as const; + }; + + const amounts = [1, 25, 50, 100, 200, 400, 800, 1600]; + const gasUseds = await Promise.all( + amounts.map(async (length) => { + const [claim, signature] = await getClaimAndSig(length); + const gas = + await l2ReverseRegistrar.estimateGas.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ); + return { gas, gasPerEach: Number((gas - 114_300n) / BigInt(length)) }; + }), + ); + + for (let i = 1; i < gasUseds.length; i++) { + expect(gasUseds[i].gasPerEach).toBeLessThan( + gasUseds[i - 1].gasPerEach * 1.15, + ); + } + }); + + it("reverts if chain IDs are not in ascending order", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const chainIds = [1n, 42161n, OPTIMISM_CHAIN_ID, 8453n]; // Not ascending + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds, + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ).toBeRevertedWithCustomError("ChainIdsNotAscending"); + }); + + it("reverts if current chain ID is not in array", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const chainIds = [1n, 8453n, 42161n]; // Ascending order, No Optimism + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds, + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ) + .toBeRevertedWithCustomError("CurrentChainNotFound") + .withArgs([OPTIMISM_CHAIN_ID]); + }); + + it("reverts if chain ID array is empty", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const chainIds: bigint[] = []; + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds, + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds, + signedAt, + }; + + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ) + .toBeRevertedWithCustomError("CurrentChainNotFound") + .withArgs([OPTIMISM_CHAIN_ID]); + }); + + it("reverts if the same signature is used twice (replay protection)", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + // First call should succeed + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ).not.toBeReverted(); + + // Second call with same signature should fail (signedAt not after inception) + await expect( + l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ), + ).toBeRevertedWithCustomError("StaleSignature"); + }); + + it("updates and returns inception correctly", async () => { + const { + l2ReverseRegistrar, + name, + signedAt, + accounts, + mockOwnableEoa, + walletClient, + } = await connection.networkHelpers.loadFixture( + setNameForContractWithSignatureFixture, + ); + + // Check initial inception is 0 + const initialInception = await l2ReverseRegistrar.read.inceptionOf([ + mockOwnableEoa.address, + ]); + expect(initialInception).toStrictEqual(0n); + + const message = createNameForOwnableMessage({ + name, + contractAddress: mockOwnableEoa.address, + owner: accounts[0].address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }); + + const signature = await walletClient.signMessage({ + message, + }); + + const claim = { + name, + addr: mockOwnableEoa.address, + chainIds: [OPTIMISM_CHAIN_ID], + signedAt, + }; + + await l2ReverseRegistrar.write.setNameForContractWithSignature( + [claim, accounts[0].address, signature], + { account: accounts[9] }, + ); + + // Check inception is updated + const updatedInception = await l2ReverseRegistrar.read.inceptionOf([ + mockOwnableEoa.address, + ]); + expect(updatedInception).toStrictEqual(signedAt); + }); + }); + + describe("name (reading reverse records)", () => { + it("returns empty string for unset address", async () => { + const { accounts, getNameForAddr } = await loadFixture(); + + await expect(getNameForAddr(accounts[5].address)).resolves.toStrictEqual( + "", + ); + }); + }); + + describe("resolve", () => { + async function resolveFixture() { + const initial = await loadFixture(); + const { l2ReverseRegistrar, accounts } = initial; + + const name = "test.eth"; + await l2ReverseRegistrar.write.setName([name], { + account: accounts[0], + }); + + return { + ...initial, + name, + }; + } + + it("can resolve name for an address via resolve()", async () => { + const { l2ReverseRegistrar, name, accounts } = + await connection.networkHelpers.loadFixture(resolveFixture); + + const addressString = accounts[0].address.slice(2).toLowerCase(); + + const coinTypeLabel = COIN_TYPE_LABEL; + const reverseLabel = "reverse"; + const fullName = `${addressString}.${coinTypeLabel}.${reverseLabel}`; + + const dnsEncodedName = dnsEncodeName(fullName); + const node = namehash(fullName); + const calldata = encodeFunctionData({ + abi: l2ReverseRegistrar.abi, + functionName: "name", + args: [node], + }); + + const result = await l2ReverseRegistrar.read.resolve([ + dnsEncodedName, + calldata, + ]); + + const resultName = decodeFunctionResult({ + abi: l2ReverseRegistrar.abi, + functionName: "name", + data: result, + }); + + expect(resultName).toStrictEqual(name); + }); + }); +}); diff --git a/contracts/test/mocks/MockContractNamer.sol b/contracts/test/mocks/MockContractNamer.sol new file mode 100644 index 000000000..b7e47bdad --- /dev/null +++ b/contracts/test/mocks/MockContractNamer.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; + +contract MockContractNamer is IContractNamer { + address internal immutable NAMER; + constructor(address namer) { + NAMER = namer; + } + function isContractNamer(address namer) external view returns (bool) { + return namer == NAMER; + } +} diff --git a/contracts/test/mocks/MockDNSSEC.sol b/contracts/test/mocks/MockDNSSEC.sol index c08d3eb04..58de26df5 100644 --- a/contracts/test/mocks/MockDNSSEC.sol +++ b/contracts/test/mocks/MockDNSSEC.sol @@ -20,16 +20,21 @@ contract MockDNSSEC is DNSSEC { _rrs = rrs_; } - function verifyRRSet( - RRSetWithSignature[] memory input - ) external view override returns (bytes memory, uint32) { + function verifyRRSet(RRSetWithSignature[] memory input) + external + view + override + returns (bytes memory, uint32) + { return verifyRRSet(input, block.timestamp); } - function verifyRRSet( - RRSetWithSignature[] memory, - uint256 - ) public view override returns (bytes memory, uint32) { + function verifyRRSet(RRSetWithSignature[] memory, uint256) + public + view + override + returns (bytes memory, uint32) + { return (_rrs, 0); } } diff --git a/contracts/test/mocks/MockERC20.sol b/contracts/test/mocks/MockERC20.sol index 3ec79d4b5..1c110a1ca 100644 --- a/contracts/test/mocks/MockERC20.sol +++ b/contracts/test/mocks/MockERC20.sol @@ -2,12 +2,9 @@ pragma solidity ^0.8.13; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; +import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; -import {HCAContext, HCAEquivalence} from "~src/hca/HCAContext.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; - -contract MockERC20 is ERC20, HCAContext { +contract MockERC20 is ERC20Permit { //////////////////////////////////////////////////////////////////////// // Storage //////////////////////////////////////////////////////////////////////// @@ -18,11 +15,7 @@ contract MockERC20 is ERC20, HCAContext { // Initialization //////////////////////////////////////////////////////////////////////// - constructor( - string memory symbol, - uint8 decimals_, - IHCAFactoryBasic factory - ) ERC20(symbol, symbol) HCAEquivalence(factory) { + constructor(string memory symbol, uint8 decimals_) ERC20(symbol, symbol) ERC20Permit(symbol) { _decimals = decimals_; } @@ -41,12 +34,9 @@ contract MockERC20 is ERC20, HCAContext { function decimals() public view virtual override returns (uint8) { return _decimals; } - - function _msgSender() internal view virtual override(Context, HCAContext) returns (address) { - return HCAContext._msgSender(); - } } + contract MockERC20Blacklist is MockERC20 { //////////////////////////////////////////////////////////////////////// // Storage @@ -64,9 +54,7 @@ contract MockERC20Blacklist is MockERC20 { // Initialization //////////////////////////////////////////////////////////////////////// - constructor() - MockERC20("BLACK", 6, IHCAFactoryBasic(0x0000000000000000000000000000000000000000)) - {} + constructor() MockERC20("BLACK", 6) {} //////////////////////////////////////////////////////////////////////// // Implementation @@ -77,20 +65,25 @@ contract MockERC20Blacklist is MockERC20 { } function transferFrom(address from, address to, uint256 amount) public override returns (bool) { - if (isBlacklisted[from]) revert Blacklisted(from); - if (isBlacklisted[to]) revert Blacklisted(to); + _checkBlacklist(from); + _checkBlacklist(to); return super.transferFrom(from, to, amount); } + + function _checkBlacklist(address addr) internal view { + if (isBlacklisted[addr]) { + revert Blacklisted(addr); + } + } } + contract MockERC20VoidReturn is MockERC20 { //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// - constructor() - MockERC20("VOID", 6, IHCAFactoryBasic(0x0000000000000000000000000000000000000000)) - {} + constructor() MockERC20("VOID", 11) {} //////////////////////////////////////////////////////////////////////// // Implementation @@ -104,20 +97,13 @@ contract MockERC20VoidReturn is MockERC20 { } } -contract MockERC20FalseReturn is MockERC20 { - //////////////////////////////////////////////////////////////////////// - // Storage - //////////////////////////////////////////////////////////////////////// - - bool public shouldFail; +contract MockERC20FalseReturn is MockERC20 { //////////////////////////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////////////////////////// - constructor() - MockERC20("FALSE", 18, IHCAFactoryBasic(0x0000000000000000000000000000000000000000)) - {} + constructor() MockERC20("FALSE", 13) {} //////////////////////////////////////////////////////////////////////// // Implementation diff --git a/contracts/test/mocks/MockHCAFactoryBasic.sol b/contracts/test/mocks/MockHCAFactoryBasic.sol deleted file mode 100644 index 142048a17..000000000 --- a/contracts/test/mocks/MockHCAFactoryBasic.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; - -contract MockHCAFactoryBasic is IHCAFactoryBasic { - mapping(address hca => address owner) internal _ownerOf; - - function setAccountOwner(address hca, address owner) external { - _ownerOf[hca] = owner; - } - - function getAccountOwner(address hca) external view returns (address) { - return _ownerOf[hca]; - } -} diff --git a/contracts/test/mocks/MockISO8601Implementer.sol b/contracts/test/mocks/MockISO8601Implementer.sol new file mode 100644 index 000000000..56a3800b2 --- /dev/null +++ b/contracts/test/mocks/MockISO8601Implementer.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {LibISO8601} from "~src/utils/LibISO8601.sol"; + +/// @notice Minimal contract for testing LibISO8601 +contract MockLibISO8601Implementer { + using LibISO8601 for uint256; + + function toISO8601_batch(uint256[] memory timestamps) public pure returns (string[] memory) { + string[] memory results = new string[](timestamps.length); + for (uint256 i = 0; i < timestamps.length; ++i) { + results[i] = timestamps[i].toISO8601(); + } + return results; + } + + function toISO8601(uint256 timestamp) public pure returns (string memory) { + return timestamp.toISO8601(); + } +} diff --git a/contracts/test/mocks/MockPremigrator.sol b/contracts/test/mocks/MockPremigrator.sol new file mode 100644 index 000000000..66a5feccb --- /dev/null +++ b/contracts/test/mocks/MockPremigrator.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {LibLabel} from "~src/utils/LibLabel.sol"; + +/// @title MockPremigrator +/// @notice Mocks premigration script state for testing on un-pre-migrated deployments. +contract MockPremigrator { + /// @notice The ETH registry to use for registration. + IPermissionedRegistry public immutable ETH_REGISTRY; + + //////////////////////////////////////////////////////////////////////// + // Initialization + //////////////////////////////////////////////////////////////////////// + + /// @notice Initializes the MockPremigrator. + /// @param ethRegistry_ The ETH registry to use for registration. + constructor(IPermissionedRegistry ethRegistry_) { + ETH_REGISTRY = ethRegistry_; + } + + //////////////////////////////////////////////////////////////////////// + // Implementation + //////////////////////////////////////////////////////////////////////// + + /// @notice Register/renew a name for pre-migration + /// @param label Label to reserve or renew + /// @param expiry Expiry for the name + /// @param registry The registry for the name + /// @param resolver The resolver for the name + function preMigrate(string calldata label, uint64 expiry, IRegistry registry, address resolver) + external + { + IPermissionedRegistry.State memory state = ETH_REGISTRY.getState(LibLabel.id(label)); + + if (state.status == IPermissionedRegistry.Status.AVAILABLE) { + ETH_REGISTRY.register(label, address(0), registry, resolver, 0, expiry); + } else if (state.status == IPermissionedRegistry.Status.RESERVED && expiry > state.expiry) { + ETH_REGISTRY.renew(state.tokenId, expiry); + } + } +} diff --git a/contracts/test/mocks/MockStandaloneReverseRegistrarImplementer.sol b/contracts/test/mocks/MockStandaloneReverseRegistrarImplementer.sol new file mode 100644 index 000000000..b5f088dbc --- /dev/null +++ b/contracts/test/mocks/MockStandaloneReverseRegistrarImplementer.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// solhint-disable no-empty-blocks, namechain/ordering + +import {StandaloneReverseRegistrar} from "~src/reverse-registrar/StandaloneReverseRegistrar.sol"; + +contract MockStandaloneReverseRegistrarImplementer is StandaloneReverseRegistrar { + constructor(string memory label) StandaloneReverseRegistrar(label) {} + + // Test helper functions + function setName(address addr, string calldata name_) public { + _setName(addr, name_); + } + + function SIMPLE_HASHED_PARENT() public view returns (bytes32) { + return _SIMPLE_HASHED_PARENT; + } + + function PARENT_LENGTH() public view returns (uint256) { + return _PARENT_LENGTH; + } +} diff --git a/contracts/test/unit/access-control/EnhancedAccessControl.t.sol b/contracts/test/unit/access-control/EnhancedAccessControl.t.sol index 4ac13beb0..acb1a9d35 100644 --- a/contracts/test/unit/access-control/EnhancedAccessControl.t.sol +++ b/contracts/test/unit/access-control/EnhancedAccessControl.t.sol @@ -6,36 +6,33 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import {EnhancedAccessControl} from "~src/access-control/EnhancedAccessControl.sol"; -import { - IEnhancedAccessControl -} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; +import {IEnhancedAccessControl} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; -import {HCAEquivalence} from "~src/hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; uint256 constant ROOT_RESOURCE = 0; + uint256 constant RESOURCE_1 = uint256(keccak256("RESOURCE_1")); + uint256 constant RESOURCE_2 = uint256(keccak256("RESOURCE_2")); uint256 constant ROLE_A = 1 << 0; // First nybble (bits 0-3) + uint256 constant ROLE_B = 1 << 4; // Second nybble (bits 4-7) + uint256 constant ROLE_C = 1 << 8; // Third nybble (bits 8-11) + uint256 constant ROLE_D = 1 << 12; // Fourth nybble (bits 12-15) uint256 constant ADMIN_ROLE_A = ROLE_A << 128; // First admin nybble (bits 128-131) + uint256 constant ADMIN_ROLE_B = ROLE_B << 128; // Second admin nybble (bits 132-135) + uint256 constant ADMIN_ROLE_C = ROLE_C << 128; // Third admin nybble (bits 136-139) + uint256 constant ADMIN_ROLE_D = ROLE_D << 128; // Fourth admin nybble (bits 140-143) -uint256 constant ALL_ROLES = ROLE_A | - ROLE_B | - ROLE_C | - ROLE_D | - ADMIN_ROLE_A | - ADMIN_ROLE_B | - ADMIN_ROLE_C | - ADMIN_ROLE_D; +uint256 constant ALL_ROLES = + ROLE_A | ROLE_B | ROLE_C | ROLE_D | ADMIN_ROLE_A | ADMIN_ROLE_B | ADMIN_ROLE_C | ADMIN_ROLE_D; contract MockEnhancedAccessControl is EnhancedAccessControl { uint256 public lastGrantedCount; @@ -54,12 +51,19 @@ contract MockEnhancedAccessControl is EnhancedAccessControl { address public lastRevokedAccount; uint256 public lastRevokedResource; - constructor(IHCAFactoryBasic hcaFactory) HCAEquivalence(hcaFactory) { + constructor() { _grantRoles(ROOT_RESOURCE, ALL_ROLES, msg.sender, true); lastGrantedCount = 0; lastRevokedCount = 0; } + function callOnlyRoles(uint256 resource, uint256 roleBitmap) + external + onlyRoles(resource, roleBitmap) + { + // Function that will revert if caller doesn't have the roles in resource + } + function callOnlyRootRoles(uint256 roleBitmap) external onlyRootRoles(roleBitmap) { // Function that will revert if caller doesn't have the roles in root resource } @@ -69,7 +73,14 @@ contract MockEnhancedAccessControl is EnhancedAccessControl { } function revokeAllRoles(uint256 resource, address account) external returns (bool) { - return _revokeAllRoles(resource, account, true); + return _revokeRoles(resource, EACBaseRolesLib.ALL_ROLES, account, true); + } + + function revokeAllRolesWithoutCallback(uint256 resource, address account) + external + returns (bool) + { + return _revokeRoles(resource, EACBaseRolesLib.ALL_ROLES, account, false); } function _onRolesGranted( @@ -78,7 +89,10 @@ contract MockEnhancedAccessControl is EnhancedAccessControl { uint256 oldRoles, uint256 newRoles, uint256 roleBitmap - ) internal override { + ) + internal + override + { ++lastGrantedCount; lastGrantedResource = resource; lastGrantedRoleBitmap = roleBitmap; @@ -94,7 +108,10 @@ contract MockEnhancedAccessControl is EnhancedAccessControl { uint256 oldRoles, uint256 newRoles, uint256 roleBitmap - ) internal override { + ) + internal + override + { ++lastRevokedCount; lastRevokedResource = resource; lastRevokedRoleBitmap = roleBitmap; @@ -104,55 +121,45 @@ contract MockEnhancedAccessControl is EnhancedAccessControl { lastRevokedAccount = account; } - function grantRolesWithoutCallback( - uint256 resource, - uint256 roleBitmap, - address account - ) external canGrantRoles(resource, roleBitmap) returns (bool) { + function grantRolesWithoutCallback(uint256 resource, uint256 roleBitmap, address account) + external + canGrantRoles(resource, roleBitmap) + returns (bool) + { if (resource == ROOT_RESOURCE) { revert EACRootResourceNotAllowed(); } return _grantRoles(resource, roleBitmap, account, false); } - function revokeRolesWithoutCallback( - uint256 resource, - uint256 roleBitmap, - address account - ) external canRevokeRoles(resource, roleBitmap) returns (bool) { + function revokeRolesWithoutCallback(uint256 resource, uint256 roleBitmap, address account) + external + canRevokeRoles(resource, roleBitmap) + returns (bool) + { if (resource == ROOT_RESOURCE) { revert EACRootResourceNotAllowed(); } return _revokeRoles(resource, roleBitmap, account, false); } - function transferRolesWithoutCallback( - uint256 resource, - address srcAccount, - address dstAccount - ) external { + function transferRolesWithoutCallback(uint256 resource, address srcAccount, address dstAccount) + external + { _transferRoles(resource, srcAccount, dstAccount, false); } - - function revokeAllRolesWithoutCallback( - uint256 resource, - address account - ) external returns (bool) { - return _revokeAllRoles(resource, account, false); - } } + contract EnhancedAccessControlTest is Test { MockEnhancedAccessControl access; - MockHCAFactoryBasic hcaFactory; address admin = address(this); address user1 = makeAddr("user1"); address user2 = makeAddr("user2"); address superuser = makeAddr("superuser"); function setUp() external { - hcaFactory = new MockHCAFactoryBasic(); - access = new MockEnhancedAccessControl(hcaFactory); + access = new MockEnhancedAccessControl(); } function test_ROOT_RESOURCE() external view { @@ -342,6 +349,33 @@ contract EnhancedAccessControlTest is Test { access.callOnlyRootRoles(ROLE_A); } + function test_only_roles() external { + // Grant role in root resource to user1 + access.grantRootRoles(ROLE_A, user1); + + // User1 should be able to call function with onlyRoles modifier + vm.prank(user1); + access.callOnlyRoles(RESOURCE_1, ROLE_A); + + // User2 doesn't have the role, should revert + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + RESOURCE_1, + ROLE_A, + user2 + ) + ); + vm.prank(user2); + access.callOnlyRoles(RESOURCE_1, ROLE_A); + + // Having the role in a specific resource does satisfy onlyRoles + access.grantRoles(RESOURCE_1, ROLE_A, user2); + + vm.prank(user2); + access.callOnlyRoles(RESOURCE_1, ROLE_A); + } + function test_has_roles_requires_all_roles() external { // Grant only ROLE_A and ROLE_B to user1 access.grantRoles(RESOURCE_1, ROLE_A | ROLE_B, user1); @@ -535,32 +569,6 @@ contract EnhancedAccessControlTest is Test { assertFalse(access.hasRootRoles(ROLE_A, user2)); } - function test_revoke_all_roles() external { - // Setup: Grant multiple roles to user1 - _grant(RESOURCE_1, ROLE_A | ROLE_B, user1); - _grant(RESOURCE_2, ROLE_A, user1); - - // Revoke all roles for RESOURCE_1 - // Verify the operation was successful - vm.expectEmit(true, true, false, true); - emit IEnhancedAccessControl.EACRolesChanged(RESOURCE_1, user1, ROLE_A | ROLE_B, 0); - assertTrue(access.revokeAllRoles(RESOURCE_1, user1), "revoke"); - - // Verify all roles for RESOURCE_1 were revoked - assertFalse(access.hasRoles(RESOURCE_1, ROLE_A, user1)); - assertFalse(access.hasRoles(RESOURCE_1, ROLE_B, user1)); - - // Verify roles for RESOURCE_2 were not affected - assertTrue(access.hasRoles(RESOURCE_2, ROLE_A, user1)); - - // Test revoking all roles when there are no roles to revoke - // Verify the operation was not successful (no roles to revoke) - // Verify no event was emitted - vm.recordLogs(); - assertFalse(access.revokeAllRoles(RESOURCE_1, user1), "noop"); - assertEq(vm.getRecordedLogs().length, 0, "silent"); - } - function test_supports_interface() external view { assertTrue(access.supportsInterface(type(IEnhancedAccessControl).interfaceId)); } @@ -860,8 +868,8 @@ contract EnhancedAccessControlTest is Test { access.grantRootRoles(ROLE_D, user1); // Verify consistency for normal resource - bool directCheck = (access.roles(RESOURCE_1, user1) & (ROLE_A | ROLE_B)) == - (ROLE_A | ROLE_B); + bool directCheck = + (access.roles(RESOURCE_1, user1) & (ROLE_A | ROLE_B)) == (ROLE_A | ROLE_B); bool helperCheck = access.hasRoles(RESOURCE_1, ROLE_A | ROLE_B, user1); assertEq(directCheck, helperCheck); @@ -1596,10 +1604,8 @@ contract EnhancedAccessControlTest is Test { (, uint256 maskCD) = access.getAssigneeCount(RESOURCE_1, ROLE_C | ROLE_D); (, uint256 maskAC) = access.getAssigneeCount(RESOURCE_1, ROLE_A | ROLE_C); (, uint256 maskBD) = access.getAssigneeCount(RESOURCE_1, ROLE_B | ROLE_D); - (, uint256 maskAll) = access.getAssigneeCount( - RESOURCE_1, - ROLE_A | ROLE_B | ROLE_C | ROLE_D - ); + (, uint256 maskAll) = + access.getAssigneeCount(RESOURCE_1, ROLE_A | ROLE_B | ROLE_C | ROLE_D); assertEq(maskAB, 0xff); // First two nybbles assertEq(maskCD, 0xff00); // Last two nybbles @@ -1763,6 +1769,10 @@ contract EnhancedAccessControlTest is Test { vm.stopPrank(); } + //////////////////////////////////////////////////////////////////////// + // Helpers + //////////////////////////////////////////////////////////////////////// + /// @dev Grant roles then require event and check getter. function _grant(uint256 resource, uint256 roles, address account) public { uint256 roles0 = access.roles(resource, account); diff --git a/contracts/test/unit/access-control/libraries/EACBaseRolesLib.t.sol b/contracts/test/unit/access-control/libraries/EACBaseRolesLib.t.sol new file mode 100644 index 000000000..b9e047574 --- /dev/null +++ b/contracts/test/unit/access-control/libraries/EACBaseRolesLib.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; + +import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; + +contract EACBaseRolesLibTest is Test { + function test_withAdminRolesApplied() external pure { + assertEq(EACBaseRolesLib.withAdminRolesApplied(EACBaseRolesLib.ALL_ROLES >> 128), 0); + assertEq( + EACBaseRolesLib.withAdminRolesApplied(EACBaseRolesLib.ADMIN_ROLES), + EACBaseRolesLib.ALL_ROLES + ); + } + + function test_withAdminRolesApplied(uint8 i) external pure { + vm.assume(i >= 32 && i < 64); + uint256 roleBitmap = 1 << (i << 2); // admin bit + assertEq( + EACBaseRolesLib.withAdminRolesApplied(roleBitmap | (EACBaseRolesLib.ALL_ROLES >> 128)), + roleBitmap | (roleBitmap >> 128) + ); + } + + function test_fromCounts() external pure { + assertEq(EACBaseRolesLib.fromCounts(0x0123456789abcdef), 0x111111111111111); + } + + function test_fromCounts(uint8 i) external pure { + vm.assume(i > 0 && i < 16); + assertEq( + EACBaseRolesLib.fromCounts(EACBaseRolesLib.ALL_ROLES * i), + EACBaseRolesLib.ALL_ROLES + ); + } + + function test_hasZeroNybbles() external pure { + assertFalse(EACBaseRolesLib.hasZeroNybbles(EACBaseRolesLib.ALL_ROLES)); + } + + function test_hasZeroNybbles(uint8 i) external pure { + vm.assume(i < 64); + assertTrue(EACBaseRolesLib.hasZeroNybbles(~(0xF << (i << 2)))); + } +} diff --git a/contracts/test/unit/dns/DNSTLDResolver.t.sol b/contracts/test/unit/dns/DNSTLDResolver.t.sol index 3716e2802..084dc206c 100644 --- a/contracts/test/unit/dns/DNSTLDResolver.t.sol +++ b/contracts/test/unit/dns/DNSTLDResolver.t.sol @@ -5,37 +5,38 @@ pragma solidity >=0.8.13; import {Test} from "forge-std/Test.sol"; +import {ENS} from "@ens/contracts/registry/ENS.sol"; +import {DNSSEC} from "@ens/contracts/dnssec-oracle/DNSSEC.sol"; +import {HexUtils} from "@ens/contracts/utils/HexUtils.sol"; import {GatewayProvider} from "@ens/contracts/ccipRead/GatewayProvider.sol"; import {IAddrResolver} from "@ens/contracts/resolvers/profiles/IAddrResolver.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import {EACBaseRolesLib} from "~src/access-control/EnhancedAccessControl.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; -import {PermissionedRegistry, IRegistryMetadata} from "~src/registry/PermissionedRegistry.sol"; -import {DNSTLDResolver, ENS, IRegistry, DNSSEC, HexUtils} from "~src/dns/DNSTLDResolver.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {DNSTLDResolver} from "~src/dns/DNSTLDResolver.sol"; +import {LabelStore} from "~src/utils/LabelStore.sol"; // coverage:ignore-next-line contract MockDNS is DNSTLDResolver { - constructor( - IRegistry rootRegistry - ) + constructor(IPermissionedRegistry rootRegistry) DNSTLDResolver( ENS(address(0)), address(0), rootRegistry, DNSSEC(address(0)), new GatewayProvider(address(1), new string[](0)), - new GatewayProvider(address(1), new string[](0)) + new GatewayProvider(address(1), new string[](0)), + IContractNamer(address(0)) ) {} function readTXT(bytes memory v) external pure returns (bytes memory) { return _readTXT(v, 0, v.length); } - function readTXT( - bytes memory v, - uint256 pos, - uint256 end - ) external pure returns (bytes memory) { + function readTXT(bytes memory v, uint256 pos, uint256 end) external pure returns (bytes memory) { return _readTXT(v, pos, end); } // function trim(bytes memory v) external pure returns (bytes memory) { @@ -46,14 +47,14 @@ contract MockDNS is DNSTLDResolver { } } + contract DNSTLDResolverTest is Test, ERC1155Holder, IAddrResolver { PermissionedRegistry rootRegistry; MockDNS dns; function setUp() external { rootRegistry = new PermissionedRegistry( - IHCAFactoryBasic(address(0)), - IRegistryMetadata(address(0)), + new LabelStore(IContractNamer(address(0))), address(this), EACBaseRolesLib.ALL_ROLES ); diff --git a/contracts/test/unit/dns/libraries/DNSTXTParserLib.t.sol b/contracts/test/unit/dns/libraries/DNSTXTParserLib.t.sol index 930b140aa..410eb4d89 100644 --- a/contracts/test/unit/dns/libraries/DNSTXTParserLib.t.sol +++ b/contracts/test/unit/dns/libraries/DNSTXTParserLib.t.sol @@ -16,6 +16,20 @@ contract DNSTXTParserLibTest is Test { assertEq(DNSTXTParserLib.find(" a=3", "a="), "3"); } + function test_find_balancedSquareBrackets() external pure { + assertEq(DNSTXTParserLib.find("a[[]]=1", "a[[]]="), "1"); + assertEq(DNSTXTParserLib.find("a[b[]]=2", "a[b[]]="), "2"); + assertEq(DNSTXTParserLib.find("a[b[c]]=3", "a[b[c]]="), "3"); + assertEq(DNSTXTParserLib.find("a[[b]]=4", "a[[b]]="), "4"); + } + + function test_find_unbalancedSquareBrackets() external pure { + assertEq(DNSTXTParserLib.find("a[[]=1", "a[]="), ""); + assertEq(DNSTXTParserLib.find("a[]]=2", "a[]="), ""); + assertEq(DNSTXTParserLib.find("a[[[=3", "a[]="), ""); + assertEq(DNSTXTParserLib.find("a[]]=4 a[]=1", "a[]="), "1"); + } + function test_find_ignored() external pure { assertEq(DNSTXTParserLib.find("a a=1", "a="), "1"); assertEq(DNSTXTParserLib.find("a[b] a=2", "a="), "2"); diff --git a/contracts/test/unit/hca/HCAContext.t.sol b/contracts/test/unit/hca/HCAContext.t.sol deleted file mode 100644 index 50c0a96c8..000000000 --- a/contracts/test/unit/hca/HCAContext.t.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file - -import {Test} from "forge-std/Test.sol"; - -import {HCAContext} from "~src/hca/HCAContext.sol"; -import {HCAEquivalence} from "~src/hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; - -contract HCAContextHarness is HCAContext { - constructor(IHCAFactoryBasic factory) HCAEquivalence(factory) {} - - function exposedMsgSender() external view returns (address) { - return _msgSender(); - } -} - -contract HCAContextTest is Test { - MockHCAFactoryBasic factory; - HCAContextHarness harness; - - address user = address(0x1111); - address hca = address(0xAAAA); - address owner = address(0xBEEF); - - function setUp() public { - factory = new MockHCAFactoryBasic(); - harness = new HCAContextHarness(factory); - } - - function test_constructor_sets_factory() public view { - // HCA_FACTORY is public immutable on the base, accessible via harness - assertEq(address(harness.HCA_FACTORY()), address(factory)); - } - - function test_msgSender_calls_HCAEquivalence() public { - vm.prank(user); - vm.expectCall( - address(factory), - abi.encodeWithSelector(factory.getAccountOwner.selector, user) - ); - address sender = harness.exposedMsgSender(); - assertEq(sender, user); - } -} diff --git a/contracts/test/unit/hca/HCAContextUpgradeable.t.sol b/contracts/test/unit/hca/HCAContextUpgradeable.t.sol deleted file mode 100644 index 0be702119..000000000 --- a/contracts/test/unit/hca/HCAContextUpgradeable.t.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file - -import {Test} from "forge-std/Test.sol"; - -import {HCAContextUpgradeable} from "~src/hca/HCAContextUpgradeable.sol"; -import {HCAEquivalence} from "~src/hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; - -contract HCAContextUpgradeableHarness is HCAContextUpgradeable { - constructor(IHCAFactoryBasic factory) HCAEquivalence(factory) {} - - function exposedMsgSender() external view returns (address) { - return _msgSender(); - } -} - -contract HCAContextUpgradeableTest is Test { - MockHCAFactoryBasic factory; - HCAContextUpgradeableHarness harness; - - address user = address(0x1111); - address hca = address(0xAAAA); - address owner = address(0xBEEF); - - function setUp() public { - factory = new MockHCAFactoryBasic(); - harness = new HCAContextUpgradeableHarness(factory); - } - - function test_constructor_sets_factory() public view { - // HCA_FACTORY is public immutable on the base, accessible via harness - assertEq(address(harness.HCA_FACTORY()), address(factory)); - } - - function test_msgSender_calls_HCAEquivalence() public { - vm.prank(user); - vm.expectCall( - address(factory), - abi.encodeWithSelector(factory.getAccountOwner.selector, user) - ); - address sender = harness.exposedMsgSender(); - assertEq(sender, user); - } -} diff --git a/contracts/test/unit/hca/HCAEquivalence.t.sol b/contracts/test/unit/hca/HCAEquivalence.t.sol deleted file mode 100644 index 8fa2cb6f8..000000000 --- a/contracts/test/unit/hca/HCAEquivalence.t.sol +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file - -import {Test} from "forge-std/Test.sol"; - -import {HCAEquivalence} from "~src/hca/HCAEquivalence.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; - -contract HCAEquivalenceHarness is HCAEquivalence { - constructor(IHCAFactoryBasic factory) HCAEquivalence(factory) {} - - function exposedMsgSender() external view returns (address) { - return _msgSenderWithHcaEquivalence(); - } -} - -contract HCAEquivalenceTest is Test { - MockHCAFactoryBasic factory; - HCAEquivalenceHarness harness; - - address user = address(0x1111); - address hca = address(0xAAAA); - address owner = address(0xBEEF); - - function setUp() public { - factory = new MockHCAFactoryBasic(); - harness = new HCAEquivalenceHarness(IHCAFactoryBasic(address(factory))); - } - - function test_constructor_sets_factory() public view { - // HCA_FACTORY is public immutable on the base, accessible via harness - assertEq(address(harness.HCA_FACTORY()), address(factory)); - } - - function test_msgSender_returns_original_when_not_hca() public { - vm.prank(user); - address sender = harness.exposedMsgSender(); - assertEq(sender, user, "_msgSender should return original sender when not HCA"); - } - - function test_msgSender_returns_owner_when_sender_is_hca() public { - factory.setAccountOwner(hca, owner); - - vm.prank(hca); - address sender = harness.exposedMsgSender(); - assertEq(sender, owner, "_msgSender should return account owner for HCA senders"); - } - - function test_msgSender_zero_owner_treated_as_eoa() public { - // Ensure no owner configured for `user` - vm.prank(user); - address sender = harness.exposedMsgSender(); - assertEq(sender, user); - } - - function test_msgSender_unrelated_mapping_does_not_affect_eoa() public { - // Configure a different HCA mapping, but call from an unrelated EOA - factory.setAccountOwner(hca, owner); - - vm.prank(user); - address sender = harness.exposedMsgSender(); - assertEq(sender, user, "Unrelated mapping should not affect EOA sender"); - } - - function test_msgSender_owner_same_as_hca_returns_hca() public { - // Edge: if factory maps HCA to itself, _msgSender returns that same address - factory.setAccountOwner(hca, hca); - - vm.prank(hca); - address sender = harness.exposedMsgSender(); - assertEq(sender, hca, "When owner == HCA, _msgSender should be the HCA address"); - } -} diff --git a/contracts/test/unit/migration/Graveyard.t.sol b/contracts/test/unit/migration/Graveyard.t.sol new file mode 100755 index 000000000..18a8ea736 --- /dev/null +++ b/contracts/test/unit/migration/Graveyard.t.sol @@ -0,0 +1,503 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import { + CAN_DO_EVERYTHING, + CANNOT_SET_RESOLVER, + CANNOT_UNWRAP, + PARENT_CANNOT_CONTROL +} from "@ens/contracts/wrapper/INameWrapper.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {HexUtils} from "@ens/contracts/utils/HexUtils.sol"; +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; + +import {Graveyard} from "~src/migration/Graveyard.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {MigrationControllerFixture} from "~test/fixtures/MigrationControllerFixture.sol"; + +contract GraveyardTest is MigrationControllerFixture { + uint256 constant N = 10; + + function setUp() external { + deployMigrationControllerFixture(); + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface(address(graveyard), type(IContractNamer).interfaceId), + "IContractNamer" + ); + } + + function test_clear_root() external { + graveyard.clear(_oneName(NameCoder.encode(""))); // noop + } + + function test_clear_eth() external { + graveyard.clear(_oneName(NameCoder.encode("eth"))); // noop + } + + function test_clear_xyz() external { + vm.expectRevert(abi.encodeWithSelector(Graveyard.NameNotClearable.selector)); + graveyard.clear(_oneName(NameCoder.encode("xyz"))); + vm.expectRevert(); + graveyard.clear(_oneName(NameCoder.encode("test.xyz"))); + } + + function test_clear_afterGrace() external { + (bytes memory name, uint256 tokenIdV1) = registerUnwrapped(testLabel); + + vm.warp(baseRegistrar.nameExpires(tokenIdV1) + gracePeriodV1); + vm.expectRevert(); + baseRegistrar.ownerOf(tokenIdV1); + assertTrue(baseRegistrar.available(tokenIdV1), "grace:available"); + + graveyard.clear(_oneName(name)); + } + + function test_clear_registered_unwrapped() external { + (bytes memory name, ) = registerUnwrapped(testLabel); + + vm.expectRevert(); + graveyard.clear(_oneName(name)); + } + + function test_clear_registered_unlocked() external { + bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); + + vm.expectRevert(); + graveyard.clear(_oneName(name)); + } + + function test_clear_registered_locked() external { + bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + + vm.expectRevert(); + graveyard.clear(_oneName(name)); + } + + function test_encodeLabelHash() external pure { + assertEq( + _encodedLabelHash(bytes32(0)), + "[0000000000000000000000000000000000000000000000000000000000000000]" + ); + assertEq( + _encodedLabelHash(0x5cee339e13375638553bdf5a6e36ba80fb9f6a4f0783680884d92b558aa471da), + "[5cee339e13375638553bdf5a6e36ba80fb9f6a4f0783680884d92b558aa471da]" + ); + } + + function test_clear_prehashedLabel_invalid() external { + bytes memory name = NameCoder.encode("eth"); + for (uint256 i; i < 32; ++i) { + vm.expectRevert(); + graveyard.clear(_oneName(abi.encodePacked(uint8(0), new bytes(i), name))); + } + } + + function test_clear_prehashedLabel_literal(bytes32 labelHash) external { + (bytes memory name, ) = registerUnwrapped(testLabel); + bytes32 node = NameCoder.namehash(name, 0); + + string memory label = _encodedLabelHash(labelHash); + bytes32 actualLabelHash = keccak256(bytes(label)); + + vm.prank(testOwner); + registryV1.setSubnodeRecord(node, actualLabelHash, friend, address(1), 0); + + _simulateMigration(name); + + node = NameCoder.namehash(node, actualLabelHash); + + assertEq(registryV1.resolver(node), address(1), "before"); + graveyard.clear(_oneName(abi.encodePacked(uint8(0), labelHash, name))); // mark as prehashed + assertEq(registryV1.resolver(node), address(1), "uncleared"); + graveyard.clear(_oneName(NameCoder.addLabel(name, label))); + assertEq(registryV1.resolver(node), address(0), "after"); + } + + function test_clear_prehashedLabel_hashed(bytes32 labelHash) external { + (bytes memory name, ) = registerUnwrapped(testLabel); + bytes32 node = NameCoder.namehash(name, 0); + + vm.prank(testOwner); + registryV1.setSubnodeRecord(node, labelHash, friend, address(1), 0); + + _simulateMigration(name); + + node = NameCoder.namehash(node, labelHash); + + assertEq(registryV1.resolver(node), address(1), "before"); + graveyard.clear(_oneName(NameCoder.addLabel(name, _encodedLabelHash(labelHash)))); + assertEq(registryV1.resolver(node), address(1), "uncleared"); + graveyard.clear(_oneName(abi.encodePacked(uint8(0), labelHash, name))); // mark as prehashed + assertEq(registryV1.resolver(node), address(0), "after"); + } + + function test_clear_unregistered() external { + vm.expectRevert(abi.encodeWithSelector(Graveyard.NameNotClearable.selector)); + graveyard.clear(_oneName(_randomEthName())); + } + + function test_clear_expired(uint256) external { + registerUnwrapped(testLabel); // ensure expiry > 0 + _simulateExpiry(NameCoder.ethName(testLabel)); // ensure expired + + graveyard.clear(_oneName(_randomEthName())); + } + + function test_clear_junk_deep(uint256) external { + bytes memory name = _randomEthName(); + bytes32 node = NameCoder.namehash(name, 0); + + registerUnwrapped(testLabel); // ensure expiry > 0 + _simulateExpiry(NameCoder.ethName(testLabel)); // ensure expired + + _claimNodes(name, 0, address(testOwner)); + vm.prank(testOwner); + registryV1.setResolver(node, address(1)); + assertEq(registryV1.resolver(node), address(1)); + + graveyard.clear(_oneName(name)); + + assertEq(registryV1.resolver(node), address(0)); + } + + function test_clear_deep() external { + (bytes memory name0, ) = registerUnwrapped(testLabel); + + bytes memory name = name0; + for (uint256 i; i < N; ++i) { + vm.prank(testOwner); + registryV1.setSubnodeRecord( + NameCoder.namehash(name, 0), + keccak256(bytes(testLabel)), + testOwner, + address(1), + 0 + ); + name = NameCoder.addLabel(name, testLabel); + } + + _simulateMigration(name0); + + graveyard.clear(_oneName(name)); + + name = name0; + for (uint256 i; i < N; ++i) { + name = NameCoder.addLabel(name, testLabel); + assertEq(registryV1.resolver(NameCoder.namehash(name, 0)), address(0), vm.toString(i)); + } + } + + function test_clear_wide() external { + bytes[] memory names = new bytes[](N); + + for (uint256 i; i < names.length; ++i) { + (bytes memory name, ) = registerUnwrapped(_label(i)); + vm.prank(testOwner); + registryV1.setSubnodeRecord( + NameCoder.namehash(name, 0), + keccak256(bytes(testLabel)), + friend, + address(1), + 0 + ); + _simulateMigration(name); + names[i] = NameCoder.addLabel(name, testLabel); + } + + graveyard.clear(names); + + for (uint256 i; i < names.length; ++i) { + assertEq( + registryV1.resolver(NameCoder.namehash(names[i], 0)), + address(0), + vm.toString(i) + ); + } + } + + function test_clear_nestedLocked_migrateBoth() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes memory name3 = + createWrappedChild(name2, testLabel, PARENT_CANNOT_CONTROL | CANNOT_UNWRAP); + + // set resolvers + vm.startPrank(testOwner); + nameWrapper.setResolver(NameCoder.namehash(name2, 0), address(1)); + nameWrapper.setResolver(NameCoder.namehash(name3, 0), address(1)); + vm.stopPrank(); + + _simulateMigration(name2); + + vm.expectRevert(); + graveyard.clear(_oneName(name3)); + + _simulateMigration(name3); + + graveyard.clear(_oneName(name3)); + + assertEq(registryV1.resolver(NameCoder.namehash(name2, 0)), address(0), "2"); + assertEq(registryV1.resolver(NameCoder.namehash(name3, 0)), address(0), "3"); + } + + function test_clear_nestedLocked_migrateParent_expiredChild() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes memory name3 = + createWrappedChild(name2, testLabel, PARENT_CANNOT_CONTROL | CANNOT_UNWRAP); + + // set resolvers + vm.startPrank(testOwner); + nameWrapper.setResolver(NameCoder.namehash(name2, 0), address(1)); + nameWrapper.setResolver(NameCoder.namehash(name3, 0), address(1)); + vm.stopPrank(); + + _simulateMigration(name2); + + vm.expectRevert(); + graveyard.clear(_oneName(name3)); + + _simulateExpiry(name3); + + graveyard.clear(_oneName(name3)); + + assertEq(registryV1.resolver(NameCoder.namehash(name2, 0)), address(0), "2"); + assertEq(registryV1.resolver(NameCoder.namehash(name3, 0)), address(0), "3"); + } + + function test_clear_nestedLocked_bothExpired() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes memory name3 = + createWrappedChild(name2, testLabel, PARENT_CANNOT_CONTROL | CANNOT_UNWRAP); + + // set resolvers + vm.startPrank(testOwner); + nameWrapper.setResolver(NameCoder.namehash(name2, 0), address(1)); + nameWrapper.setResolver(NameCoder.namehash(name3, 0), address(1)); + vm.stopPrank(); + + // expiry(name2) > expiry(name3) + vm.prank(ethControllerV1); + nameWrapper.renew(uint256(keccak256(bytes(testLabel))), 10 days); + + vm.expectRevert(); + graveyard.clear(_oneName(name3)); + + _simulateExpiry(name3); + + vm.expectRevert(); + graveyard.clear(_oneName(name3)); + + _simulateExpiry(name2); + + graveyard.clear(_oneName(name3)); + + assertEq(registryV1.resolver(NameCoder.namehash(name2, 0)), address(0), "2"); + assertEq(registryV1.resolver(NameCoder.namehash(name3, 0)), address(0), "3"); + } + + function test_clear_migrateParent_unwrappedChild() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes memory name3 = NameCoder.addLabel(name2, testLabel); + + // claim 3LD ownership without wrapping + _claimNodes(name3, 0, testOwner); + + // set resolvers + vm.startPrank(testOwner); + nameWrapper.setResolver(NameCoder.namehash(name2, 0), address(1)); + registryV1.setResolver(NameCoder.namehash(name3, 0), address(1)); + vm.stopPrank(); + + _simulateMigration(name2); + + vm.expectRevert(abi.encodeWithSelector(Graveyard.NameRequiresPreimage.selector)); + graveyard.clear(_oneName(abi.encodePacked(uint8(0), keccak256(bytes(testLabel)), name2))); + + graveyard.clear(_oneName(name3)); + + assertEq(registryV1.resolver(NameCoder.namehash(name2, 0)), address(0), "2"); + assertEq(registryV1.resolver(NameCoder.namehash(name3, 0)), address(0), "3"); + } + + function test_clear_detachedAndUnmigrated() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes memory name3 = createWrappedChild(name2, testLabel, PARENT_CANNOT_CONTROL); + + // set resolvers + vm.startPrank(testOwner); + nameWrapper.setResolver(NameCoder.namehash(name2, 0), address(1)); + nameWrapper.setResolver(NameCoder.namehash(name3, 0), address(1)); + vm.stopPrank(); + + _simulateMigration(name2); + + vm.expectRevert(); + graveyard.clear(_oneName(name3)); + + graveyard.clear(_oneName(name2)); + + _simulateMigration(name3); + + graveyard.clear(_oneName(name3)); + + assertEq(registryV1.resolver(NameCoder.namehash(name2, 0)), address(0), "2"); + assertEq(registryV1.resolver(NameCoder.namehash(name3, 0)), address(0), "3"); + } + + function test_clear_detachedAndExpired(bool unwrapped) external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes memory name3 = createWrappedChild(name2, testLabel, PARENT_CANNOT_CONTROL); + + // set resolvers + vm.startPrank(testOwner); + nameWrapper.setResolver(NameCoder.namehash(name2, 0), address(1)); + nameWrapper.setResolver(NameCoder.namehash(name3, 0), address(1)); + vm.stopPrank(); + + if (unwrapped) { + vm.prank(testOwner); + nameWrapper.unwrap( + NameCoder.namehash(name2, 0), + keccak256(bytes(NameCoder.firstLabel(name3))), + address(testOwner) + ); + } + + _simulateExpiry(name2); + + graveyard.clear(_oneName(name3)); + + assertEq(registryV1.resolver(NameCoder.namehash(name2, 0)), address(0), "2"); + assertEq(registryV1.resolver(NameCoder.namehash(name3, 0)), address(0), "3"); + } + + function test_clear_locked_expired() external { + bytes memory name0 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes memory name = name0; + for (uint256 i; i < N; ++i) { + name = createWrappedChild(name, testLabel, PARENT_CANNOT_CONTROL | CANNOT_UNWRAP); + vm.prank(testOwner); + nameWrapper.setResolver(NameCoder.namehash(name, 0), address(1)); + } + + vm.expectRevert(); + graveyard.clear(_oneName(name)); + + _simulateExpiry(name0); + + graveyard.clear(_oneName(name)); + + name = name0; + for (uint256 i; i < N; ++i) { + name = NameCoder.addLabel(name, testLabel); + assertEq(registryV1.resolver(NameCoder.namehash(name, 0)), address(0), vm.toString(i)); + } + } + + function test_clear_complex() external { + bytes memory name2 = registerWrappedETH2LD("2", CANNOT_UNWRAP); + bytes memory name3 = createWrappedChild(name2, "3", PARENT_CANNOT_CONTROL); + bytes memory name4 = createWrappedChild(name3, "4", CAN_DO_EVERYTHING); + + // set resolvers + vm.startPrank(testOwner); + nameWrapper.setResolver(NameCoder.namehash(name3, 0), address(1)); + nameWrapper.setResolver(NameCoder.namehash(name3, 0), address(1)); + nameWrapper.setResolver(NameCoder.namehash(name4, 0), address(1)); + vm.stopPrank(); + + // unwrap name4 + vm.prank(testOwner); + nameWrapper.unwrap( + NameCoder.namehash(name3, 0), + keccak256(bytes(NameCoder.firstLabel(name4))), + address(testOwner) + ); + + // name2 = locked + // name3 = detached (wrapped unlocked emancipated) + // name4 = unwrapped + + _simulateMigration(name2); + _simulateMigration(name3); + + graveyard.clear(_oneName(name4)); + + assertEq(registryV1.resolver(NameCoder.namehash(name2, 0)), address(0), "2"); + assertEq(registryV1.resolver(NameCoder.namehash(name3, 0)), address(0), "3"); + assertEq(registryV1.resolver(NameCoder.namehash(name4, 0)), address(0), "4"); + } + + //////////////////////////////////////////////////////////////////////// + // Helpers + //////////////////////////////////////////////////////////////////////// + + /// @dev Clear resolver if possible and transfer to graveyard. + function _simulateMigration(bytes memory name) internal { + bytes32 node = NameCoder.namehash(name, 0); + (bytes32 labelHash, uint256 offset) = NameCoder.readLabel(name, 0); + bytes32 parentNode = NameCoder.namehash(name, offset); + address owner = registryV1.owner(node); + if (owner == address(nameWrapper)) { + uint32 fuses; + (owner, fuses, ) = nameWrapper.getData(uint256(node)); + if ((fuses & CANNOT_SET_RESOLVER) == 0) { + vm.prank(owner); + nameWrapper.setResolver(node, address(0)); + } + if ((fuses & CANNOT_UNWRAP) == 0) { + vm.prank(owner); + nameWrapper.unwrap(parentNode, labelHash, address(graveyard)); + } else { + vm.prank(owner); + nameWrapper.safeTransferFrom(owner, address(graveyard), uint256(node), 1, ""); + } + } else if (parentNode == NameCoder.ETH_NODE) { + vm.prank(owner); + registryV1.setRecord( + node, + address(graveyard), // owner + address(0), // resolver + 0 // ttl + ); + vm.prank(owner); + baseRegistrar.safeTransferFrom(owner, address(graveyard), uint256(labelHash)); + } else { + revert("migrated failed"); + } + } + + /// @dev Warp past expiry + grace. + function _simulateExpiry(bytes memory name) internal { + (bytes32 labelHash, uint256 offset) = NameCoder.readLabel(name, 0); + if (NameCoder.namehash(name, offset) == NameCoder.ETH_NODE) { + vm.warp(baseRegistrar.nameExpires(uint256(labelHash)) + gracePeriodV1); + } else { + (address owner, , uint64 expiry) = + nameWrapper.getData(uint256(NameCoder.namehash(name, 0))); + if (owner != address(0)) { + vm.warp(expiry + 1); // see: gracePeriodV1 definition + } + } + } + + /// @dev Create random .eth name with known 2LD. + function _randomEthName() internal returns (bytes memory name) { + name = NameCoder.ethName(testLabel); + for (uint256 n = vm.randomUint(0, 10); n > 0; --n) { + name = NameCoder.addLabel(name, new string(vm.randomUint(1, 255))); + } + } + + /// @dev Convert labelhash to encoded form. + function _encodedLabelHash(bytes32 labelHash) internal pure returns (string memory) { + return string(abi.encodePacked("[", HexUtils.bytesToHex(abi.encodePacked(labelHash)), "]")); + } + + function _oneName(bytes memory name) internal pure returns (bytes[] memory names) { + names = new bytes[](1); + names[0] = name; + } +} diff --git a/contracts/test/unit/migration/LockedMigrationController.t.sol b/contracts/test/unit/migration/LockedMigrationController.t.sol index 5f5d6e0a0..72fe3051b 100644 --- a/contracts/test/unit/migration/LockedMigrationController.t.sol +++ b/contracts/test/unit/migration/LockedMigrationController.t.sol @@ -2,85 +2,98 @@ pragma solidity >=0.8.13; import {console} from "forge-std/console.sol"; + import { INameWrapper, OperationProhibited, CANNOT_UNWRAP, CAN_DO_EVERYTHING, + CANNOT_APPROVE, CANNOT_BURN_FUSES, CANNOT_TRANSFER, CANNOT_SET_RESOLVER, - CANNOT_SET_TTL, CANNOT_CREATE_SUBDOMAIN, PARENT_CANNOT_CONTROL, - IS_DOT_ETH, CAN_EXTEND_EXPIRY } from "@ens/contracts/wrapper/NameWrapper.sol"; +import {ENS} from "@ens/contracts/registry/ENS.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import {IERC1155Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {IVerifiableFactory} from "@ensdomains/verifiable-factory/IVerifiableFactory.sol"; -import {UnauthorizedCaller} from "~src/CommonErrors.sol"; -import {ENSV1Resolver} from "~src/resolver/ENSV1Resolver.sol"; -import {ENSV2Resolver} from "~src/resolver/ENSV2Resolver.sol"; +import {InvalidOwner, UnauthorizedCaller} from "~src/CommonErrors.sol"; import {LibLabel} from "~src/utils/LibLabel.sol"; +import {ILabelStore} from "~src/utils/interfaces/ILabelStore.sol"; +import {LibMigration} from "~src/migration/libraries/LibMigration.sol"; import {WrappedErrorLib} from "~src/utils/WrappedErrorLib.sol"; -import { - LockedMigrationController, - IPermissionedRegistry -} from "~src/migration/LockedMigrationController.sol"; -import {InvalidOwner, FUSES_TO_BURN} from "~src/migration/LockedWrapperReceiver.sol"; -import { - IEnhancedAccessControl, - EACBaseRolesLib -} from "~src/access-control/EnhancedAccessControl.sol"; -import { - WrapperRegistry, - IWrapperRegistry, - IStandardRegistry, - IRegistry, - UUPSUpgradeable, - RegistryRolesLib, - LibMigration -} from "~src/registry/WrapperRegistry.sol"; -import { - MigrationControllerFixture, - ERC165Checker, - NameCoder -} from "./MigrationControllerFixture.sol"; -import {V1Fixture, ENS} from "~test/fixtures/V1Fixture.sol"; -import {V2Fixture, VerifiableFactory} from "~test/fixtures/V2Fixture.sol"; +import {LockedMigrationController} from "~src/migration/LockedMigrationController.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {IStandardRegistry} from "~src/registry/interfaces/IStandardRegistry.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {IEnhancedAccessControl} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; +import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; +import {WrapperRegistry, IWrapperRegistry} from "~src/registry/WrapperRegistry.sol"; +import {IRegistryEvents} from "~src/registry/interfaces/IRegistryEvents.sol"; +import {ApprovedUpgradeGate} from "~src/registry/ApprovedUpgradeGate.sol"; +import {PublicResolverV2} from "~src/resolver/PublicResolverV2.sol"; +import {IAddressSet} from "~src/utils/interfaces/IAddressSet.sol"; +import {PermissionedAddressSet} from "~src/utils/PermissionedAddressSet.sol"; +import {MigrationControllerFixture} from "~test/fixtures/MigrationControllerFixture.sol"; contract LockedMigrationControllerTest is MigrationControllerFixture { LockedMigrationController migrationController; + ApprovedUpgradeGate approvedUpgradeGate; WrapperRegistry wrapperRegistryImpl; + PermissionedAddressSet publicResolverSet; + PublicResolverV2 publicResolver; + + function setUp() external { + deployMigrationControllerFixture(); + + approvedUpgradeGate = new ApprovedUpgradeGate(address(this)); - function setUp() public override { - super.setUp(); + publicResolverSet = new PermissionedAddressSet(address(this)); + publicResolver = new PublicResolverV2(nameWrapper, rootRegistry, contractNamer); + + vm.expectEmit(); + emit IRegistryEvents.RegistryCreated(); wrapperRegistryImpl = new WrapperRegistry( nameWrapper, + address(graveyard), verifiableFactory, address(ensV1Resolver), - hcaFactory, - metadata + approvedUpgradeGate, + labelStore, + publicResolverSet, + address(publicResolver), + address(this) // namer ); + migrationController = new LockedMigrationController( - ethRegistry, nameWrapper, + address(graveyard), + ethRegistry, verifiableFactory, - address(wrapperRegistryImpl) + address(wrapperRegistryImpl), + publicResolverSet, + address(publicResolver), + contractNamer ); - ethRegistry.grantRootRoles(RegistryRolesLib.ROLE_REGISTRAR, premigrationController); + ethRegistry.grantRootRoles( RegistryRolesLib.ROLE_REGISTER_RESERVED, address(migrationController) ); - ethRegistrarV1.setResolver(address(ensV2Resolver)); } - function test_constructor() external view { - assertEq(address(migrationController.ETH_REGISTRY()), address(ethRegistry), "ETH_REGISTRY"); + function test_constructor_controller() external view { + assertEq(address(migrationController.GRAVEYARD()), address(graveyard), "GRAVEYARD"); assertEq(address(migrationController.NAME_WRAPPER()), address(nameWrapper), "NAME_WRAPPER"); + assertEq(address(migrationController.ETH_REGISTRY()), address(ethRegistry), "ETH_REGISTRY"); assertEq( address(migrationController.VERIFIABLE_FACTORY()), address(verifiableFactory), @@ -91,11 +104,28 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { address(wrapperRegistryImpl), "WRAPPER_REGISTRY_IMPL" ); + assertEq( + address(migrationController.CONTRACT_NAMER()), + address(contractNamer), + "CONTRACT_NAMER" + ); + assertEq(migrationController.getWrappedName(), NameCoder.encode("eth"), "getWrappedName"); assertEq(migrationController.getWrappedNode(), NameCoder.ETH_NODE, "getWrappedNode"); } - function test_supportsInterface() external view { + function test_constructor_registry() external view { + assertEq(address(wrapperRegistryImpl.GRAVEYARD()), address(graveyard), "GRAVEYARD"); + assertEq(address(wrapperRegistryImpl.NAME_WRAPPER()), address(nameWrapper), "NAME_WRAPPER"); + assertEq( + address(wrapperRegistryImpl.VERIFIABLE_FACTORY()), + address(verifiableFactory), + "VERIFIABLE_FACTORY" + ); + assertEq(wrapperRegistryImpl.V1_RESOLVER(), address(ensV1Resolver), "V1_RESOLVER"); + } + + function test_supportsInterface_controller() external view { assertTrue( ERC165Checker.supportsInterface( address(migrationController), @@ -105,33 +135,122 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ); } + function test_supportsInterface_registry() external view { + assertTrue( + ERC165Checker.supportsInterface( + address(migrationController), + type(IERC1155Receiver).interfaceId + ), + "IERC1155Receiver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(wrapperRegistryImpl), + type(IWrapperRegistry).interfaceId + ), + "IWrapperRegistry" + ); + } + + function test_implementationIsNameable() external view { + assertTrue(wrapperRegistryImpl.isContractNamer(address(this))); + } + + function test_wrapperRegistryUpgrade_revertsForUnapprovedTarget() external { + WrapperRegistry registry = _deployWrapperRegistryProxy(); + WrapperRegistryV2Mock newImplementation = _newWrapperRegistryV2Mock(); + + vm.expectRevert( + abi.encodeWithSelector( + IWrapperRegistry.UpgradeTargetNotApproved.selector, + address(newImplementation) + ) + ); + vm.prank(testOwner); + registry.upgradeToAndCall(address(newImplementation), ""); + } + + function test_wrapperRegistryUpgrade_allowsApprovedTarget() external { + WrapperRegistry registry = _deployWrapperRegistryProxy(); + WrapperRegistryV2Mock newImplementation = _newWrapperRegistryV2Mock(); + + approvedUpgradeGate.setImplementationApproval(address(newImplementation), true); + + vm.prank(testOwner); + registry.upgradeToAndCall(address(newImplementation), ""); + + assertEq(WrapperRegistryV2Mock(address(registry)).version(), 2, "version"); + } + + function test_wrapperRegistryUpgrade_requiresUpgradeRole() external { + WrapperRegistry registry = _deployWrapperRegistryProxy(); + WrapperRegistryV2Mock newImplementation = _newWrapperRegistryV2Mock(); + + approvedUpgradeGate.setImplementationApproval(address(newImplementation), true); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + registry.ROOT_RESOURCE(), + RegistryRolesLib.ROLE_UPGRADE, + actor + ) + ); + vm.prank(actor); + registry.upgradeToAndCall(address(newImplementation), ""); + } + + function test_MIN_DATA_SIZE() external pure { + LibMigration.Data memory md; + assertLt(abi.encode(md).length, LibMigration.MIN_DATA_SIZE, "empty"); + md.label = new string(1); // shortest + assertEq(abi.encode(md).length, LibMigration.MIN_DATA_SIZE, "short"); + } + function test_finishERC1155Migration_unauthorizedCaller() external { - vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, user)); - vm.prank(user); + vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, actor)); + vm.prank(actor); migrationController.finishERC1155Migration(new uint256[](0), new LibMigration.Data[](0)); } function test_safeTransferFrom_unauthorizedCaller() external { - uint256 tokenId = dummy1155.mint(user); + uint256 tokenId = dummy1155.mint(actor); vm.expectRevert( WrappedErrorLib.wrap(abi.encodeWithSelector(UnauthorizedCaller.selector, dummy1155)) ); - vm.prank(user); - dummy1155.safeTransferFrom(user, address(migrationController), tokenId, 1, ""); // wrong + vm.prank(actor); + dummy1155.safeTransferFrom(actor, address(migrationController), tokenId, 1, ""); // wrong } - function test_migrate_invalidData() external { + function test_onERC1155Received_unauthorizedCaller() external { + vm.expectRevert( + WrappedErrorLib.wrap(abi.encodeWithSelector(UnauthorizedCaller.selector, actor)) + ); + vm.prank(actor); + migrationController.onERC1155Received(address(0), address(0), 1, 1, ""); + } + + function test_onERC1155Received_invalidData() external { + vm.expectRevert( + WrappedErrorLib.wrap(abi.encodeWithSelector(LibMigration.InvalidData.selector)) + ); + vm.prank(address(nameWrapper)); + migrationController.onERC1155Received(address(0), address(0), 1, 1, ""); + } + + function test_migrate_invalidData(bytes calldata v) external { + vm.assume(v.length < LibMigration.MIN_DATA_SIZE); bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); vm.expectRevert( WrappedErrorLib.wrap(abi.encodeWithSelector(LibMigration.InvalidData.selector)) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name, 0)), 1, - "" // wrong + v // wrong ); } @@ -141,7 +260,7 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { uint256[] memory amounts = new uint256[](1); LibMigration.Data[] memory mds = new LibMigration.Data[](1); ids[0] = uint256(NameCoder.namehash(name, 0)); - mds[0] = _makeData(name); + mds[0] = _lockedData(name); amounts[0] = 1; bytes memory payload = abi.encode(mds); uint256 fakeLength = 0; @@ -157,9 +276,9 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ) ) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeBatchTransferFrom( - user, + testOwner, address(migrationController), ids, amounts, @@ -167,14 +286,33 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ); } - function test_migrate_invalidReceiver() external { + function test_migrate_invalidOwner() external { bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _lockedData(name); md.owner = address(0); // wrong vm.expectRevert(WrappedErrorLib.wrap(abi.encodeWithSelector(InvalidOwner.selector))); - vm.prank(user); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(NameCoder.namehash(name, 0)), + 1, + abi.encode(md) + ); + } + + function test_migrate_invalidReceiver() external { + bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + LibMigration.Data memory md = _lockedData(name); + md.owner = address(ethRegistry); // not a IERC1155Receiver + vm.expectRevert( + WrappedErrorLib.wrap( + abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, md.owner) + ) + ); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name, 0)), 1, @@ -185,16 +323,16 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { function test_migrate_nameDataMismatch() external { bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); bytes32 node = NameCoder.namehash(name, 0); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _lockedData(name); md.label = "wrong"; vm.expectRevert( WrappedErrorLib.wrap( abi.encodeWithSelector(LibMigration.NameDataMismatch.selector, node) ) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(node), 1, @@ -205,13 +343,13 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { function test_migrate_nameNotLocked() external { bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); bytes32 node = NameCoder.namehash(name, 0); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _lockedData(name); vm.expectRevert( WrappedErrorLib.wrap(abi.encodeWithSelector(LibMigration.NameNotLocked.selector, node)) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(node), 1, @@ -222,7 +360,7 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { function test_migrate_notReserved() external { premigrationController = address(0); // disable premigration bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _lockedData(name); vm.expectRevert( WrappedErrorLib.wrap( abi.encodeWithSelector( @@ -233,69 +371,94 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ) ) ); - vm.prank(user); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(NameCoder.namehash(name, 0)), + 1, + abi.encode(md) + ); + } + + function test_checkIfMigrated() external { + bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + LibMigration.Data memory md = _lockedData(name); + uint256 tokenIdV1 = LibLabel.id(md.label); + + assertFalse(ethRegistry.hasRoles(tokenIdV1, RegistryRolesLib.ROLE_WAS_RESERVED, testOwner)); + + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name, 0)), 1, abi.encode(md) ); + + assertTrue(ethRegistry.hasRoles(tokenIdV1, RegistryRolesLib.ROLE_WAS_RESERVED, testOwner)); } function test_migrate() external { bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); checkResolution(name, address(ensV2Resolver), address(ensV1Resolver)); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _lockedData(name); bytes32 node = NameCoder.namehash(name, 0); - address expectedRegistry = _computeVerifiableFactoryAddress( - address(migrationController), - md.salt - ); + uint256 salt = uint256(node); uint256 tokenIdV1 = LibLabel.id(md.label); uint256 tokenId = LibLabel.withVersion(tokenIdV1, 0); + address expectedRegistry = + _computeVerifiableFactoryAddress(address(migrationController), salt); + uint64 expectedExpiry = + uint64(baseRegistrar.nameExpires(tokenIdV1)) + premigrationBonusPeriod; + address virtualOwner = address(ethRegistry); vm.expectEmit(); - emit IERC1155.TransferSingle(user, user, address(migrationController), uint256(node), 1); + emit IERC1155.TransferSingle( + testOwner, + testOwner, + address(migrationController), + uint256(node), + 1 + ); vm.expectEmit(); emit ENS.NewResolver(node, address(0)); // emit IERC1967.Upgraded() vm.expectEmit(); + emit IRegistryEvents.RegistryCreated(); + vm.expectEmit(); emit IEnhancedAccessControl.EACRolesChanged( 0 /*ROOT_RESOURCE*/, - md.owner, + virtualOwner, 0 /*old roles*/, + RegistryRolesLib.ROLE_UPGRADE | RegistryRolesLib.ROLE_UPGRADE_ADMIN | - RegistryRolesLib.ROLE_UPGRADE | - RegistryRolesLib.ROLE_REGISTRAR | - RegistryRolesLib.ROLE_REGISTRAR_ADMIN | - RegistryRolesLib.ROLE_RENEW | - RegistryRolesLib.ROLE_RENEW_ADMIN + RegistryRolesLib.ROLE_REGISTRAR | + RegistryRolesLib.ROLE_REGISTRAR_ADMIN | + RegistryRolesLib.ROLE_RENEW | + RegistryRolesLib.ROLE_RENEW_ADMIN | + RegistryRolesLib.ROLE_CAN_NAME | + RegistryRolesLib.ROLE_CAN_NAME_ADMIN ); // emit Initializable.Initialized() vm.expectEmit(); - emit VerifiableFactory.ProxyDeployed( + emit IVerifiableFactory.ProxyDeployed( address(migrationController), expectedRegistry, - md.salt, + salt, address(wrapperRegistryImpl) ); vm.expectEmit(); - emit IRegistry.NameRegistered( + emit IRegistryEvents.LabelRegistered( tokenId, bytes32(tokenIdV1), md.label, md.owner, - uint64(ethRegistrarV1.nameExpires(tokenIdV1)), + expectedExpiry, address(migrationController) ); vm.expectEmit(); - emit IERC1155.TransferSingle( - address(migrationController), - address(0), - md.owner, - tokenId, - 1 - ); + emit IERC1155.TransferSingle(address(migrationController), address(0), md.owner, tokenId, 1); vm.expectEmit(); emit IPermissionedRegistry.TokenResource(tokenId, tokenId); vm.expectEmit(); @@ -304,28 +467,24 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { md.owner, 0 /*old roles*/, RegistryRolesLib.ROLE_SET_RESOLVER | - RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN | - RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN + RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN | + RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN | + RegistryRolesLib.ROLE_WAS_RESERVED ); vm.expectEmit(); - emit IRegistry.SubregistryUpdated( + emit IRegistryEvents.SubregistryUpdated( tokenId, IRegistry(expectedRegistry), address(migrationController) ); vm.expectEmit(); - emit IRegistry.ResolverUpdated(tokenId, md.resolver, address(migrationController)); - vm.expectEmit(); - emit INameWrapper.FusesSet( - node, - FUSES_TO_BURN | CANNOT_UNWRAP | PARENT_CANNOT_CONTROL | IS_DOT_ETH - ); - vm.prank(user); + emit IRegistryEvents.ResolverUpdated(tokenId, md.resolver, address(migrationController)); + vm.prank(testOwner); uint256 g = gasleft(); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), - uint256(NameCoder.namehash(name, 0)), + uint256(node), 1, abi.encode(md) ); @@ -333,24 +492,25 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { assertEq(ethRegistry.getTokenId(tokenIdV1), tokenId, "tokenId"); assertEq(ethRegistry.ownerOf(tokenId), md.owner, "owner"); - assertEq(ethRegistry.getExpiry(tokenId), ethRegistrarV1.nameExpires(tokenIdV1), "expiry"); + assertEq(ethRegistry.getExpiry(tokenId), expectedExpiry, "expiry"); assertEq(ethRegistry.getResolver(md.label), md.resolver, "resolver"); checkResolution(name, address(ensV2Resolver), md.resolver); - IWrapperRegistry subregistry = IWrapperRegistry( - address(ethRegistry.getSubregistry(md.label)) - ); + IWrapperRegistry subregistry = + IWrapperRegistry(address(ethRegistry.getSubregistry(md.label))); assertTrue( - ERC165Checker.supportsInterface( - address(subregistry), - type(IWrapperRegistry).interfaceId - ), + ERC165Checker.supportsInterface(address(subregistry), type(IWrapperRegistry).interfaceId), "IWrapperRegistry" ); assertTrue( - subregistry.hasRootRoles(RegistryRolesLib.ROLE_REGISTRAR, md.owner), + subregistry.hasRootRoles(RegistryRolesLib.ROLE_REGISTRAR, address(ethRegistry)), "ROLE_REGISTRAR" ); - assertEq(subregistry.roleCount(RegistryRolesLib.ROLE_SET_PARENT), 0, "ROLE_SET_PARENT"); + assertEq( + subregistry.roleCount(subregistry.ROOT_RESOURCE()) & + (RegistryRolesLib.ROLE_SET_PARENT * 15), + 0, + "ROLE_SET_PARENT" + ); assertEq(subregistry.getWrappedNode(), node, "getWrappedNode"); assertEq(subregistry.getWrappedName(), name, "getWrappedName"); assertEq(universalResolver.findCanonicalName(subregistry), name, "findCanonicalName"); @@ -363,15 +523,15 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { LibMigration.Data[] memory mds = new LibMigration.Data[](count); for (uint256 i; i < count; ++i) { bytes memory name = registerWrappedETH2LD(_label(i), CANNOT_UNWRAP); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _lockedData(name); md.resolver = address(uint160(i)); mds[i] = md; ids[i] = uint256(NameCoder.namehash(name, 0)); amounts[i] = 1; } - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeBatchTransferFrom( - user, + testOwner, address(migrationController), ids, amounts, @@ -380,7 +540,7 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { for (uint256 i; i < count; ++i) { string memory label = _label(i); uint256 tokenId = ethRegistry.getTokenId(LibLabel.id(label)); - assertEq(ethRegistry.ownerOf(tokenId), user, "owner"); + assertEq(ethRegistry.ownerOf(tokenId), testOwner, "owner"); assertEq(ethRegistry.getResolver(label), address(uint160(i)), "resolver"); assertTrue( ERC165Checker.supportsInterface( @@ -398,11 +558,9 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { uint256[] memory amounts = new uint256[](count); LibMigration.Data[] memory mds = new LibMigration.Data[](count); for (uint256 i; i < count; ++i) { - bytes memory name = registerWrappedETH2LD( - _label(i), - i == count - 1 ? CAN_DO_EVERYTHING : CANNOT_UNWRAP - ); - LibMigration.Data memory md = _makeData(name); + bytes memory name = + registerWrappedETH2LD(_label(i), i == count - 1 ? CAN_DO_EVERYTHING : CANNOT_UNWRAP); + LibMigration.Data memory md = _lockedData(name); mds[i] = md; ids[i] = uint256(NameCoder.namehash(name, 0)); amounts[i] = 1; @@ -412,9 +570,9 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { abi.encodeWithSelector(LibMigration.NameNotLocked.selector, ids[count - 1]) ) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeBatchTransferFrom( - user, + testOwner, address(migrationController), ids, amounts, @@ -422,21 +580,72 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ); } + function test_migrate_transferRegistryControl() external { + bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes32 node = NameCoder.namehash(name, 0); + LibMigration.Data memory md = _lockedData(name); + + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(node), + 1, + abi.encode(md) + ); + + IWrapperRegistry registry = IWrapperRegistry(address(ethRegistry.getSubregistry(md.label))); + address virtualOwner = address(ethRegistry); + + vm.prank(testOwner); + registry.setApprovalForAll(actor, true); + + uint256 rootRoles = registry.roles(registry.ROOT_RESOURCE(), virtualOwner); + assertEq(registry.roles(registry.ROOT_RESOURCE(), testOwner), rootRoles, "before:owner"); + assertEq(registry.roles(registry.ROOT_RESOURCE(), friend), 0, "before:friend"); + assertEq(registry.roles(registry.ROOT_RESOURCE(), actor), 0, "before:actor"); + + // owner cannot grant admin + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + registry.ROOT_RESOURCE(), + rootRoles, + testOwner + ) + ); + vm.prank(testOwner); + registry.grantRootRoles(rootRoles, friend); + + // transfer token + uint256 tokenId = ethRegistry.findTokenId(md.label); + vm.prank(testOwner); + ethRegistry.safeTransferFrom(testOwner, friend, tokenId, 1, ""); + + // effective roles have "transferred" + assertEq(registry.roles(registry.ROOT_RESOURCE(), testOwner), 0, "after:owner"); + assertEq(registry.roles(registry.ROOT_RESOURCE(), friend), rootRoles, "after:friend"); + assertEq(registry.roles(registry.ROOT_RESOURCE(), actor), 0, "after:actor"); + + // underlying virtual owner roles are unchanged + assertEq(registry.roles(registry.ROOT_RESOURCE(), virtualOwner), rootRoles, "virtual"); + } + function test_migrate_lockedResolver() external { bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); bytes32 node = NameCoder.namehash(name, 0); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _lockedData(name); address frozenResolver = makeAddr("frozenResolver"); - vm.prank(user); + vm.prank(testOwner); nameWrapper.setResolver(node, frozenResolver); - vm.prank(user); + vm.prank(testOwner); nameWrapper.setFuses(node, uint16(CANNOT_UNWRAP | CANNOT_SET_RESOLVER)); assertNotEq(md.resolver, frozenResolver, "diff"); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(node), 1, @@ -446,28 +655,60 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { uint256 tokenId = ethRegistry.getTokenId(LibLabel.id(md.label)); assertEq(ethRegistry.getResolver(md.label), frozenResolver, "frozen"); checkResolution(name, frozenResolver, frozenResolver); - assertFalse(ethRegistry.hasRoles(tokenId, RegistryRolesLib.ROLE_SET_RESOLVER, user)); + assertFalse(ethRegistry.hasRoles(tokenId, RegistryRolesLib.ROLE_SET_RESOLVER, testOwner)); vm.expectRevert( abi.encodeWithSelector( IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, tokenId, RegistryRolesLib.ROLE_SET_RESOLVER, - user + testOwner ) ); - vm.prank(user); + vm.prank(testOwner); ethRegistry.setResolver(tokenId, testResolver); } + function test_migrate_lockedResolver_publicResolver() external { + bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); + bytes32 node = NameCoder.namehash(name, 0); + LibMigration.Data memory md = _lockedData(name); + + address oldPublicResolver = makeAddr("oldPublicResolver"); + vm.prank(testOwner); + nameWrapper.setResolver(node, oldPublicResolver); + vm.prank(testOwner); + nameWrapper.setFuses(node, uint16(CANNOT_UNWRAP | CANNOT_SET_RESOLVER)); + assertNotEq(md.resolver, oldPublicResolver, "diff"); + + // add as approved PublicResolver + publicResolverSet.approve(oldPublicResolver, true); + + assertFalse(publicResolver.canModifyName(node, testOwner), "before"); + + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(node), + 1, + abi.encode(md) + ); + + assertTrue(publicResolver.canModifyName(node, testOwner), "after"); + + assertEq(ethRegistry.getResolver(md.label), address(publicResolver), "prV2"); + checkResolution(name, address(oldPublicResolver), address(publicResolver)); + } + function test_migrate_lockedTransfer() external { bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP | CANNOT_TRANSFER); bytes32 node = NameCoder.namehash(name, 0); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _lockedData(name); vm.expectRevert(abi.encodeWithSelector(OperationProhibited.selector, node)); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(node), 1, @@ -475,13 +716,13 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ); } - function test_migrate_lockedExpiry() external { - bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP | CAN_EXTEND_EXPIRY); - LibMigration.Data memory md = _makeData(name); + function test_migrate_lockedFuses() external { + bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP | CANNOT_BURN_FUSES); + LibMigration.Data memory md = _lockedData(name); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name, 0)), 1, @@ -489,30 +730,28 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ); uint256 tokenId = ethRegistry.getTokenId(LibLabel.id(md.label)); - assertFalse(ethRegistry.hasRoles(tokenId, RegistryRolesLib.ROLE_RENEW, user)); - - vm.expectRevert( - abi.encodeWithSelector( - IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, - tokenId, - RegistryRolesLib.ROLE_RENEW, - user - ) + assertEq( + ethRegistry.roles(tokenId, testOwner) & EACBaseRolesLib.ADMIN_ROLES, + RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, + "token" + ); + IWrapperRegistry registry = IWrapperRegistry(address(ethRegistry.getSubregistry(md.label))); + address virtualOwner = address(ethRegistry); + assertEq( + registry.roles(registry.ROOT_RESOURCE(), virtualOwner) & EACBaseRolesLib.ADMIN_ROLES, + 0, + "registry" ); - vm.prank(user); - ethRegistry.renew(tokenId, _soon()); } - function test_migrate_lockedChildren() external { - bytes memory name = registerWrappedETH2LD( - testLabel, - CANNOT_UNWRAP | CANNOT_CREATE_SUBDOMAIN - ); - LibMigration.Data memory md = _makeData(name); + function test_migrate_cannotCreateChildren() external { + bytes memory name = + registerWrappedETH2LD(testLabel, CANNOT_UNWRAP | CANNOT_CREATE_SUBDOMAIN); + LibMigration.Data memory md = _lockedData(name); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name, 0)), 1, @@ -520,20 +759,20 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ); uint256 tokenId = ethRegistry.getTokenId(LibLabel.id(md.label)); - assertFalse(ethRegistry.hasRoles(tokenId, RegistryRolesLib.ROLE_REGISTRAR, user)); + assertFalse(ethRegistry.hasRoles(tokenId, RegistryRolesLib.ROLE_REGISTRAR, testOwner)); vm.expectRevert( abi.encodeWithSelector( IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, ethRegistry.ROOT_RESOURCE(), RegistryRolesLib.ROLE_REGISTRAR, - user + testOwner ) ); - vm.prank(user); + vm.prank(testOwner); ethRegistry.register( string.concat(testLabel, testLabel), - user, + testOwner, IRegistry(address(0)), address(0), 0, @@ -541,51 +780,217 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { ); } - function test_migrate_lockedFuses() external { - bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP | CANNOT_BURN_FUSES); - LibMigration.Data memory md = _makeData(name); + function test_migrate_cannotCreateChildren_cannotRevive() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes32 node2 = NameCoder.namehash(name2, 0); + bytes memory name3 = createWrappedChild(name2, "sub", PARENT_CANNOT_CONTROL); - vm.prank(user); + // burn fuse + vm.prank(testOwner); + nameWrapper.setFuses(node2, uint16(CANNOT_CREATE_SUBDOMAIN)); + + // migrate 2LD + LibMigration.Data memory data2 = _lockedData(name2); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), - uint256(NameCoder.namehash(name, 0)), + uint256(node2), 1, - abi.encode(md) + abi.encode(data2) ); + IWrapperRegistry registry2 = + IWrapperRegistry(address(ethRegistry.getSubregistry(data2.label))); - uint256 tokenId = ethRegistry.getTokenId(LibLabel.id(md.label)); - assertEq( - ethRegistry.roles(tokenId, user) & EACBaseRolesLib.ADMIN_ROLES, - RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, - "token" + // migrate 3LD + LibMigration.Data memory data3 = _unlockedData(name3); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(registry2), + uint256(NameCoder.namehash(name3, 0)), + 1, + abi.encode(data3) ); - IWrapperRegistry registry = IWrapperRegistry(address(ethRegistry.getSubregistry(md.label))); - assertEq( - registry.roles(registry.ROOT_RESOURCE(), user) & EACBaseRolesLib.ADMIN_ROLES, - RegistryRolesLib.ROLE_UPGRADE_ADMIN | RegistryRolesLib.ROLE_RENEW_ADMIN, - "registry" + + // can renew + uint256 tokenId = registry2.findTokenId(data3.label); + uint64 newExpiry = registry2.getExpiry(tokenId) + 1; + vm.prank(testOwner); + registry2.renew(tokenId, newExpiry); + + vm.warp(newExpiry); + assertEq(uint8(registry2.getStatus(tokenId)), uint8(IPermissionedRegistry.Status.AVAILABLE)); + + // cannot revive + vm.expectRevert(abi.encodeWithSelector(IStandardRegistry.LabelExpired.selector, tokenId)); + vm.prank(testOwner); + registry2.renew(tokenId, _soon()); + } + + function test_migrate_canCreateChildren_canRevive() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes32 node2 = NameCoder.namehash(name2, 0); + bytes memory name3 = createWrappedChild(name2, "sub", PARENT_CANNOT_CONTROL); + + // migrate 2LD (CANNOT_CREATE_SUBDOMAIN not burned -> ROLE_REGISTRAR retained) + LibMigration.Data memory data2 = _lockedData(name2); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(node2), + 1, + abi.encode(data2) + ); + IWrapperRegistry registry2 = + IWrapperRegistry(address(ethRegistry.getSubregistry(data2.label))); + + // migrate 3LD + LibMigration.Data memory data3 = _unlockedData(name3); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(registry2), + uint256(NameCoder.namehash(name3, 0)), + 1, + abi.encode(data3) + ); + + // let it expire + uint256 tokenId = registry2.findTokenId(data3.label); + uint64 expiry = registry2.getExpiry(tokenId); + vm.warp(expiry); + assertEq(uint8(registry2.getStatus(tokenId)), uint8(IPermissionedRegistry.Status.AVAILABLE)); + + // can revive: root role holder may revive because CANNOT_CREATE_SUBDOMAIN was not burned + uint64 newExpiry = _soon(); + vm.prank(address(ethRegistry)); + registry2.renew(tokenId, newExpiry); + assertEq(uint8(registry2.getStatus(tokenId)), uint8(IPermissionedRegistry.Status.REGISTERED)); + assertEq(registry2.getExpiry(tokenId), newExpiry); + } + + function test_migrate_canExtendExpiry() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + vm.prank(friend); + bytes memory name3 = + this.createWrappedChild( + name2, + "sub", + CANNOT_UNWRAP | PARENT_CANNOT_CONTROL | CAN_EXTEND_EXPIRY + ); + + // migrate 2LD + LibMigration.Data memory data2 = _lockedData(name2); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(NameCoder.namehash(name2, 0)), + 1, + abi.encode(data2) + ); + IWrapperRegistry registry2 = + IWrapperRegistry(address(ethRegistry.getSubregistry(data2.label))); + + // migrate 3LD + LibMigration.Data memory data3 = _lockedData(name3); + vm.prank(friend); + nameWrapper.safeTransferFrom( + friend, + address(registry2), + uint256(NameCoder.namehash(name3, 0)), + 1, + abi.encode(data3) ); + + uint256 tokenId = registry2.getTokenId(LibLabel.id(data3.label)); + assertTrue(registry2.hasRoles(tokenId, RegistryRolesLib.ROLE_RENEW, friend), "ROLE_RENEW"); + + uint64 expiry = registry2.getExpiry(tokenId); + vm.prank(friend); + registry2.renew(tokenId, expiry + 1); } - function test_migrate_emancipatedChildren() external { + function test_migrate_emancipated_canExtendExpiry() external { bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); - bytes memory name3 = createWrappedChild( - name2, - "sub", - CANNOT_UNWRAP | PARENT_CANNOT_CONTROL + vm.prank(friend); + bytes memory name3 = + this.createWrappedChild(name2, "sub", PARENT_CANNOT_CONTROL | CAN_EXTEND_EXPIRY); + vm.prank(friend); + bytes memory name3plain = this.createWrappedChild(name2, "plain", PARENT_CANNOT_CONTROL); + + // migrate 2LD + LibMigration.Data memory data2 = _lockedData(name2); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(NameCoder.namehash(name2, 0)), + 1, + abi.encode(data2) ); - bytes memory name3unmigrated = createWrappedChild( - name2, - "unmigrated", - CANNOT_UNWRAP | PARENT_CANNOT_CONTROL + IWrapperRegistry registry2 = + IWrapperRegistry(address(ethRegistry.getSubregistry(data2.label))); + + // migrate emancipated 3LD with CAN_EXTEND_EXPIRY + LibMigration.Data memory data3 = _lockedData(name3); + vm.prank(friend); + nameWrapper.safeTransferFrom( + friend, + address(registry2), + uint256(NameCoder.namehash(name3, 0)), + 1, + abi.encode(data3) + ); + + uint256 tokenId = registry2.getTokenId(LibLabel.id(data3.label)); + assertTrue( + registry2.hasRoles( + tokenId, + RegistryRolesLib.ROLE_RENEW | RegistryRolesLib.ROLE_RENEW_ADMIN, + friend + ), + "ROLE_RENEW + ROLE_RENEW_ADMIN" + ); + + uint64 expiry = registry2.getExpiry(tokenId); + vm.prank(friend); + registry2.renew(tokenId, expiry + 1); + + // migrate emancipated 3LD without CAN_EXTEND_EXPIRY + LibMigration.Data memory data3plain = _lockedData(name3plain); + vm.prank(friend); + nameWrapper.safeTransferFrom( + friend, + address(registry2), + uint256(NameCoder.namehash(name3plain, 0)), + 1, + abi.encode(data3plain) ); + uint256 tokenIdPlain = registry2.getTokenId(LibLabel.id(data3plain.label)); + assertFalse( + registry2.hasRoles(tokenIdPlain, RegistryRolesLib.ROLE_RENEW, friend), + "no ROLE_RENEW" + ); + } + + function test_migrate_lockedChildren() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + vm.prank(friend); + bytes memory name3 = + this.createWrappedChild(name2, "sub", CANNOT_UNWRAP | PARENT_CANNOT_CONTROL); + vm.prank(friend); + bytes memory name3unmigrated = + this.createWrappedChild(name2, "unmigrated", CANNOT_UNWRAP | PARENT_CANNOT_CONTROL); + // migrate 2LD - LibMigration.Data memory data2 = _makeData(name2); - vm.prank(user); + LibMigration.Data memory data2 = _lockedData(name2); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name2, 0)), 1, @@ -596,24 +1001,18 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { data2.owner, "owner2" ); - IWrapperRegistry registry2 = IWrapperRegistry( - address(ethRegistry.getSubregistry(data2.label)) - ); + IWrapperRegistry registry2 = + IWrapperRegistry(address(ethRegistry.getSubregistry(data2.label))); assertTrue( ERC165Checker.supportsInterface(address(registry2), type(IWrapperRegistry).interfaceId), "registry2" ); // migrate 3LD - LibMigration.Data memory data3 = _makeData(name3); - vm.expectEmit(); - emit INameWrapper.FusesSet( - NameCoder.namehash(name3, 0), - FUSES_TO_BURN | CANNOT_UNWRAP | PARENT_CANNOT_CONTROL - ); - vm.prank(user); + LibMigration.Data memory data3 = _lockedData(name3); + vm.prank(friend); nameWrapper.safeTransferFrom( - user, + friend, address(registry2), uint256(NameCoder.namehash(name3, 0)), 1, @@ -634,36 +1033,328 @@ contract LockedMigrationControllerTest is MigrationControllerFixture { // check migrated 3LD child vm.expectRevert( - abi.encodeWithSelector(IStandardRegistry.NameAlreadyRegistered.selector, data3.label) + abi.encodeWithSelector(IStandardRegistry.LabelAlreadyRegistered.selector, data3.label) + ); + vm.prank(friend); + registry2.register(data3.label, testOwner, IRegistry(address(0)), address(0), 0, _soon()); + + // check unmigrated 3LD child + vm.expectRevert(abi.encodeWithSelector(LibMigration.NameRequiresMigration.selector)); + vm.prank(friend); + registry2.register( + NameCoder.firstLabel(name3unmigrated), + friend, + IRegistry(address(0)), + address(0), + 0, + _soon() + ); + + vm.prank(friend); + nameWrapper.setResolver(NameCoder.namehash(name3unmigrated, 0), testResolver); + checkResolution(name3unmigrated, testResolver, address(ensV1Resolver)); + } + + function test_migrate_detachedChildren_wrapped() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + vm.prank(friend); + bytes memory name3 = this.createWrappedChild(name2, "sub", PARENT_CANNOT_CONTROL); + vm.prank(friend); + bytes memory name3unmigrated = + this.createWrappedChild(name2, "unmigrated", PARENT_CANNOT_CONTROL); + + // migrate 2LD + LibMigration.Data memory data2 = _lockedData(name2); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(NameCoder.namehash(name2, 0)), + 1, + abi.encode(data2) + ); + assertEq( + ethRegistry.ownerOf(ethRegistry.getTokenId(LibLabel.id(data2.label))), + data2.owner, + "owner2" + ); + IWrapperRegistry registry2 = + IWrapperRegistry(address(ethRegistry.getSubregistry(data2.label))); + assertTrue( + ERC165Checker.supportsInterface(address(registry2), type(IWrapperRegistry).interfaceId), + "registry2" + ); + + // migrate 3LD + LibMigration.Data memory data3 = _lockedData(name3); + data3.subregistry = testRegistry; // override + vm.prank(friend); + nameWrapper.safeTransferFrom( + friend, + address(registry2), + uint256(NameCoder.namehash(name3, 0)), + 1, + abi.encode(data3) + ); + assertEq(registry2.getResolver(data3.label), data3.resolver, "resolver3"); + checkResolution(name3, address(ensV2Resolver), data3.resolver); + assertEq( + registry2.ownerOf(registry2.getTokenId(LibLabel.id(data3.label))), + data3.owner, + "owner3" + ); + assertEq(address(registry2.getSubregistry(data3.label)), address(testRegistry), "registry3"); + assertEq(registryV1.owner(NameCoder.namehash(name3, 0)), address(graveyard), "graveyard3"); + + // check migrated 3LD child + vm.expectRevert( + abi.encodeWithSelector(IStandardRegistry.LabelAlreadyRegistered.selector, data3.label) ); - vm.prank(user); - registry2.register(data3.label, user, IRegistry(address(0)), address(0), 0, _soon()); + vm.prank(friend); + registry2.register(data3.label, testOwner, IRegistry(address(0)), address(0), 0, _soon()); // check unmigrated 3LD child vm.expectRevert(abi.encodeWithSelector(LibMigration.NameRequiresMigration.selector)); - vm.prank(user); + vm.prank(friend); registry2.register( NameCoder.firstLabel(name3unmigrated), - user, + friend, IRegistry(address(0)), address(0), 0, _soon() ); - vm.prank(user); + vm.prank(friend); nameWrapper.setResolver(NameCoder.namehash(name3unmigrated, 0), testResolver); checkResolution(name3unmigrated, testResolver, address(ensV1Resolver)); } - function _makeData(bytes memory name) internal view returns (LibMigration.Data memory) { + function test_migrate_detachedChildren_unwrapped() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + vm.prank(friend); + bytes memory name3 = this.createWrappedChild(name2, "sub", PARENT_CANNOT_CONTROL); + bytes32 parentNode = NameCoder.namehash(name2, 0); + bytes32 subNode = NameCoder.namehash(name3, 0); + bytes32 subLabelHash = keccak256(bytes("sub")); + + // unwrap the emancipated child before the parent is migrated + vm.prank(friend); + nameWrapper.unwrap(parentNode, subLabelHash, friend); + (address ownerAfterUnwrap, uint32 fusesAfterUnwrap, ) = + nameWrapper.getData(uint256(subNode)); + assertEq(ownerAfterUnwrap, address(0), "wrapper owner cleared on unwrap"); + assertEq( + fusesAfterUnwrap & PARENT_CANNOT_CONTROL, + PARENT_CANNOT_CONTROL, + "PCC fuse persists across burn" + ); + assertEq(registryV1.owner(subNode), friend, "v1 registry owner is friend after unwrap"); + + // migrate 2LD parent + LibMigration.Data memory data2 = _lockedData(name2); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(parentNode), + 1, + abi.encode(data2) + ); + IWrapperRegistry registry2 = + IWrapperRegistry(address(ethRegistry.getSubregistry(data2.label))); + address virtualOwner = address(ethRegistry); + + // the registry itself holds ROLE_REGISTRAR on registry2 by default, + // so they could otherwise re-register the unwrapped emancipated subname in v2 + assertTrue( + registry2.hasRoles( + registry2.ROOT_RESOURCE(), + RegistryRolesLib.ROLE_REGISTRAR, + virtualOwner + ), + "testOwner has ROLE_REGISTRAR on registry2" + ); + vm.expectRevert(abi.encodeWithSelector(LibMigration.NameRequiresMigration.selector)); + vm.prank(testOwner); + registry2.register("sub", testOwner, IRegistry(address(0)), address(0), 0, _soon()); + + // resolver lookup falls through to v1 + assertEq( + registry2.getResolver("sub"), + address(ensV1Resolver), + "unwrapped emancipated subname resolves through V1" + ); + + // legitimate subname owner can still migrate via re-wrap (preserves PCC automatically) + vm.prank(friend); + registryV1.setApprovalForAll(address(nameWrapper), true); + vm.prank(friend); + nameWrapper.wrap(name3, friend, address(0)); + (address rewrappedOwner, uint32 rewrappedFuses, ) = nameWrapper.getData(uint256(subNode)); + assertEq(rewrappedOwner, friend, "re-wrap restores wrapper ownership"); + assertEq( + rewrappedFuses & PARENT_CANNOT_CONTROL, + PARENT_CANNOT_CONTROL, + "re-wrap restores PCC from preserved storage" + ); + + LibMigration.Data memory data3 = _unlockedData(name3); + data3.owner = friend; // override + vm.prank(friend); + nameWrapper.safeTransferFrom( + friend, + address(registry2), + uint256(subNode), + 1, + abi.encode(data3) + ); + assertEq(registry2.getResolver(data3.label), data3.resolver, "resolver3 after migration"); + assertEq( + registry2.ownerOf(registry2.getTokenId(LibLabel.id(data3.label))), + friend, + "owner3 after migration" + ); + assertEq( + address(registry2.getSubregistry(data3.label)), + address(testRegistry), + "subregistry3 after migration" + ); + assertEq(registryV1.owner(subNode), address(graveyard), "v1 graveyarded after migration"); + } + + function test_migrate_detachedChildren_unwrappedAndAbandoned() external { + bytes memory name2 = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + vm.prank(friend); + bytes memory name3 = this.createWrappedChild(name2, "sub", PARENT_CANNOT_CONTROL); + bytes32 parentNode = NameCoder.namehash(name2, 0); + bytes32 subNode = NameCoder.namehash(name3, 0); + bytes32 subLabelHash = keccak256(bytes("sub")); + + // friend unwraps the emancipated child to themselves, then abandons it + // by clearing the v1 registry record + vm.prank(friend); + nameWrapper.unwrap(parentNode, subLabelHash, friend); + vm.prank(friend); + registryV1.setOwner(subNode, address(0)); + assertEq(registryV1.owner(subNode), address(0), "v1 record cleared"); + (, uint32 fusesAfterAbandon, ) = nameWrapper.getData(uint256(subNode)); + assertEq( + fusesAfterAbandon & PARENT_CANNOT_CONTROL, + PARENT_CANNOT_CONTROL, + "PCC fuse still set even after abandonment" + ); + + // migrate parent + LibMigration.Data memory data2 = _lockedData(name2); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(parentNode), + 1, + abi.encode(data2) + ); + IWrapperRegistry registry2 = + IWrapperRegistry(address(ethRegistry.getSubregistry(data2.label))); + + // abandoned orphan must not lock the label forever — guard treats the empty + // v1 record as relinquishment and allows fresh registration in v2 + vm.prank(testOwner); + uint256 tokenId = + registry2.register("sub", testOwner, IRegistry(address(0)), address(0), 0, _soon()); + assertEq(registry2.ownerOf(tokenId), testOwner, "label registered to new owner"); + } + + function test_migrate_frozenTokenApproval() external { + bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + bytes32 node = NameCoder.namehash(name, 0); + + // give approval + vm.prank(testOwner); + nameWrapper.approve(address(this), uint256(node)); + assertEq(nameWrapper.getApproved(uint256(node)), address(this), "approved"); + + // freeze approval + vm.prank(testOwner); + nameWrapper.setFuses(node, uint16(CANNOT_APPROVE)); + + LibMigration.Data memory data = _lockedData(name); + vm.expectRevert( + WrappedErrorLib.wrap( + abi.encodeWithSelector(LibMigration.FrozenTokenApproval.selector, node) + ) + ); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(node), + 1, + abi.encode(data) + ); + } + + function _deployWrapperRegistryProxy() internal returns (WrapperRegistry) { + bytes memory name = NameCoder.ethName(testLabel); + bytes32 node = NameCoder.namehash(name, 0); + uint256 salt = uint256(node); + address proxyAddress = + verifiableFactory.deployProxy( + address(wrapperRegistryImpl), + salt, + abi.encodeCall( + IWrapperRegistry.initialize, + (node, ethRegistry, testLabel, RegistryRolesLib.ROLE_UPGRADE) + ) + ); + ethRegistry.register(testLabel, testOwner, IRegistry(proxyAddress), address(0), 0, _soon()); + return WrapperRegistry(proxyAddress); + } + + function _newWrapperRegistryV2Mock() internal returns (WrapperRegistryV2Mock) { return - LibMigration.Data({ - label: NameCoder.firstLabel(name), - owner: user, - subregistry: IRegistry(address(0)), // ignored by LockedMigrationController - resolver: testResolver, - salt: uint256(keccak256(abi.encode(name, block.timestamp))) - }); + new WrapperRegistryV2Mock( + nameWrapper, + address(graveyard), + verifiableFactory, + address(ensV1Resolver), + approvedUpgradeGate, + labelStore, + publicResolverSet, + address(publicResolver), + address(this) + ); + } +} + + +contract WrapperRegistryV2Mock is WrapperRegistry { + constructor( + INameWrapper nameWrapper, + address graveyard, + IVerifiableFactory verifiableFactory, + address ensV1Resolver, + ApprovedUpgradeGate upgradeGate, + ILabelStore labelStore, + IAddressSet publicResolverSet, + address publicResolver, + address namer + ) + WrapperRegistry( + nameWrapper, + graveyard, + verifiableFactory, + ensV1Resolver, + upgradeGate, + labelStore, + publicResolverSet, + publicResolver, + namer + ) + {} + + function version() public pure returns (uint256) { + return 2; } } diff --git a/contracts/test/unit/migration/MigrationControllerFixture.sol b/contracts/test/unit/migration/MigrationControllerFixture.sol deleted file mode 100755 index e3f7d89c0..000000000 --- a/contracts/test/unit/migration/MigrationControllerFixture.sol +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; -import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; -import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; - -import {ENSV1Resolver} from "~src/resolver/ENSV1Resolver.sol"; -import {ENSV2Resolver} from "~src/resolver/ENSV2Resolver.sol"; -import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; -import {V1Fixture} from "~test/fixtures/V1Fixture.sol"; -import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; - -// initial gas analysis -// * Unwrapped: 160300 -// * Unlocked: 179367 -// * Locked: 658489 (~500k for VerifiedFactory => WrapperRegistry) - -contract MigrationControllerFixture is V1Fixture, V2Fixture { - ENSV1Resolver ensV1Resolver; - ENSV2Resolver ensV2Resolver; - MockERC1155 dummy1155; - - string testLabel = "test"; - address testResolver = makeAddr("resolver"); - IRegistry testRegistry = IRegistry(makeAddr("registry")); - address premigrationController = makeAddr("premigrationController"); - - function setUp() public virtual { - deployV1Fixture(); - deployV2Fixture(); - ensV1Resolver = new ENSV1Resolver(registryV1, batchGatewayProvider); - ensV2Resolver = new ENSV2Resolver(rootRegistry, batchGatewayProvider); - dummy1155 = new MockERC1155(); - ethRegistrarV1.setResolver(address(ensV2Resolver)); - } - - /// @dev Ensure premigration has occurred. - function registerUnwrapped( - string memory label - ) public override returns (bytes memory name, uint256 tokenId) { - (name, tokenId) = super.registerUnwrapped(label); - if (address(premigrationController) != address(0)) { - vm.prank(premigrationController); - ethRegistry.register( - label, - address(0), // reserve - IRegistry(address(0)), - address(ensV1Resolver), // fallback - 0, - uint64(ethRegistrarV1.nameExpires(tokenId)) - ); - } - } - - /// @dev Check resolver and fallback logic. - function checkResolution( - bytes memory name, - address resolverV1, - address resolverV2 - ) public view { - assertEq(findResolverV1(name), resolverV1, "findResolverV1"); - assertEq(findResolverV2(name), resolverV2, "findResolverV2"); - if (resolverV2 == address(ensV1Resolver)) { - (address r, ) = ensV1Resolver.getResolver(name); - assertEq(r, resolverV1, "compositeV1"); - } else if (resolverV1 == address(ensV2Resolver)) { - (address r, ) = ensV2Resolver.getResolver(name); - assertEq(r, resolverV2, "compositeV2"); - assertEq(registryV1.resolver(NameCoder.namehash(name, 0)), address(0), "resolverV1"); - } - } - - function _label(uint256 i) internal view returns (string memory) { - return string.concat(testLabel, vm.toString(i)); - } - - function _soon() internal view returns (uint64) { - return uint64(block.timestamp + 1000); - } -} - -contract MockERC1155 is ERC1155 { - uint256 _id; - constructor() ERC1155("") {} - function mint(address to) external returns (uint256) { - _mint(to, _id, 1, ""); - return _id++; - } -} diff --git a/contracts/test/unit/migration/MigrationHelper.t.sol b/contracts/test/unit/migration/MigrationHelper.t.sol new file mode 100755 index 000000000..528651f0b --- /dev/null +++ b/contracts/test/unit/migration/MigrationHelper.t.sol @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import { + CAN_DO_EVERYTHING, + CANNOT_UNWRAP, + PARENT_CANNOT_CONTROL +} from "@ens/contracts/wrapper/INameWrapper.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; + +import {LibMigration} from "~src/migration/libraries/LibMigration.sol"; +import {UnlockedMigrationController} from "~src/migration/UnlockedMigrationController.sol"; +import {LockedMigrationController} from "~src/migration/LockedMigrationController.sol"; +import {ApprovedUpgradeGate} from "~src/registry/ApprovedUpgradeGate.sol"; +import {WrapperRegistry} from "~src/registry/WrapperRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {MigrationHelper, LockedChildren} from "~src/migration/MigrationHelper.sol"; +import {PermissionedAddressSet} from "~src/utils/PermissionedAddressSet.sol"; +import {MigrationControllerFixture} from "~test/fixtures/MigrationControllerFixture.sol"; + +contract MigrationHelperTest is MigrationControllerFixture { + UnlockedMigrationController unlockedController; + LockedMigrationController lockedController; + WrapperRegistry wrapperRegistryImpl; + MigrationHelper helper; + + address hacker = makeAddr("hacker"); + + function setUp() external { + deployMigrationControllerFixture(); + + // unlocked + unlockedController = new UnlockedMigrationController( + nameWrapper, + address(graveyard), + ethRegistry, + contractNamer + ); + ethRegistry.grantRootRoles(RegistryRolesLib.ROLE_REGISTRAR, premigrationController); + ethRegistry.grantRootRoles( + RegistryRolesLib.ROLE_REGISTER_RESERVED, + address(unlockedController) + ); + + // locked + ApprovedUpgradeGate approvedUpgradeGate = new ApprovedUpgradeGate(address(this)); + PermissionedAddressSet publicResolverSet = new PermissionedAddressSet(address(this)); + wrapperRegistryImpl = new WrapperRegistry( + nameWrapper, + address(graveyard), + verifiableFactory, + address(ensV1Resolver), + approvedUpgradeGate, + labelStore, + publicResolverSet, + address(0), // publicResolver + address(this) // namer + ); + lockedController = new LockedMigrationController( + nameWrapper, + address(graveyard), + ethRegistry, + verifiableFactory, + address(wrapperRegistryImpl), + publicResolverSet, + address(0), // publicResolver + contractNamer + ); + ethRegistry.grantRootRoles(RegistryRolesLib.ROLE_REGISTRAR, premigrationController); + ethRegistry.grantRootRoles( + RegistryRolesLib.ROLE_REGISTER_RESERVED, + address(lockedController) + ); + + helper = new MigrationHelper( + rootRegistry, + unlockedController, + lockedController, + contractNamer + ); + } + + function test_migrate_unwrapped_notApproved() external { + (bytes memory name, ) = registerUnwrapped(testLabel); + + LibMigration.Data[] memory mds = _toArray(_unlockedData(name)); + + vm.expectRevert("ERC721: caller is not token owner or approved"); + vm.prank(testOwner); + helper.migrate( + mds, + new LibMigration.Data[][](0), + new LibMigration.Data[][](0), + new LockedChildren[](0) + ); + } + + function test_migrate_unlocked_notApproved() external { + bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); + + LibMigration.Data[][] memory groups = _toGroups(_toArray(_unlockedData(name))); + + vm.expectRevert("ERC1155: caller is not owner nor approved"); + vm.prank(testOwner); + helper.migrate( + new LibMigration.Data[](0), + groups, + new LibMigration.Data[][](0), + new LockedChildren[](0) + ); + } + + function test_migrate_locked_notApproved() external { + bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + + LibMigration.Data[][] memory groups = _toGroups(_toArray(_lockedData(name))); + + vm.expectRevert("ERC1155: caller is not owner nor approved"); + vm.prank(testOwner); + helper.migrate( + new LibMigration.Data[](0), + new LibMigration.Data[][](0), + groups, + new LockedChildren[](0) + ); + } + + function test_migrate_unwrapped_notOperator() external { + (bytes memory name, ) = registerUnwrapped(testLabel); + + vm.prank(testOwner); + baseRegistrar.setApprovalForAll(address(helper), true); + + LibMigration.Data[] memory mds = _toArray(_unlockedData(name)); + + vm.expectRevert( + abi.encodeWithSelector( + MigrationHelper.NotApprovedOperator.selector, + baseRegistrar, + testOwner + ) + ); + vm.prank(hacker); + helper.migrate( + mds, + new LibMigration.Data[][](0), + new LibMigration.Data[][](0), + new LockedChildren[](0) + ); + } + + function test_migrate_unlocked_notOperator() external { + bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); + + vm.prank(testOwner); + nameWrapper.setApprovalForAll(address(helper), true); + + LibMigration.Data[][] memory groups = _toGroups(_toArray(_unlockedData(name))); + + vm.expectRevert( + abi.encodeWithSelector( + MigrationHelper.NotApprovedOperator.selector, + nameWrapper, + testOwner + ) + ); + vm.prank(hacker); + helper.migrate( + new LibMigration.Data[](0), + groups, + new LibMigration.Data[][](0), + new LockedChildren[](0) + ); + } + + function test_migrate_locked_notOperator() external { + bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); + + vm.prank(testOwner); + nameWrapper.setApprovalForAll(address(helper), true); + + LibMigration.Data[][] memory groups = _toGroups(_toArray(_lockedData(name))); + + vm.expectRevert( + abi.encodeWithSelector( + MigrationHelper.NotApprovedOperator.selector, + nameWrapper, + testOwner + ) + ); + vm.prank(hacker); + helper.migrate( + new LibMigration.Data[](0), + new LibMigration.Data[][](0), + groups, + new LockedChildren[](0) + ); + } + + function test_migrate_notSameOwner_wrappedOwnerMismatch() external { + bytes memory name1 = registerWrappedETH2LD("a", CAN_DO_EVERYTHING); + vm.prank(friend); + bytes memory name2 = this.registerWrappedETH2LD("b", CAN_DO_EVERYTHING); + + LibMigration.Data[] memory mds = new LibMigration.Data[](2); + mds[0] = _unlockedData(name1); + mds[1] = _unlockedData(name2); // wrong: owner is friend + + LibMigration.Data[][] memory groups = _toGroups(mds); + + vm.prank(testOwner); + nameWrapper.setApprovalForAll(address(helper), true); + vm.prank(friend); + nameWrapper.setApprovalForAll(testOwner, true); + vm.prank(friend); + nameWrapper.setApprovalForAll(address(helper), true); + + vm.expectRevert( + abi.encodeWithSelector( + MigrationHelper.WrappedOwnerMismatch.selector, + NameCoder.namehash(name2, 0) + ) + ); + vm.prank(testOwner); + helper.migrate( + new LibMigration.Data[](0), + groups, + new LibMigration.Data[][](0), + new LockedChildren[](0) + ); + } + + function test_migrate_notSameOwner() external { + bytes memory name1 = registerWrappedETH2LD("a", CAN_DO_EVERYTHING); + vm.prank(friend); + bytes memory name2 = this.registerWrappedETH2LD("b", CAN_DO_EVERYTHING); + + LibMigration.Data[][] memory groups = new LibMigration.Data[][](2); + groups[0] = _toArray(_unlockedData(name1)); + groups[1] = _toArray(_unlockedData(name2)); + + // testOwner grants approval to helper + vm.prank(testOwner); + nameWrapper.setApprovalForAll(address(helper), true); + + // friend must grant approval to operator AND helper! + + // only helper + vm.startPrank(friend); + nameWrapper.setApprovalForAll(testOwner, false); + nameWrapper.setApprovalForAll(address(helper), true); + vm.stopPrank(); + + vm.expectRevert( + abi.encodeWithSelector(MigrationHelper.NotApprovedOperator.selector, nameWrapper, friend) + ); + vm.prank(testOwner); + helper.migrate( + new LibMigration.Data[](0), + groups, + new LibMigration.Data[][](0), + new LockedChildren[](0) + ); + + // only operator + vm.startPrank(friend); + nameWrapper.setApprovalForAll(testOwner, true); + nameWrapper.setApprovalForAll(address(helper), false); + vm.stopPrank(); + + vm.expectRevert("ERC1155: caller is not owner nor approved"); + vm.prank(testOwner); + helper.migrate( + new LibMigration.Data[](0), + groups, + new LibMigration.Data[][](0), + new LockedChildren[](0) + ); + + // both + vm.startPrank(friend); + nameWrapper.setApprovalForAll(testOwner, true); + nameWrapper.setApprovalForAll(address(helper), true); + vm.stopPrank(); + + vm.prank(testOwner); + helper.migrate( + new LibMigration.Data[](0), + groups, + new LibMigration.Data[][](0), + new LockedChildren[](0) + ); + } + + function test_migrate_parentAndChildren_parentNotMigrated() external { + bytes memory name2 = registerWrappedETH2LD("2", CANNOT_UNWRAP); + bytes memory name3 = createWrappedChild(name2, "3", PARENT_CANNOT_CONTROL); + + vm.prank(testOwner); + nameWrapper.setApprovalForAll(address(helper), true); + + LockedChildren[] memory lcs = new LockedChildren[](1); + lcs[0] = LockedChildren(name2, _toGroups(_toArray(_lockedData(name3)))); + + vm.expectRevert(abi.encodeWithSelector(MigrationHelper.ParentNotMigrated.selector, name2)); + vm.prank(testOwner); + helper.migrate( + new LibMigration.Data[](0), + new LibMigration.Data[][](0), + new LibMigration.Data[][](0), // wrong: forgot parent + lcs + ); + } + + function test_migrate_parentAndChildren() external { + bytes memory name2 = registerWrappedETH2LD("2", CANNOT_UNWRAP); + vm.prank(friend); + bytes memory name3a = + this.createWrappedChild(name2, "3a", PARENT_CANNOT_CONTROL | CANNOT_UNWRAP); + vm.prank(friend); + bytes memory name3b = this.createWrappedChild(name2, "3b", PARENT_CANNOT_CONTROL); + + vm.prank(testOwner); + nameWrapper.setApprovalForAll(address(helper), true); + vm.prank(friend); + nameWrapper.setApprovalForAll(testOwner, true); + vm.prank(friend); + nameWrapper.setApprovalForAll(address(helper), true); + + LibMigration.Data[][] memory groups = _toGroups(_toArray(_lockedData(name2))); + + LibMigration.Data[] memory mds = new LibMigration.Data[](2); + mds[0] = _lockedData(name3a); + mds[1] = _unlockedData(name3b); + + LockedChildren[] memory lcs = new LockedChildren[](1); + lcs[0] = LockedChildren(name2, _toGroups(mds)); + + vm.prank(testOwner); + helper.migrate(new LibMigration.Data[](0), new LibMigration.Data[][](0), groups, lcs); + } + + function test_migrate_0unwrapped_0unlocked_0locked() external { + _testMigrate(0, 0, 0); + } + function test_migrate_1unwrapped_0unlocked_0locked() external { + _testMigrate(1, 0, 0); + } + function test_migrate_0unwrapped_1unlocked_0locked() external { + _testMigrate(0, 1, 0); + } + function test_migrate_0unwrapped_0unlocked_1locked() external { + _testMigrate(0, 0, 1); + } + function test_migrate_1unwrapped_1unlocked_1locked() external { + _testMigrate(1, 1, 1); + } + function test_migrate_2unwrapped_2unlocked_2locked() external { + _testMigrate(2, 2, 2); + } + function test_migrate_7unwrapped_8unlocked_9locked() external { + _testMigrate(7, 8, 9); + } + + function _testMigrate(uint256 numUnwrapped, uint256 numUnlocked, uint256 numLocked) public { + LibMigration.Data[] memory unwrapped = new LibMigration.Data[](numUnwrapped); + LibMigration.Data[] memory unlocked = new LibMigration.Data[](numUnlocked); + LibMigration.Data[] memory locked = new LibMigration.Data[](numLocked); + + testLabel = "unwrapped"; + for (uint256 i; i < numUnwrapped; ++i) { + (bytes memory name, ) = registerUnwrapped(_label(i)); + unwrapped[i] = _unlockedData(name); + } + testLabel = "unlocked"; + for (uint256 i; i < numUnlocked; ++i) { + bytes memory name = registerWrappedETH2LD(_label(i), CAN_DO_EVERYTHING); + unlocked[i] = _unlockedData(name); + } + testLabel = "locked"; + for (uint256 i; i < numLocked; ++i) { + bytes memory name = registerWrappedETH2LD(_label(i), CANNOT_UNWRAP); + locked[i] = _lockedData(name); + } + + if (numUnwrapped > 0) { + vm.prank(testOwner); + baseRegistrar.setApprovalForAll(address(helper), true); + } + if (numUnlocked > 0 || numLocked > 0) { + vm.prank(testOwner); + nameWrapper.setApprovalForAll(address(helper), true); + } + + LibMigration.Data[][] memory unlockedGroups = _toGroups(unlocked); + LibMigration.Data[][] memory lockedGroups = _toGroups(locked); + + vm.prank(testOwner); + helper.migrate(unwrapped, unlockedGroups, lockedGroups, new LockedChildren[](0)); + } + + function _toArray(LibMigration.Data memory md) + internal + pure + returns (LibMigration.Data[] memory mds) + { + mds = new LibMigration.Data[](1); + mds[0] = md; + } + + function _toGroups(LibMigration.Data[] memory mds) + internal + pure + returns (LibMigration.Data[][] memory groups) + { + groups = new LibMigration.Data[][](1); + groups[0] = mds; + } +} diff --git a/contracts/test/unit/migration/UnlockedMigrationController.t.sol b/contracts/test/unit/migration/UnlockedMigrationController.t.sol index 763896dcb..9e3ff3688 100644 --- a/contracts/test/unit/migration/UnlockedMigrationController.t.sol +++ b/contracts/test/unit/migration/UnlockedMigrationController.t.sol @@ -4,51 +4,41 @@ pragma solidity >=0.8.13; // solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file import {console} from "forge-std/console.sol"; -import { - INameWrapper, - CAN_DO_EVERYTHING, - CANNOT_UNWRAP -} from "@ens/contracts/wrapper/INameWrapper.sol"; + +import {CAN_DO_EVERYTHING, CANNOT_UNWRAP} from "@ens/contracts/wrapper/INameWrapper.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import {IERC1155Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {InvalidOwner, UnauthorizedCaller} from "~src/CommonErrors.sol"; import {WrappedErrorLib} from "~src/utils/WrappedErrorLib.sol"; -import { - IEnhancedAccessControl, - EACBaseRolesLib -} from "~src/access-control/EnhancedAccessControl.sol"; -import { - PermissionedRegistry, - IPermissionedRegistry, - RegistryRolesLib, - IRegistry, - IRegistryMetadata, - LibLabel -} from "~src/registry/PermissionedRegistry.sol"; -import { - UnlockedMigrationController, - LibMigration, - InvalidOwner, - UnauthorizedCaller -} from "~src/migration/UnlockedMigrationController.sol"; -import { - MigrationControllerFixture, - ERC165Checker, - NameCoder -} from "./MigrationControllerFixture.sol"; -import {V1Fixture, ENS} from "~test/fixtures/V1Fixture.sol"; -import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; +import {LibLabel} from "~src/utils/LibLabel.sol"; +import {LibMigration} from "~src/migration/libraries/LibMigration.sol"; +import {IEnhancedAccessControl} from "~src/access-control/EnhancedAccessControl.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {IRegistryEvents} from "~src/registry/interfaces/IRegistryEvents.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {REGISTRATION_ROLE_BITMAP} from "~src/registrar/ETHRegistrar.sol"; +import {UnlockedMigrationController} from "~src/migration/UnlockedMigrationController.sol"; +import {MigrationControllerFixture} from "~test/fixtures/MigrationControllerFixture.sol"; contract UnlockedMigrationControllerTest is MigrationControllerFixture { UnlockedMigrationController migrationController; - function setUp() public override { - super.setUp(); - migrationController = new UnlockedMigrationController(ethRegistry, nameWrapper); - ethRegistry.grantRootRoles(RegistryRolesLib.ROLE_REGISTRAR, premigrationController); + function setUp() external { + deployMigrationControllerFixture(); + + migrationController = new UnlockedMigrationController( + nameWrapper, + address(graveyard), + ethRegistry, + contractNamer + ); ethRegistry.grantRootRoles( RegistryRolesLib.ROLE_REGISTER_RESERVED, address(migrationController) @@ -56,8 +46,14 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { } function test_constructor() external view { - assertEq(address(migrationController.ETH_REGISTRY()), address(ethRegistry), "ETH_REGISTRY"); assertEq(address(migrationController.NAME_WRAPPER()), address(nameWrapper), "NAME_WRAPPER"); + assertEq(address(migrationController.GRAVEYARD()), address(graveyard), "GRAVEYARD"); + assertEq(address(migrationController.ETH_REGISTRY()), address(ethRegistry), "ETH_REGISTRY"); + assertEq( + address(migrationController.CONTRACT_NAMER()), + address(contractNamer), + "CONTRACT_NAMER" + ); } function test_supportsInterface() external view { @@ -77,45 +73,82 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { ); } + function test_onERC721Received_unauthorizedCaller() external { + vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, actor)); + vm.prank(actor); + migrationController.onERC721Received(address(0), address(0), 1, ""); + } + + function test_onERC721Received_invalidData() external { + vm.expectRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector)); + vm.prank(address(baseRegistrar)); + migrationController.onERC721Received(address(0), address(0), 1, ""); + } + + function test_onERC1155Received_unauthorizedCaller() external { + vm.expectRevert( + WrappedErrorLib.wrap(abi.encodeWithSelector(UnauthorizedCaller.selector, actor)) + ); + vm.prank(actor); + migrationController.onERC1155Received(address(0), address(0), 1, 1, ""); + } + + function test_onERC1155Received_invalidData() external { + vm.expectRevert( + WrappedErrorLib.wrap(abi.encodeWithSelector(LibMigration.InvalidData.selector)) + ); + vm.prank(address(nameWrapper)); + migrationController.onERC1155Received(address(0), address(0), 1, 1, ""); + } + function test_finishERC1155Migration_unauthorizedCaller() external { - vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, user)); - vm.prank(user); + vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, actor)); + vm.prank(actor); migrationController.finishERC1155Migration(new uint256[](0), new LibMigration.Data[](0)); } - function test_safeTransferFrom_unauthorizedCaller() external { - uint256 tokenId = dummy1155.mint(user); + function test_unwrapped_safeTransferFrom_unauthorizedCaller() external { + uint256 tokenId = dummy721.mint(actor); + vm.expectRevert(abi.encodeWithSelector(UnauthorizedCaller.selector, dummy721)); + vm.prank(actor); + dummy721.safeTransferFrom(actor, address(migrationController), tokenId); // wrong + } + + function test_wrapped_safeTransferFrom_unauthorizedCaller() external { + uint256 tokenId = dummy1155.mint(actor); vm.expectRevert( WrappedErrorLib.wrap(abi.encodeWithSelector(UnauthorizedCaller.selector, dummy1155)) ); - vm.prank(user); - dummy1155.safeTransferFrom(user, address(migrationController), tokenId, 1, ""); // wrong + vm.prank(actor); + dummy1155.safeTransferFrom(actor, address(migrationController), tokenId, 1, ""); // wrong } - function test_unwrapped_invalidData() external { + function test_unwrapped_invalidData(bytes calldata v) external { + vm.assume(v.length < LibMigration.MIN_DATA_SIZE); (, uint256 tokenIdV1) = registerUnwrapped(testLabel); vm.expectRevert(abi.encodeWithSelector(LibMigration.InvalidData.selector)); - vm.prank(user); - ethRegistrarV1.safeTransferFrom( - user, + vm.prank(testOwner); + baseRegistrar.safeTransferFrom( + testOwner, address(migrationController), tokenIdV1, - "" // wrong + v // wrong ); } - function test_wrapped_invalidData() external { + function test_wrapped_invalidData(bytes calldata v) external { + vm.assume(v.length < LibMigration.MIN_DATA_SIZE); bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); vm.expectRevert( WrappedErrorLib.wrap(abi.encodeWithSelector(LibMigration.InvalidData.selector)) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name, 0)), 1, - "" // wrong + v // wrong ); } @@ -125,7 +158,7 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { uint256[] memory amounts = new uint256[](1); LibMigration.Data[] memory mds = new LibMigration.Data[](1); ids[0] = uint256(NameCoder.namehash(name, 0)); - mds[0] = _makeData(name); + mds[0] = _unlockedData(name); amounts[0] = 1; bytes memory payload = abi.encode(mds); uint256 fakeLength = 0; @@ -141,9 +174,9 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { ) ) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeBatchTransferFrom( - user, + testOwner, address(migrationController), ids, amounts, @@ -151,28 +184,64 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { ); } - function test_unwrapped_invalidReceiver() external { + function test_unwrapped_invalidOwner() external { (bytes memory name, uint256 tokenIdV1) = registerUnwrapped(testLabel); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _unlockedData(name); md.owner = address(0); // wrong vm.expectRevert(abi.encodeWithSelector(InvalidOwner.selector)); - vm.prank(user); - ethRegistrarV1.safeTransferFrom( - user, + vm.prank(testOwner); + baseRegistrar.safeTransferFrom( + testOwner, address(migrationController), tokenIdV1, abi.encode(md) ); } - function test_wrapped_invalidReceiver() external { + function test_wrapped_invalidOwner() external { bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _unlockedData(name); md.owner = address(0); // wrong vm.expectRevert(WrappedErrorLib.wrap(abi.encodeWithSelector(InvalidOwner.selector))); - vm.prank(user); + vm.prank(testOwner); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(NameCoder.namehash(name, 0)), + 1, + abi.encode(md) + ); + } + + function test_unwrapped_invalidReceiver() external { + (bytes memory name, uint256 tokenIdV1) = registerUnwrapped(testLabel); + LibMigration.Data memory md = _unlockedData(name); + md.owner = address(ethRegistry); // not a IERC1155Receiver + vm.expectRevert( + abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, md.owner) + ); + vm.prank(testOwner); + baseRegistrar.safeTransferFrom( + testOwner, + address(migrationController), + tokenIdV1, + abi.encode(md) + ); + } + + function test_wrapped_invalidReceiver() external { + bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); + LibMigration.Data memory md = _unlockedData(name); + md.owner = address(ethRegistry); // not a IERC1155Receiver + + vm.expectRevert( + WrappedErrorLib.wrap( + abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, md.owner) + ) + ); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name, 0)), 1, @@ -180,19 +249,33 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { ); } + function test_unwrapped_nameDataMismatch() external { + (bytes memory name, uint256 tokenIdV1) = registerUnwrapped(testLabel); + LibMigration.Data memory md = _unlockedData(name); + md.label = "wrong"; + vm.expectRevert(abi.encodeWithSelector(LibMigration.NameDataMismatch.selector, tokenIdV1)); + vm.prank(testOwner); + baseRegistrar.safeTransferFrom( + testOwner, + address(migrationController), + tokenIdV1, + abi.encode(md) + ); + } + function test_wrapped_nameDataMismatch() external { bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); bytes32 node = NameCoder.namehash(name, 0); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _unlockedData(name); md.label = "wrong"; vm.expectRevert( WrappedErrorLib.wrap( abi.encodeWithSelector(LibMigration.NameDataMismatch.selector, node) ) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(node), 1, @@ -203,13 +286,13 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { function test_wrapped_nameIsLocked() external { bytes memory name = registerWrappedETH2LD(testLabel, CANNOT_UNWRAP); bytes32 node = NameCoder.namehash(name, 0); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _unlockedData(name); vm.expectRevert( WrappedErrorLib.wrap(abi.encodeWithSelector(LibMigration.NameIsLocked.selector, node)) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(node), 1, @@ -220,7 +303,7 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { function test_unwrapped_notReserved() external { premigrationController = address(0); // disable premigration (bytes memory name, uint256 tokenIdV1) = registerUnwrapped(testLabel); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _unlockedData(name); vm.expectRevert( abi.encodeWithSelector( IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, @@ -229,9 +312,9 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { address(migrationController) ) ); - vm.prank(user); - ethRegistrarV1.safeTransferFrom( - user, + vm.prank(testOwner); + baseRegistrar.safeTransferFrom( + testOwner, address(migrationController), tokenIdV1, abi.encode(md) @@ -241,7 +324,7 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { function test_wrapped_notReserved() external { premigrationController = address(0); // disable premigration bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _unlockedData(name); vm.expectRevert( WrappedErrorLib.wrap( abi.encodeWithSelector( @@ -252,9 +335,9 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { ) ) ); - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), uint256(NameCoder.namehash(name, 0)), 1, @@ -262,43 +345,63 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { ); } + function test_checkIfMigrated() external { + (bytes memory name, uint256 tokenIdV1) = registerUnwrapped(testLabel); + LibMigration.Data memory md = _unlockedData(name); + + assertFalse(ethRegistry.hasRoles(tokenIdV1, RegistryRolesLib.ROLE_WAS_RESERVED, testOwner)); + + vm.prank(testOwner); + baseRegistrar.safeTransferFrom( + testOwner, + address(migrationController), + tokenIdV1, + abi.encode(md) + ); + + assertTrue(ethRegistry.hasRoles(tokenIdV1, RegistryRolesLib.ROLE_WAS_RESERVED, testOwner)); + } + function test_unwrapped_migrate() external { (bytes memory name, uint256 tokenIdV1) = registerUnwrapped(testLabel); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _unlockedData(name); uint256 tokenId = LibLabel.withVersion(tokenIdV1, 0); + uint64 expectedExpiry = + uint64(baseRegistrar.nameExpires(tokenIdV1)) + premigrationBonusPeriod; vm.expectEmit(); - emit IERC721.Transfer(user, address(migrationController), tokenIdV1); + emit IERC721.Transfer(testOwner, address(migrationController), tokenIdV1); vm.expectEmit(); - emit IRegistry.NameRegistered( + emit IRegistryEvents.LabelRegistered( tokenId, - keccak256(bytes(md.label)), + bytes32(tokenIdV1), md.label, md.owner, - uint64(ethRegistrarV1.nameExpires(tokenIdV1)), + expectedExpiry, address(migrationController) ); vm.expectEmit(); - emit IERC1155.TransferSingle( - address(migrationController), - address(0), - md.owner, - tokenId, - 1 - ); + emit IERC1155.TransferSingle(address(migrationController), address(0), md.owner, tokenId, 1); vm.expectEmit(); emit IPermissionedRegistry.TokenResource(tokenId, tokenId); vm.expectEmit(); - emit IRegistry.SubregistryUpdated( + emit IEnhancedAccessControl.EACRolesChanged( + tokenId, + md.owner, + 0 /*old roles*/, + REGISTRATION_ROLE_BITMAP | RegistryRolesLib.ROLE_WAS_RESERVED + ); + vm.expectEmit(); + emit IRegistryEvents.SubregistryUpdated( tokenId, IRegistry(md.subregistry), address(migrationController) ); vm.expectEmit(); - emit IRegistry.ResolverUpdated(tokenId, md.resolver, address(migrationController)); - vm.prank(user); + emit IRegistryEvents.ResolverUpdated(tokenId, md.resolver, address(migrationController)); + vm.prank(testOwner); uint256 g = gasleft(); - ethRegistrarV1.safeTransferFrom( - user, + baseRegistrar.safeTransferFrom( + testOwner, address(migrationController), tokenIdV1, abi.encode(md) @@ -307,7 +410,7 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { assertEq(ethRegistry.getTokenId(tokenIdV1), tokenId, "tokenId"); assertEq(ethRegistry.ownerOf(tokenId), md.owner, "owner"); - assertEq(ethRegistry.getExpiry(tokenId), ethRegistrarV1.nameExpires(tokenIdV1), "expiry"); + assertEq(ethRegistry.getExpiry(tokenId), expectedExpiry, "expiry"); assertEq(ethRegistry.getResolver(md.label), md.resolver, "resolver"); checkResolution(name, address(ensV2Resolver), md.resolver); assertEq( @@ -316,54 +419,59 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { "subregistry" ); assertEq(registryV1.resolver(NameCoder.namehash(name, 0)), address(0), "resolverV1"); + assertEq(registryV1.owner(NameCoder.namehash(name, 0)), address(graveyard), "graveyard"); } function test_wrapped_migrate() external { bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); - LibMigration.Data memory md = _makeData(name); - uint256 tokenIdV1 = uint256(keccak256(bytes(md.label))); + LibMigration.Data memory md = _unlockedData(name); + uint256 tokenIdV1 = LibLabel.id(md.label); uint256 tokenId = LibLabel.withVersion(tokenIdV1, 0); + uint64 expectedExpiry = + uint64(baseRegistrar.nameExpires(tokenIdV1)) + premigrationBonusPeriod; + bytes32 node = NameCoder.namehash(name, 0); vm.expectEmit(); emit IERC1155.TransferSingle( - user, - user, + testOwner, + testOwner, address(migrationController), - uint256(NameCoder.namehash(name, 0)), + uint256(node), 1 ); vm.expectEmit(); - emit IRegistry.NameRegistered( + emit IRegistryEvents.LabelRegistered( tokenId, - keccak256(bytes(md.label)), + bytes32(tokenIdV1), md.label, md.owner, - uint64(ethRegistrarV1.nameExpires(tokenIdV1)), + expectedExpiry, address(migrationController) ); vm.expectEmit(); - emit IERC1155.TransferSingle( - address(migrationController), - address(0), - md.owner, - tokenId, - 1 - ); + emit IERC1155.TransferSingle(address(migrationController), address(0), md.owner, tokenId, 1); vm.expectEmit(); emit IPermissionedRegistry.TokenResource(tokenId, tokenId); vm.expectEmit(); - emit IRegistry.SubregistryUpdated( + emit IEnhancedAccessControl.EACRolesChanged( + tokenId, + md.owner, + 0 /*old roles*/, + REGISTRATION_ROLE_BITMAP | RegistryRolesLib.ROLE_WAS_RESERVED + ); + vm.expectEmit(); + emit IRegistryEvents.SubregistryUpdated( tokenId, IRegistry(md.subregistry), address(migrationController) ); vm.expectEmit(); - emit IRegistry.ResolverUpdated(tokenId, md.resolver, address(migrationController)); - vm.prank(user); + emit IRegistryEvents.ResolverUpdated(tokenId, md.resolver, address(migrationController)); + vm.prank(testOwner); uint256 g = gasleft(); nameWrapper.safeTransferFrom( - user, + testOwner, address(migrationController), - uint256(NameCoder.namehash(name, 0)), + uint256(node), 1, abi.encode(md) ); @@ -371,7 +479,7 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { assertEq(ethRegistry.getTokenId(tokenIdV1), tokenId, "tokenId"); assertEq(ethRegistry.ownerOf(tokenId), md.owner, "owner"); - assertEq(ethRegistry.getExpiry(tokenId), ethRegistrarV1.nameExpires(tokenIdV1), "expiry"); + assertEq(ethRegistry.getExpiry(tokenId), expectedExpiry, "expiry"); assertEq(ethRegistry.getResolver(md.label), md.resolver, "resolver"); checkResolution(name, address(ensV2Resolver), md.resolver); assertEq( @@ -379,6 +487,63 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { address(md.subregistry), "subregistry" ); + assertEq(registryV1.resolver(node), address(0), "resolverV1"); + assertEq(registryV1.owner(NameCoder.namehash(name, 0)), address(graveyard), "graveyard"); + } + + function test_unwrapped_migrateViaApproval(bool all) external { + (bytes memory name, uint256 tokenIdV1) = registerUnwrapped(testLabel); + LibMigration.Data memory md = _unlockedData(name); + + // give friend approval + vm.prank(testOwner); + if (all) { + baseRegistrar.setApprovalForAll(friend, true); + } else { + baseRegistrar.approve(friend, tokenIdV1); + } + + // friend initiates migration + vm.prank(friend); + baseRegistrar.safeTransferFrom( + testOwner, + address(migrationController), + tokenIdV1, + abi.encode(md) + ); + + uint256 tokenId = ethRegistry.getTokenId(LibLabel.id(md.label)); + assertEq(ethRegistry.ownerOf(tokenId), md.owner, "owner"); + } + + function test_wrapped_migrateViaApproval() external { + /* bool all */ + bytes memory name = registerWrappedETH2LD(testLabel, CAN_DO_EVERYTHING); + LibMigration.Data memory md = _unlockedData(name); + bytes32 node = NameCoder.namehash(name, 0); + + // give friend approval + vm.prank(testOwner); + // if (all) { + nameWrapper.setApprovalForAll(friend, true); + + // } else { + // nameWrapper.approve(friend, uint256(node)); + // } + // see: V1Fixture.t.sol: `test_nameWrapper_approveBug()` + + // friend initiates migration + vm.prank(friend); + nameWrapper.safeTransferFrom( + testOwner, + address(migrationController), + uint256(node), + 1, + abi.encode(md) + ); + + uint256 tokenId = ethRegistry.getTokenId(LibLabel.id(md.label)); + assertEq(ethRegistry.ownerOf(tokenId), md.owner, "owner"); } function test_wrapped_migrateBatch(uint8 count) external { @@ -387,16 +552,17 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { uint256[] memory amounts = new uint256[](count); LibMigration.Data[] memory mds = new LibMigration.Data[](count); for (uint256 i; i < count; ++i) { + testDuration = uint64(vm.randomUint(1, 1000 days)); bytes memory name = registerWrappedETH2LD(_label(i), CAN_DO_EVERYTHING); - LibMigration.Data memory md = _makeData(name); + LibMigration.Data memory md = _unlockedData(name); md.resolver = address(uint160(i)); mds[i] = md; ids[i] = uint256(NameCoder.namehash(name, 0)); amounts[i] = 1; } - vm.prank(user); + vm.prank(testOwner); nameWrapper.safeBatchTransferFrom( - user, + testOwner, address(migrationController), ids, amounts, @@ -404,19 +570,16 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { ); for (uint256 i; i < count; ++i) { LibMigration.Data memory md = mds[i]; - uint256 tokenId = ethRegistry.getTokenId(LibLabel.id(md.label)); + uint256 tokenIdV1 = LibLabel.id(md.label); + uint256 tokenId = ethRegistry.getTokenId(tokenIdV1); assertEq(ethRegistry.ownerOf(tokenId), md.owner, "owner"); assertEq( ethRegistry.getExpiry(tokenId), - ethRegistrarV1.nameExpires(uint256(keccak256(bytes(md.label)))), + baseRegistrar.nameExpires(tokenIdV1) + premigrationBonusPeriod, "expiry" ); assertEq(ethRegistry.getResolver(md.label), md.resolver, "resolver"); - checkResolution( - NameCoder.ethName(md.label), - address(ensV2Resolver), - address(uint160(i)) - ); + checkResolution(NameCoder.ethName(md.label), address(ensV2Resolver), address(uint160(i))); assertEq( address(ethRegistry.getSubregistry(md.label)), address(md.subregistry), @@ -425,14 +588,31 @@ contract UnlockedMigrationControllerTest is MigrationControllerFixture { } } - function _makeData(bytes memory name) internal view returns (LibMigration.Data memory) { - return - LibMigration.Data({ - label: NameCoder.firstLabel(name), - owner: user, - subregistry: testRegistry, - resolver: testResolver, - salt: 0 // ignored by UnlockedMigrationController - }); + function test_wrapped_migrateBatch_lastOneWrong(uint8 count) external { + vm.assume(count > 1 && count < 5); + uint256[] memory ids = new uint256[](count); + uint256[] memory amounts = new uint256[](count); + LibMigration.Data[] memory mds = new LibMigration.Data[](count); + for (uint256 i; i < count; ++i) { + bytes memory name = + registerWrappedETH2LD(_label(i), i == count - 1 ? CANNOT_UNWRAP : CAN_DO_EVERYTHING); + LibMigration.Data memory md = _unlockedData(name); + mds[i] = md; + ids[i] = uint256(NameCoder.namehash(name, 0)); + amounts[i] = 1; + } + vm.expectRevert( + WrappedErrorLib.wrap( + abi.encodeWithSelector(LibMigration.NameIsLocked.selector, ids[count - 1]) + ) + ); + vm.prank(testOwner); + nameWrapper.safeBatchTransferFrom( + testOwner, + address(migrationController), + ids, + amounts, + abi.encode(mds) + ); } } diff --git a/contracts/test/unit/registrar/AbstractETHRegistrar.t.sol b/contracts/test/unit/registrar/AbstractETHRegistrar.t.sol new file mode 100755 index 000000000..5ea144692 --- /dev/null +++ b/contracts/test/unit/registrar/AbstractETHRegistrar.t.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +import {AbstractETHRegistrar} from "~src/registrar/AbstractETHRegistrar.sol"; +import {IETHRenewer} from "~src/registrar/interfaces/IETHRenewer.sol"; +import {IRentPriceOracle} from "~src/registrar/interfaces/IRentPriceOracle.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {MigrationControllerFixture} from "~test/fixtures/MigrationControllerFixture.sol"; +import {StandardRentPriceOracleFixture} from "~test/fixtures/StandardRentPriceOracleFixture.sol"; + +contract AbstractETHRegistrarTest is MigrationControllerFixture, StandardRentPriceOracleFixture { + MockRegistrar ethRegistrar; + + function setUp() external { + deployMigrationControllerFixture(); + deployStandardRentPriceOracleFixture(); + + ethRegistrar = new MockRegistrar(address(this), ethRegistry, beneficiary, rentPriceOracle); + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface(address(ethRegistrar), type(IETHRenewer).interfaceId), + "IETHRenewer" + ); + } + + function test_constructor() external view { + assertEq(ethRegistrar.owner(), address(this), "owner"); + assertEq(address(ethRegistrar.ETH_REGISTRY()), address(ethRegistry), "ETH_REGISTRY"); + assertEq(address(ethRegistrar.BENEFICIARY()), address(beneficiary), "BENFICIARY"); + assertEq( + address(ethRegistrar.rentPriceOracle()), + address(rentPriceOracle), + "rentPriceOracle" + ); + } + + function test_setRentPriceOracle() external { + IRentPriceOracle oracle = IRentPriceOracle(makeAddr("oracle")); + vm.expectEmit(); + emit AbstractETHRegistrar.RentPriceOracleUpdated(oracle); + ethRegistrar.setRentPriceOracle(oracle); + assertEq(address(ethRegistrar.rentPriceOracle()), address(oracle)); + } + + function test_setRentPriceOracle_notAuthorized() external { + address actor = makeAddr("actor"); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, actor)); + vm.prank(actor); + ethRegistrar.setRentPriceOracle(IRentPriceOracle(address(1))); + } +} + + +contract MockRegistrar is AbstractETHRegistrar { + uint64 public constant GRACE_PERIOD = 0; + constructor( + address owner_, + IPermissionedRegistry ethRegistry, + address beneficiary, + IRentPriceOracle oracle + ) + AbstractETHRegistrar(owner_, ethRegistry, beneficiary, oracle) + {} + function _isRenewable(IPermissionedRegistry.State memory) internal pure override returns (bool) { + return false; + } + function getRemainingGracePeriod(string calldata) external pure returns (uint64) { + return 0; + } +} diff --git a/contracts/test/unit/registrar/BatchRegistrar.t.sol b/contracts/test/unit/registrar/BatchRegistrar.t.sol new file mode 100644 index 000000000..946b77b46 --- /dev/null +++ b/contracts/test/unit/registrar/BatchRegistrar.t.sol @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, namechain/ordering, one-contract-per-file + +import {Vm} from "forge-std/Test.sol"; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {BatchRegistrar} from "~src/registrar/BatchRegistrar.sol"; +import {LibLabel} from "~src/utils/LibLabel.sol"; +import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; + +contract BatchRegistrarTest is V2Fixture { + BatchRegistrar batchRegistrar; + + address owner = address(this); + address resolver = address(0xABCD); + + function setUp() external { + deployV2Fixture(); + batchRegistrar = new BatchRegistrar(ethRegistry, owner); + + ethRegistry.grantRootRoles( + RegistryRolesLib.ROLE_REGISTRAR | RegistryRolesLib.ROLE_RENEW, + address(batchRegistrar) + ); + } + + function test_batchRegister_lengthMismatch() external { + vm.expectRevert(abi.encodeWithSelector(BatchRegistrar.InputLengthMismatch.selector)); + batchRegistrar.batchRegister( + IRegistry(address(0)), + resolver, + new string[](0), + new uint64[](1) + ); + } + + function test_batchRegister_new_names() public { + string[] memory labels = new string[](3); + uint64[] memory expires = new uint64[](3); + + labels[0] = "test1"; + expires[0] = uint64(block.timestamp + 86400); + + labels[1] = "test2"; + expires[1] = uint64(block.timestamp + 86400 * 2); + + labels[2] = "test3"; + expires[2] = uint64(block.timestamp + 86400 * 3); + + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + for (uint256 i = 0; i < labels.length; i++) { + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id(labels[i])); + assertEq( + uint256(state.status), + uint256(IPermissionedRegistry.Status.RESERVED), + "Status should be RESERVED" + ); + assertEq(state.expiry, expires[i], "Expiry should match"); + assertEq(ethRegistry.getResolver(labels[i]), resolver, "Resolver should match"); + } + } + + function test_batchRegister_renews_if_newer_expiry() public { + uint64 originalExpiry = uint64(block.timestamp + 86400); + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "test"; + expires[0] = originalExpiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id("test")); + assertEq(state.expiry, originalExpiry, "Initial expiry should match"); + + uint64 newExpiry = uint64(block.timestamp + 86400 * 365); + expires[0] = newExpiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + state = ethRegistry.getState(LibLabel.id("test")); + assertEq(state.expiry, newExpiry, "Expiry should be renewed"); + } + + function test_batchRegister_skips_if_same_or_older_expiry() public { + uint64 originalExpiry = uint64(block.timestamp + 86400 * 365); + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "test"; + expires[0] = originalExpiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id("test")); + assertEq(state.expiry, originalExpiry, "Initial expiry should match"); + + uint64 earlierExpiry = uint64(block.timestamp + 86400); + expires[0] = earlierExpiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + state = ethRegistry.getState(LibLabel.id("test")); + assertEq(state.expiry, originalExpiry, "Expiry should remain unchanged"); + } + + function test_batchRegister_mixed_new_and_existing() public { + uint64 originalExpiry = uint64(block.timestamp + 86400); + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "existing"; + expires[0] = originalExpiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + uint64 newExpiry = uint64(block.timestamp + 86400 * 365); + string[] memory mixedLabels = new string[](3); + uint64[] memory mixedExpires = new uint64[](3); + + mixedLabels[0] = "new1"; + mixedExpires[0] = newExpiry; + + mixedLabels[1] = "existing"; + mixedExpires[1] = newExpiry; + + mixedLabels[2] = "new2"; + mixedExpires[2] = newExpiry; + + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, mixedLabels, mixedExpires); + + IPermissionedRegistry.State memory state1 = ethRegistry.getState(LibLabel.id("new1")); + assertEq( + uint256(state1.status), + uint256(IPermissionedRegistry.Status.RESERVED), + "new1 should be RESERVED" + ); + assertEq(state1.expiry, newExpiry, "new1 expiry should match"); + + IPermissionedRegistry.State memory state2 = ethRegistry.getState(LibLabel.id("new2")); + assertEq( + uint256(state2.status), + uint256(IPermissionedRegistry.Status.RESERVED), + "new2 should be RESERVED" + ); + assertEq(state2.expiry, newExpiry, "new2 expiry should match"); + + IPermissionedRegistry.State memory existingState = + ethRegistry.getState(LibLabel.id("existing")); + assertEq(existingState.expiry, newExpiry, "existing expiry should be renewed"); + } + + function test_batchRegister_re_reserves_expired_names() public { + uint64 originalExpiry = uint64(block.timestamp + 86400); + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "expiring"; + expires[0] = originalExpiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + vm.warp(block.timestamp + 86401); + + uint64 newExpiry = uint64(block.timestamp + 86400 * 365); + expires[0] = newExpiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id("expiring")); + assertEq( + uint256(state.status), + uint256(IPermissionedRegistry.Status.RESERVED), + "Should be re-reserved" + ); + assertEq(state.expiry, newExpiry, "Expiry should match new expiry"); + } + + function test_batchRegister_empty_array() public { + string[] memory labels = new string[](0); + uint64[] memory expires = new uint64[](0); + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + } + + function test_batchRegister_single_name() public { + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "single"; + expires[0] = uint64(block.timestamp + 86400); + + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id("single")); + assertEq( + uint256(state.status), + uint256(IPermissionedRegistry.Status.RESERVED), + "Status should be RESERVED" + ); + assertEq(state.expiry, expires[0], "Expiry should match"); + } + + function test_batchRegister_onlyOwner() public { + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "test"; + expires[0] = uint64(block.timestamp + 86400); + + address unauthorized = address(0xBEEF); + vm.expectRevert( + abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, unauthorized) + ); + vm.prank(unauthorized); + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + } + + function test_batchRegister_duplicateLabelsInBatch() public { + uint64 expiry1 = uint64(block.timestamp + 86400); + uint64 expiry2 = uint64(block.timestamp + 86400 * 2); + + string[] memory labels = new string[](2); + uint64[] memory expires = new uint64[](2); + labels[0] = "duplicate"; + expires[0] = expiry1; + labels[1] = "duplicate"; + expires[1] = expiry2; + + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id("duplicate")); + assertEq( + uint256(state.status), + uint256(IPermissionedRegistry.Status.RESERVED), + "Status should be RESERVED" + ); + assertEq(state.expiry, expiry2, "Expiry should be the renewed (second) value"); + } + + function test_batchRegister_events() public { + uint64 expiry = uint64(block.timestamp + 86400); + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "eventtest"; + expires[0] = expiry; + + vm.recordLogs(); + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + Vm.Log[] memory logs = vm.getRecordedLogs(); + + bytes32 labelReservedSig = keccak256("LabelReserved(uint256,bytes32,string,uint64,address)"); + bool foundLabelReserved = false; + for (uint256 i = 0; i < logs.length; i++) { + if (logs[i].topics[0] == labelReservedSig) { + foundLabelReserved = true; + bytes32 labelHash = keccak256(bytes("eventtest")); + assertEq(logs[i].topics[2], labelHash, "labelHash topic should match"); + assertEq( + logs[i].topics[3], + bytes32(uint256(uint160(address(batchRegistrar)))), + "sender topic should match" + ); + break; + } + } + assertTrue(foundLabelReserved, "LabelReserved event should be emitted"); + + uint64 newExpiry = uint64(block.timestamp + 86400 * 2); + expires[0] = newExpiry; + + vm.recordLogs(); + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + logs = vm.getRecordedLogs(); + + bytes32 expiryUpdatedSig = keccak256("ExpiryUpdated(uint256,uint64,address)"); + bool foundExpiryUpdated = false; + for (uint256 i = 0; i < logs.length; i++) { + if (logs[i].topics[0] == expiryUpdatedSig) { + foundExpiryUpdated = true; + break; + } + } + assertTrue(foundExpiryUpdated, "ExpiryUpdated event should be emitted"); + } + + function test_batchRegister_skips_already_registered_names() public { + uint64 expiry = uint64(block.timestamp + 86400 * 365); + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "registered"; + expires[0] = expiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + ethRegistry.grantRootRoles(RegistryRolesLib.ROLE_REGISTER_RESERVED, address(this)); + address realOwner = address(0x1234); + ethRegistry.register( + "registered", + realOwner, + IRegistry(address(0)), + resolver, + RegistryRolesLib.ROLE_SET_RESOLVER, + expiry + ); + + IPermissionedRegistry.State memory stateBefore = + ethRegistry.getState(LibLabel.id("registered")); + assertEq(uint256(stateBefore.status), uint256(IPermissionedRegistry.Status.REGISTERED)); + + uint64 newExpiry = uint64(block.timestamp + 86400 * 730); + string[] memory mixedLabels = new string[](3); + uint64[] memory mixedExpires = new uint64[](3); + mixedLabels[0] = "fresh1"; + mixedExpires[0] = newExpiry; + mixedLabels[1] = "registered"; + mixedExpires[1] = newExpiry; + mixedLabels[2] = "fresh2"; + mixedExpires[2] = newExpiry; + + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, mixedLabels, mixedExpires); + + IPermissionedRegistry.State memory stateAfter = + ethRegistry.getState(LibLabel.id("registered")); + assertEq(uint256(stateAfter.status), uint256(IPermissionedRegistry.Status.REGISTERED)); + assertEq(ethRegistry.ownerOf(stateAfter.tokenId), realOwner, "Owner should remain unchanged"); + assertEq(stateAfter.expiry, expiry, "Expiry should remain unchanged"); + + IPermissionedRegistry.State memory fresh1 = ethRegistry.getState(LibLabel.id("fresh1")); + assertEq(uint256(fresh1.status), uint256(IPermissionedRegistry.Status.RESERVED)); + assertEq(fresh1.expiry, newExpiry); + + IPermissionedRegistry.State memory fresh2 = ethRegistry.getState(LibLabel.id("fresh2")); + assertEq(uint256(fresh2.status), uint256(IPermissionedRegistry.Status.RESERVED)); + assertEq(fresh2.expiry, newExpiry); + } + + function test_batchRegister_reservedThenRegister() public { + uint64 expiry = uint64(block.timestamp + 86400 * 365); + string[] memory labels = new string[](1); + uint64[] memory expires = new uint64[](1); + labels[0] = "migratable"; + expires[0] = expiry; + batchRegistrar.batchRegister(IRegistry(address(0)), resolver, labels, expires); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id("migratable")); + assertEq( + uint256(state.status), + uint256(IPermissionedRegistry.Status.RESERVED), + "Should be RESERVED" + ); + + ethRegistry.grantRootRoles(RegistryRolesLib.ROLE_REGISTER_RESERVED, address(this)); + + address realOwner = address(0x1234); + ethRegistry.register( + "migratable", + realOwner, + IRegistry(address(0)), + resolver, + RegistryRolesLib.ROLE_SET_RESOLVER, + expiry + ); + + state = ethRegistry.getState(LibLabel.id("migratable")); + assertEq( + uint256(state.status), + uint256(IPermissionedRegistry.Status.REGISTERED), + "Should be REGISTERED" + ); + assertEq(ethRegistry.ownerOf(state.tokenId), realOwner, "Owner should be realOwner"); + } +} diff --git a/contracts/test/unit/registrar/ETHRegistrar.t.sol b/contracts/test/unit/registrar/ETHRegistrar.t.sol index 9341c3017..4a32312f7 100644 --- a/contracts/test/unit/registrar/ETHRegistrar.t.sol +++ b/contracts/test/unit/registrar/ETHRegistrar.t.sol @@ -3,109 +3,45 @@ pragma solidity >=0.8.13; // solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file -import {Test} from "forge-std/Test.sol"; - import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; -import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; - -import {StandardPricing} from "./StandardPricing.sol"; - -import {PermissionedRegistry, IEnhancedAccessControl} from "~src/registry/PermissionedRegistry.sol"; -import {SimpleRegistryMetadata} from "~src/registry/SimpleRegistryMetadata.sol"; -import { - ETHRegistrar, - IETHRegistrar, - IRegistry, - RegistryRolesLib, - EACBaseRolesLib, - LibLabel, - InvalidOwner, - REGISTRATION_ROLE_BITMAP, - ROLE_SET_ORACLE -} from "~src/registrar/ETHRegistrar.sol"; -import { - StandardRentPriceOracle, - IRentPriceOracle, - PaymentRatio, - DiscountPoint -} from "~src/registrar/StandardRentPriceOracle.sol"; -import { - MockERC20, - MockERC20Blacklist, - MockERC20VoidReturn, - MockERC20FalseReturn -} from "~test/mocks/MockERC20.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; - -contract ETHRegistrarTest is Test { - PermissionedRegistry ethRegistry; - MockHCAFactoryBasic hcaFactory; - - StandardRentPriceOracle rentPriceOracle; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; + +import {InvalidOwner} from "~src/CommonErrors.sol"; +import {LibLabel} from "~src/utils/LibLabel.sol"; +import {IRegistryEvents} from "~src/registry/interfaces/IRegistryEvents.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {IETHRegistrar} from "~src/registrar/interfaces/IETHRegistrar.sol"; +import {IETHRenewer} from "~src/registrar/interfaces/IETHRenewer.sol"; +import {ETHRegistrar, REGISTRATION_ROLE_BITMAP} from "~src/registrar/ETHRegistrar.sol"; +import {MockERC20, MockERC20Blacklist} from "~test/mocks/MockERC20.sol"; +import {MigrationControllerFixture} from "~test/fixtures/MigrationControllerFixture.sol"; +import {StandardRentPriceOracleFixture} from "~test/fixtures/StandardRentPriceOracleFixture.sol"; +import {StandardRegistrar} from "~test/StandardRegistrar.sol"; + +contract ETHRegistrarTest is MigrationControllerFixture, StandardRentPriceOracleFixture { ETHRegistrar ethRegistrar; - MockERC20 tokenUSDC; - MockERC20 tokenDAI; - MockERC20Blacklist tokenBlack; - MockERC20VoidReturn tokenVoid; - MockERC20FalseReturn tokenFalse; - - address user = makeAddr("user"); - address beneficiary = makeAddr("beneficiary"); - - string testLabel = "testname"; - address testSender = user; - address testOwner = user; - IRegistry testRegistry = IRegistry(makeAddr("registry")); - address testResolver = makeAddr("resolver"); - IERC20 testPaymentToken; ///| - bytes32 testSecret; ////////| - bytes32 testReferrer; //////| set below - uint64 testDuration; ///////| - uint256 testCommitDelay; ///| + bytes32 testReferrer = keccak256("referrer"); + bytes32 testSecret = keccak256("secret"); + MockERC20 testPaymentToken; + uint64 testCommitDelay; function setUp() external { - hcaFactory = new MockHCAFactoryBasic(); - ethRegistry = new PermissionedRegistry( - hcaFactory, - new SimpleRegistryMetadata(hcaFactory), - address(this), - EACBaseRolesLib.ALL_ROLES - ); - - tokenUSDC = new MockERC20("USDC", 6, hcaFactory); - tokenDAI = new MockERC20("DAI", 18, hcaFactory); - tokenBlack = new MockERC20Blacklist(); - tokenVoid = new MockERC20VoidReturn(); - tokenFalse = new MockERC20FalseReturn(); - - PaymentRatio[] memory paymentRatios = new PaymentRatio[](5); - paymentRatios[0] = StandardPricing.ratioFromStable(tokenUSDC); - paymentRatios[1] = StandardPricing.ratioFromStable(tokenDAI); - paymentRatios[2] = StandardPricing.ratioFromStable(tokenBlack); - paymentRatios[3] = StandardPricing.ratioFromStable(tokenVoid); - paymentRatios[4] = StandardPricing.ratioFromStable(tokenFalse); - - rentPriceOracle = new StandardRentPriceOracle( - address(this), - ethRegistry, - StandardPricing.getBaseRates(), - new DiscountPoint[](0), // disabled discount - StandardPricing.PREMIUM_PRICE_INITIAL, - StandardPricing.PREMIUM_HALVING_PERIOD, - StandardPricing.PREMIUM_PERIOD, - paymentRatios - ); + deployMigrationControllerFixture(); + deployStandardRentPriceOracleFixture(); ethRegistrar = new ETHRegistrar( + address(this), ethRegistry, - hcaFactory, beneficiary, - StandardPricing.MIN_COMMITMENT_AGE, - StandardPricing.MAX_COMMITMENT_AGE, - StandardPricing.MIN_REGISTER_DURATION, - rentPriceOracle + rentPriceOracle, + StandardRegistrar.GRACE_PERIOD_V2, + StandardRegistrar.MIN_COMMITMENT_AGE, + StandardRegistrar.MAX_COMMITMENT_AGE, + StandardRegistrar.MIN_REGISTER_DURATION ); ethRegistry.grantRootRoles( @@ -113,193 +49,75 @@ contract ETHRegistrarTest is Test { address(ethRegistrar) ); - for (uint256 i; i < paymentRatios.length; i++) { - MockERC20 token = MockERC20(address(paymentRatios[i].token)); - token.mint(user, 1e9 * 10 ** token.decimals()); - vm.prank(user); - token.approve(address(ethRegistrar), type(uint256).max); - } - - vm.warp(rentPriceOracle.premiumPeriod()); // avoid timestamp issues - + setupPaymentTokens(testOwner, address(ethRegistrar)); testPaymentToken = tokenUSDC; - testSecret = bytes32(vm.randomUint()); - testReferrer = bytes32(vm.randomUint()); testDuration = ethRegistrar.MIN_REGISTER_DURATION(); - testCommitDelay = ethRegistrar.MIN_COMMITMENT_AGE() + 1; + testCommitDelay = ethRegistrar.MIN_COMMITMENT_AGE(); + + uint256 t = + Math.max(gracePeriodV1, ethRegistrar.GRACE_PERIOD()) + rentPriceOracle.PREMIUM_PERIOD(); + if (block.timestamp < t) { + vm.warp(t); // avoid timestamp issues + } + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface(address(ethRegistrar), type(IETHRegistrar).interfaceId), + "IETHRegistrar" + ); } function test_constructor() external view { - assertEq(address(ethRegistrar.REGISTRY()), address(ethRegistry), "REGISTRY"); - assertEq(ethRegistrar.BENEFICIARY(), address(beneficiary), "BENEFICIARY"); + assertEq(ethRegistrar.GRACE_PERIOD(), StandardRegistrar.GRACE_PERIOD_V2, "GRACE_PERIOD"); assertEq( ethRegistrar.MIN_COMMITMENT_AGE(), - StandardPricing.MIN_COMMITMENT_AGE, + StandardRegistrar.MIN_COMMITMENT_AGE, "MIN_COMMITMENT_AGE" ); assertEq( ethRegistrar.MAX_COMMITMENT_AGE(), - StandardPricing.MAX_COMMITMENT_AGE, + StandardRegistrar.MAX_COMMITMENT_AGE, "MAX_COMMITMENT_AGE" ); assertEq( ethRegistrar.MIN_REGISTER_DURATION(), - StandardPricing.MIN_REGISTER_DURATION, + StandardRegistrar.MIN_REGISTER_DURATION, "MIN_REGISTER_DURATION" ); - assertEq( - address(ethRegistrar.rentPriceOracle()), - address(rentPriceOracle), - "rentPriceOracle" - ); } function test_constructor_emptyRange() external { - vm.expectRevert(abi.encodeWithSelector(IETHRegistrar.MaxCommitmentAgeTooLow.selector)); + vm.expectRevert(abi.encodeWithSelector(ETHRegistrar.MaxCommitmentAgeTooLow.selector)); new ETHRegistrar( + address(this), ethRegistry, - hcaFactory, beneficiary, + rentPriceOracle, + 0, 1, // minCommitmentAge 1, // maxCommitmentAge - 0, - rentPriceOracle + 0 ); } function test_constructor_invalidRange() external { - vm.expectRevert(abi.encodeWithSelector(IETHRegistrar.MaxCommitmentAgeTooLow.selector)); + vm.expectRevert(abi.encodeWithSelector(ETHRegistrar.MaxCommitmentAgeTooLow.selector)); new ETHRegistrar( + address(this), ethRegistry, - hcaFactory, beneficiary, + rentPriceOracle, + 0, 1, // minCommitmentAge 0, // maxCommitmentAge - 0, - rentPriceOracle + 0 ); } - function test_setRentPriceOracle() external { - PaymentRatio[] memory paymentRatios = new PaymentRatio[](1); - paymentRatios[0] = PaymentRatio(tokenUSDC, 1, 1); - uint256[] memory baseRates = new uint256[](2); - baseRates[0] = 1; - baseRates[1] = 0; - StandardRentPriceOracle oracle = new StandardRentPriceOracle( - address(this), - ethRegistry, - baseRates, - new DiscountPoint[](0), // disabled discount - 0, // \ - 0, // disabled premium - 0, // / - paymentRatios - ); - ethRegistrar.setRentPriceOracle(oracle); - assertTrue(ethRegistrar.isValid("a"), "a"); - assertFalse(ethRegistrar.isValid("ab"), "ab"); - assertFalse(ethRegistrar.isValid("abcdef"), "abcdef"); - assertFalse(ethRegistrar.isPaymentToken(tokenDAI), "DAI"); - (uint256 base, ) = ethRegistrar.rentPrice("a", address(0), 1, tokenUSDC); - assertEq(base, 1, "rent"); // 1 * 10^x / 10^x = 1 - } - - function test_setRentPriceOracle_notAuthorized() external { - PaymentRatio[] memory paymentRatios = new PaymentRatio[](1); - paymentRatios[0] = PaymentRatio(tokenUSDC, 1, 1); - StandardRentPriceOracle oracle = new StandardRentPriceOracle( - address(this), - ethRegistry, - new uint256[](0), // disabled rentals - new DiscountPoint[](0), // disabled discount - 0, - 0, - 0, - paymentRatios - ); - vm.startPrank(user); - vm.expectRevert( - abi.encodeWithSelector( - IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, - ethRegistry.ROOT_RESOURCE(), - ROLE_SET_ORACLE, - user - ) - ); - ethRegistrar.setRentPriceOracle(oracle); - vm.stopPrank(); - } - - function test_isPaymentToken() external view { - assertTrue(rentPriceOracle.isPaymentToken(tokenUSDC), "USDC"); - assertTrue(rentPriceOracle.isPaymentToken(tokenDAI), "DAI"); - assertTrue(rentPriceOracle.isPaymentToken(tokenBlack), "Black"); - assertTrue(rentPriceOracle.isPaymentToken(tokenVoid), "Void"); - assertTrue(rentPriceOracle.isPaymentToken(tokenFalse), "False"); - assertFalse(rentPriceOracle.isPaymentToken(IERC20(address(0)))); - } - - // same as StandardRentPriceOracle.t.sol - function test_isValid() external view { - assertFalse(rentPriceOracle.isValid("")); - assertEq(rentPriceOracle.isValid("a"), StandardPricing.RATE_1CP > 0); - assertEq(rentPriceOracle.isValid("ab"), StandardPricing.RATE_2CP > 0); - assertEq(rentPriceOracle.isValid("abc"), StandardPricing.RATE_3CP > 0); - assertEq(rentPriceOracle.isValid("abce"), StandardPricing.RATE_4CP > 0); - assertEq(rentPriceOracle.isValid("abcde"), StandardPricing.RATE_5CP > 0); - assertEq( - rentPriceOracle.isValid("abcdefghijklmnopqrstuvwxyz"), - StandardPricing.RATE_5CP > 0 - ); - } - - function _makeCommitment() internal view returns (bytes32) { - return - ethRegistrar.makeCommitment( - testLabel, - testOwner, - testSecret, - testRegistry, - testResolver, - testDuration, - testReferrer - ); - } - - function _register() external returns (uint256 tokenId) { - bytes32 commitment = _makeCommitment(); - vm.startPrank(testSender); - ethRegistrar.commit(commitment); - vm.warp(block.timestamp + testCommitDelay); - tokenId = ethRegistrar.register( - testLabel, - testOwner, - testSecret, - testRegistry, - testResolver, - testDuration, - testPaymentToken, - testReferrer - ); - vm.stopPrank(); - } - - function _renew() external { - vm.prank(testSender); - ethRegistrar.renew(testLabel, testDuration, testPaymentToken, testReferrer); - } - - function _reserve() internal { - ethRegistry.register( - testLabel, - address(0), - IRegistry(address(0)), - address(0), - 0, - uint64(block.timestamp + testDuration) - ); - } + //////////////////////////////////////////////////////////////////////// + // Commit / Reveal + //////////////////////////////////////////////////////////////////////// function test_commit() external { bytes32 commitment = _makeCommitment(); @@ -340,22 +158,51 @@ contract ETHRegistrarTest is Test { ethRegistrar.commit(commitment); } - function test_isAvailable() external { - assertTrue(ethRegistrar.isAvailable(testLabel), "before"); - this._register(); - assertFalse(ethRegistrar.isAvailable(testLabel), "after"); + function test_commit_consumed() external { + bytes32 commitment = _makeCommitment(); + this.register(); + assertEq(ethRegistrar.commitmentAt(commitment), 0); + } + + //////////////////////////////////////////////////////////////////////// + // register() + //////////////////////////////////////////////////////////////////////// + + function test_isAvailable_unregistered() external view { + assertTrue(ethRegistrar.isAvailable(testLabel)); } - function test_register() external { - (uint256 base, uint256 premium) = ethRegistrar.rentPrice( + function test_register(uint32 available, uint32 duration) external { + vm.assume( + duration >= ethRegistrar.MIN_REGISTER_DURATION() && + available < 2 * rentPriceOracle.PREMIUM_PERIOD() + ); + vm.warp(ethRegistry.getExpiry(this.register()) + ethRegistrar.GRACE_PERIOD() + available); + + testDuration = duration; + (uint256 base, uint256 premium) = + rentPriceOracle.getRegisterPrice( + testLabel, + available + testCommitDelay, // commit-reveal + testDuration, + testPaymentToken + ); + uint256 labelId = LibLabel.id(testLabel); + uint256 tokenId = LibLabel.withVersion(labelId, 1); + uint64 expiry = + uint64(block.timestamp) + testDuration + testCommitDelay; + vm.expectEmit(); + emit IRegistryEvents.LabelRegistered( + tokenId, + bytes32(labelId), testLabel, testOwner, - testDuration, - testPaymentToken + expiry, + address(ethRegistrar) ); vm.expectEmit(); emit IETHRegistrar.NameRegistered( - LibLabel.withVersion(LibLabel.id(testLabel), 0), + tokenId, testLabel, testOwner, testRegistry, @@ -366,49 +213,101 @@ contract ETHRegistrarTest is Test { base, premium ); - uint256 tokenId = this._register(); + assertEq(this.register(), tokenId, "token"); assertEq(ethRegistry.ownerOf(tokenId), testOwner, "owner"); - assertEq(ethRegistry.getExpiry(tokenId), uint64(block.timestamp) + testDuration, "expiry"); + assertEq(ethRegistry.getExpiry(tokenId), expiry, "expiry"); + assertTrue(ethRegistry.hasRoles(tokenId, REGISTRATION_ROLE_BITMAP, testOwner), "roles"); + assertFalse(ethRegistrar.isAvailable(testLabel), "isAvailable"); } - function test_register_premium_start() external { - uint256 tokenId = this._register(); - uint64 expiry = ethRegistry.getExpiry(tokenId); - vm.warp(expiry); - assertEq(rentPriceOracle.premiumPrice(expiry), rentPriceOracle.premiumPriceAfter(0)); + function test_register_balanceChanges(uint32 available, uint32 duration) external { + vm.assume( + duration >= ethRegistrar.MIN_REGISTER_DURATION() && + available < 2 * rentPriceOracle.PREMIUM_PERIOD() + ); + vm.warp(ethRegistry.getExpiry(this.register()) + ethRegistrar.GRACE_PERIOD() + available); + uint256 owner0 = testPaymentToken.balanceOf(testOwner); + uint256 beneficiary0 = testPaymentToken.balanceOf(beneficiary); + (uint256 base, uint256 premium) = + rentPriceOracle.getRegisterPrice( + testLabel, + available + testCommitDelay, // commit-reveal + duration, + testPaymentToken + ); + testDuration = duration; + this.register(); + uint256 amount = base + premium; + assertEq(owner0 - amount, testPaymentToken.balanceOf(testOwner), "owner"); + assertEq(beneficiary0 + amount, testPaymentToken.balanceOf(beneficiary), "beneficiary"); } - function test_register_premium_end() external { - uint256 tokenId = this._register(); - uint64 expiry = ethRegistry.getExpiry(tokenId); - vm.warp(expiry + rentPriceOracle.premiumPeriod()); - assertEq(rentPriceOracle.premiumPrice(expiry), 0); + function test_register_whileRegistered(uint32 duration) external { + vm.assume(duration < testDuration); + uint256 tokenId = this.register(); + vm.warp(block.timestamp + duration); + assertEq( + uint8(ethRegistry.getStatus(tokenId)), + uint8(IPermissionedRegistry.Status.REGISTERED), + "status" + ); + assertFalse(ethRegistrar.isAvailable(testLabel), "isAvailable"); + assertEq(ethRegistrar.getRemainingGracePeriod(testLabel), 0, "remaining"); } - function test_register_premium_latestOwner() external { - uint256 tokenId = this._register(); - vm.warp(ethRegistry.getExpiry(tokenId)); - (uint256 base, uint256 premium) = ethRegistrar.rentPrice( - testLabel, - testOwner, - testDuration, - testPaymentToken + function test_register_duringGrace(uint32 graceDebt) external { + vm.assume(graceDebt < ethRegistrar.GRACE_PERIOD()); + uint256 tokenId = this.register(); + vm.warp(ethRegistry.getExpiry(tokenId) + graceDebt); + assertEq( + uint8(ethRegistry.getStatus(tokenId)), + uint8(IPermissionedRegistry.Status.AVAILABLE), + "status" + ); + assertFalse(ethRegistrar.isAvailable(testLabel), "isAvailable"); + assertEq( + ethRegistrar.getRemainingGracePeriod(testLabel), + ethRegistrar.GRACE_PERIOD() - graceDebt, + "remaining" + ); + } + + function test_register_afterGrace(uint32 available) external { + vm.assume(available < rentPriceOracle.PREMIUM_PERIOD() * 2); + uint256 tokenId = this.register(); + vm.warp(ethRegistry.getExpiry(tokenId) + ethRegistrar.GRACE_PERIOD() + available); + assertEq( + uint8(ethRegistry.getStatus(tokenId)), + uint8(IPermissionedRegistry.Status.AVAILABLE), + "status" ); + assertTrue(ethRegistrar.isAvailable(testLabel), "isAvailable"); + assertEq(ethRegistrar.getRemainingGracePeriod(testLabel), 0, "remaining"); + this.register(); + } + + function test_register_afterPremium() external { + uint256 tokenId = this.register(); + vm.warp( + ethRegistry.getExpiry(tokenId) + + ethRegistrar.GRACE_PERIOD() + rentPriceOracle.PREMIUM_PERIOD() + ); + (, uint256 premium) = + rentPriceOracle.getRegisterPrice( + testLabel, + type(uint64).max, + testDuration, + testPaymentToken + ); + this.register(); assertEq(premium, 0, "premium"); - uint256 balance0 = testPaymentToken.balanceOf(testOwner); - this._register(); - assertEq(balance0 - base, testPaymentToken.balanceOf(testOwner), "balance"); } function test_register_insufficientAllowance() external { - vm.prank(testSender); + vm.prank(testOwner); tokenUSDC.approve(address(ethRegistrar), 0); - (uint256 base, uint256 premium) = ethRegistrar.rentPrice( - testLabel, - testOwner, - testDuration, - testPaymentToken - ); + (uint256 base, uint256 premium) = + ethRegistrar.getRegisterPrice(testLabel, testDuration, testPaymentToken); vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientAllowance.selector, @@ -417,30 +316,31 @@ contract ETHRegistrarTest is Test { base + premium // needed ) ); - this._register(); + this.register(); } function test_register_insufficientBalance() external { - tokenUSDC.nuke(testSender); - (uint256 base, uint256 premium) = ethRegistrar.rentPrice( - testLabel, - testOwner, - testDuration, - testPaymentToken - ); + testPaymentToken.nuke(testOwner); + (uint256 base, uint256 premium) = + rentPriceOracle.getRegisterPrice( + testLabel, + type(uint64).max, + testDuration, + testPaymentToken + ); vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientBalance.selector, - testSender, // sender - 0, // allowance + testOwner, // sender + 0, // balance base + premium // needed ) ); - this._register(); + this.register(); } function test_register_commitmentTooNew() external { - uint256 dt = 1; + uint64 dt = 1; testCommitDelay = ethRegistrar.MIN_COMMITMENT_AGE() - dt; uint256 t = block.timestamp + testCommitDelay; vm.expectRevert( @@ -451,11 +351,11 @@ contract ETHRegistrarTest is Test { t ) ); - this._register(); + this.register(); } function test_register_commitmentTooOld() external { - uint256 dt = 1; + uint64 dt = 1; testCommitDelay = ethRegistrar.MAX_COMMITMENT_AGE() + dt; uint256 t = block.timestamp + testCommitDelay; vm.expectRevert( @@ -466,207 +366,239 @@ contract ETHRegistrarTest is Test { t ) ); - this._register(); + this.register(); } - function test_register_durationTooShort() external { - testDuration = ethRegistrar.MIN_REGISTER_DURATION() - 1; - vm.expectRevert( - abi.encodeWithSelector( - IETHRegistrar.DurationTooShort.selector, - testDuration, - ethRegistrar.MIN_REGISTER_DURATION() - ) - ); - this._register(); + function test_register_durationTooShort(uint32 duration) external { + uint64 min = ethRegistrar.MIN_REGISTER_DURATION(); + vm.assume(duration < min); + testDuration = duration; + vm.expectRevert(abi.encodeWithSelector(IETHRenewer.DurationTooShort.selector, duration, min)); + this.register(); } function test_register_nullOwner() external { - testOwner = address(0); // aka reserve() + testOwner = address(0); vm.expectRevert(abi.encodeWithSelector(InvalidOwner.selector)); - this._register(); + this.register(); } function test_register_registered() external { - this._register(); + this.register(); vm.expectRevert(abi.encodeWithSelector(IETHRegistrar.NameNotAvailable.selector, testLabel)); - this._register(); + this.register(); } - function test_register_reserved() external { - _reserve(); + function test_register_premigrated(uint32 during) external { + vm.assume(during < testDuration + gracePeriodV1); + registerUnwrapped(testLabel); + vm.warp(block.timestamp + during); + assertFalse(ethRegistrar.isAvailable(testLabel), "isAvailable"); + assertFalse(ethRegistrar.isRenewable(testLabel), "isRenewable"); vm.expectRevert(abi.encodeWithSelector(IETHRegistrar.NameNotAvailable.selector, testLabel)); - this._register(); + this.register(); } - function test_renew() external { - uint256 tokenId = this._register(); - uint64 expiry0 = ethRegistry.getExpiry(tokenId); - (uint256 base, ) = ethRegistrar.rentPrice( - testLabel, - testOwner, - testDuration, - testPaymentToken - ); + //////////////////////////////////////////////////////////////////////// + // renew() + //////////////////////////////////////////////////////////////////////// + + function test_isRenewable_unregistered() external view { + assertFalse(ethRegistrar.isRenewable(testLabel)); + } + + function test_renew(uint32 duration) external { + vm.assume(duration >= ethRegistrar.MIN_RENEW_DURATION()); + uint256 tokenId = this.register(); + testDuration = duration; + uint64 newExpiry = ethRegistry.getExpiry(tokenId) + testDuration; + uint256 amount = ethRegistrar.getRenewPrice(testLabel, testDuration, testPaymentToken); vm.expectEmit(); - emit IETHRegistrar.NameRenewed( - LibLabel.withVersion(LibLabel.id(testLabel), 0), + emit IRegistryEvents.ExpiryUpdated(tokenId, newExpiry, address(ethRegistrar)); + vm.expectEmit(); + emit IETHRenewer.NameRenewed( + tokenId, testLabel, testDuration, - expiry0 + testDuration, + newExpiry, testPaymentToken, testReferrer, - base + amount ); - this._renew(); - assertEq(ethRegistry.getExpiry(tokenId), expiry0 + testDuration); + this.renew(); + assertEq(ethRegistry.getExpiry(tokenId), newExpiry); } - function test_renew_reserved() external { - _reserve(); - this._renew(); + function test_renew_balanceChanges(uint32 duration) external { + vm.assume(duration >= ethRegistrar.MIN_RENEW_DURATION()); + this.register(); + uint256 owner0 = testPaymentToken.balanceOf(testOwner); + uint256 beneficiary0 = testPaymentToken.balanceOf(beneficiary); + uint256 amount = ethRegistrar.getRenewPrice(testLabel, duration, testPaymentToken); + vm.prank(testOwner); + ethRegistrar.renew(testLabel, duration, testPaymentToken, testReferrer); + assertEq(owner0 - amount, testPaymentToken.balanceOf(testOwner), "owner"); + assertEq(beneficiary0 + amount, testPaymentToken.balanceOf(beneficiary), "beneficiary"); } function test_renew_available() external { - vm.expectRevert(abi.encodeWithSelector(IETHRegistrar.NameIsAvailable.selector, testLabel)); - this._renew(); + vm.expectRevert(abi.encodeWithSelector(IETHRenewer.NameNotRenewable.selector, testLabel)); + this.renew(); } - function test_renew_expired() external { - uint256 tokenId = this._register(); - vm.warp(ethRegistry.getExpiry(tokenId)); - vm.expectRevert(abi.encodeWithSelector(IETHRegistrar.NameIsAvailable.selector, testLabel)); - this._renew(); + function test_renew_duringGrace(uint32 graceDebt) external { + vm.assume(graceDebt < ethRegistrar.GRACE_PERIOD()); + uint256 tokenId = this.register(); + vm.warp(ethRegistry.getExpiry(tokenId) + graceDebt); + this.renew(); } - function test_renew_0duration() external { - this._register(); - testDuration = 0; - vm.expectRevert(abi.encodeWithSelector(IRentPriceOracle.NotValid.selector, testLabel)); - this._renew(); + function test_renew_afterGrace() external { + uint256 tokenId = this.register(); + vm.warp(ethRegistry.getExpiry(tokenId) + ethRegistrar.GRACE_PERIOD()); + vm.expectRevert(abi.encodeWithSelector(IETHRenewer.NameNotRenewable.selector, testLabel)); + this.renew(); } - function test_renew_insufficientAllowance() external { - this._register(); - vm.prank(testSender); - tokenUSDC.approve(address(ethRegistrar), 0); - (uint256 base, ) = ethRegistrar.rentPrice( - testLabel, - testOwner, - testDuration, - testPaymentToken + function test_renew_durationTooShort() external { + uint64 min = ethRegistrar.MIN_RENEW_DURATION(); + this.register(); + testDuration = min - 1; + vm.expectRevert( + abi.encodeWithSelector(IETHRenewer.DurationTooShort.selector, testDuration, min) ); + this.renew(); + } + + function test_renew_insufficientAllowance() external { + this.register(); + vm.prank(testOwner); + testPaymentToken.approve(address(ethRegistrar), 0); + uint256 amount = ethRegistrar.getRenewPrice(testLabel, testDuration, testPaymentToken); vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientAllowance.selector, - address(ethRegistrar), - 0, - base + address(ethRegistrar), // spender + 0, // allowance + amount // needed ) ); - this._renew(); + this.renew(); } - function test_supportsInterface() external view { - assertTrue( - ERC165Checker.supportsInterface(address(ethRegistrar), type(IETHRegistrar).interfaceId), - "IETHRegistrar" - ); - assertTrue( - ERC165Checker.supportsInterface( - address(ethRegistrar), - type(IRentPriceOracle).interfaceId - ), - "IRentPriceOracle" + function test_renew_insufficientBalance() external { + this.register(); + testPaymentToken.nuke(testOwner); + uint256 amount = ethRegistrar.getRenewPrice(testLabel, testDuration, testPaymentToken); + vm.expectRevert( + abi.encodeWithSelector( + IERC20Errors.ERC20InsufficientBalance.selector, + testOwner, // sender + 0, // balance + amount // needed + ) ); + this.renew(); } - function test_beneficiary_register() external { - (uint256 base, ) = ethRegistrar.rentPrice( - testLabel, - testOwner, - testDuration, - testPaymentToken - ); - uint256 balance0 = testPaymentToken.balanceOf(beneficiary); - this._register(); - assertEq(testPaymentToken.balanceOf(beneficiary), balance0 + base); + //////////////////////////////////////////////////////////////////////// + // Payment Processing + //////////////////////////////////////////////////////////////////////// + + function test_voidReturn_acceptedBySafeERC20() external { + // register + testPaymentToken = tokenVoid; + this.register(); + + // renew + this.renew(); } - function test_beneficiary_renew() external { - this._register(); - uint256 balance0 = testPaymentToken.balanceOf(beneficiary); - (uint256 base, ) = ethRegistrar.rentPrice( - testLabel, - testOwner, - testDuration, - testPaymentToken + function test_falseReturn_rejectedBySafeERC20() external { + // register + testPaymentToken = tokenFalse; + vm.expectRevert( + abi.encodeWithSelector(SafeERC20.SafeERC20FailedOperation.selector, tokenFalse) ); - this._renew(); - assertEq(testPaymentToken.balanceOf(beneficiary), balance0 + base); - } + this.register(); - function test_registry_bitmap() external { - uint256 tokenId = this._register(); - assertTrue(ethRegistry.hasRoles(tokenId, REGISTRATION_ROLE_BITMAP, testOwner)); + // renew + testPaymentToken = tokenUSDC; + this.register(); + testPaymentToken = tokenFalse; + vm.expectRevert( + abi.encodeWithSelector(SafeERC20.SafeERC20FailedOperation.selector, tokenFalse) + ); + this.renew(); } - function test_blacklist_user() external { - tokenBlack.setBlacklisted(user, true); - vm.expectRevert(abi.encodeWithSelector(MockERC20Blacklist.Blacklisted.selector, user)); + function test_blacklisted_payer() external { + tokenBlack.setBlacklisted(testOwner, true); + + // register testPaymentToken = tokenBlack; - this._register(); + vm.expectRevert(abi.encodeWithSelector(MockERC20Blacklist.Blacklisted.selector, testOwner)); + this.register(); + + // renew testPaymentToken = tokenUSDC; - this._register(); + this.register(); + testPaymentToken = tokenBlack; + vm.expectRevert(abi.encodeWithSelector(MockERC20Blacklist.Blacklisted.selector, testOwner)); + this.renew(); } - function test_blacklist_beneficiary() external { - tokenBlack.setBlacklisted(ethRegistrar.BENEFICIARY(), true); - vm.expectRevert( - abi.encodeWithSelector( - MockERC20Blacklist.Blacklisted.selector, - ethRegistrar.BENEFICIARY() - ) - ); + function test_blacklisted_beneficiary() external { + tokenBlack.setBlacklisted(beneficiary, true); + + // register testPaymentToken = tokenBlack; - this._register(); + vm.expectRevert(abi.encodeWithSelector(MockERC20Blacklist.Blacklisted.selector, beneficiary)); + this.register(); + + // renew testPaymentToken = tokenUSDC; - this._register(); + this.register(); + testPaymentToken = tokenBlack; + vm.expectRevert(abi.encodeWithSelector(MockERC20Blacklist.Blacklisted.selector, beneficiary)); + this.renew(); } - function test_registered_name_has_transfer_role() external { - uint256 tokenId = this._register(); + //////////////////////////////////////////////////////////////////////// + // Helpers + //////////////////////////////////////////////////////////////////////// - assertTrue( - ethRegistry.hasRoles(tokenId, RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, testOwner), - "Registered name owner should have ROLE_CAN_TRANSFER" - ); + function _makeCommitment() internal view returns (bytes32) { + return + ethRegistrar.makeCommitment( + testLabel, + testOwner, + testSecret, + testRegistry, + testResolver, + testDuration, + testReferrer + ); } - function test_registered_name_can_be_transferred() external { - uint256 tokenId = this._register(); - address newOwner = makeAddr("newOwner"); - + function register() external returns (uint256 tokenId) { + ethRegistrar.commit(_makeCommitment()); + vm.warp(block.timestamp + testCommitDelay); vm.prank(testOwner); - ethRegistry.safeTransferFrom(testOwner, newOwner, tokenId, 1, ""); - - assertEq( - ethRegistry.ownerOf(tokenId), - newOwner, - "Token should be transferred to new owner" + tokenId = ethRegistrar.register( + testLabel, + testOwner, + testSecret, + testRegistry, + testResolver, + testDuration, + testPaymentToken, + testReferrer ); } - function test_voidReturn_acceptedBySafeERC20() public { - testPaymentToken = tokenVoid; - this._register(); - } - - function test_falseReturn_rejectedBySafeERC20() public { - testPaymentToken = tokenFalse; - vm.expectRevert( - abi.encodeWithSelector(SafeERC20.SafeERC20FailedOperation.selector, tokenFalse) - ); - this._register(); + function renew() external { + vm.prank(testOwner); + ethRegistrar.renew(testLabel, testDuration, testPaymentToken, testReferrer); } } diff --git a/contracts/test/unit/registrar/ETHRenewerV1.t.sol b/contracts/test/unit/registrar/ETHRenewerV1.t.sol new file mode 100755 index 000000000..88908699c --- /dev/null +++ b/contracts/test/unit/registrar/ETHRenewerV1.t.sol @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {console} from "forge-std/Test.sol"; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {IBaseRegistrar} from "@ens/contracts/ethregistrar/IBaseRegistrar.sol"; + +import {LibLabel} from "~src/utils/LibLabel.sol"; +import {IRegistryEvents} from "~src/registry/interfaces/IRegistryEvents.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {IETHRenewer} from "~src/registrar/interfaces/IETHRenewer.sol"; +import {ETHRenewerV1} from "~src/registrar/ETHRenewerV1.sol"; +import {MigrationControllerFixture} from "~test/fixtures/MigrationControllerFixture.sol"; +import {StandardRentPriceOracleFixture} from "~test/fixtures/StandardRentPriceOracleFixture.sol"; +import {MockERC20} from "~test/mocks/MockERC20.sol"; +import {StandardRegistrar} from "~test/StandardRegistrar.sol"; + +// [gas analysis] +// test_renew(): 56159 +// test_syncWrapper_unwrapped(): 52572 +// test_syncWrapper_wrapped(): +// N | Gas +// 0 | 36785 +// 1 | 43289 +// 2 | 47798 +// 3 | 58807 +// 4 | 69819 +// 5 | 80833 + +contract ETHRenewerV1Test is MigrationControllerFixture, StandardRentPriceOracleFixture { + ETHRenewerV1 ethRenewerV1; + + bytes32 testReferrer = keccak256("referrer"); + MockERC20 testPaymentToken; + + function setUp() external { + deployMigrationControllerFixture(); + deployStandardRentPriceOracleFixture(); + + ethRenewerV1 = new ETHRenewerV1( + address(this), + ethRegistry, + beneficiary, + rentPriceOracle, + StandardRegistrar.GRACE_PERIOD_V2, + StandardRegistrar.BONUS_PERIOD, + nameWrapper, + address(wrappedController) + ); + + ethRegistry.grantRootRoles(RegistryRolesLib.ROLE_RENEW, address(ethRenewerV1)); + + baseRegistrar.addController(address(ethRenewerV1)); + baseRegistrar.transferOwnership(address(ethRenewerV1)); + nameWrapper.renounceOwnership(); + + // note: nameWrapper is still baseRegistrar controller, see: _activateV2() + + setupPaymentTokens(testOwner, address(ethRenewerV1)); + testPaymentToken = tokenUSDC; + testDuration = ethRenewerV1.MIN_RENEW_DURATION(); + + assertEq( + StandardRegistrar.GRACE_PERIOD_V2 + StandardRegistrar.BONUS_PERIOD, + gracePeriodV1, + "invariant: graceV2 + bonus == graceV1" + ); + } + + function test_constructor() external view { + assertEq(ethRenewerV1.GRACE_PERIOD(), gracePeriodV1, "GRACE_PERIOD"); + assertEq(address(ethRenewerV1.NAME_WRAPPER()), address(nameWrapper), "NAME_WRAPPER"); + assertEq(address(ethRenewerV1.BASE_REGISTRAR()), address(baseRegistrar), "BASE_REGISTRAR"); + assertEq( + address(ethRenewerV1.WRAPPED_CONTROLLER()), + address(wrappedController), + "WRAPPED_CONTROLLER" + ); + } + + function test_transferRegistrarOwnership() external { + ethRenewerV1.transferRegistrarOwnership(actor); + assertEq(baseRegistrar.owner(), actor); + } + + function test_transferRegistrarOwnership_notAuthorized() external { + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, actor)); + vm.prank(actor); + ethRenewerV1.transferRegistrarOwnership(actor); + } + + function test_setRegistrarResolver() external { + assertEq(registryV1.resolver(NameCoder.ETH_NODE), address(ensV2Resolver)); + + ethRenewerV1.setRegistrarResolver(address(1)); + + assertEq(registryV1.resolver(NameCoder.ETH_NODE), address(1)); + } + + function test_setRegistrarResolver_notAuthorized() external { + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, actor)); + vm.prank(actor); + ethRenewerV1.setRegistrarResolver(address(1)); + } + + //////////////////////////////////////////////////////////////////////// + // renew() + //////////////////////////////////////////////////////////////////////// + + function test_isRenewable_unregistered() external view { + assertFalse(ethRenewerV1.isRenewable(testLabel)); + } + + function test_renew() external { + (, uint256 tokenIdV1) = registerUnwrapped(testLabel); + uint256 tokenId = LibLabel.withVersion(tokenIdV1, 0); + uint64 newExpiry = ethRegistry.getExpiry(tokenId) + testDuration; + uint256 amount = ethRenewerV1.getRenewPrice(testLabel, testDuration, testPaymentToken); + vm.expectEmit(); + emit IRegistryEvents.ExpiryUpdated(tokenId, newExpiry, address(ethRenewerV1)); + vm.expectEmit(); + emit IBaseRegistrar.NameRenewed(tokenIdV1, newExpiry - premigrationBonusPeriod); + vm.expectEmit(); + emit IETHRenewer.NameRenewed( + tokenId, + testLabel, + testDuration, + newExpiry, + testPaymentToken, + testReferrer, + amount + ); + vm.prank(testOwner); + uint256 g = gasleft(); + ethRenewerV1.renew(testLabel, testDuration, testPaymentToken, testReferrer); + g -= gasleft(); + console.log("Gas: %s", g); + } + + function test_renew_registered(uint32 duration) external { + vm.assume(duration >= ethRenewerV1.MIN_RENEW_DURATION()); + (, uint256 tokenIdV1) = registerUnwrapped(testLabel); + assertEq(uint8(getStatusV1(tokenIdV1)), uint8(StatusV1.REGISTERED), "status0"); + assertTrue(ethRenewerV1.isRenewable(testLabel), "isRenewable"); + assertEq(ethRenewerV1.getRemainingGracePeriod(testLabel), 0, "remaining"); + + uint256 expiryV1 = baseRegistrar.nameExpires(tokenIdV1); + uint64 expiryV2 = ethRegistry.getExpiry(tokenIdV1); + vm.prank(testOwner); + ethRenewerV1.renew(testLabel, duration, testPaymentToken, testReferrer); + + assertEq(uint8(getStatusV1(tokenIdV1)), uint8(StatusV1.REGISTERED), "status"); // same + assertEq(baseRegistrar.nameExpires(tokenIdV1), expiryV1 + duration, "expiryV1"); + assertEq(ethRegistry.getExpiry(tokenIdV1), expiryV2 + duration, "expiryV2"); + assertEq( + baseRegistrar.nameExpires(tokenIdV1) + premigrationBonusPeriod, + ethRegistry.getExpiry(tokenIdV1), + "sync" + ); + } + + function test_renew_duringGrace_outOfGrace(uint32 graceDebt) external { + vm.assume(graceDebt < gracePeriodV1); + (, uint256 tokenIdV1) = registerUnwrapped(testLabel); + + uint256 expiryV1 = baseRegistrar.nameExpires(tokenIdV1); + uint64 expiryV2 = ethRegistry.getExpiry(tokenIdV1); + + vm.warp(expiryV1 + graceDebt); + assertEq(uint8(getStatusV1(tokenIdV1)), uint8(StatusV1.GRACE), "status0"); + assertTrue(ethRenewerV1.isRenewable(testLabel), "isRenewable"); + assertEq( + ethRenewerV1.getRemainingGracePeriod(testLabel), + gracePeriodV1 - graceDebt, + "remaining" + ); + + uint64 duration = gracePeriodV1; + vm.prank(testOwner); + ethRenewerV1.renew(testLabel, duration, testPaymentToken, testReferrer); + + assertEq(uint8(getStatusV1(tokenIdV1)), uint8(StatusV1.REGISTERED), "status"); + assertEq(ethRenewerV1.getRemainingGracePeriod(testLabel), 0, "remaining"); + assertEq(baseRegistrar.nameExpires(tokenIdV1), expiryV1 + duration, "expiryV1"); + assertEq(ethRegistry.getExpiry(tokenIdV1), expiryV2 + duration, "expiryV2"); + assertEq( + baseRegistrar.nameExpires(tokenIdV1) + premigrationBonusPeriod, + ethRegistry.getExpiry(tokenIdV1), + "sync" + ); + } + + function test_renew_duringGrace_stillInGrace(uint32 graceDebt, uint32 duration) external { + vm.assume( + duration >= ethRenewerV1.MIN_RENEW_DURATION() && + graceDebt >= duration && + graceDebt < gracePeriodV1 + ); + (, uint256 tokenIdV1) = registerUnwrapped(testLabel); + + uint256 expiryV1 = baseRegistrar.nameExpires(tokenIdV1); + uint64 expiryV2 = ethRegistry.getExpiry(tokenIdV1); + + vm.warp(expiryV1 + graceDebt); + assertEq(uint8(getStatusV1(tokenIdV1)), uint8(StatusV1.GRACE), "status0"); + assertTrue(ethRenewerV1.isRenewable(testLabel), "isRenewable"); + + vm.prank(testOwner); + ethRenewerV1.renew(testLabel, duration, testPaymentToken, testReferrer); + + assertEq(uint8(getStatusV1(tokenIdV1)), uint8(StatusV1.GRACE), "status"); // still + assertEq( + ethRenewerV1.getRemainingGracePeriod(testLabel), + gracePeriodV1 - (graceDebt - duration), + "remaining" + ); + assertEq(baseRegistrar.nameExpires(tokenIdV1), expiryV1 + duration, "expiryV1"); + assertEq(ethRegistry.getExpiry(tokenIdV1), expiryV2 + duration, "expiryV2"); + assertEq( + baseRegistrar.nameExpires(tokenIdV1) + premigrationBonusPeriod, + ethRegistry.getExpiry(tokenIdV1), + "sync" + ); + } + + function test_renew_afterGrace() external { + (, uint256 tokenIdV1) = registerUnwrapped(testLabel); + + vm.warp(baseRegistrar.nameExpires(tokenIdV1) + gracePeriodV1); + assertEq(uint8(getStatusV1(tokenIdV1)), uint8(StatusV1.AVAILABLE), "status0"); + assertFalse(ethRenewerV1.isRenewable(testLabel), "isRenewable"); + assertEq(ethRenewerV1.getRemainingGracePeriod(testLabel), 0, "remaining"); + + uint64 duration = ethRenewerV1.MIN_RENEW_DURATION(); + vm.expectRevert(abi.encodeWithSelector(IETHRenewer.NameNotRenewable.selector, testLabel)); + vm.prank(testOwner); + ethRenewerV1.renew(testLabel, duration, testPaymentToken, testReferrer); + } + + function test_renew_balanceChanges(uint32 during, uint32 duration) external { + vm.assume( + duration >= ethRenewerV1.MIN_RENEW_DURATION() && during < testDuration + gracePeriodV1 + ); + registerUnwrapped(testLabel); + vm.warp(block.timestamp + during); + uint256 owner0 = testPaymentToken.balanceOf(testOwner); + uint256 beneficiary0 = testPaymentToken.balanceOf(beneficiary); + uint256 amount = ethRenewerV1.getRenewPrice(testLabel, duration, testPaymentToken); + vm.prank(testOwner); + ethRenewerV1.renew(testLabel, duration, testPaymentToken, testReferrer); + assertEq(owner0 - amount, testPaymentToken.balanceOf(testOwner), "owner"); + assertEq(beneficiary0 + amount, testPaymentToken.balanceOf(beneficiary), "beneficiary"); + } + + function test_renew_durationTooShort() external { + uint64 min = ethRenewerV1.MIN_RENEW_DURATION(); + uint64 duration = min - 1; + registerUnwrapped(testLabel); + vm.expectRevert(abi.encodeWithSelector(IETHRenewer.DurationTooShort.selector, duration, min)); + vm.prank(testOwner); + ethRenewerV1.renew(testLabel, duration, testPaymentToken, testReferrer); + } + + function test_renew_insufficientAllowance() external { + registerUnwrapped(testLabel); + vm.prank(testOwner); + testPaymentToken.approve(address(ethRenewerV1), 0); + uint256 amount = ethRenewerV1.getRenewPrice(testLabel, testDuration, testPaymentToken); + vm.expectRevert( + abi.encodeWithSelector( + IERC20Errors.ERC20InsufficientAllowance.selector, + address(ethRenewerV1), // spender + 0, // allowance + amount // needed + ) + ); + vm.prank(testOwner); + ethRenewerV1.renew(testLabel, testDuration, testPaymentToken, testReferrer); + } + + function test_renew_insufficientBalance() external { + registerUnwrapped(testLabel); + testPaymentToken.nuke(testOwner); + uint256 amount = ethRenewerV1.getRenewPrice(testLabel, testDuration, testPaymentToken); + vm.expectRevert( + abi.encodeWithSelector( + IERC20Errors.ERC20InsufficientBalance.selector, + testOwner, // sender + 0, // balance + amount // needed + ) + ); + vm.prank(testOwner); + ethRenewerV1.renew(testLabel, testDuration, testPaymentToken, testReferrer); + } + + //////////////////////////////////////////////////////////////////////// + // syncWrapper() + //////////////////////////////////////////////////////////////////////// + + function test_syncWrapper_unwrapped() external { + registerUnwrapped(testLabel); + _activateV2(true); + string[] memory labels = new string[](1); + labels[0] = testLabel; + uint256 g = gasleft(); + ethRenewerV1.syncWrapper(labels); // noop + g -= gasleft(); + console.log("Gas: %s", g); + } + + function test_syncWrapper_wrapped() external { + uint256 k; + console.log("N | Gas"); + for (uint256 n; n <= 5; ++n) { + string[] memory labels = new string[](n); + _activateV2(false); + for (uint256 i; i < n; ++i) { + string memory label = labels[i] = _label(k++); + registerWrappedETH2LD(label, 0); + vm.prank(address(ethControllerV1)); + baseRegistrar.renew(LibLabel.id(label), 1); + } + _activateV2(true); + uint256 g = gasleft(); + ethRenewerV1.syncWrapper(labels); + g -= gasleft(); + console.log("%s | %s", n, g); + } + } + + function _activateV2(bool on) internal { + vm.prank(address(ethRenewerV1)); + if (on) { + baseRegistrar.removeController(address(nameWrapper)); + } else { + baseRegistrar.addController(address(nameWrapper)); + } + } +} diff --git a/contracts/test/unit/registrar/StandardPricing.sol b/contracts/test/unit/registrar/StandardPricing.sol deleted file mode 100644 index 1801595be..000000000 --- a/contracts/test/unit/registrar/StandardPricing.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file - -import {PaymentRatio, DiscountPoint} from "~src/registrar/StandardRentPriceOracle.sol"; -import {MockERC20} from "~test/mocks/MockERC20.sol"; - -library StandardPricing { - uint64 constant SEC_PER_YEAR = 31_557_600; // 365.25 - uint64 constant SEC_PER_DAY = 86400; // 1 days - - uint64 constant MIN_COMMITMENT_AGE = 1 minutes; - uint64 constant MAX_COMMITMENT_AGE = 1 days; - uint64 constant MIN_REGISTER_DURATION = 28 days; - - uint8 constant PRICE_DECIMALS = 12; - - uint256 constant PRICE_SCALE = 10 ** PRICE_DECIMALS; - - uint256 constant RATE_1CP = 0; - uint256 constant RATE_2CP = 0; - uint256 constant RATE_3CP = (640 * PRICE_SCALE + SEC_PER_YEAR - 1) / SEC_PER_YEAR; - uint256 constant RATE_4CP = (160 * PRICE_SCALE + SEC_PER_YEAR - 1) / SEC_PER_YEAR; - uint256 constant RATE_5CP = (5 * PRICE_SCALE + SEC_PER_YEAR - 1) / SEC_PER_YEAR; - - uint256 constant PREMIUM_PRICE_INITIAL = 100_000_000 * PRICE_SCALE; - uint64 constant PREMIUM_HALVING_PERIOD = SEC_PER_DAY; - uint64 constant PREMIUM_PERIOD = 21 * SEC_PER_DAY; - - function getBaseRates() internal pure returns (uint256[] memory rates) { - rates = new uint256[](5); - rates[0] = RATE_1CP; - rates[1] = RATE_2CP; - rates[2] = RATE_3CP; - rates[3] = RATE_4CP; - rates[4] = RATE_5CP; - } - - function discountRatio(uint256 numer, uint256 denom) internal pure returns (uint128) { - require(numer < denom, "discountRatio"); - uint256 scale = uint256(type(uint128).max); - return uint128((scale * numer + denom - 1) / denom); - } - - function getDiscountPoints() internal pure returns (DiscountPoint[] memory points) { - // see: StandardRentPriceOracle.updateDiscountFunction() - // * 2yr @ 5.00% == 1yr @ 0.00% + 1yr @ x => +1yr @ x = 10.00% - // * 3yr @ 10.00% == 2yr @ 5.00% + 1yr @ x => +1yr @ x = 20.00% - // * 5yr @ 17.50% == 3yr @ 10.00% + 2yr @ x => +2yr @ x = 28.75% - // * 10yr @ 25.00% == 5yr @ 17.50% + 5yr @ x => +5yr @ x = 32.50% - // * 25yr @ 30.00% == 10yr @ 25.00% + 15yr @ x => +15yr @ x = 33.33% - points = new DiscountPoint[](6); - points[0] = DiscountPoint(SEC_PER_YEAR, 0); - points[1] = DiscountPoint(SEC_PER_YEAR, discountRatio(1, 10)); // 10% - points[2] = DiscountPoint(SEC_PER_YEAR, discountRatio(2, 10)); - points[3] = DiscountPoint(SEC_PER_YEAR * 2, discountRatio(2875, 10000)); - points[4] = DiscountPoint(SEC_PER_YEAR * 5, discountRatio(325, 1000)); - points[5] = DiscountPoint(SEC_PER_YEAR * 15, discountRatio(1, 3)); // 33.3% - } - - function ratioFromStable(MockERC20 token) internal view returns (PaymentRatio memory) { - uint8 d = token.decimals(); - if (d > PRICE_DECIMALS) { - return PaymentRatio(token, uint128(10) ** (d - PRICE_DECIMALS), 1); - } else { - return PaymentRatio(token, 1, uint128(10) ** (PRICE_DECIMALS - d)); - } - } -} diff --git a/contracts/test/unit/registrar/StandardRentPriceOracle.t.sol b/contracts/test/unit/registrar/StandardRentPriceOracle.t.sol index e304e3aa8..85ddeea81 100644 --- a/contracts/test/unit/registrar/StandardRentPriceOracle.t.sol +++ b/contracts/test/unit/registrar/StandardRentPriceOracle.t.sol @@ -3,455 +3,540 @@ pragma solidity >=0.8.13; // solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file -import {Test} from "forge-std/Test.sol"; - -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; -import {StandardPricing} from "./StandardPricing.sol"; - -import {EACBaseRolesLib} from "~src/access-control/EnhancedAccessControl.sol"; -import {PermissionedRegistry, IRegistry} from "~src/registry/PermissionedRegistry.sol"; -import {SimpleRegistryMetadata} from "~src/registry/SimpleRegistryMetadata.sol"; -import {LibHalving} from "~src/registrar/libraries/LibHalving.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {IEnhancedAccessControl} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; +import {IRentPriceOracle} from "~src/registrar/interfaces/IRentPriceOracle.sol"; import { StandardRentPriceOracle, PaymentRatio, - IRentPriceOracle, - DiscountPoint + DiscountPoint, + DEFAULT_ROLE_BITMAP, + ROLE_UPDATE_TOKEN, + ROLE_UPDATE_TOKEN_ADMIN, + ROLE_DISABLE_TOKEN, + ROLE_DISABLE_TOKEN_ADMIN, + ROLE_CAN_NAME, + ROLE_CAN_NAME_ADMIN } from "~src/registrar/StandardRentPriceOracle.sol"; -import {MockERC20} from "~test/mocks/MockERC20.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; - -contract StandardRentPriceOracleTest is Test, ERC1155Holder { - PermissionedRegistry ethRegistry; - MockHCAFactoryBasic hcaFactory; - - StandardRentPriceOracle rentPriceOracle; +import {StandardRentPriceOracleFixture} from "~test/fixtures/StandardRentPriceOracleFixture.sol"; +import {StandardRegistrar} from "~test/StandardRegistrar.sol"; - MockERC20 tokenUSDC; - MockERC20 tokenIdentity; +/// @dev The expiry parameter of `getRenewPrice()` is currently unused. +uint64 constant UNUSED_EXPIRY = 0; - address user = makeAddr("user"); +contract StandardRentPriceOracleTest is StandardRentPriceOracleFixture { + address actor = makeAddr("actor"); function setUp() external { - hcaFactory = new MockHCAFactoryBasic(); - ethRegistry = new PermissionedRegistry( - hcaFactory, - new SimpleRegistryMetadata(hcaFactory), - address(this), - EACBaseRolesLib.ALL_ROLES + deployStandardRentPriceOracleFixture(); + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface( + address(rentPriceOracle), + type(IRentPriceOracle).interfaceId + ) ); + assertTrue( + ERC165Checker.supportsInterface( + address(rentPriceOracle), + type(IContractNamer).interfaceId + ) + ); + } - tokenUSDC = new MockERC20("USDC", 6, hcaFactory); - tokenIdentity = new MockERC20("ID", StandardPricing.PRICE_DECIMALS, hcaFactory); + function test_DEFAULT_ROLE_BITMAP() external pure { + assertEq( + DEFAULT_ROLE_BITMAP, + ROLE_UPDATE_TOKEN | + ROLE_UPDATE_TOKEN_ADMIN | + ROLE_DISABLE_TOKEN | + ROLE_DISABLE_TOKEN_ADMIN | + ROLE_CAN_NAME | + ROLE_CAN_NAME_ADMIN + ); + } - PaymentRatio[] memory paymentRatios = new PaymentRatio[](2); - paymentRatios[0] = StandardPricing.ratioFromStable(tokenUSDC); - paymentRatios[1] = StandardPricing.ratioFromStable(tokenIdentity); + function test_constructor() external view { + assertTrue(rentPriceOracle.hasRootRoles(DEFAULT_ROLE_BITMAP, address(this)), "roles"); + assertEq( + abi.encode(rentPriceOracle.getBaseRates()), + abi.encode(StandardRegistrar.getBaseRates()) + ); + assertEq( + abi.encode(rentPriceOracle.getDiscountPoints()), + abi.encode(StandardRegistrar.getDiscountPoints()) + ); + assertEq( + rentPriceOracle.DISCOUNT_DENOMINATOR(), + StandardRegistrar.DISCOUNT_DENOMINATOR, + "DISCOUNT_DENOMINATOR" + ); + assertEq( + rentPriceOracle.PREMIUM_PRICE_INITIAL(), + StandardRegistrar.PREMIUM_PRICE_INITIAL, + "PREMIUM_PRICE_INITIAL" + ); + assertEq( + rentPriceOracle.PREMIUM_HALVING_PERIOD(), + StandardRegistrar.PREMIUM_HALVING_PERIOD, + "PREMIUM_HALVING_PERIOD" + ); + assertEq( + rentPriceOracle.PREMIUM_PERIOD(), + StandardRegistrar.PREMIUM_PERIOD, + "PREMIUM_PERIOD" + ); + for (uint256 i; i < paymentTokens.length; ++i) { + assertTrue(rentPriceOracle.isPaymentToken(paymentTokens[i]), paymentTokens[i].name()); + } + } - rentPriceOracle = new StandardRentPriceOracle( + function test_constructor_emitPaymentTokenUpdated() external { + PaymentRatio[] memory v = new PaymentRatio[](1); + v[0] = PaymentRatio(tokenUSDC, 1, 1); + vm.expectEmit(); + emit StandardRentPriceOracle.PaymentTokenUpdated(tokenUSDC, 1, 1); + new StandardRentPriceOracle( address(this), - ethRegistry, - StandardPricing.getBaseRates(), - StandardPricing.getDiscountPoints(), - StandardPricing.PREMIUM_PRICE_INITIAL, - StandardPricing.PREMIUM_HALVING_PERIOD, - StandardPricing.PREMIUM_PERIOD, - paymentRatios + new uint256[](1), + new DiscountPoint[](0), + 0, + 0, + 0, + 0, + v ); - - vm.warp(rentPriceOracle.premiumPeriod()); // avoid timestamp issues } - function test_constructor_invalidRatio() external { - PaymentRatio[] memory paymentRatios = new PaymentRatio[](1); - paymentRatios[0] = PaymentRatio(tokenUSDC, 1, 0); - vm.expectRevert(abi.encodeWithSelector(StandardRentPriceOracle.InvalidRatio.selector)); + function test_constructor_invalidBaseRates() external { + vm.expectRevert(abi.encodeWithSelector(StandardRentPriceOracle.InvalidBaseRates.selector)); new StandardRentPriceOracle( address(this), - ethRegistry, - new uint256[](0), + new uint256[](0), // wrong new DiscountPoint[](0), 0, 0, 0, - paymentRatios + 0, + new PaymentRatio[](0) ); } - function test_supportsInterface() external view { - assertTrue( - ERC165Checker.supportsInterface( - address(rentPriceOracle), - type(IRentPriceOracle).interfaceId - ) + function test_constructor_invalidDiscount_notIncreasingDurations() external { + DiscountPoint[] memory v = new DiscountPoint[](2); + v[0] = DiscountPoint(100, 2); + v[1] = DiscountPoint(100, 1); // wrong: 100 -> 100 => no increase + vm.expectRevert(abi.encodeWithSelector(StandardRentPriceOracle.InvalidDiscount.selector)); + new StandardRentPriceOracle( + address(this), + new uint256[](1), + v, + 3, // denominator + 0, + 0, + 0, + new PaymentRatio[](0) ); } - function test_isPaymentToken() external view { - assertTrue(rentPriceOracle.isPaymentToken(tokenUSDC), "USDC"); - assertTrue(rentPriceOracle.isPaymentToken(tokenIdentity), "ID"); - assertFalse(rentPriceOracle.isPaymentToken(IERC20(address(0)))); + function test_constructor_invalidDiscount_notDecreasingNumerators() external { + DiscountPoint[] memory v = new DiscountPoint[](2); + v[0] = DiscountPoint(100, 1); + v[1] = DiscountPoint(200, 1); // wrong: 1 -> 1 => no decrease + vm.expectRevert(abi.encodeWithSelector(StandardRentPriceOracle.InvalidDiscount.selector)); + new StandardRentPriceOracle( + address(this), + new uint256[](1), + v, + 3, // denominator + 0, + 0, + 0, + new PaymentRatio[](0) + ); } - function test_updatePaymentToken_remove() external { - IERC20 paymentToken = tokenUSDC; - assertTrue(rentPriceOracle.isPaymentToken(paymentToken), "before"); - vm.expectEmit(true, false, false, false); - emit IRentPriceOracle.PaymentTokenRemoved(paymentToken); - rentPriceOracle.updatePaymentToken(paymentToken, 0, 0); - assertFalse(rentPriceOracle.isPaymentToken(paymentToken), "after"); + function test_constructor_invalidDiscount_aboveDenominator() external { + DiscountPoint[] memory v = new DiscountPoint[](1); + v[0] = DiscountPoint(1, 3); // wrong: 3/3 => 0% discount + vm.expectRevert(abi.encodeWithSelector(StandardRentPriceOracle.InvalidDiscount.selector)); + new StandardRentPriceOracle( + address(this), + new uint256[](1), + v, + 3, // denominator + 0, + 0, + 0, + new PaymentRatio[](0) + ); } - function test_updatePaymentToken_add() external { - IERC20 paymentToken = IERC20(address(1)); - assertFalse(rentPriceOracle.isPaymentToken(paymentToken), "before"); - vm.expectEmit(true, false, false, false); - emit IRentPriceOracle.PaymentTokenAdded(paymentToken); - rentPriceOracle.updatePaymentToken(paymentToken, 1, 1); - assertTrue(rentPriceOracle.isPaymentToken(paymentToken), "after"); + function test_constructor_invalidDiscount_free() external { + DiscountPoint[] memory v = new DiscountPoint[](1); + v[0] = DiscountPoint(1, 0); // wrong: 0/3 => 100% discount + vm.expectRevert(abi.encodeWithSelector(StandardRentPriceOracle.InvalidDiscount.selector)); + new StandardRentPriceOracle( + address(this), + new uint256[](1), + v, + 3, // denominator + 0, + 0, + 0, + new PaymentRatio[](0) + ); } - function test_updatePaymentToken_invalidRatio() external { + function test_constructor_invalidRatio() external { + PaymentRatio[] memory v = new PaymentRatio[](1); + v[0] = PaymentRatio(tokenUSDC, 1, 0); // wrong vm.expectRevert(abi.encodeWithSelector(StandardRentPriceOracle.InvalidRatio.selector)); - rentPriceOracle.updatePaymentToken(tokenUSDC, 0, 1); + new StandardRentPriceOracle( + address(this), + new uint256[](1), + new DiscountPoint[](0), + 0, + 0, + 0, + 0, + v + ); } - function test_updatePaymentToken_notOwner() external { - vm.startPrank(user); - vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user)); - rentPriceOracle.updatePaymentToken(tokenUSDC, 0, 0); // remove - vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user)); - rentPriceOracle.updatePaymentToken(tokenUSDC, 1, 1); // add - vm.stopPrank(); - } + //////////////////////////////////////////////////////////////////////// + // Payment Tokens + //////////////////////////////////////////////////////////////////////// - function test_isValid() external view { - assertFalse(rentPriceOracle.isValid("")); - assertEq(rentPriceOracle.isValid("a"), StandardPricing.RATE_1CP > 0); - assertEq(rentPriceOracle.isValid("ab"), StandardPricing.RATE_2CP > 0); - assertEq(rentPriceOracle.isValid("abc"), StandardPricing.RATE_3CP > 0); - assertEq(rentPriceOracle.isValid("abce"), StandardPricing.RATE_4CP > 0); - assertEq(rentPriceOracle.isValid("abcde"), StandardPricing.RATE_5CP > 0); - assertEq( - rentPriceOracle.isValid("abcdefghijklmnopqrstuvwxyz"), - StandardPricing.RATE_5CP > 0 - ); + function test_isPaymentToken_unknown() external view { + assertFalse(rentPriceOracle.isPaymentToken(invalidPaymentToken)); } - function _testRentPrice(uint256 n, uint256 rate) internal { - string memory label = new string(n); - uint256 base = rentPriceOracle.baseRate(label); - assertEq(base, rate, "rate"); - // duration must be before initial discount or price will be reduced - _testRentPrice(label, rate, StandardPricing.SEC_PER_YEAR, tokenUSDC); - _testRentPrice(label, rate, StandardPricing.SEC_PER_YEAR, tokenIdentity); + function test_getPaymentTokenRatio_exists() external view { + (uint128 numer, uint128 denom) = rentPriceOracle.getPaymentTokenRatio(tokenUSDC); + PaymentRatio memory pr = StandardRegistrar.ratioFromStable(tokenUSDC); + assertEq(numer, pr.numer, "numer"); + assertEq(denom, pr.denom, "denom"); } - function _testRentPrice( - string memory label, - uint256 rate, - uint64 dur, - MockERC20 token - ) internal { - if (rate == 0) { - vm.expectRevert(abi.encodeWithSelector(IRentPriceOracle.NotValid.selector, label)); - } - (uint256 base, ) = rentPriceOracle.rentPrice(label, address(0), dur, token); - PaymentRatio memory t = StandardPricing.ratioFromStable(token); - assertEq(base, Math.mulDiv(rate * dur, t.numer, t.denom, Math.Rounding.Ceil), token.name()); + function test_getPaymentTokenRatio_unknown() external view { + (uint128 numer, uint128 denom) = rentPriceOracle.getPaymentTokenRatio(invalidPaymentToken); + assertEq(numer, 0, "numer"); + assertEq(denom, 0, "denom"); } - function test_rentPrice_0() external { - _testRentPrice(0, 0); - } - function test_rentPrice_1() external { - _testRentPrice(1, StandardPricing.RATE_1CP); - } - function test_rentPrice_2() external { - _testRentPrice(2, StandardPricing.RATE_2CP); - } - function test_rentPrice_3() external { - _testRentPrice(3, StandardPricing.RATE_3CP); - } - function test_rentPrice_4() external { - _testRentPrice(4, StandardPricing.RATE_4CP); + function test_updatePaymentToken_add() external { + assertFalse(rentPriceOracle.isPaymentToken(invalidPaymentToken)); + vm.expectEmit(); + emit StandardRentPriceOracle.PaymentTokenUpdated(invalidPaymentToken, 1, 1); + rentPriceOracle.updatePaymentToken(invalidPaymentToken, 1, 1); + (uint128 numer, uint128 denom) = rentPriceOracle.getPaymentTokenRatio(invalidPaymentToken); + assertEq(numer, 1, "numer"); + assertEq(denom, 1, "denom"); + assertTrue(rentPriceOracle.isPaymentToken(invalidPaymentToken)); + } + + function test_updatePaymentToken_edit() external { + rentPriceOracle.updatePaymentToken(invalidPaymentToken, 1, 1); + vm.expectEmit(); + emit StandardRentPriceOracle.PaymentTokenUpdated(invalidPaymentToken, 2, 2); + rentPriceOracle.updatePaymentToken(invalidPaymentToken, 2, 2); + (uint128 numer, uint128 denom) = rentPriceOracle.getPaymentTokenRatio(invalidPaymentToken); + assertEq(numer, 2, "numer"); + assertEq(denom, 2, "denom"); + assertTrue(rentPriceOracle.isPaymentToken(invalidPaymentToken)); } - function test_rentPrice_5() external { - _testRentPrice(5, StandardPricing.RATE_5CP); + + function test_updatePaymentToken_remove() external { + IERC20 paymentToken = randomPaymentToken(); + assertTrue(rentPriceOracle.isPaymentToken(paymentToken)); + vm.expectEmit(); + emit StandardRentPriceOracle.PaymentTokenUpdated(paymentToken, 0, 0); + rentPriceOracle.updatePaymentToken(paymentToken, 0, 0); + assertFalse(rentPriceOracle.isPaymentToken(paymentToken)); } - function test_rentPrice_255() external { - _testRentPrice(255, StandardPricing.RATE_5CP); + + function test_updatePaymentToken_unchanged() external { + rentPriceOracle.updatePaymentToken(invalidPaymentToken, 1, 1); + vm.recordLogs(); + rentPriceOracle.updatePaymentToken(invalidPaymentToken, 1, 1); // noop + assertEq(vm.getRecordedLogs().length, 0); } - function test_rentPrice_256() external { - _testRentPrice(256, 0); + + function test_updatePaymentToken_invalidRatio() external { + vm.expectRevert(abi.encodeWithSelector(StandardRentPriceOracle.InvalidRatio.selector)); + rentPriceOracle.updatePaymentToken(randomPaymentToken(), 0, 1); } - function test_rentPrice_paymentTokenNotSupported() external { - IERC20 paymentToken = IERC20(makeAddr("fake")); + function test_updatePaymentToken_notAuthorized() external { vm.expectRevert( - abi.encodeWithSelector(IRentPriceOracle.PaymentTokenNotSupported.selector, paymentToken) + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + rentPriceOracle.ROOT_RESOURCE(), + ROLE_UPDATE_TOKEN, + actor + ) ); - rentPriceOracle.rentPrice("abcde", user, 0, paymentToken); + vm.prank(actor); + rentPriceOracle.updatePaymentToken(randomPaymentToken(), 0, 0); } - function test_premiumPriceInitial() external view { - assertEq(rentPriceOracle.premiumPriceInitial(), StandardPricing.PREMIUM_PRICE_INITIAL); + function test_disablePaymentToken() external { + IERC20 paymentToken = randomPaymentToken(); + vm.expectEmit(); + emit StandardRentPriceOracle.PaymentTokenUpdated(paymentToken, 0, 0); + rentPriceOracle.disablePaymentToken(paymentToken); } - function test_premiumPriceAfter_start() external view { - assertEq( - rentPriceOracle.premiumPriceAfter(0), - StandardPricing.PREMIUM_PRICE_INITIAL - - LibHalving.halving( - StandardPricing.PREMIUM_PRICE_INITIAL, - StandardPricing.PREMIUM_HALVING_PERIOD, - StandardPricing.PREMIUM_PERIOD - ) - ); - } - - function test_premiumPriceAfter_end() external view { - uint64 dur = rentPriceOracle.premiumPeriod(); - uint64 dt = 1; - assertGt(rentPriceOracle.premiumPriceAfter(dur - dt), 0, "before"); - assertEq(rentPriceOracle.premiumPriceAfter(dur), 0, "at"); - assertEq(rentPriceOracle.premiumPriceAfter(dur + dt), 0, "after"); + function test_disablePaymentToken_unchanged() external { + vm.recordLogs(); + rentPriceOracle.disablePaymentToken(invalidPaymentToken); // noop + assertEq(vm.getRecordedLogs().length, 0); } - function test_premiumPrice() external view { - assertEq(rentPriceOracle.premiumPrice(0), 0, "0"); - assertEq( - rentPriceOracle.premiumPrice(uint64(block.timestamp)), - rentPriceOracle.premiumPriceAfter(0), - "start" - ); - assertEq( - rentPriceOracle.premiumPrice(uint64(block.timestamp + rentPriceOracle.premiumPeriod())), - 0, - "end" + function test_disablePaymentToken_notAuthorized() external { + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + rentPriceOracle.ROOT_RESOURCE(), + ROLE_DISABLE_TOKEN, + actor + ) ); + vm.prank(actor); + rentPriceOracle.disablePaymentToken(randomPaymentToken()); } - function test_updateBaseRates() external { - uint256[] memory rates = new uint256[](2); - rates[0] = 1; - rates[1] = 0; - vm.expectEmit(false, false, false, true); - emit StandardRentPriceOracle.BaseRatesChanged(rates); - rentPriceOracle.updateBaseRates(rates); - assertEq(abi.encode(rentPriceOracle.getBaseRates()), abi.encode(rates)); - } + //////////////////////////////////////////////////////////////////////// + // Discount + //////////////////////////////////////////////////////////////////////// - function test_updateBaseRates_disable() external { - rentPriceOracle.updateBaseRates(new uint256[](0)); - for (uint256 i; i < 256; i++) { - assertEq(rentPriceOracle.baseRate(new string(i)), 0); + function _applyDiscount(uint256[3] memory v0, uint64 t0, uint64 t1, uint256[3] memory v) + internal + view + { + for (uint256 i; i < v0.length; ++i) { + if (t0 > 0) { + assertGt(rentPriceOracle.applyDiscount(v0[i], t0 - 1), v[i], "prev"); + } + assertEq(rentPriceOracle.applyDiscount(v0[i], t0), v[i], "t0"); + assertEq(rentPriceOracle.applyDiscount(v0[i], t1), v[i], "t1"); + if (t1 < type(uint64).max) { + assertLt(rentPriceOracle.applyDiscount(v0[i], t1 + 1), v[i], "next"); + } } } - function test_updateBaseRates_notOwner() external { - vm.startPrank(user); - vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user)); - rentPriceOracle.updateBaseRates(new uint256[](1)); - vm.stopPrank(); + // these tests are fragile and specific to the chosen discount points + function test_applyDiscount_fragile() external view { + uint64 y = StandardRegistrar.SEC_PER_YEAR; + uint256[3] memory v0 = [uint256(800), 16000, 64000]; + _applyDiscount(v0, 0, 2 * y - 1, v0); + _applyDiscount(v0, 2 * y, 3 * y - 1, [uint256(700), 14000, 56000]); + _applyDiscount(v0, 3 * y, 6 * y - 1, [uint256(550), 11000, 44000]); + _applyDiscount(v0, 6 * y, type(uint64).max, [uint256(450), 9000, 36000]); } - function test_getBaseRates() external view { + //////////////////////////////////////////////////////////////////////// + // Premium + //////////////////////////////////////////////////////////////////////// + + function test_getPremiumPriceAfter_start() external view { assertEq( - abi.encode(rentPriceOracle.getBaseRates()), - abi.encode(StandardPricing.getBaseRates()) + rentPriceOracle.getPremiumPriceAfter(0), + rentPriceOracle.PREMIUM_PRICE_INITIAL() - rentPriceOracle.PREMIUM_PRICE_OFFSET() ); } - function test_updatePremiumPricing() external { - vm.expectEmit(false, false, false, false); - emit StandardRentPriceOracle.PremiumPricingChanged(256000, 1, 8); - rentPriceOracle.updatePremiumPricing(256000, 1, 8); - assertEq(rentPriceOracle.premiumPriceAfter(0), 255000, "0"); - assertEq(rentPriceOracle.premiumPriceAfter(1), 127000, "1"); - assertEq(rentPriceOracle.premiumPriceAfter(2), 63000, "2"); - assertEq(rentPriceOracle.premiumPriceAfter(3), 31000, "3"); - assertEq(rentPriceOracle.premiumPriceAfter(4), 15000, "4"); - assertEq(rentPriceOracle.premiumPriceAfter(5), 7000, "5"); - assertEq(rentPriceOracle.premiumPriceAfter(6), 3000, "6"); - assertEq(rentPriceOracle.premiumPriceAfter(7), 1000, "7"); - assertEq(rentPriceOracle.premiumPriceAfter(8), 0, "8"); - } - - function test_updatePremiumPricing_disable() external { - rentPriceOracle.updatePremiumPricing(0, 0, 0); - assertEq(rentPriceOracle.premiumPriceAfter(0), 0, "after"); - assertEq(rentPriceOracle.premiumPriceInitial(), 0, "initial"); - } - - function test_updatePremiumPricing_notOwner() external { - vm.startPrank(user); - vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user)); - rentPriceOracle.updatePremiumPricing(0, 0, 0); - vm.stopPrank(); + function test_getPremiumPriceAfter_end() external view { + uint64 dur = rentPriceOracle.PREMIUM_PERIOD(); + assertEq(rentPriceOracle.getPremiumPriceAfter(dur), 0, "at"); + assertEq(rentPriceOracle.getPremiumPriceAfter(dur + 1), 0, "after"); + } + + function test_getPremiumPriceAfter_calc() external { + StandardRentPriceOracle oracle = + new StandardRentPriceOracle( + address(this), + new uint256[](1), + new DiscountPoint[](0), + 0, + 256000, + 1, + 8, + new PaymentRatio[](0) + ); + assertEq(oracle.getPremiumPriceAfter(0), 255000, "0"); + assertEq(oracle.getPremiumPriceAfter(1), 127000, "1"); + assertEq(oracle.getPremiumPriceAfter(2), 63000, "2"); + assertEq(oracle.getPremiumPriceAfter(3), 31000, "3"); + assertEq(oracle.getPremiumPriceAfter(4), 15000, "4"); + assertEq(oracle.getPremiumPriceAfter(5), 7000, "5"); + assertEq(oracle.getPremiumPriceAfter(6), 3000, "6"); + assertEq(oracle.getPremiumPriceAfter(7), 1000, "7"); + assertEq(oracle.getPremiumPriceAfter(8), 0, "8"); + } + + //////////////////////////////////////////////////////////////////////// + // getRegisterPrice() + //////////////////////////////////////////////////////////////////////// + + function test_getRegisterPrice_calc(uint256) external { + string memory label = new string(vm.randomUint(3, 255)); + uint64 duration = uint64(vm.randomUint(0, 10000 days)); + uint64 available = uint64(vm.randomUint(0, rentPriceOracle.PREMIUM_PERIOD() * 2)); + IERC20 paymentToken = randomPaymentToken(); + (uint256 base, uint256 premium) = + rentPriceOracle.getRegisterPrice(label, available, duration, paymentToken); + uint256 baseUnits = rentPriceOracle.getBasePrice(label, duration); + uint256 premiumUnits = rentPriceOracle.getPremiumPriceAfter(available); + assertEq( + base + premium, + rentPriceOracle.convertUnits(baseUnits + premiumUnits, paymentToken), + "total" + ); + assertEq(premium, rentPriceOracle.convertUnits(premiumUnits, paymentToken), "premium"); } - function _testAverageDiscount(uint64 t, uint256 average) internal view { - uint256 value = (rentPriceOracle.integratedDiscount(t) + t - 1) / t; - uint256 diff = value > average ? value - average : average - value; - assert(diff <= 1); + function test_getRegisterPrice_notValid() external { + uint256[5] memory v = [uint256(0), 1, 2, 256, 1000]; + for (uint256 i; i < v.length; ++i) { + string memory label = new string(v[i]); + vm.expectRevert(abi.encodeWithSelector(IRentPriceOracle.NotValid.selector, label)); + rentPriceOracle.getRegisterPrice(label, 0, 1, tokenUSDC); + } } - // these tests are fragile and specific to the chosen discount points - function test_discountAfter_start() external view { - assertEq(rentPriceOracle.integratedDiscount(0), 0); - } - function test_discountAfter_1year() external view { - _testAverageDiscount(StandardPricing.SEC_PER_YEAR, 0); - } - function test_discountAfter_1year_4mos_partial() external view { - _testAverageDiscount( - (StandardPricing.SEC_PER_YEAR * 4) / 3, - StandardPricing.discountRatio(25, 1000) - ); - } - function test_discountAfter_2years() external view { - _testAverageDiscount( - StandardPricing.SEC_PER_YEAR * 2, - StandardPricing.discountRatio(5, 100) - ); - } - function test_discountAfter_2years_6mos_partial() external view { - _testAverageDiscount( - (StandardPricing.SEC_PER_YEAR * 5) / 2, - StandardPricing.discountRatio(8, 100) - ); - } - function test_discountAfter_3years() external view { - _testAverageDiscount( - StandardPricing.SEC_PER_YEAR * 3, - StandardPricing.discountRatio(10, 100) - ); - } - function test_discountAfter_4years_partial() external view { - _testAverageDiscount( - StandardPricing.SEC_PER_YEAR * 4, - StandardPricing.discountRatio(146875, 1000000) - ); - } - function test_discountAfter_5years() external view { - _testAverageDiscount( - StandardPricing.SEC_PER_YEAR * 5, - StandardPricing.discountRatio(175, 1000) - ); - } - function test_discountAfter_8years_partial() external view { - _testAverageDiscount( - StandardPricing.SEC_PER_YEAR * 8, - StandardPricing.discountRatio(23125, 100000) + function test_getRegisterPrice_paymentTokenNotSupported() external { + vm.expectRevert( + abi.encodeWithSelector( + IRentPriceOracle.PaymentTokenNotSupported.selector, + invalidPaymentToken + ) ); - } - function test_discountAfter_10years() external view { - _testAverageDiscount( - StandardPricing.SEC_PER_YEAR * 10, - StandardPricing.discountRatio(25, 100) + rentPriceOracle.getRegisterPrice( + new string(5), + 0, + StandardRegistrar.MIN_REGISTER_DURATION, + invalidPaymentToken ); } - function test_discountAfter_30years() external view { - _testAverageDiscount( - StandardPricing.SEC_PER_YEAR * 30, - StandardPricing.discountRatio(30, 100) + + //////////////////////////////////////////////////////////////////////// + // getRenewPrice() + //////////////////////////////////////////////////////////////////////// + + function test_getRenewPrice_calc(uint256) external { + string memory label = new string(vm.randomUint(3, 255)); + uint64 duration = uint64(vm.randomUint(1, 10000 days)); + IERC20 paymentToken = randomPaymentToken(); + assertEq( + rentPriceOracle.getRenewPrice(label, UNUSED_EXPIRY, duration, paymentToken), + rentPriceOracle.convertUnits(rentPriceOracle.getBasePrice(label, duration), paymentToken) ); } - function test_discountAfter_end() external view { - _testAverageDiscount(type(uint64).max, StandardPricing.discountRatio(30, 100)); + + function test_getRenewPrice_notValid() external { + uint256[5] memory v = [uint256(0), 1, 2, 256, 1000]; + for (uint256 i; i < v.length; ++i) { + string memory label = new string(v[i]); + vm.expectRevert(abi.encodeWithSelector(IRentPriceOracle.NotValid.selector, label)); + rentPriceOracle.getRenewPrice(label, UNUSED_EXPIRY, 0, randomPaymentToken()); + } } - function _testDiscountedRentPrice(string memory label, uint64 dur0, uint64 dur1) internal { - ethRegistry.register( - label, - address(this), - IRegistry(address(0)), - address(0), - 0, - uint64(block.timestamp) + dur0 + function test_getRenewPrice_paymentTokenNotSupported() external { + vm.expectRevert( + abi.encodeWithSelector( + IRentPriceOracle.PaymentTokenNotSupported.selector, + invalidPaymentToken + ) ); - uint256 base0 = rentPriceOracle.baseRate(label) * dur1; - (uint256 base1, ) = rentPriceOracle.rentPrice(label, address(this), dur1, tokenIdentity); - assertEq( - base1, - base0 - - Math.mulDiv( - base0, - rentPriceOracle.integratedDiscount(dur0 + dur1) - - rentPriceOracle.integratedDiscount(dur0), - uint256(type(uint128).max) * dur1 - ) + rentPriceOracle.getRenewPrice( + new string(5), + UNUSED_EXPIRY, + StandardRegistrar.MIN_REGISTER_DURATION, + invalidPaymentToken ); } - function _testDiscountedPermutations(uint256 n) internal { - bytes memory buf = new bytes(n); - for (uint64 i = 1; i < 3; i++) { - buf[0] = bytes1(uint8(i)); - for (uint64 j = 1; j < 10; j++) { - buf[1] = bytes1(uint8(j)); - _testDiscountedRentPrice( - string(buf), - StandardPricing.SEC_PER_YEAR * i, - StandardPricing.SEC_PER_YEAR * j - ); - } + //////////////////////////////////////////////////////////////////////// + // Utilities + //////////////////////////////////////////////////////////////////////// + + function test_getLength() external view { + for (uint256 i; i < 1000; i++) { + assertEq(rentPriceOracle.getLength(new string(i)), i); } + assertEq(rentPriceOracle.getLength(unicode"⌚"), 1); + assertEq(rentPriceOracle.getLength(unicode"🇺🇸"), 2); + assertEq(rentPriceOracle.getLength(unicode"🍄‍🟫"), 3); + assertEq(rentPriceOracle.getLength(unicode"👨🏻‍🌾"), 4); + assertEq(rentPriceOracle.getLength(unicode"🧑‍🤝‍🧑"), 5); + assertEq(rentPriceOracle.getLength(unicode"👨🏻‍🦯‍➡"), 6); + assertEq(rentPriceOracle.getLength(unicode"🏴󠁧󠁢󠁥󠁮󠁧󠁿"), 7); + assertEq(rentPriceOracle.getLength(unicode"👨🏻‍💻👩🏻‍💻"), 8); + assertEq(rentPriceOracle.getLength(unicode"👨🏻‍❤‍💋‍👨🏻"), 9); } - function test_discountedRentPrice_3() external { - _testDiscountedPermutations(3); - } - function test_discountedRentPrice_4() external { - _testDiscountedPermutations(4); - } - function test_discountedRentPrice_5() external { - _testDiscountedPermutations(5); + function test_isValid() external view { + assertFalse(rentPriceOracle.isValid("")); + assertEq(rentPriceOracle.isValid("a"), StandardRegistrar.RATE_1CP > 0); + assertEq(rentPriceOracle.isValid("ab"), StandardRegistrar.RATE_2CP > 0); + assertEq(rentPriceOracle.isValid("abc"), StandardRegistrar.RATE_3CP > 0); + assertEq(rentPriceOracle.isValid("abce"), StandardRegistrar.RATE_4CP > 0); + assertEq(rentPriceOracle.isValid("abcde"), StandardRegistrar.RATE_5CP > 0); + assertEq(rentPriceOracle.isValid(new string(255)), StandardRegistrar.RATE_5CP > 0); + } + + function test_getBasePrice_1sec() external view { + assertEq(rentPriceOracle.getBasePrice(new string(0), 1), 0); + assertEq(rentPriceOracle.getBasePrice(new string(1), 1), StandardRegistrar.RATE_1CP); + assertEq(rentPriceOracle.getBasePrice(new string(2), 1), StandardRegistrar.RATE_2CP); + assertEq(rentPriceOracle.getBasePrice(new string(3), 1), StandardRegistrar.RATE_3CP); + assertEq(rentPriceOracle.getBasePrice(new string(4), 1), StandardRegistrar.RATE_4CP); + for (uint256 i = 5; i <= 255; ++i) { + assertEq(rentPriceOracle.getBasePrice(new string(i), 1), StandardRegistrar.RATE_5CP); + } + assertEq(rentPriceOracle.getBasePrice(new string(256), 1), 0); } - function test_updateDiscountPoints() external { - DiscountPoint[] memory points = new DiscountPoint[](2); - points[0] = DiscountPoint(100, 4); - points[1] = DiscountPoint(200, 1); - vm.expectEmit(false, false, false, true); - emit StandardRentPriceOracle.DiscountPointsChanged(points); - rentPriceOracle.updateDiscountPoints(points); - assertEq(abi.encode(rentPriceOracle.getDiscountPoints()), abi.encode(points)); - assertEq(rentPriceOracle.integratedDiscount(50), 200); // 50*4 - assertEq(rentPriceOracle.integratedDiscount(500), 1000); // 100*4 + 200*1 + (500-300)*(100*4+200*1)/300 + function test_convertUnits_calc(uint192 x) external view { + IERC20 paymentToken = randomPaymentToken(); + (uint128 numer, uint128 denom) = rentPriceOracle.getPaymentTokenRatio(paymentToken); + assertEq( + rentPriceOracle.convertUnits(x, paymentToken), + Math.mulDiv(x, numer, denom, Math.Rounding.Ceil) + ); } - function test_updateDiscountPoints_disable() external { - rentPriceOracle.updateDiscountPoints(new DiscountPoint[](0)); - assertEq(rentPriceOracle.integratedDiscount(type(uint64).max), 0); + function test_convertUnits_identity(uint256 x) external view { + assertEq(rentPriceOracle.convertUnits(x, tokenIdentity), x); } - function test_updateDiscountPoints_invalidDiscountPoint() external { - DiscountPoint[] memory points = new DiscountPoint[](1); - points[0] = DiscountPoint(0, 1); + function test_convertUnits_paymentTokenNotSupported() external { vm.expectRevert( - abi.encodeWithSelector(StandardRentPriceOracle.InvalidDiscountPoint.selector) + abi.encodeWithSelector( + IRentPriceOracle.PaymentTokenNotSupported.selector, + invalidPaymentToken + ) ); - rentPriceOracle.updateDiscountPoints(points); + rentPriceOracle.convertUnits(0, invalidPaymentToken); } - function test_updateDiscountPoints_notOwner() external { - vm.startPrank(user); - vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, user)); - rentPriceOracle.updateDiscountPoints(new DiscountPoint[](0)); - vm.stopPrank(); - } + function test_isContractNamer() external { + assertTrue(rentPriceOracle.isContractNamer(address(this))); - function test_getDiscountPoints() external view { - assertEq( - abi.encode(rentPriceOracle.getDiscountPoints()), - abi.encode(StandardPricing.getDiscountPoints()) - ); + assertFalse(rentPriceOracle.isContractNamer(actor), "before"); + rentPriceOracle.grantRootRoles(ROLE_CAN_NAME, actor); + assertTrue(rentPriceOracle.isContractNamer(actor), "granted"); + rentPriceOracle.revokeRootRoles(ROLE_CAN_NAME, actor); + assertFalse(rentPriceOracle.isContractNamer(actor), "revoked"); } } diff --git a/contracts/test/unit/registrar/libraries/LibHalving.t.sol b/contracts/test/unit/registrar/libraries/LibHalving.t.sol index cc7c86217..dae14ef63 100644 --- a/contracts/test/unit/registrar/libraries/LibHalving.t.sol +++ b/contracts/test/unit/registrar/libraries/LibHalving.t.sol @@ -28,12 +28,7 @@ contract LibHalvingTest is Test { _assertNear(LibHalving.halving(226801697741, 2055, 7691), 16944188740, 16944070054, 6); _assertNear(LibHalving.halving(8346969424321, 2447, 14567), 134739948345, 134739878463, 7); _assertNear(LibHalving.halving(45287518154421, 3882, 57451), 1588328639, 1588313410, 6); - _assertNear( - LibHalving.halving(570920124541253, 9882, 107044), - 313151078238, - 313149809990, - 6 - ); + _assertNear(LibHalving.halving(570920124541253, 9882, 107044), 313151078238, 313149809990, 6); _assertNear( LibHalving.halving(7645843420289247, 2217, 5130), 1537665107975056, diff --git a/contracts/test/unit/registry/ApprovedUpgradeGate.t.sol b/contracts/test/unit/registry/ApprovedUpgradeGate.t.sol new file mode 100644 index 000000000..0247f8a0b --- /dev/null +++ b/contracts/test/unit/registry/ApprovedUpgradeGate.t.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {Test} from "forge-std/Test.sol"; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +import {ApprovedUpgradeGate} from "~src/registry/ApprovedUpgradeGate.sol"; + +contract ApprovedUpgradeGateTest is Test { + ApprovedUpgradeGate gate; + + address owner = makeAddr("owner"); + address nonOwner = makeAddr("nonOwner"); + address implementation = makeAddr("implementation"); + + function setUp() public { + gate = new ApprovedUpgradeGate(owner); + } + + function test_constructor_setsOwner() external view { + assertEq(gate.owner(), owner, "owner"); + assertFalse(gate.approvedImplementations(implementation), "implementation"); + } + + function test_setImplementationApproval_approvesImplementation() external { + vm.expectEmit(true, true, false, true, address(gate)); + emit ApprovedUpgradeGate.ImplementationApprovalChanged(implementation, true); + + vm.prank(owner); + gate.setImplementationApproval(implementation, true); + + assertTrue(gate.approvedImplementations(implementation), "implementation"); + } + + function test_setImplementationApproval_revokesImplementation() external { + vm.prank(owner); + gate.setImplementationApproval(implementation, true); + + vm.expectEmit(true, true, false, true, address(gate)); + emit ApprovedUpgradeGate.ImplementationApprovalChanged(implementation, false); + + vm.prank(owner); + gate.setImplementationApproval(implementation, false); + + assertFalse(gate.approvedImplementations(implementation), "implementation"); + } + + function test_setImplementationApproval_revertsWhenNotOwner() external { + vm.expectRevert( + abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, nonOwner) + ); + vm.prank(nonOwner); + gate.setImplementationApproval(implementation, true); + + assertFalse(gate.approvedImplementations(implementation), "implementation"); + } +} diff --git a/contracts/test/unit/registry/BaseUriRegistryMetadata.t.sol b/contracts/test/unit/registry/BaseUriRegistryMetadata.t.sol deleted file mode 100644 index 1300021fa..000000000 --- a/contracts/test/unit/registry/BaseUriRegistryMetadata.t.sol +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file - -import {Test} from "forge-std/Test.sol"; - -import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; -import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; - -import {EACBaseRolesLib} from "~src/access-control/EnhancedAccessControl.sol"; -import {IEnhancedAccessControl} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; -import {BaseUriRegistryMetadata} from "~src/registry/BaseUriRegistryMetadata.sol"; -import {IRegistryMetadata} from "~src/registry/interfaces/IRegistryMetadata.sol"; -import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; -import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; - -contract BaseUriRegistryMetadataTest is Test, ERC1155Holder { - MockHCAFactoryBasic hcaFactory; - PermissionedRegistry registry; - PermissionedRegistry parentRegistry; - BaseUriRegistryMetadata metadata; - - uint256 constant ROLE_UPDATE_METADATA = 1 << 0; - - uint256 constant DEFAULT_ROLE_BITMAP = - RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER; - - uint256 constant ROOT_RESOURCE = 0; - - function setUp() public { - hcaFactory = new MockHCAFactoryBasic(); - metadata = new BaseUriRegistryMetadata(hcaFactory); - - // Use the valid ALL_ROLES value for deployer roles - uint256 deployerRoles = EACBaseRolesLib.ALL_ROLES; - registry = new PermissionedRegistry(hcaFactory, metadata, address(this), deployerRoles); - } - - function test_registry_metadata_base_uri() public { - uint256 tokenId = uint256(keccak256(bytes("sub"))); - - registry.register( - "sub", - address(this), - registry, - address(0), - DEFAULT_ROLE_BITMAP, - uint64(block.timestamp + 1000) - ); - - assertEq(registry.uri(tokenId), ""); - - string memory expectedUri = "ipfs://base/{id}"; - metadata.setTokenBaseUri(expectedUri); - assertEq(metadata.tokenUri(tokenId), expectedUri); - assertEq(registry.uri(tokenId), expectedUri); - } - - function test_registry_metadata_base_uri_multiple_tokens() public { - string memory expectedUri = "ipfs://base/{id}"; - uint256 tokenId1 = uint256(keccak256(bytes("sub1"))); - uint256 tokenId2 = uint256(keccak256(bytes("sub2"))); - - registry.register( - "sub1", - address(this), - registry, - address(0), - DEFAULT_ROLE_BITMAP, - uint64(block.timestamp + 1000) - ); - registry.register( - "sub2", - address(this), - registry, - address(0), - DEFAULT_ROLE_BITMAP, - uint64(block.timestamp + 1000) - ); - - metadata.setTokenBaseUri(expectedUri); - - assertEq(metadata.tokenUri(tokenId1), expectedUri); - assertEq(metadata.tokenUri(tokenId2), expectedUri); - assertEq(registry.uri(tokenId1), expectedUri); - assertEq(registry.uri(tokenId2), expectedUri); - } - - function test_registry_metadata_base_uri_update() public { - string memory initialUri = "ipfs://initial/{id}"; - string memory updatedUri = "ipfs://updated/{id}"; - uint256 tokenId = uint256(keccak256(bytes("sub"))); - - registry.register( - "sub", - address(this), - registry, - address(0), - DEFAULT_ROLE_BITMAP, - uint64(block.timestamp + 1000) - ); - - metadata.setTokenBaseUri(initialUri); - assertEq(metadata.tokenUri(tokenId), initialUri); - - metadata.setTokenBaseUri(updatedUri); - assertEq(metadata.tokenUri(tokenId), updatedUri); - } - - function test_registry_metadata_unauthorized() public { - string memory expectedUri = "ipfs://test/"; - - vm.expectRevert( - abi.encodeWithSelector( - IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, - ROOT_RESOURCE, - ROLE_UPDATE_METADATA, - address(1) - ) - ); - vm.prank(address(1)); - metadata.setTokenBaseUri(expectedUri); - } - - function test_registry_metadata_supports_interface() public view { - assertEq(metadata.supportsInterface(type(IRegistryMetadata).interfaceId), true); - assertEq(metadata.supportsInterface(type(IEnhancedAccessControl).interfaceId), true); - assertEq(metadata.supportsInterface(type(IERC165).interfaceId), true); - } -} diff --git a/contracts/test/unit/registry/MetadataMixin.t.sol b/contracts/test/unit/registry/MetadataMixin.t.sol deleted file mode 100644 index fdcc186bf..000000000 --- a/contracts/test/unit/registry/MetadataMixin.t.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; - -// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file - -import {Test} from "forge-std/Test.sol"; - -import {IRegistryMetadata} from "~src/registry/interfaces/IRegistryMetadata.sol"; -import {MetadataMixin} from "~src/registry/MetadataMixin.sol"; - -// Mock implementation of IRegistryMetadata for testing -contract MockMetadataProvider is IRegistryMetadata { - mapping(uint256 tokenId => string uri) private _tokenUris; - - function setTokenUri(uint256 tokenId, string memory uri) external { - _tokenUris[tokenId] = uri; - } - - function tokenUri(uint256 tokenId) external view override returns (string memory) { - return _tokenUris[tokenId]; - } -} - -// Concrete implementation of MetadataMixin for testing -contract MetadataMixinImpl is MetadataMixin { - constructor(IRegistryMetadata _metadataProvider) MetadataMixin(_metadataProvider) {} - - // Expose internal function as public for testing - function getTokenURI(uint256 tokenId) public view returns (string memory) { - return _tokenURI(tokenId); - } -} - -contract MetadataMixinTest is Test { - MetadataMixinImpl public mixinImpl; - MockMetadataProvider public mockProvider; - MockMetadataProvider public newMockProvider; - - function setUp() public { - mockProvider = new MockMetadataProvider(); - mixinImpl = new MetadataMixinImpl(mockProvider); - newMockProvider = new MockMetadataProvider(); - } - - function testInitialMetadataProvider() public view { - assertEq(address(mixinImpl.METADATA_PROVIDER()), address(mockProvider)); - } - - function testTokenURI() public { - // Set token URI in the mock provider - string memory expectedUri = "ipfs://test-uri"; - uint256 tokenId = 123; - mockProvider.setTokenUri(tokenId, expectedUri); - - // Verify token URI is correctly returned - string memory uri = mixinImpl.getTokenURI(tokenId); - assertEq(uri, expectedUri); - } - - function testTokenURIWithZeroAddress() public { - // Create new implementation with zero address - MetadataMixinImpl implWithZeroAddr = new MetadataMixinImpl(IRegistryMetadata(address(0))); - - // Should return empty string when metadata provider is zero address - string memory uri = implWithZeroAddr.getTokenURI(123); - assertEq(uri, ""); - } -} diff --git a/contracts/test/unit/registry/PermissionedRegistry.t.sol b/contracts/test/unit/registry/PermissionedRegistry.t.sol index a6a2938d6..39baf846c 100644 --- a/contracts/test/unit/registry/PermissionedRegistry.t.sol +++ b/contracts/test/unit/registry/PermissionedRegistry.t.sol @@ -3,32 +3,34 @@ pragma solidity >=0.8.13; // solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file -import {Vm, Test} from "forge-std/Test.sol"; +import {Test, Vm} from "forge-std/Test.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import {IERC1155Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; -import { - PermissionedRegistry, - IPermissionedRegistry, - IEnhancedAccessControl, - IRegistry, - IStandardRegistry, - IRegistryMetadata, - IHCAFactoryBasic, - EACBaseRolesLib, - RegistryRolesLib, - NameCoder, - LibLabel -} from "~src/registry/PermissionedRegistry.sol"; -import {SimpleRegistryMetadata} from "~src/registry/SimpleRegistryMetadata.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; - -contract PermissionedRegistryTest is Test, ERC1155Holder { +import {LibLabel} from "~src/utils/LibLabel.sol"; +import {IEnhancedAccessControl} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; +import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {IRegistryEvents} from "~src/registry/interfaces/IRegistryEvents.sol"; +import {IOwnedRegistry} from "~src/registry/interfaces/IOwnedRegistry.sol"; +import {IStandardRegistry} from "~src/registry/interfaces/IStandardRegistry.sol"; +import {ITemporalRegistry} from "~src/registry/interfaces/ITemporalRegistry.sol"; +import {ITokenizedRegistry} from "~src/registry/interfaces/ITokenizedRegistry.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {IRegistryURIRenderer} from "~src/registry/interfaces/IRegistryURIRenderer.sol"; +import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; +import {LabelStore, ILabelStore} from "~src/utils/LabelStore.sol"; + +uint256 constant DEFAULT_ROLE_BITMAP = EACBaseRolesLib.ALL_ROLES; + +contract PermissionedRegistryTest is Test, ERC1155Holder, IRegistryURIRenderer { MockPermissionedRegistry registry; - MockHCAFactoryBasic hcaFactory; - IRegistryMetadata metadata; + LabelStore labelStore; address user1 = makeAddr("user1"); address user2 = makeAddr("user2"); @@ -41,19 +43,24 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { uint64 testExpiry = uint64(block.timestamp + 1000); IRegistry testRegistry = IRegistry(makeAddr("registry")); - function setUp() public { - hcaFactory = new MockHCAFactoryBasic(); - metadata = new SimpleRegistryMetadata(hcaFactory); - registry = new MockPermissionedRegistry( - hcaFactory, - metadata, - address(this), - EACBaseRolesLib.ALL_ROLES - ); + function setUp() external { + labelStore = new LabelStore(IContractNamer(address(0))); + + vm.expectEmit(); + emit IRegistryEvents.RegistryCreated(); + registry = new MockPermissionedRegistry(labelStore, address(this), DEFAULT_ROLE_BITMAP); + } + + function test_initForProxyImplementation() external { + vm.expectEmit(); + emit IRegistryEvents.RegistryCreated(); + new PermissionedRegistry(labelStore, address(0), 0); } function test_constructor() external view { - assertTrue(registry.hasRootRoles(EACBaseRolesLib.ALL_ROLES, address(this))); + assertEq(address(registry.LABEL_STORE()), address(labelStore), "LABEL_STORE"); + + assertTrue(registry.hasRootRoles(DEFAULT_ROLE_BITMAP, address(this))); } function test_supportsInterface() external view { @@ -62,10 +69,20 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { registry.supportsInterface(type(IStandardRegistry).interfaceId), "IStandardRegistry" ); + assertTrue(registry.supportsInterface(type(IOwnedRegistry).interfaceId), "IOwnedRegistry"); + assertTrue( + registry.supportsInterface(type(ITokenizedRegistry).interfaceId), + "ITokenizedRegistry" + ); + assertTrue( + registry.supportsInterface(type(ITemporalRegistry).interfaceId), + "ITemporalRegistry" + ); assertTrue( registry.supportsInterface(type(IPermissionedRegistry).interfaceId), "IPermissionedRegistry" ); + assertTrue(registry.supportsInterface(type(IContractNamer).interfaceId), "IContractNamer"); } //////////////////////////////////////////////////////////////////////// @@ -74,10 +91,12 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { function test_register() external { uint256 labelId = LibLabel.id(testLabel); - uint256 expectedTokenId = LibLabel.withVersion(labelId, 0); + uint256 tokenId = LibLabel.withVersion(labelId, 0); + vm.expectEmit(); + emit ILabelStore.Label(bytes32(labelId), testLabel); vm.expectEmit(); - emit IRegistry.NameRegistered( - expectedTokenId, + emit IRegistryEvents.LabelRegistered( + tokenId, bytes32(labelId), testLabel, testOwner, @@ -85,31 +104,33 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { address(this) ); vm.expectEmit(); - emit IERC1155.TransferSingle(address(this), address(0), testOwner, expectedTokenId, 1); + emit IERC1155.TransferSingle(address(this), address(0), testOwner, tokenId, 1); vm.expectEmit(); - emit IPermissionedRegistry.TokenResource(expectedTokenId, expectedTokenId); + emit IPermissionedRegistry.TokenResource(tokenId, tokenId); vm.expectEmit(); - emit IRegistry.SubregistryUpdated(expectedTokenId, testRegistry, address(this)); + emit IRegistryEvents.SubregistryUpdated(tokenId, testRegistry, address(this)); vm.expectEmit(); - emit IRegistry.ResolverUpdated(expectedTokenId, testResolver, address(this)); - uint256 tokenId = this._register(); + emit IRegistryEvents.ResolverUpdated(tokenId, testResolver, address(this)); + assertEq(this._register(), tokenId, "token"); assertEq(registry.getExpiry(tokenId), testExpiry, "expiry"); assertEq(registry.ownerOf(tokenId), testOwner, "owner"); assertEq(registry.getResolver(testLabel), testResolver, "resolver"); assertEq(address(registry.getSubregistry(testLabel)), address(testRegistry), "registry"); assertTrue(registry.hasRoles(tokenId, testRoles, testOwner), "roles"); + assertEq(labelStore.getLabel(tokenId), testLabel, "label"); } function test_register_expired() external { - this._register(); + uint256 tokenId = this._register(); vm.warp(testExpiry); testExpiry += testExpiry; this._register(); + assertEq(registry.latestOwnerOf(tokenId), address(0)); } // is this needed? - function test_register_roles(uint16 compactRoles) external { - testRoles = _expandRoles(compactRoles); + function test_register_roles(uint256) external { + testRoles = _randomRoleBitmap(true, true); assertTrue(registry.hasRoles(this._register(), testRoles, testOwner)); } @@ -117,14 +138,14 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { testResolver = address(0); vm.recordLogs(); this._register(); - _expectNoEmit(vm.getRecordedLogs(), IRegistry.ResolverUpdated.selector); + _expectNoEmit(vm.getRecordedLogs(), IRegistryEvents.ResolverUpdated.selector); } function test_register_withNullRegistry() external { testRegistry = IRegistry(address(0)); vm.recordLogs(); this._register(); - _expectNoEmit(vm.getRecordedLogs(), IRegistry.SubregistryUpdated.selector); + _expectNoEmit(vm.getRecordedLogs(), IRegistryEvents.SubregistryUpdated.selector); } function test_register_notAuthorized() external { @@ -144,10 +165,11 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { this._register(); } - function test_register_cannotSetPastExpiration() external { - testExpiry = 0; + function test_register_cannotSetPastExpiry() external { + vm.warp(2); + testExpiry = uint64(block.timestamp) - 1; vm.expectRevert( - abi.encodeWithSelector(IStandardRegistry.CannotSetPastExpiration.selector, testExpiry) + abi.encodeWithSelector(IStandardRegistry.CannotSetPastExpiry.selector, testExpiry) ); this._register(); } @@ -167,7 +189,7 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { function test_register_alreadyRegistered() external { this._register(); vm.expectRevert( - abi.encodeWithSelector(IStandardRegistry.NameAlreadyRegistered.selector, testLabel) + abi.encodeWithSelector(IStandardRegistry.LabelAlreadyRegistered.selector, testLabel) ); this._register(); } @@ -177,10 +199,13 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { //////////////////////////////////////////////////////////////////////// function test_reserve() external { + uint256 labelId = LibLabel.id(testLabel); + vm.expectEmit(); + emit ILabelStore.Label(bytes32(labelId), testLabel); vm.expectEmit(); - emit IRegistry.NameReserved( - LibLabel.withVersion(LibLabel.id(testLabel), 0), - bytes32(LibLabel.id(testLabel)), + emit IRegistryEvents.LabelReserved( + LibLabel.withVersion(labelId, 0), + bytes32(labelId), testLabel, testExpiry, address(this) @@ -192,14 +217,30 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { assertEq(state.expiry, testExpiry, "expiry"); assertEq(registry.getResolver(testLabel), testResolver, "resolver"); assertEq(address(registry.getSubregistry(testLabel)), address(0), "registry"); + assertEq(labelStore.getLabel(tokenId), testLabel, "label"); + } + + function test_reserve_canSetPastExpiry() external { + vm.warp(2); + testExpiry = 1; + this._reserve(); + } + + function test_reserve_cannotSetPastExpiryAtGenesis() external { + testExpiry = 0; // genesis + vm.expectRevert( + abi.encodeWithSelector(IStandardRegistry.CannotSetPastExpiry.selector, testExpiry) + ); + this._reserve(); } function test_reserve_alreadyReserved() external { this._reserve(); registry.grantRootRoles(RegistryRolesLib.ROLE_REGISTRAR, actor); vm.expectRevert( - abi.encodeWithSelector(IPermissionedRegistry.NameAlreadyReserved.selector, testLabel) + abi.encodeWithSelector(IPermissionedRegistry.LabelAlreadyReserved.selector, testLabel) ); + vm.prank(actor); this._reserve(); } @@ -210,7 +251,7 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { actor ); vm.expectRevert( - abi.encodeWithSelector(IStandardRegistry.NameAlreadyRegistered.selector, testLabel) + abi.encodeWithSelector(IStandardRegistry.LabelAlreadyRegistered.selector, testLabel) ); vm.prank(actor); this._reserve(); @@ -278,7 +319,7 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { uint256 tokenId = this._register(); ++testExpiry; vm.expectEmit(); - emit IRegistry.ExpiryUpdated(tokenId, testExpiry, address(this)); + emit IRegistryEvents.ExpiryUpdated(tokenId, testExpiry, address(this)); registry.renew(tokenId, testExpiry); assertEq(registry.getExpiry(tokenId), testExpiry); } @@ -292,15 +333,34 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { function test_renew_available() external { uint256 tokenId = registry.getTokenId(LibLabel.id(testLabel)); - vm.expectRevert(abi.encodeWithSelector(IStandardRegistry.NameExpired.selector, tokenId)); + vm.expectRevert(abi.encodeWithSelector(IStandardRegistry.LabelExpired.selector, tokenId)); + registry.renew(tokenId, testExpiry); + } + + function test_renew_expiredReservation_asRoot() external { + uint256 tokenId = this._reserve(); + vm.warp(testExpiry); + testExpiry += testExpiry; + registry.renew(tokenId, testExpiry); + assertEq(registry.getExpiry(tokenId), testExpiry); } - function test_renew_expired() external { + function test_renew_expiredRegistration_asRoot() external { uint256 tokenId = this._register(); vm.warp(testExpiry); testExpiry += testExpiry; - vm.expectRevert(abi.encodeWithSelector(IStandardRegistry.NameExpired.selector, tokenId)); + registry.renew(tokenId, testExpiry); + assertEq(registry.getExpiry(tokenId), testExpiry); + } + + function test_renew_expiredRegistration_asOwner() external { + testRoles = RegistryRolesLib.ROLE_RENEW; + uint256 tokenId = this._register(); + vm.warp(testExpiry); + testExpiry += testExpiry; + vm.expectRevert(abi.encodeWithSelector(IStandardRegistry.LabelExpired.selector, tokenId)); + vm.prank(testOwner); registry.renew(tokenId, testExpiry); } @@ -322,12 +382,12 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { registry.renew(tokenId, testExpiry); } - function test_renew_cannotReduceExpiration() external { + function test_renew_cannotReduceExpiry() external { uint256 tokenId = this._register(); testExpiry -= 1; vm.expectRevert( abi.encodeWithSelector( - IStandardRegistry.CannotReduceExpiration.selector, + IStandardRegistry.CannotReduceExpiry.selector, testExpiry + 1, testExpiry ) @@ -366,14 +426,14 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { function test_unregister_available() external { uint256 tokenId = registry.getTokenId(LibLabel.id(testLabel)); - vm.expectRevert(abi.encodeWithSelector(IStandardRegistry.NameExpired.selector, tokenId)); + vm.expectRevert(abi.encodeWithSelector(IStandardRegistry.LabelExpired.selector, tokenId)); registry.unregister(tokenId); } function test_unregister_registered() external { uint256 tokenId = this._register(); vm.expectEmit(); - emit IRegistry.NameUnregistered(tokenId, address(this)); + emit IRegistryEvents.LabelUnregistered(tokenId, address(this)); vm.expectEmit(); emit IERC1155.TransferSingle(address(this), testOwner, address(0), tokenId, 1); registry.unregister(tokenId); @@ -392,7 +452,7 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { uint256 tokenId = this._reserve(); vm.recordLogs(); vm.expectEmit(); - emit IRegistry.NameUnregistered(tokenId, address(this)); + emit IRegistryEvents.LabelUnregistered(tokenId, address(this)); registry.unregister(tokenId); _expectNoEmit(vm.getRecordedLogs(), IERC1155.TransferSingle.selector); } @@ -454,7 +514,7 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { function test_setParent() external { vm.expectEmit(); - emit IRegistry.ParentUpdated(testRegistry, testLabel, address(this)); + emit IRegistryEvents.ParentUpdated(testRegistry, testLabel, address(this)); registry.setParent(testRegistry, testLabel); (IRegistry parent, string memory label) = registry.getParent(); assertEq(address(parent), address(testRegistry), "parent"); @@ -482,7 +542,7 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { testRoles = RegistryRolesLib.ROLE_SET_SUBREGISTRY; uint256 tokenId = this._register(); vm.expectEmit(); - emit IRegistry.SubregistryUpdated(tokenId, testRegistry, testOwner); + emit IRegistryEvents.SubregistryUpdated(tokenId, testRegistry, testOwner); vm.prank(testOwner); registry.setSubregistry(tokenId, testRegistry); vm.assertEq(address(registry.getSubregistry(testLabel)), address(testRegistry)); @@ -529,10 +589,12 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { function test_setResolver() external { testRoles = RegistryRolesLib.ROLE_SET_RESOLVER; uint256 tokenId = this._register(); - vm.expectEmit(); - emit IRegistry.ResolverUpdated(tokenId, testResolver, testOwner); + vm.recordLogs(); vm.prank(testOwner); registry.setResolver(tokenId, testResolver); + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertEq(logs.length, 1, "logs"); + _assertResolverUpdated(logs[0], tokenId, testResolver, testOwner); vm.assertEq(registry.getResolver(testLabel), testResolver, "before"); vm.warp(testExpiry); vm.assertEq(registry.getResolver(testLabel), address(0), "after"); @@ -579,6 +641,8 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { uint256 tokenId = this._register(); assertEq(registry.ownerOf(tokenId), testOwner, "exact"); assertEq(registry.ownerOf(tokenId + 1), address(0), "+1"); + vm.warp(testExpiry); + assertEq(registry.ownerOf(tokenId), address(0), "expired"); } // cleared after burn @@ -593,10 +657,107 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { assertEq(registry.latestOwnerOf(tokenId), testOwner, "expired"); } + function test_balanceOf() external { + assertEq(registry.balanceOf(address(0), 0), 0, "zero"); + assertEq( + registry.balanceOf(testOwner, LibLabel.withVersion(LibLabel.id(testLabel), 0)), + 0, + "available" + ); + uint256 tokenId = this._register(); + assertEq(registry.balanceOf(testOwner, tokenId), 1, "registered"); + assertEq(registry.balanceOf(testOwner, LibLabel.withVersion(tokenId, 1)), 0, "next"); + registry.unregister(tokenId); + assertEq(registry.balanceOf(testOwner, tokenId), 0, "unregistered"); + } + + function test_balanceOfBatch() external { + address[] memory acs = new address[](3); + uint256[] memory ids = new uint256[](3); + ids[0] = ids[1] = this._register(); + ids[2] = ids[0] + 1; + acs[0] = acs[2] = testOwner; + uint256[] memory bals = registry.balanceOfBatch(acs, ids); + assertEq(bals[0], 1); + assertEq(bals[1], 0, "wrong owner"); + assertEq(bals[2], 0, "wrong token"); + } + + function test_balanceOfBatch_arrayLength() external { + vm.expectRevert( + abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidArrayLength.selector, 1, 0) + ); + registry.balanceOfBatch(new address[](0), new uint256[](1)); + } + function test_safeTransferFrom() external { testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; uint256 tokenId = this._register(); + StrictERC1155Holder r = new StrictERC1155Holder(false); + vm.expectEmit(); + emit IERC1155.TransferSingle(user1, user1, address(r), tokenId, 1); + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenId, user1, testRoles, 0); // revoke (transfer 1/2) + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenId, address(r), 0, testRoles); // grant (transfer 2/2) + vm.prank(user1); + registry.safeTransferFrom(user1, address(r), tokenId, 1, ""); + } + + function test_safeTransferFrom_noop() external { + testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; + uint256 tokenId = this._register(); + vm.expectEmit(); + emit IERC1155.TransferSingle(user1, user1, user2, tokenId, 0); + vm.recordLogs(); + vm.prank(user1); + registry.safeTransferFrom(user1, user2, tokenId, 0, ""); + _expectNoEmit(vm.getRecordedLogs(), IEnhancedAccessControl.EACRolesChanged.selector); + } + + function test_safeTransferFrom_multiple(uint256 amount) external { + vm.assume(amount >= 2); + testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; + uint256 tokenId = this._register(); + vm.expectRevert( + abi.encodeWithSelector( + IERC1155Errors.ERC1155InsufficientBalance.selector, + user1, + 1, + amount, + tokenId + ) + ); + vm.prank(user1); + registry.safeTransferFrom(user1, user2, tokenId, amount, ""); + } + + function test_safeTransferFrom_invalidReceiver() external { + uint256 tokenId = this._register(); + address to; // wrong + vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, to)); + vm.prank(user1); + registry.safeTransferFrom(user1, to, tokenId, 1, ""); + } + + function test_safeTransferFrom_invalidSender() external { + uint256 tokenId = this._register(); + address from; // wrong + vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidSender.selector, from)); vm.prank(user1); + registry.__safeTransferFrom(from, user2, tokenId, 1, ""); + } + + function test_safeTransferFrom_missingApproval() external { + uint256 tokenId = this._register(); + vm.expectRevert( + abi.encodeWithSelector( + IERC1155Errors.ERC1155MissingApprovalForAll.selector, + user2, + user1 + ) + ); + vm.prank(user2); registry.safeTransferFrom(user1, user2, tokenId, 1, ""); } @@ -620,39 +781,121 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { registry.safeTransferFrom(user1, user2, tokenId, 1, ""); } + function test_safeTransferFrom_rootAuthorizationIgnored() external { + // even though root has ROLE_CAN_TRANSFER_ADMIN and has approval for transfer, + // the transfer role check is only applied to the token owner + assertTrue(registry.hasRootRoles(RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, address(this))); + uint256 tokenId = this._register(); + assertEq(registry.ownerOf(tokenId), user1); + vm.prank(user1); + registry.setApprovalForAll(address(this), true); + vm.expectRevert( + abi.encodeWithSelector(IStandardRegistry.TransferDisallowed.selector, tokenId, user1) + ); + registry.safeTransferFrom(user1, user2, tokenId, 1, ""); + } + + function test_safeTransferFrom_rootOwnedTokenWithoutRoles() external { + // as long as the token owner has ROLE_CAN_TRANSFER_ADMIN on root or token, the transfer can occur + assertTrue(registry.hasRootRoles(RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN, address(this))); + testOwner = address(this); // mint to account with root + uint256 tokenId = this._register(); + assertEq(registry.roles(tokenId, address(this)), 0); // no roles + registry.safeTransferFrom(address(this), user2, tokenId, 1, ""); + } + function test_safeBatchTransferFrom() external { testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; uint256[] memory tokenIds = new uint256[](2); tokenIds[0] = this._register(); - testLabel = "abc"; + testLabel = string.concat(testLabel, testLabel); tokenIds[1] = this._register(); uint256[] memory amounts = new uint256[](2); amounts[0] = 1; amounts[1] = 1; + StrictERC1155Holder r = new StrictERC1155Holder(true); + vm.expectEmit(); + emit IERC1155.TransferBatch(user1, user1, address(r), tokenIds, amounts); + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenIds[0], user1, testRoles, 0); + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenIds[0], address(r), 0, testRoles); + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenIds[1], user1, testRoles, 0); + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenIds[1], address(r), 0, testRoles); + vm.prank(user1); + registry.safeBatchTransferFrom(user1, address(r), tokenIds, amounts, ""); + } + + function test_safeBatchTransferFrom_noop() external { + testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; + uint256[] memory tokenIds = new uint256[](2); + tokenIds[0] = this._register(); + testLabel = string.concat(testLabel, testLabel); + tokenIds[1] = this._register(); + uint256[] memory amounts = new uint256[](2); vm.prank(user1); registry.safeBatchTransferFrom(user1, user2, tokenIds, amounts, ""); } + function test_safeBatchTransferFrom_noopAfterTransfer() external { + testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; + uint256[] memory tokenIds = new uint256[](2); + tokenIds[0] = tokenIds[1] = this._register(); + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1; + vm.expectRevert( + abi.encodeWithSelector(IStandardRegistry.TransferDisallowed.selector, tokenIds[1], user1) + ); + vm.prank(user1); + registry.safeBatchTransferFrom(user1, user2, tokenIds, amounts, ""); + } + + function test_safeBatchTransferFrom_twiceToSelf() external { + testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; + uint256[] memory tokenIds = new uint256[](2); + tokenIds[0] = tokenIds[1] = this._register(); + uint256[] memory amounts = new uint256[](2); + amounts[0] = amounts[1] = 1; + vm.prank(user1); + registry.safeBatchTransferFrom(user1, user1, tokenIds, amounts, ""); + } + function test_safeBatchTransferFrom_oneError() external { uint256[] memory tokenIds = new uint256[](2); tokenIds[0] = this._register(); // no transfer role - testLabel = "abc"; + testLabel = string.concat(testLabel, testLabel); testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; tokenIds[1] = this._register(); uint256[] memory amounts = new uint256[](2); amounts[0] = 1; amounts[1] = 1; vm.expectRevert( - abi.encodeWithSelector( - IStandardRegistry.TransferDisallowed.selector, - tokenIds[0], - user1 - ) + abi.encodeWithSelector(IStandardRegistry.TransferDisallowed.selector, tokenIds[0], user1) ); vm.prank(user1); registry.safeBatchTransferFrom(user1, user2, tokenIds, amounts, ""); } + function test_safeBatchTransferFrom_invalidReceiver() external { + uint256 tokenId = this._register(); + uint256[] memory v; + address to; // wrong + vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidReceiver.selector, to)); + vm.prank(user1); + registry.safeBatchTransferFrom(user1, to, v, v, ""); + } + + function test_safeBatchTransferFrom_invalidSender() external { + uint256 tokenId = this._register(); + uint256[] memory v; + address from; // wrong + vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidSender.selector, from)); + vm.prank(user1); + registry.__safeBatchTransferFrom(from, user2, v, v, ""); + } + //////////////////////////////////////////////////////////////////////// // getState() //////////////////////////////////////////////////////////////////////// @@ -754,12 +997,17 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { assertEq(registry.getExpiry(LibLabel.withVersion(tokenId, version)), testExpiry); } + function test_getOwner_anyId(uint32 version) external { + uint256 tokenId = this._register(); + assertEq(registry.getOwner(LibLabel.withVersion(tokenId, version)), testOwner); + } + function test_getStatus_anyId(uint32 version) external { uint256 tokenId = this._register(); - assertEq( - uint8(registry.getStatus(LibLabel.withVersion(tokenId, version))), - uint8(IPermissionedRegistry.Status.REGISTERED) - ); + uint256 anyId = LibLabel.withVersion(tokenId, version); + assertEq(uint8(registry.getStatus(anyId)), uint8(IPermissionedRegistry.Status.REGISTERED)); + vm.warp(testExpiry); + assertEq(uint8(registry.getStatus(anyId)), uint8(IPermissionedRegistry.Status.AVAILABLE)); } function test_getState_anyId(uint32 version) external { @@ -805,41 +1053,94 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { function test_roles_anyId(uint32 version) external { testRoles = EACBaseRolesLib.ALL_ROLES; uint256 tokenId = this._register(); - assertEq(registry.roles(LibLabel.withVersion(tokenId, version), testOwner), testRoles); + uint256 anyId = LibLabel.withVersion(tokenId, version); + assertEq(registry.roles(anyId, testOwner), testRoles); + vm.warp(testExpiry); + assertEq(registry.roles(anyId, testOwner), 0); } function test_roleCount_anyId(uint32 version) external { testRoles = EACBaseRolesLib.ALL_ROLES; uint256 tokenId = this._register(); - assertEq(registry.roleCount(LibLabel.withVersion(tokenId, version)), testRoles); + uint256 anyId = LibLabel.withVersion(tokenId, version); + assertEq(registry.roleCount(anyId), testRoles); + vm.warp(testExpiry); + assertEq(registry.roleCount(anyId), 0); } function test_hasRoles_anyId(uint32 version) external { testRoles = EACBaseRolesLib.ALL_ROLES; uint256 tokenId = this._register(); - assertTrue(registry.hasRoles(LibLabel.withVersion(tokenId, version), testRoles, testOwner)); + uint256 anyId = LibLabel.withVersion(tokenId, version); + assertTrue(registry.hasRoles(anyId, testRoles, testOwner)); + vm.warp(testExpiry); + assertFalse(registry.hasRoles(anyId, testRoles, testOwner)); } function test_hasAssignees_anyId(uint32 version) external { testRoles = EACBaseRolesLib.ALL_ROLES; uint256 tokenId = this._register(); - assertTrue(registry.hasAssignees(LibLabel.withVersion(tokenId, version), testRoles)); + uint256 anyId = LibLabel.withVersion(tokenId, version); + assertTrue(registry.hasAssignees(anyId, testRoles)); + vm.warp(testExpiry); + assertFalse(registry.hasAssignees(anyId, testRoles)); } function test_getAssigneeCount_anyId(uint32 version) external { testRoles = EACBaseRolesLib.ALL_ROLES; uint256 tokenId = this._register(); - (uint256 counts, ) = registry.getAssigneeCount( - LibLabel.withVersion(tokenId, version), - testRoles - ); + uint256 anyId = LibLabel.withVersion(tokenId, version); + (uint256 counts, ) = registry.getAssigneeCount(anyId, testRoles); assertEq(counts, testRoles); + vm.warp(testExpiry); + (counts, ) = registry.getAssigneeCount(anyId, testRoles); + assertEq(counts, 0); + } + + //////////////////////////////////////////////////////////////////////// + // Low-level Interfaces + //////////////////////////////////////////////////////////////////////// + + function test_findExpiry() external { + assertEq(registry.findExpiry(testLabel), 0); + uint256 tokenId = this._register(); + assertEq(registry.findExpiry(testLabel), testExpiry); + registry.unregister(tokenId); + assertEq(registry.findExpiry(testLabel), block.timestamp, "burn"); + this._register(); + assertEq(registry.findExpiry(testLabel), testExpiry, "again"); + } + + function test_findTokenId() external { + assertEq(registry.findTokenId(testLabel), LibLabel.withVersion(LibLabel.id(testLabel), 0)); + uint256 tokenId = this._register(); + assertEq(registry.findTokenId(testLabel), tokenId); + registry.unregister(tokenId); + assertEq(registry.findTokenId(testLabel), tokenId + 1, "burn"); + tokenId = this._register(); + assertEq(registry.findTokenId(testLabel), tokenId, "again"); + } + + function test_findOwner() external { + assertEq(registry.findOwner(testLabel), address(0)); + uint256 tokenId = this._register(); + assertEq(registry.findOwner(testLabel), testOwner); + registry.unregister(tokenId); + assertEq(registry.findOwner(testLabel), address(0), "burn"); + tokenId = this._register(); + assertEq(registry.findOwner(testLabel), testOwner, "again"); } //////////////////////////////////////////////////////////////////////// // Token Regeneration //////////////////////////////////////////////////////////////////////// + function test_burn_invalidSender() external { + address from; // wrong + vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidSender.selector, from)); + registry.__burn(from, 0, 0); + } + function test_regenerate_mintBurn() external { IPermissionedRegistry.State memory s0 = registry.getState(this._register()); registry.unregister(s0.tokenId); @@ -853,8 +1154,8 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { assertEq(s1.resource + 1, s2.resource, "resource:12"); } - function test_regenerate_safeTransferFrom(uint16 compactRoles) external { - testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN | _expandRoles(compactRoles); + function test_regenerate_safeTransferFrom(uint256) external { + testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN | _randomRoleBitmap(true, true); uint256 tokenId = this._register(); IPermissionedRegistry.State memory s0 = registry.getState(tokenId); assertEq(s0.latestOwner, user1, "before:owner"); @@ -884,18 +1185,397 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { assertEq(s1.latestOwner, s2.latestOwner, "owner:12"); } + //////////////////////////////////////////////////////////////////////// + // EAC Override: grantRoles() and revokeRoles() + //////////////////////////////////////////////////////////////////////// + + function test_grantRoles_asOwner(uint256) external { + uint256 roleBitmap = _randomRoleBitmap(false, true); + + testRoles = roleBitmap << 128; // admin + uint256 tokenId = this._register(); + + vm.expectEmit(); + emit IRegistryEvents.TokenRegenerated(tokenId, tokenId + 1); + vm.prank(testOwner); + assertTrue(registry.grantRoles(tokenId, roleBitmap, user2)); + } + + function test_grantRoles_asRoot(uint256) external { + uint256 roleBitmap = _randomRoleBitmap(false, true); + + uint256 tokenId = this._register(); + + assertTrue(registry.grantRoles(tokenId, roleBitmap, testOwner)); + } + + function test_grantRoles_withAdminAsOwner(uint256) external { + uint256 roleBitmap = _randomRoleBitmap(true, false); + + uint256 tokenId = this._register(); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + tokenId, // same as resource + roleBitmap, + testOwner + ) + ); + vm.prank(testOwner); + registry.grantRoles(tokenId, roleBitmap, user2); + } + + function test_grantRoles_withAdminAsOwnerAndRoot(uint256) external { + uint256 roleBitmap = _randomRoleBitmap(true, false); + + testOwner = address(this); // mint to account with root + uint256 tokenId = this._register(); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + tokenId, // same as resource + roleBitmap, + address(this) + ) + ); + registry.grantRoles(tokenId, roleBitmap, user2); + } + + function test_grantRoles_whileUnregistered(uint256 anyId) external { + vm.assume(anyId > 0); + uint256 roleBitmap = _randomRoleBitmap(true, true); + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + LibLabel.withVersion(anyId, 1), // next + roleBitmap, + address(this) + ) + ); + registry.grantRoles(anyId, roleBitmap, user2); + } + + function test_grantRoles_whileExpired(uint256) external { + uint256 roleBitmap = _randomRoleBitmap(true, true); + + uint256 tokenId = this._register(); + vm.warp(testExpiry); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + tokenId + 1, // next + roleBitmap, + address(this) + ) + ); + registry.grantRoles(tokenId, roleBitmap, user2); + } + + function test_grantRoles_whileReserved(uint256) external { + uint256 roleBitmap = _randomRoleBitmap(true, true); + + uint256 tokenId = this._reserve(); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + tokenId, // same as resource + roleBitmap, + address(this) + ) + ); + registry.grantRoles(tokenId, roleBitmap, user2); + } + + function test_revokeRoles_asOwnerHavingAdmin(uint256) external { + uint256 roleBitmap = _randomRoleBitmap(false, true); + uint256 adminRoleBitmap = roleBitmap << 128; + + testRoles = adminRoleBitmap | roleBitmap; // both + uint256 tokenId = this._register(); + + // revoke normal role + vm.expectEmit(); + emit IRegistryEvents.TokenRegenerated(tokenId, tokenId + 1); + vm.prank(testOwner); + assertTrue(registry.revokeRoles(tokenId, roleBitmap, testOwner)); + + // revoke admin role + vm.prank(testOwner); + assertTrue(registry.revokeRoles(tokenId, adminRoleBitmap, testOwner)); + } + + function test_revokeRoles_asOwnerLackingAdmin(uint256) external { + testRoles = _randomRoleBitmap(false, true); + + uint256 tokenId = this._register(); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotRevokeRoles.selector, + tokenId, // same as resource + testRoles, + testOwner + ) + ); + vm.prank(testOwner); + registry.revokeRoles(tokenId, testRoles, testOwner); + } + + function test_revokeRoles_asRoot(uint256) external { + testRoles = _randomRoleBitmap(true, true); + + uint256 tokenId = this._register(); + + assertTrue(registry.revokeRoles(tokenId, testRoles, testOwner)); + } + + function test_revokeRoles_whileExpired(uint256) external { + testRoles = _randomRoleBitmap(true, true); + + uint256 tokenId = this._register(); + vm.warp(testExpiry); + + assertFalse(registry.revokeRoles(tokenId, testRoles, testOwner)); + } + + function test_revokeRoles_whileReserved(uint256) external { + uint256 roleBitmap = _randomRoleBitmap(true, true); + + uint256 tokenId = this._reserve(); + + assertFalse(registry.revokeRoles(tokenId, roleBitmap, testOwner)); + } + + //////////////////////////////////////////////////////////////////////// + // EAC Override: setApprovalForAll() + //////////////////////////////////////////////////////////////////////// + + function test_setApprovalForAll_invalidOperator() external { + address to; // wrong + vm.expectRevert(abi.encodeWithSelector(IERC1155Errors.ERC1155InvalidOperator.selector, to)); + registry.setApprovalForAll(to, true); + } + + function test_setApprovalForAll_roles(uint256) external { + testRoles = _randomRoleBitmap(true, false); + uint256 tokenId = this._register(); + testRoles >>= 128; // convert to normal + + vm.prank(testOwner); + registry.setApprovalForAll(user2, true); + + vm.prank(user2); + registry.grantRoles(tokenId, testRoles, actor); + vm.prank(user2); + registry.revokeRoles(tokenId, testRoles, actor); + assertEq(registry.roles(tokenId, actor), 0); + + vm.prank(testOwner); + registry.setApprovalForAll(user2, false); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + tokenId, // same as resource + testRoles, + user2 + ) + ); + vm.prank(user2); + registry.grantRoles(tokenId, testRoles, actor); + } + + function test_setApprovalForAll_revokeRoles() external { + testRoles = EACBaseRolesLib.ALL_ROLES; + uint256 tokenId = this._register(); + + vm.prank(testOwner); + registry.setApprovalForAll(user2, true); + + // approval roles are aliased and not an actual assignee + (uint256 counts, ) = registry.getAssigneeCount(tokenId, testRoles); + assertEq(counts, EACBaseRolesLib.ALL_ROLES * 1); // not * 2 + assertEq(registry.roles(tokenId, testOwner), testRoles, "before:owner"); // real + assertEq(registry.roles(tokenId, user2), testRoles, "before:approved"); // alias + + // cant revoke aliased roles + vm.prank(user2); + assertFalse(registry.revokeRoles(tokenId, testRoles, user2)); + + // can revoke real roles via approval + vm.prank(user2); + assertTrue(registry.revokeRoles(tokenId, testRoles, testOwner)); + + // since roles are aliased, revoking real roles => aliased roles + (counts, ) = registry.getAssigneeCount(tokenId, testRoles); + assertEq(counts, 0); + assertEq(registry.roles(tokenId, testOwner), 0, "after:owner"); + assertEq(registry.roles(tokenId, user2), 0, "after:approved"); + } + + function test_setApprovalForAll_blendedRoles() external { + testRoles = RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN; + uint256 tokenId = this._register(); + + // user2 has token roles via approval + vm.prank(testOwner); + registry.setApprovalForAll(user2, true); + + // user2 has token roles via grant + vm.prank(testOwner); + registry.grantRoles(tokenId, RegistryRolesLib.ROLE_SET_RESOLVER, user2); + + // user2 has root roles + registry.grantRootRoles(RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN, user2); + + // user2 effectively has roles from all sources + assertTrue( + registry.hasRoles( + tokenId, + RegistryRolesLib.ROLE_SET_RESOLVER | + RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN | + RegistryRolesLib.ROLE_SET_SUBREGISTRY_ADMIN, + user2 + ) + ); + } + + function test_setApprovalForAll_setResolver() external { + testRoles = RegistryRolesLib.ROLE_SET_RESOLVER; + uint256 tokenId = this._register(); + + // without approval + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + tokenId, // same as resource + testRoles, + user2 + ) + ); + vm.prank(user2); + registry.setResolver(tokenId, testResolver); + + vm.prank(testOwner); + registry.setApprovalForAll(user2, true); + + // with approval + vm.prank(user2); + registry.setResolver(tokenId, testResolver); + } + + function test_setApprovalForAll_setSubregistry() external { + testRoles = RegistryRolesLib.ROLE_SET_SUBREGISTRY; + uint256 tokenId = this._register(); + + // without approval + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + tokenId, // same as resource + testRoles, + user2 + ) + ); + vm.prank(user2); + registry.setSubregistry(tokenId, testRegistry); + + vm.prank(testOwner); + registry.setApprovalForAll(user2, true); + + // with approval + vm.prank(user2); + registry.setSubregistry(tokenId, testRegistry); + } + + //////////////////////////////////////////////////////////////////////// + // IContractNamer + //////////////////////////////////////////////////////////////////////// + + function test_isContractNamer() external { + assertTrue(registry.isContractNamer(address(this))); + + assertFalse(registry.isContractNamer(user1), "before"); + registry.grantRootRoles(RegistryRolesLib.ROLE_CAN_NAME, user1); + assertTrue(registry.isContractNamer(user1), "granted"); + registry.revokeRootRoles(RegistryRolesLib.ROLE_CAN_NAME, user1); + assertFalse(registry.isContractNamer(user1), "revoked"); + } + + //////////////////////////////////////////////////////////////////////// + // setURI() and uri() + //////////////////////////////////////////////////////////////////////// + + function test_uri_unset() external view { + assertEq(registry.uri(0), ""); + assertEq(registry.uri(1), ""); + } + + function test_setURI_onlyURI() external { + string memory uri = "ipfs://base/{id}"; + registry.setURI(uri, IRegistryURIRenderer(address(0))); + + uint256 tokenId = this._register(); + assertEq(registry.uri(0), uri); + assertEq(registry.uri(tokenId), uri); + } + + // IRegistryURIRenderer + function renderURI(IRegistry, uint256 tokenId) external pure returns (string memory) { + return vm.toString(tokenId); + } + + function test_setURI_withRenderer() external { + IRegistryURIRenderer renderer = IRegistryURIRenderer(address(this)); // see: renderURI() + registry.setURI("", renderer); + + uint256 tokenId = this._register(); + assertEq(registry.uri(0), renderer.renderURI(registry, 0)); + assertEq(registry.uri(tokenId), renderer.renderURI(registry, tokenId)); + } + + function test_setURI_notAuthorized() external { + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + registry.ROOT_RESOURCE(), + RegistryRolesLib.ROLE_SET_URI, + actor + ) + ); + vm.prank(actor); + registry.setURI("", IRegistryURIRenderer(address(0))); + } + //////////////////////////////////////////////////////////////////////// // Specific Cases //////////////////////////////////////////////////////////////////////// + // scenerio: how to transfer a registry control + function test_transferRegistryControl() external { + uint256 roleBitmap = registry.roles(registry.ROOT_RESOURCE(), address(this)); + // 1. grant same roles + registry.grantRootRoles(roleBitmap, user1); + assertTrue(registry.hasRootRoles(roleBitmap, user1), "granted"); + assertEq(registry.roleCount(registry.ROOT_RESOURCE()), EACBaseRolesLib.ALL_ROLES * 2); + // 2. revoke our roles + registry.revokeRootRoles(roleBitmap, address(this)); + assertFalse(registry.hasRootRoles(roleBitmap, address(this)), "revoked"); + // 3. registry is transferred + assertEq(registry.roleCount(registry.ROOT_RESOURCE()), EACBaseRolesLib.ALL_ROLES * 1); + } + // scenerio: // 1. user2 buys token from an exchange from user1 // 2. user1 detects and frontruns a revoke() that cripples the token // 3. user2 receives crippled token => angry! function test_transferAbortsAfterRevoke() external { testRoles = - RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN | - RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN; + RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN | RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN; uint256 tokenId = this._register(); // make token available for sale vm.prank(user1); @@ -940,6 +1620,93 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { registry.safeTransferFrom(user1, user2, tokenId, 1, ""); } + // scenerio: + // 1. token expires, role modification is frozen + // 2. transfer while expired, hasRoles() still exists + function test_transferWhileExpired() external { + testRoles = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; + uint256 tokenId = this._register(); + // step #1: token expires + vm.warp(testExpiry); + // step #2: transfer while expired + vm.expectRevert( + abi.encodeWithSelector(IStandardRegistry.TransferDisallowed.selector, tokenId, user1) + ); + vm.prank(user1); + registry.safeTransferFrom(user1, user2, tokenId, 1, ""); + } + + // scenerio: BET-594 + // if EACRolesChanged is emit after callback execution, it is out of order + // 1. role A is granted => regenerate + // 2. callback triggers another action + // 3. role B is granted => regenerate (during callback) + // 4. EACRolesChanged is emit for B + // 5. EACRolesChanged is emit for A + function test_reentrantCallbackEventOrdering_grantRoles() external { + ReentrantReceiver r = new ReentrantReceiver(registry); + + uint256 role = RegistryRolesLib.ROLE_SET_RESOLVER; + + testOwner = address(r); + testRoles = RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN; + uint256 tokenId = this._register(); + + // make it so we grant another role during callback + r.setReceiverCalldata( + abi.encodeCall(PermissionedRegistry.grantRoles, (tokenId, role, actor)) + ); + + // grant => burn+mint => grant again + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenId, user2, 0, role); // grant 1 + vm.expectEmit(); + emit IRegistryEvents.TokenRegenerated(tokenId, tokenId + 1); + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenId, actor, 0, role); // grant 2 + vm.expectEmit(); + emit IRegistryEvents.TokenRegenerated(tokenId + 1, tokenId + 2); + vm.prank(address(r)); + registry.grantRoles(tokenId, role, user2); + } + + // same as above except for revoke + function test_reentrantCallbackEventOrdering_revokeRoles() external { + ReentrantReceiver r = new ReentrantReceiver(registry); + + uint256 role1 = RegistryRolesLib.ROLE_CAN_TRANSFER_ADMIN; + uint256 role2 = RegistryRolesLib.ROLE_SET_RESOLVER_ADMIN; + + testOwner = address(r); + testRoles = role1 | role2; + uint256 tokenId = this._register(); + + // make it so we revoke another role during callback + r.setReceiverCalldata( + abi.encodeCall(PermissionedRegistry.revokeRoles, (tokenId, role2, testOwner)) + ); + + // revoke => burn+mint => revoke again + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenId, testOwner, testRoles, role2); // revoke 1 + vm.expectEmit(); + emit IRegistryEvents.TokenRegenerated(tokenId, tokenId + 1); + vm.expectEmit(); + emit IEnhancedAccessControl.EACRolesChanged(tokenId, testOwner, role2, 0); // revoke 2 + vm.expectEmit(); + emit IRegistryEvents.TokenRegenerated(tokenId + 1, tokenId + 2); + vm.prank(testOwner); + registry.revokeRoles(tokenId, role1, testOwner); + } + + // scenerio: emanicipation concern: root can revoke token + function test_rootRevokeToken(uint8 role) external { + vm.assume(role >= 32 && role < 64); + testRoles = 1 << (role << 2); // every admin role + uint256 tokenId = this._register(); + assertTrue(registry.revokeRoles(tokenId, testRoles, testOwner)); + } + //////////////////////////////////////////////////////////////////////// // Internals //////////////////////////////////////////////////////////////////////// @@ -1014,29 +1781,151 @@ contract PermissionedRegistryTest is Test, ERC1155Holder { function _expectNoEmit(Vm.Log[] memory logs, bytes32 topic0) internal pure { for (uint256 i; i < logs.length; ++i) { - if (logs[i].topics[0] == topic0) { - revert(string.concat("found unexpected event: ", vm.toString(topic0))); - } + assertNotEq(logs[i].topics[0], topic0, "found unexpected event"); } } - function _expandRoles(uint16 compactRoles) internal pure returns (uint256 roles) { - for (uint256 i; i < 16; ++i) { - if ((compactRoles & (1 << i)) != 0) { - roles |= (1 << (i << 2)); + function _assertResolverUpdated( + Vm.Log memory log, + uint256 tokenId, + address resolver, + address sender + ) + internal + pure + { + assertEq(log.topics.length, 4, "topic count"); + assertEq(log.topics[0], IRegistryEvents.ResolverUpdated.selector, "topic0"); + assertEq(log.topics[1], bytes32(tokenId), "tokenId"); + assertEq(log.topics[2], bytes32(uint256(uint160(resolver))), "resolver"); + assertEq(log.topics[3], bytes32(uint256(uint160(sender))), "sender"); + assertEq(log.data.length, 0, "data"); + } + + /// @dev Randomly pick a role corresponding to the enable regions. + // If both regions are enabled, pick 1-2 roles. + function _randomRoleBitmap(bool admin, bool normal) internal returns (uint256 roleBitmap) { + if (admin && normal) { + roleBitmap = 1 << (vm.randomUint(0, 63) << 2); + if (vm.randomBool()) { + roleBitmap |= 1 << (vm.randomUint(0, 63) << 2); } + } else if (normal) { + roleBitmap = 1 << (vm.randomUint(0, 31) << 2); + } else if (admin) { + roleBitmap = 1 << (vm.randomUint(32, 63) << 2); + } else { + revert("bug"); } } } + contract MockPermissionedRegistry is PermissionedRegistry { - constructor( - IHCAFactoryBasic hcaFactory, - IRegistryMetadata metadata, - address ownerAddress, - uint256 ownerRoles - ) PermissionedRegistry(hcaFactory, metadata, ownerAddress, ownerRoles) {} + constructor(ILabelStore labelStore, address rootAccount, uint256 roleBitmap) + PermissionedRegistry(labelStore, rootAccount, roleBitmap) + {} function getEntry(uint256 anyId) external view returns (PermissionedRegistry.Entry memory) { return _entry(anyId); } + function __safeTransferFrom( + address from, + address to, + uint256 id, + uint256 value, + bytes memory data + ) + external + { + _safeTransferFrom(from, to, id, value, data); + } + function __safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) + external + { + _safeBatchTransferFrom(from, to, ids, values, data); + } + function __burn(address from, uint256 id, uint256 value) external { + _burn(from, id, value); + } +} + + +contract ReentrantReceiver is ERC1155Holder { + PermissionedRegistry immutable REGISTRY; + bytes _data; + constructor(PermissionedRegistry registry) { + REGISTRY = registry; + } + function setReceiverCalldata(bytes calldata data) external { + _data = data; + } + function onERC1155Received( + address operator, + address from, + uint256 id, + uint256 value, + bytes memory data + ) + public + override + returns (bytes4) + { + if (from == address(0)) { + // during mint(), eg. token regeneration(), mutate the registry + bytes memory v = _data; + if (v.length > 0) { + delete _data; // consume calldata + bool ok; + (ok, v) = address(REGISTRY).call(v); // execute it + if (!ok) { + assembly { + revert(add(v, 32), mload(v)) // propagate + } + } + } + } + return super.onERC1155Received(operator, from, id, value, data); + } +} + + +contract StrictERC1155Holder is ERC1155Holder { + bool immutable BATCH; + constructor(bool batch) { + BATCH = batch; + } + function onERC1155Received( + address operator, + address from, + uint256 id, + uint256 value, + bytes memory data + ) + public + override + returns (bytes4) + { + require(!BATCH); + return super.onERC1155Received(operator, from, id, value, data); + } + function onERC1155BatchReceived( + address operator, + address from, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) + public + override + returns (bytes4) + { + require(BATCH); + return super.onERC1155BatchReceived(operator, from, ids, values, data); + } } diff --git a/contracts/test/unit/registry/SimpleRegistryMetadata.t.sol b/contracts/test/unit/registry/SimpleRegistryMetadata.t.sol deleted file mode 100644 index f37e3bcf8..000000000 --- a/contracts/test/unit/registry/SimpleRegistryMetadata.t.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file - -import {Test} from "forge-std/Test.sol"; - -import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; -import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; - -import { - PermissionedRegistry, - RegistryRolesLib, - IRegistryMetadata, - EACBaseRolesLib, - IEnhancedAccessControl, - LibLabel -} from "~src/registry/PermissionedRegistry.sol"; -import {SimpleRegistryMetadata} from "~src/registry/SimpleRegistryMetadata.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; - -contract SimpleRegistryMetadataTest is Test, ERC1155Holder { - MockHCAFactoryBasic hcaFactory; - PermissionedRegistry registry; - SimpleRegistryMetadata metadata; - - // Hardcoded role constants - uint256 constant ROLE_UPDATE_METADATA = 1 << 0; - uint256 constant ROLE_UPDATE_METADATA_ADMIN = ROLE_UPDATE_METADATA << 128; - - uint256 constant DEFAULT_ROLE_BITMAP = - RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER; - - function setUp() public { - hcaFactory = new MockHCAFactoryBasic(); - metadata = new SimpleRegistryMetadata(hcaFactory); - // Use the valid ALL_ROLES value for deployer roles - uint256 deployerRoles = EACBaseRolesLib.ALL_ROLES; - registry = new PermissionedRegistry(hcaFactory, metadata, address(this), deployerRoles); - } - - function test_registry_metadata_token_uri() public { - uint256 tokenId = registry.register( - "test", - address(this), - registry, - address(0), - DEFAULT_ROLE_BITMAP, - uint64(block.timestamp + 1000) - ); - - assertEq(registry.uri(tokenId), ""); - - string memory expectedUri = "ipfs://test"; - metadata.setTokenUri(tokenId, expectedUri); - assertEq(metadata.tokenUri(tokenId), expectedUri); - assertEq(registry.uri(tokenId), expectedUri); - } - - function test_registry_metadata_unauthorized() public { - uint256 tokenId = registry.getTokenId(LibLabel.id("dne")); - string memory expectedUri = "ipfs://test"; - vm.expectRevert( - abi.encodeWithSelector( - IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, - metadata.ROOT_RESOURCE(), - ROLE_UPDATE_METADATA, - address(1) - ) - ); - vm.prank(address(1)); - metadata.setTokenUri(tokenId, expectedUri); - } - - function test_registry_metadata_supports_interface() public view { - assertEq(metadata.supportsInterface(type(IRegistryMetadata).interfaceId), true); - assertEq(metadata.supportsInterface(type(IEnhancedAccessControl).interfaceId), true); - assertEq(metadata.supportsInterface(type(IERC165).interfaceId), true); - } -} diff --git a/contracts/test/unit/registry/UserRegistry.t.sol b/contracts/test/unit/registry/UserRegistry.t.sol index 042b00aa9..95c3ee091 100644 --- a/contracts/test/unit/registry/UserRegistry.t.sol +++ b/contracts/test/unit/registry/UserRegistry.t.sol @@ -8,15 +8,15 @@ import {Test} from "forge-std/Test.sol"; import {VerifiableFactory} from "@ensdomains/verifiable-factory/VerifiableFactory.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; +import {InvalidOwner} from "~src/CommonErrors.sol"; import {EACBaseRolesLib} from "~src/access-control/EnhancedAccessControl.sol"; import {IEnhancedAccessControl} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; -import {IRegistryMetadata} from "~src/registry/interfaces/IRegistryMetadata.sol"; +import {IRegistryEvents} from "~src/registry/interfaces/IRegistryEvents.sol"; import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; -import {SimpleRegistryMetadata} from "~src/registry/SimpleRegistryMetadata.sol"; import {UserRegistry} from "~src/registry/UserRegistry.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; +import {LabelStore, ILabelStore} from "~src/utils/LabelStore.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; contract UserRegistryTest is Test, ERC1155Holder { // Test constants @@ -24,8 +24,7 @@ contract UserRegistryTest is Test, ERC1155Holder { // Contracts VerifiableFactory factory; - MockHCAFactoryBasic hcaFactory; - SimpleRegistryMetadata metadata; + LabelStore labelStore; UserRegistry implementation; UserRegistry proxy; @@ -35,25 +34,21 @@ contract UserRegistryTest is Test, ERC1155Holder { address user2 = makeAddr("user2"); function setUp() public { - // Deploy the factory factory = new VerifiableFactory(); - - // Deploy the HCA factory - hcaFactory = new MockHCAFactoryBasic(); - - // Deploy metadata provider - metadata = new SimpleRegistryMetadata(hcaFactory); + labelStore = new LabelStore(IContractNamer(address(0))); // Deploy the implementation - implementation = new UserRegistry(hcaFactory, metadata); + vm.expectEmit(); + emit IRegistryEvents.RegistryCreated(); + implementation = new UserRegistry(labelStore, address(this)); // Create initialization data - bytes memory initData = abi.encodeCall( - UserRegistry.initialize, - (admin, EACBaseRolesLib.ALL_ROLES) - ); + bytes memory initData = + abi.encodeCall(UserRegistry.initialize, (admin, EACBaseRolesLib.ALL_ROLES)); // Deploy the proxy using the factory + vm.expectEmit(); + emit IRegistryEvents.RegistryCreated(); vm.prank(admin); address proxyAddress = factory.deployProxy(address(implementation), SALT, initData); @@ -61,9 +56,26 @@ contract UserRegistryTest is Test, ERC1155Holder { proxy = UserRegistry(proxyAddress); } + function test_implementationIsNameable() external view { + assertTrue(implementation.isContractNamer(address(this))); + } + + function test_initialize_invalidOwner() external { + vm.expectRevert(abi.encodeWithSelector(InvalidOwner.selector)); + factory.deployProxy( + address(implementation), + SALT, + abi.encodeCall(UserRegistry.initialize, (address(0), EACBaseRolesLib.ALL_ROLES)) + ); + } + function test_initialization() public view { // Verify the proxy was deployed correctly - assertTrue(factory.verifyContract(address(proxy)), "Proxy should be verified"); + assertEq( + factory.verifyContract(address(proxy)), + address(implementation), + "Proxy should be verified" + ); // Verify admin has the expected roles assertTrue( @@ -90,10 +102,7 @@ contract UserRegistryTest is Test, ERC1155Holder { ); // Verify proxy supports required interfaces - assertTrue( - proxy.supportsInterface(type(IRegistry).interfaceId), - "Should support IRegistry" - ); + assertTrue(proxy.supportsInterface(type(IRegistry).interfaceId), "Should support IRegistry"); // UUPSUpgradeable doesn't have an interface ID, so we check for ERC1155 interface assertTrue(proxy.supportsInterface(0xd9b67a26), "Should support ERC1155"); } @@ -104,14 +113,15 @@ contract UserRegistryTest is Test, ERC1155Holder { // Register a domain as admin vm.prank(admin); - uint256 tokenId = proxy.register( - label, - user1, - IRegistry(address(0)), - address(0), - RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, - uint64(block.timestamp + 365 days) - ); + uint256 tokenId = + proxy.register( + label, + user1, + IRegistry(address(0)), + address(0), + RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, + uint64(block.timestamp + 365 days) + ); // Verify the domain was registered correctly assertEq(proxy.ownerOf(tokenId), user1, "Domain should be owned by user1"); @@ -138,14 +148,15 @@ contract UserRegistryTest is Test, ERC1155Holder { function test_domain_management() public { // Register a domain vm.prank(admin); - uint256 tokenId = proxy.register( - "mdtdomain", - user1, - IRegistry(address(0)), - address(0), - RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, - uint64(block.timestamp + 365 days) - ); + uint256 tokenId = + proxy.register( + "mdtdomain", + user1, + IRegistry(address(0)), + address(0), + RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, + uint64(block.timestamp + 365 days) + ); // User1 sets a resolver address resolver = address(0x123); @@ -180,14 +191,15 @@ contract UserRegistryTest is Test, ERC1155Holder { // User1 should be able to register domains now vm.prank(user1); - uint256 tokenId = proxy.register( - "user1domain", - user2, - IRegistry(address(0)), - address(0), - RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, - uint64(block.timestamp + 365 days) - ); + uint256 tokenId = + proxy.register( + "user1domain", + user2, + IRegistry(address(0)), + address(0), + RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, + uint64(block.timestamp + 365 days) + ); // Verify registration was successful assertEq(proxy.ownerOf(tokenId), user2, "Domain should be owned by user2"); @@ -237,14 +249,15 @@ contract UserRegistryTest is Test, ERC1155Holder { // Register a domain as admin vm.prank(admin); - uint256 tokenId = proxy.register( - label, - user1, - IRegistry(address(0)), - address(0), - RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, - expires - ); + uint256 tokenId = + proxy.register( + label, + user1, + IRegistry(address(0)), + address(0), + RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, + expires + ); // Verify registration assertEq(proxy.ownerOf(tokenId), user1, "Domain should be owned by user1"); @@ -254,7 +267,7 @@ contract UserRegistryTest is Test, ERC1155Holder { // Test for contract upgradeability function test_upgrade() public { // Deploy a new implementation - UserRegistryV2Mock newImplementation = new UserRegistryV2Mock(hcaFactory, metadata); + UserRegistryV2Mock newImplementation = new UserRegistryV2Mock(labelStore, address(this)); // Upgrade the proxy vm.prank(admin); @@ -267,7 +280,7 @@ contract UserRegistryTest is Test, ERC1155Holder { function test_Revert_unauthorized_upgrade() public { // Deploy a new implementation - UserRegistryV2Mock newImplementation = new UserRegistryV2Mock(hcaFactory, metadata); + UserRegistryV2Mock newImplementation = new UserRegistryV2Mock(labelStore, address(this)); // User1 tries to upgrade without permission vm.expectRevert( @@ -282,22 +295,23 @@ contract UserRegistryTest is Test, ERC1155Holder { proxy.upgradeToAndCall(address(newImplementation), ""); } - function test_domain_expiration() public { + function test_domain_expiry() public { // Register a domain with short expiry vm.prank(admin); - uint256 tokenId = proxy.register( - "expiredomain", - user1, - IRegistry(address(0)), - address(0), - RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, - uint64(block.timestamp + 1 days) - ); + uint256 tokenId = + proxy.register( + "expiredomain", + user1, + IRegistry(address(0)), + address(0), + RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, + uint64(block.timestamp + 1 days) + ); // Verify it exists assertEq(proxy.ownerOf(tokenId), user1, "Domain should be owned by user1"); - // Advance time past expiration + // Advance time past expiry vm.warp(block.timestamp + 2 days); // Verify domain is expired @@ -310,26 +324,25 @@ contract UserRegistryTest is Test, ERC1155Holder { // Should be able to register it again vm.prank(admin); - uint256 newTokenId = proxy.register( - "expiredomain", - user2, - IRegistry(address(0)), - address(0), - RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, - uint64(block.timestamp + 1 days) - ); + uint256 newTokenId = + proxy.register( + "expiredomain", + user2, + IRegistry(address(0)), + address(0), + RegistryRolesLib.ROLE_SET_SUBREGISTRY | RegistryRolesLib.ROLE_SET_RESOLVER, + uint64(block.timestamp + 1 days) + ); // Verify new registration assertEq(proxy.ownerOf(newTokenId), user2, "Domain should be owned by user2"); } } + // Mock V2 contract for testing upgrades contract UserRegistryV2Mock is UserRegistry { - constructor( - IHCAFactoryBasic _hcaFactory, - IRegistryMetadata _metadataProvider - ) UserRegistry(_hcaFactory, _metadataProvider) {} + constructor(ILabelStore labelStore, address namer) UserRegistry(labelStore, namer) {} function version() public pure returns (uint256) { return 2; } diff --git a/contracts/test/unit/resolver/PermissionedResolver.t.sol b/contracts/test/unit/resolver/PermissionedResolver.t.sol index 397668a3d..64a2bf1c1 100644 --- a/contracts/test/unit/resolver/PermissionedResolver.t.sol +++ b/contracts/test/unit/resolver/PermissionedResolver.t.sol @@ -3,89 +3,65 @@ pragma solidity ^0.8.13; import {Test} from "forge-std/Test.sol"; -import {VerifiableFactory} from "@ensdomains/verifiable-factory/VerifiableFactory.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {IProxyAuthorization} from "@ensdomains/verifiable-factory/IProxyAuthorization.sol"; +import {VerifiableFactory} from "@ensdomains/verifiable-factory/VerifiableFactory.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {ResolverFeatures} from "@ens/contracts/resolvers/ResolverFeatures.sol"; +import {ENSIP19, COIN_TYPE_ETH, COIN_TYPE_DEFAULT} from "@ens/contracts/utils/ENSIP19.sol"; +import {IERC7996} from "@ens/contracts/utils/IERC7996.sol"; +import {IMulticallable} from "@ens/contracts/resolvers/IMulticallable.sol"; +import {IABIResolver} from "@ens/contracts/resolvers/profiles/IABIResolver.sol"; +import {IAddressResolver} from "@ens/contracts/resolvers/profiles/IAddressResolver.sol"; +import {IAddrResolver} from "@ens/contracts/resolvers/profiles/IAddrResolver.sol"; +import {IContentHashResolver} from "@ens/contracts/resolvers/profiles/IContentHashResolver.sol"; +import {IDataResolver} from "@ens/contracts/resolvers/profiles/IDataResolver.sol"; +import {IHasAddressResolver} from "@ens/contracts/resolvers/profiles/IHasAddressResolver.sol"; +import {IInterfaceResolver} from "@ens/contracts/resolvers/profiles/IInterfaceResolver.sol"; +import {INameResolver} from "@ens/contracts/resolvers/profiles/INameResolver.sol"; +import {IPubkeyResolver} from "@ens/contracts/resolvers/profiles/IPubkeyResolver.sol"; +import {ITextResolver} from "@ens/contracts/resolvers/profiles/ITextResolver.sol"; +import {IVersionableResolver} from "@ens/contracts/resolvers/profiles/IVersionableResolver.sol"; import {IEnhancedAccessControl} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; import {EACBaseRolesLib} from "~src/access-control/libraries/EACBaseRolesLib.sol"; -import { - PermissionedResolver, - PermissionedResolverLib, - IMulticallable, - IABIResolver, - IAddrResolver, - IAddressResolver, - IContentHashResolver, - IExtendedResolver, - IHasAddressResolver, - IInterfaceResolver, - INameResolver, - IPubkeyResolver, - ITextResolver, - IVersionableResolver, - NameCoder, - ResolverFeatures, - IERC7996, - ENSIP19, - COIN_TYPE_ETH, - COIN_TYPE_DEFAULT -} from "~src/resolver/PermissionedResolver.sol"; -import {MockHCAFactoryBasic} from "~test/mocks/MockHCAFactoryBasic.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {IPermissionedResolver} from "~src/resolver/interfaces/IPermissionedResolver.sol"; +import {PermissionedResolverLib} from "~src/resolver/libraries/PermissionedResolverLib.sol"; +import {PermissionedResolver} from "~src/resolver/PermissionedResolver.sol"; + +bytes4 constant TEST_SELECTOR = 0x12345678; contract PermissionedResolverTest is Test { uint256 constant DEFAULT_ROLES = EACBaseRolesLib.ALL_ROLES; - struct I { - bytes4 interfaceId; - string name; - } - function _supportedInterfaces() internal pure returns (I[] memory v) { - uint256 i; - v = new I[](15); - v[i++] = I(type(IExtendedResolver).interfaceId, "IExtendedResolver"); - v[i++] = I(type(IERC7996).interfaceId, "IERC7996"); - v[i++] = I(type(IMulticallable).interfaceId, "IMulticallable"); - v[i++] = I(type(IABIResolver).interfaceId, "IABIResolver"); - v[i++] = I(type(IAddrResolver).interfaceId, "IAddrResolver"); - v[i++] = I(type(IAddressResolver).interfaceId, "IAddressResolver"); - v[i++] = I(type(IContentHashResolver).interfaceId, "IContentHashResolver"); - v[i++] = I(type(IHasAddressResolver).interfaceId, "IHasAddressResolver"); - v[i++] = I(type(IInterfaceResolver).interfaceId, "IInterfaceResolver"); - v[i++] = I(type(INameResolver).interfaceId, "INameResolver"); - v[i++] = I(type(IPubkeyResolver).interfaceId, "IPubkeyResolver"); - v[i++] = I(type(ITextResolver).interfaceId, "ITextResolver"); - v[i++] = I(type(IVersionableResolver).interfaceId, "IVersionableResolver"); - v[i++] = I(type(UUPSUpgradeable).interfaceId, "UUPSUpgradeable"); - v[i++] = I(type(IEnhancedAccessControl).interfaceId, "IEnhancedAccessControl"); - assertEq(v.length, i); - } - - MockHCAFactoryBasic hcaFactory; + VerifiableFactory factory; + PermissionedResolver implementation; PermissionedResolver resolver; address owner = makeAddr("owner"); + address actor = makeAddr("actor"); address friend = makeAddr("friend"); bytes testName; bytes32 testNode; - address testAddr = 0x8000000000000000000000000000000000000001; + address testAddr = makeAddr("test"); bytes testAddress = abi.encodePacked(testAddr); string testString = "abc"; function setUp() external { - VerifiableFactory factory = new VerifiableFactory(); - hcaFactory = new MockHCAFactoryBasic(); - PermissionedResolver resolverImpl = new PermissionedResolver(hcaFactory); + factory = new VerifiableFactory(); + implementation = new PermissionedResolver(address(this)); + testName = NameCoder.encode("test.eth"); testNode = NameCoder.namehash(testName, 0); - bytes memory initData = abi.encodeCall( - PermissionedResolver.initialize, - (owner, DEFAULT_ROLES) - ); + bytes memory initData = + abi.encodeCall(PermissionedResolver.initialize, (owner, DEFAULT_ROLES, new bytes[](0))); resolver = PermissionedResolver( - factory.deployProxy(address(resolverImpl), uint256(keccak256(initData)), initData) + factory.deployProxy(address(implementation), uint256(keccak256(initData)), initData) ); } @@ -93,14 +69,40 @@ contract PermissionedResolverTest is Test { // Init //////////////////////////////////////////////////////////////////////// - function test_constructor() external view { - assertEq(address(resolver.HCA_FACTORY()), address(hcaFactory), "HCA_FACTORY"); - } - function test_initialize() external view { assertTrue(resolver.hasRootRoles(DEFAULT_ROLES, owner), "roles"); } + function test_initialize_unowned() external { + bytes memory initData = + abi.encodeCall(PermissionedResolver.initialize, (address(0), 0, new bytes[](0))); + PermissionedResolver r = + PermissionedResolver( + factory.deployProxy(address(implementation), uint256(keccak256(initData)), initData) + ); + assertEq(r.roleCount(r.ROOT_RESOURCE()), 0); + } + + function test_initalize_with_setters() external { + bytes[] memory m = new bytes[](2); + m[0] = abi.encodeCall(PermissionedResolver.setName, (testNode, testString)); + m[1] = abi.encodeCall(PermissionedResolver.setContenthash, (testNode, testAddress)); + + bytes memory initData = abi.encodeCall(PermissionedResolver.initialize, (address(0), 0, m)); + PermissionedResolver r = + PermissionedResolver( + factory.deployProxy(address(implementation), uint256(keccak256(initData)), initData) + ); + + assertEq(r.name(testNode), testString, "name()"); + assertEq(r.contenthash(testNode), testAddress, "contenthash()"); + } + + function test_canUpgradeFrom() external view { + assertTrue(resolver.canUpgradeFrom(address(0))); // accepts + assertTrue(resolver.canUpgradeFrom(address(1))); // any address + } + function test_upgrade() external { MockUpgrade upgrade = new MockUpgrade(); vm.prank(owner); @@ -110,6 +112,7 @@ contract PermissionedResolverTest is Test { function test_upgrade_notAuthorized() external { MockUpgrade upgrade = new MockUpgrade(); + assertTrue(resolver.canUpgradeFrom(address(upgrade))); vm.expectRevert( abi.encodeWithSelector( IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, @@ -123,21 +126,92 @@ contract PermissionedResolverTest is Test { } function test_supportsInterface() external view { - assertTrue(ERC165Checker.supportsERC165(address(resolver)), "ERC165"); - I[] memory v = _supportedInterfaces(); - for (uint256 i; i < v.length; i++) { - assertTrue( - ERC165Checker.supportsInterface(address(resolver), v[i].interfaceId), - v[i].name - ); - } - } + assertTrue( + ERC165Checker.supportsInterface( + address(resolver), + type(IPermissionedResolver).interfaceId + ), + "IPermissionedResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(resolver), + type(IEnhancedAccessControl).interfaceId + ), + "IEnhancedAccessControl" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IContractNamer).interfaceId), + "IContractNamer" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IMulticallable).interfaceId), + "IMulticallable" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IERC7996).interfaceId), + "IERC7996" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(UUPSUpgradeable).interfaceId), + "UUPSUpgradeable" + ); - function test_supportsFeature() external view { + // profiles + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IABIResolver).interfaceId), + "IABIResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IAddrResolver).interfaceId), + "IAddrResolver" + ); assertTrue( - resolver.supportsFeature(ResolverFeatures.RESOLVE_MULTICALL), - "RESOLVE_MULTICALL" + ERC165Checker.supportsInterface(address(resolver), type(IAddressResolver).interfaceId), + "IAddressResolver" ); + assertTrue( + ERC165Checker.supportsInterface( + address(resolver), + type(IContentHashResolver).interfaceId + ), + "IContentHashResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IDataResolver).interfaceId), + "IDataResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IHasAddressResolver).interfaceId), + "IHasAddressResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IInterfaceResolver).interfaceId), + "IInterfaceResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(INameResolver).interfaceId), + "INameResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(IPubkeyResolver).interfaceId), + "IPubkeyResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(resolver), type(ITextResolver).interfaceId), + "ITextResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(resolver), + type(IVersionableResolver).interfaceId + ), + "IVersionableResolver" + ); + } + + function test_supportsFeature() external view { + assertTrue(resolver.supportsFeature(ResolverFeatures.RESOLVE_MULTICALL), "RESOLVE_MULTICALL"); } //////////////////////////////////////////////////////////////////////// @@ -152,7 +226,7 @@ contract PermissionedResolverTest is Test { function test_alias_root() external { vm.expectEmit(); - emit PermissionedResolver.AliasChanged( + emit IPermissionedResolver.AliasChanged( NameCoder.encode(""), NameCoder.encode("test.eth"), NameCoder.encode(""), @@ -162,11 +236,7 @@ contract PermissionedResolverTest is Test { resolver.setAlias(NameCoder.encode(""), NameCoder.encode("test.eth")); assertEq(resolver.getAlias(NameCoder.encode("")), NameCoder.encode("test.eth"), "root"); - assertEq( - resolver.getAlias(NameCoder.encode("sub")), - NameCoder.encode("sub.test.eth"), - "sub" - ); + assertEq(resolver.getAlias(NameCoder.encode("sub")), NameCoder.encode("sub.test.eth"), "sub"); } function test_alias_exact() external { @@ -218,20 +288,66 @@ contract PermissionedResolverTest is Test { } //////////////////////////////////////////////////////////////////////// - // grantNameRoles(), grantTextRoles(), and grantAddrRoles() + // authorizeNameRoles() //////////////////////////////////////////////////////////////////////// - function test_grantNameRoles() external { + function test_grantRoles_disabled(uint256 resource, address account) external { + vm.assume(resource > 0); + uint256 roleBitmap = EACBaseRolesLib.ALL_ROLES; + vm.prank(owner); + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + resource, + roleBitmap, + account + ) + ); + resolver.grantRoles(resource, roleBitmap, account); + } + + function test_revokeRoles_disabled(uint256 resource, address account) external { + vm.assume(resource > 0); + uint256 roleBitmap = EACBaseRolesLib.ALL_ROLES; + vm.prank(owner); + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotRevokeRoles.selector, + resource, + roleBitmap, + account + ) + ); + resolver.revokeRoles(resource, roleBitmap, account); + } + + function test_authorizeNameRoles() external { uint256 roleBitmap = EACBaseRolesLib.ALL_ROLES; uint256 resource = PermissionedResolverLib.resource(NameCoder.namehash(testName, 0), 0); vm.expectEmit(); emit PermissionedResolver.NamedResource(resource, testName); vm.prank(owner); - resolver.grantNameRoles(testName, roleBitmap, friend); - assertTrue(resolver.hasRoles(resource, roleBitmap, friend)); + assertTrue(resolver.authorizeNameRoles(testName, roleBitmap, friend, true), "grant"); + assertTrue(resolver.hasRoles(resource, roleBitmap, friend), "granted"); + + vm.prank(owner); + assertTrue(resolver.authorizeNameRoles(testName, roleBitmap, friend, false), "revoked"); + assertFalse(resolver.hasRoles(resource, roleBitmap, friend), "revoked"); + } + + function test_authorizeNameRoles_root() external { + bytes memory name = NameCoder.encode(""); + uint256 roleBitmap = EACBaseRolesLib.ALL_ROLES; + vm.prank(owner); + assertTrue(resolver.authorizeNameRoles(name, roleBitmap, friend, true), "grant"); + assertTrue(resolver.hasRootRoles(roleBitmap, friend), "granted"); + + vm.prank(owner); + assertTrue(resolver.authorizeNameRoles(name, roleBitmap, friend, false), "revoke"); + assertFalse(resolver.hasRootRoles(roleBitmap, friend), "revoked"); } - function test_grantNameRoles_notAuthorized() external { + function test_authorizeNameRoles_notAuthorized() external { uint256 roleBitmap = EACBaseRolesLib.ALL_ROLES; vm.expectRevert( abi.encodeWithSelector( @@ -242,27 +358,52 @@ contract PermissionedResolverTest is Test { ) ); vm.prank(friend); - resolver.grantNameRoles(testName, roleBitmap, owner); + resolver.authorizeNameRoles(testName, roleBitmap, owner, true); } - function test_grantTextRoles() external { - uint256 resource = PermissionedResolverLib.resource( - NameCoder.namehash(testName, 0), - PermissionedResolverLib.textPart(testString) - ); + //////////////////////////////////////////////////////////////////////// + // authorizeTextRoles() + //////////////////////////////////////////////////////////////////////// + + function test_authorizeTextRoles(string calldata key) external { + uint256 resource = + PermissionedResolverLib.resource( + NameCoder.namehash(testName, 0), + PermissionedResolverLib.partHash(key) + ); vm.expectEmit(); - emit PermissionedResolver.NamedTextResource( - resource, - testName, - keccak256(bytes(testString)), - testString - ); + emit PermissionedResolver.NamedTextResource(resource, testName, keccak256(bytes(key)), key); vm.prank(owner); - resolver.grantTextRoles(testName, testString, friend); + resolver.authorizeTextRoles(testName, key, friend, true); assertTrue(resolver.hasRoles(resource, PermissionedResolverLib.ROLE_SET_TEXT, friend)); + + vm.prank(owner); + resolver.authorizeTextRoles(testName, key, friend, false); + assertFalse(resolver.hasRoles(resource, PermissionedResolverLib.ROLE_SET_TEXT, friend)); } - function test_grantTextRoles_notAuthorized() external { + function test_authorizeTextRoles_anyName() external { + vm.prank(owner); + resolver.authorizeTextRoles(NameCoder.encode(""), testString, friend, true); + vm.prank(owner); + resolver.authorizeTextRoles(NameCoder.encode(""), testString, friend, false); + } + + function test_authorizeTextRoles_notRoot() external { + vm.prank(owner); + resolver.authorizeNameRoles( + testName, + PermissionedResolverLib.ROLE_SET_TEXT_ADMIN, + actor, + true + ); + vm.prank(actor); + resolver.authorizeTextRoles(testName, testString, friend, true); + vm.prank(actor); + resolver.authorizeTextRoles(testName, testString, friend, false); + } + + function test_authorizeTextRoles_notAuthorized() external { vm.expectRevert( abi.encodeWithSelector( IEnhancedAccessControl.EACCannotGrantRoles.selector, @@ -272,22 +413,54 @@ contract PermissionedResolverTest is Test { ) ); vm.prank(friend); - resolver.grantTextRoles(testName, testString, owner); + resolver.authorizeTextRoles(testName, testString, owner, true); } - function test_grantAddrRoles(uint256 coinType) external { - uint256 resource = PermissionedResolverLib.resource( - NameCoder.namehash(testName, 0), - PermissionedResolverLib.addrPart(coinType) - ); + //////////////////////////////////////////////////////////////////////// + // authorizeAddrRoles(), and authorizeDataRoles() + //////////////////////////////////////////////////////////////////////// + + function test_authorizeAddrRoles(uint256 coinType) external { + uint256 resource = + PermissionedResolverLib.resource( + NameCoder.namehash(testName, 0), + PermissionedResolverLib.partHash(coinType) + ); vm.expectEmit(); emit PermissionedResolver.NamedAddrResource(resource, testName, coinType); vm.prank(owner); - resolver.grantAddrRoles(testName, coinType, friend); + resolver.authorizeAddrRoles(testName, coinType, friend, true); assertTrue(resolver.hasRoles(resource, PermissionedResolverLib.ROLE_SET_ADDR, friend)); + + vm.prank(owner); + resolver.authorizeAddrRoles(testName, coinType, friend, false); + assertFalse(resolver.hasRoles(resource, PermissionedResolverLib.ROLE_SET_ADDR, friend)); } - function test_grantAddrRoles_notAuthorized() external { + function test_authorizeAddrRoles_anyName() external { + uint256 coinType = 0; + vm.prank(owner); + resolver.authorizeAddrRoles(NameCoder.encode(""), coinType, friend, true); + vm.prank(owner); + resolver.authorizeAddrRoles(NameCoder.encode(""), coinType, friend, false); + } + + function test_authorizeAddrRoles_notRoot() external { + uint256 coinType = 0; + vm.prank(owner); + resolver.authorizeNameRoles( + testName, + PermissionedResolverLib.ROLE_SET_ADDR_ADMIN, + actor, + true + ); + vm.prank(actor); + resolver.authorizeAddrRoles(testName, coinType, friend, true); + vm.prank(actor); + resolver.authorizeAddrRoles(testName, coinType, friend, false); + } + + function test_authorizeAddrRoles_notAuthorized() external { vm.expectRevert( abi.encodeWithSelector( IEnhancedAccessControl.EACCannotGrantRoles.selector, @@ -297,58 +470,62 @@ contract PermissionedResolverTest is Test { ) ); vm.prank(friend); - resolver.grantAddrRoles(testName, 0, owner); + resolver.authorizeAddrRoles(testName, 0, owner, true); } //////////////////////////////////////////////////////////////////////// - // revokeRoles() [corresponding to granters above] + // authorizeDataRoles() //////////////////////////////////////////////////////////////////////// - function test_revokeRoles_name() external { - uint256 roleBitmap = EACBaseRolesLib.ALL_ROLES; + function test_authorizeDataRoles(string calldata key) external { + uint256 resource = + PermissionedResolverLib.resource( + NameCoder.namehash(testName, 0), + PermissionedResolverLib.partHash(key) + ); + vm.expectEmit(); + emit PermissionedResolver.NamedDataResource(resource, testName, keccak256(bytes(key)), key); vm.prank(owner); - resolver.grantNameRoles(testName, roleBitmap, friend); + resolver.authorizeDataRoles(testName, key, friend, true); + assertTrue(resolver.hasRoles(resource, PermissionedResolverLib.ROLE_SET_DATA, friend)); + vm.prank(owner); - assertTrue( - resolver.revokeRoles( - PermissionedResolverLib.resource(NameCoder.namehash(testName, 0), 0), - roleBitmap, - friend - ) - ); + resolver.authorizeDataRoles(testName, key, friend, false); + assertFalse(resolver.hasRoles(resource, PermissionedResolverLib.ROLE_SET_DATA, friend)); } - function test_revokeRoles_text() external { + function test_authorizeDataRoles_anyName() external { vm.prank(owner); - resolver.grantTextRoles(testName, testString, friend); + resolver.authorizeDataRoles(NameCoder.encode(""), testString, friend, true); vm.prank(owner); - assertTrue( - resolver.revokeRoles( - PermissionedResolverLib.resource( - NameCoder.namehash(testName, 0), - PermissionedResolverLib.textPart(testString) - ), - PermissionedResolverLib.ROLE_SET_TEXT, - friend - ) - ); + resolver.authorizeDataRoles(NameCoder.encode(""), testString, friend, false); } - function test_revokeRoles_addr() external { - uint256 coinType = 0; + function test_authorizeDataRoles_notRoot() external { vm.prank(owner); - resolver.grantAddrRoles(testName, coinType, friend); - vm.prank(owner); - assertTrue( - resolver.revokeRoles( - PermissionedResolverLib.resource( - NameCoder.namehash(testName, 0), - PermissionedResolverLib.addrPart(coinType) - ), - PermissionedResolverLib.ROLE_SET_ADDR, + resolver.authorizeNameRoles( + testName, + PermissionedResolverLib.ROLE_SET_DATA_ADMIN, + actor, + true + ); + vm.prank(actor); + resolver.authorizeDataRoles(testName, testString, friend, true); + vm.prank(actor); + resolver.authorizeDataRoles(testName, testString, friend, false); + } + + function test_authorizeDataRoles_notAuthorized() external { + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACCannotGrantRoles.selector, + PermissionedResolverLib.resource(NameCoder.namehash(testName, 0), 0), + PermissionedResolverLib.ROLE_SET_DATA, friend ) ); + vm.prank(friend); + resolver.authorizeDataRoles(testName, testString, owner, true); } //////////////////////////////////////////////////////////////////////// @@ -376,10 +553,8 @@ contract PermissionedResolverTest is Test { assertEq(resolver.addr(testNode), a, "immediate"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(IAddrResolver.addr, (bytes32(0))) - ); + bytes memory result = + resolver.resolve(testName, abi.encodeCall(IAddrResolver.addr, (bytes32(0)))); assertEq(result, abi.encode(a), "extended"); } @@ -394,10 +569,8 @@ contract PermissionedResolverTest is Test { assertEq(resolver.addr(testNode, coinType), a, "immediate"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(IAddressResolver.addr, (bytes32(0), coinType)) - ); + bytes memory result = + resolver.resolve(testName, abi.encodeCall(IAddressResolver.addr, (bytes32(0), coinType))); assertEq(result, abi.encode(a), "extended"); } @@ -419,10 +592,11 @@ contract PermissionedResolverTest is Test { assertTrue(resolver.hasAddr(testNode, COIN_TYPE_ETH), "null"); assertFalse(resolver.hasAddr(testNode, COIN_TYPE_DEFAULT), "unset"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(IHasAddressResolver.hasAddr, (bytes32(0), COIN_TYPE_ETH)) - ); + bytes memory result = + resolver.resolve( + testName, + abi.encodeCall(IHasAddressResolver.hasAddr, (bytes32(0), COIN_TYPE_ETH)) + ); assertEq(result, abi.encode(true), "extended"); } @@ -452,14 +626,14 @@ contract PermissionedResolverTest is Test { function test_setAddr_invalidEVM_tooShort() external { bytes memory v = new bytes(19); - vm.expectRevert(abi.encodeWithSelector(PermissionedResolver.InvalidEVMAddress.selector, v)); + vm.expectRevert(abi.encodeWithSelector(IPermissionedResolver.InvalidEVMAddress.selector, v)); vm.prank(owner); resolver.setAddr(testNode, COIN_TYPE_ETH, v); } function test_setAddr_invalidEVM_tooLong() external { bytes memory v = new bytes(21); - vm.expectRevert(abi.encodeWithSelector(PermissionedResolver.InvalidEVMAddress.selector, v)); + vm.expectRevert(abi.encodeWithSelector(IPermissionedResolver.InvalidEVMAddress.selector, v)); vm.prank(owner); resolver.setAddr(testNode, COIN_TYPE_ETH, v); } @@ -476,6 +650,31 @@ contract PermissionedResolverTest is Test { resolver.setAddr(testNode, COIN_TYPE_ETH, ""); } + function test_setData(string calldata key, bytes calldata value) external { + vm.expectEmit(); + emit IDataResolver.DataChanged(testNode, key, key, value); + vm.prank(owner); + resolver.setData(testNode, key, value); + + assertEq(resolver.data(testNode, key), value, "immediate"); + + bytes memory result = + resolver.resolve(testName, abi.encodeCall(IDataResolver.data, (bytes32(0), key))); + assertEq(result, abi.encode(value), "extended"); + } + + function test_setData_notAuthorized() external { + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + PermissionedResolverLib.resource(testNode, 0), + PermissionedResolverLib.ROLE_SET_DATA, + address(this) + ) + ); + resolver.setData(testNode, testString, ""); + } + function test_setText(string calldata key, string calldata value) external { vm.expectEmit(); emit ITextResolver.TextChanged(testNode, key, key, value); @@ -484,10 +683,8 @@ contract PermissionedResolverTest is Test { assertEq(resolver.text(testNode, key), value, "immediate"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(ITextResolver.text, (bytes32(0), key)) - ); + bytes memory result = + resolver.resolve(testName, abi.encodeCall(ITextResolver.text, (bytes32(0), key))); assertEq(result, abi.encode(value), "extended"); } @@ -511,10 +708,8 @@ contract PermissionedResolverTest is Test { assertEq(resolver.name(testNode), name, "immediate"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(INameResolver.name, (bytes32(0))) - ); + bytes memory result = + resolver.resolve(testName, abi.encodeCall(INameResolver.name, (bytes32(0)))); assertEq(result, abi.encode(name), "extended"); } @@ -538,10 +733,11 @@ contract PermissionedResolverTest is Test { assertEq(resolver.contenthash(testNode), v, "immediate"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(IContentHashResolver.contenthash, (bytes32(0))) - ); + bytes memory result = + resolver.resolve( + testName, + abi.encodeCall(IContentHashResolver.contenthash, (bytes32(0))) + ); assertEq(result, abi.encode(v), "extended"); } @@ -566,10 +762,8 @@ contract PermissionedResolverTest is Test { (bytes32 x_, bytes32 y_) = resolver.pubkey(testNode); assertEq(abi.encode(x_, y_), abi.encode(x, y), "immediate"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(IPubkeyResolver.pubkey, (bytes32(0))) - ); + bytes memory result = + resolver.resolve(testName, abi.encodeCall(IPubkeyResolver.pubkey, (bytes32(0)))); assertEq(result, abi.encode(x, y), "extended"); } @@ -598,25 +792,19 @@ contract PermissionedResolverTest is Test { bytes memory expect = data.length > 0 ? abi.encode(contentType, data) : abi.encode(0, ""); assertEq(abi.encode(contentType_, data_), expect, "immediate"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(IABIResolver.ABI, (bytes32(0), contentTypes)) - ); + bytes memory result = + resolver.resolve(testName, abi.encodeCall(IABIResolver.ABI, (bytes32(0), contentTypes))); assertEq(result, expect, "extended"); } function test_setABI_invalidContentType_noBits() external { - vm.expectRevert( - abi.encodeWithSelector(PermissionedResolver.InvalidContentType.selector, 0) - ); + vm.expectRevert(abi.encodeWithSelector(IPermissionedResolver.InvalidContentType.selector, 0)); vm.prank(owner); resolver.setABI(testNode, 0, ""); } function test_setABI_invalidContentType_manyBits() external { - vm.expectRevert( - abi.encodeWithSelector(PermissionedResolver.InvalidContentType.selector, 3) - ); + vm.expectRevert(abi.encodeWithSelector(IPermissionedResolver.InvalidContentType.selector, 3)); vm.prank(owner); resolver.setABI(testNode, 3, ""); } @@ -643,25 +831,29 @@ contract PermissionedResolverTest is Test { assertEq(resolver.interfaceImplementer(testNode, interfaceId), impl, "immediate"); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(IInterfaceResolver.interfaceImplementer, (bytes32(0), interfaceId)) - ); + bytes memory result = + resolver.resolve( + testName, + abi.encodeCall(IInterfaceResolver.interfaceImplementer, (bytes32(0), interfaceId)) + ); assertEq(result, abi.encode(impl), "extended"); } - function test_interfaceImplementer_overlap() external { + function test_interfaceImplementer_withPointer() external { + MockInterface c = new MockInterface(); + assertTrue(ERC165Checker.supportsInterface(address(c), TEST_SELECTOR)); + vm.prank(owner); - resolver.setAddr(testNode, COIN_TYPE_ETH, abi.encodePacked(resolver)); + resolver.setAddr(testNode, COIN_TYPE_ETH, abi.encodePacked(c)); - I[] memory v = _supportedInterfaces(); - for (uint256 i; i < v.length; ++i) { - assertEq( - resolver.interfaceImplementer(testNode, v[i].interfaceId), - address(resolver), - v[i].name + assertEq(resolver.interfaceImplementer(testNode, TEST_SELECTOR), address(c), "immediate"); + + bytes memory result = + resolver.resolve( + testName, + abi.encodeCall(IInterfaceResolver.interfaceImplementer, (bytes32(0), TEST_SELECTOR)) ); - } + assertEq(result, abi.encode(c), "extended"); } function test_setInterface_notAuthorized() external { @@ -732,10 +924,8 @@ contract PermissionedResolverTest is Test { answers[2] = abi.encode(testString); answers[3] = abi.encode(testAddress); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(PermissionedResolver.multicall, (calls)) - ); + bytes memory result = + resolver.resolve(testName, abi.encodeCall(PermissionedResolver.multicall, (calls))); assertEq(result, abi.encode(answers)); } @@ -743,23 +933,19 @@ contract PermissionedResolverTest is Test { vm.prank(owner); resolver.setName(testNode, testString); - bytes4 selector = 0x12345678; - bytes[] memory calls = new bytes[](2); calls[0] = abi.encodeCall(INameResolver.name, (testNode)); - calls[1] = abi.encodeWithSelector(selector, selector); + calls[1] = abi.encodeWithSelector(TEST_SELECTOR); bytes[] memory answers = new bytes[](calls.length); answers[0] = abi.encode(testString); answers[1] = abi.encodeWithSelector( - PermissionedResolver.UnsupportedResolverProfile.selector, - selector + IPermissionedResolver.UnsupportedResolverProfile.selector, + TEST_SELECTOR ); - bytes memory result = resolver.resolve( - testName, - abi.encodeCall(PermissionedResolver.multicall, (calls)) - ); + bytes memory result = + resolver.resolve(testName, abi.encodeCall(PermissionedResolver.multicall, (calls))); assertEq(result, abi.encode(answers)); } @@ -780,7 +966,7 @@ contract PermissionedResolverTest is Test { resolver.setText(testNode, testString, "A"); vm.prank(owner); - resolver.grantTextRoles(NameCoder.encode(""), testString, friend); + resolver.authorizeTextRoles(NameCoder.encode(""), testString, friend, true); vm.prank(friend); resolver.setText(testNode, testString, "B"); @@ -813,7 +999,7 @@ contract PermissionedResolverTest is Test { resolver.setText(testNode, testString, "A"); vm.prank(owner); - resolver.grantTextRoles(testName, testString, friend); + resolver.authorizeTextRoles(testName, testString, friend, true); vm.prank(friend); resolver.setText(testNode, testString, "B"); @@ -830,6 +1016,69 @@ contract PermissionedResolverTest is Test { resolver.setText(~testNode, testString, "C"); } + function test_setData_anyNode_onePart() external { + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + PermissionedResolverLib.resource(testNode, 0), + PermissionedResolverLib.ROLE_SET_DATA, + friend + ) + ); + vm.prank(friend); + resolver.setData(testNode, testString, "A"); + + vm.prank(owner); + resolver.authorizeDataRoles(NameCoder.encode(""), testString, friend, true); + + vm.prank(friend); + resolver.setData(testNode, testString, "B"); + + vm.prank(friend); + resolver.setData(~testNode, testString, "C"); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + PermissionedResolverLib.resource(testNode, 0), + PermissionedResolverLib.ROLE_SET_DATA, + friend + ) + ); + vm.prank(friend); + resolver.setData(testNode, string.concat(testString, testString), "D"); + } + + function test_setData_oneNode_onePart() external { + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + PermissionedResolverLib.resource(testNode, 0), + PermissionedResolverLib.ROLE_SET_DATA, + friend + ) + ); + vm.prank(friend); + resolver.setData(testNode, testString, "A"); + + vm.prank(owner); + resolver.authorizeDataRoles(testName, testString, friend, true); + + vm.prank(friend); + resolver.setData(testNode, testString, "B"); + + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + PermissionedResolverLib.resource(~testNode, 0), + PermissionedResolverLib.ROLE_SET_DATA, + friend + ) + ); + vm.prank(friend); + resolver.setData(~testNode, testString, "C"); + } + function test_setAddr_anyNode_onePart() external { uint256 coinType = 0; vm.expectRevert( @@ -844,7 +1093,7 @@ contract PermissionedResolverTest is Test { resolver.setAddr(testNode, coinType, hex"01"); vm.prank(owner); - resolver.grantAddrRoles(NameCoder.encode(""), coinType, friend); + resolver.authorizeAddrRoles(NameCoder.encode(""), coinType, friend, true); vm.prank(friend); resolver.setAddr(testNode, coinType, hex"02"); @@ -878,7 +1127,7 @@ contract PermissionedResolverTest is Test { resolver.setAddr(testNode, coinType, hex"01"); vm.prank(owner); - resolver.grantAddrRoles(testName, coinType, friend); + resolver.authorizeAddrRoles(testName, coinType, friend, true); vm.prank(friend); resolver.setAddr(testNode, coinType, hex"02"); @@ -894,11 +1143,43 @@ contract PermissionedResolverTest is Test { vm.prank(friend); resolver.setAddr(~testNode, coinType, hex"03"); } + + //////////////////////////////////////////////////////////////////////// + // IContractNamer + //////////////////////////////////////////////////////////////////////// + + function test_implementationIsNameable() external view { + assertTrue(implementation.isContractNamer(address(this))); + } + + function test_isContractNamer() external { + assertTrue(resolver.isContractNamer(owner)); + assertFalse(resolver.isContractNamer(friend), "before"); + + vm.prank(owner); + resolver.grantRootRoles(PermissionedResolverLib.ROLE_CAN_NAME, friend); + assertTrue(resolver.isContractNamer(friend), "granted"); + + vm.prank(owner); + resolver.revokeRootRoles(PermissionedResolverLib.ROLE_CAN_NAME, friend); + assertFalse(resolver.isContractNamer(friend), "revoked"); + } } -contract MockUpgrade is UUPSUpgradeable { + +contract MockUpgrade is UUPSUpgradeable, IProxyAuthorization { function addr(bytes32) external pure returns (address) { return address(1); } + function canUpgradeFrom(address) external pure returns (bool) { + return true; + } function _authorizeUpgrade(address) internal override {} } + + +contract MockInterface is ERC165 { + function supportsInterface(bytes4 interfaceId) public view override returns (bool) { + return interfaceId == TEST_SELECTOR || super.supportsInterface(interfaceId); + } +} diff --git a/contracts/test/unit/resolver/PublicResolverV2.t.sol b/contracts/test/unit/resolver/PublicResolverV2.t.sol new file mode 100755 index 000000000..1b6902216 --- /dev/null +++ b/contracts/test/unit/resolver/PublicResolverV2.t.sol @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {IMulticallable} from "@ens/contracts/resolvers/IMulticallable.sol"; +import {IABIResolver} from "@ens/contracts/resolvers/profiles/IABIResolver.sol"; +import {IAddressResolver} from "@ens/contracts/resolvers/profiles/IAddressResolver.sol"; +import {IAddrResolver} from "@ens/contracts/resolvers/profiles/IAddrResolver.sol"; +import {IContentHashResolver} from "@ens/contracts/resolvers/profiles/IContentHashResolver.sol"; +import {IDNSRecordResolver} from "@ens/contracts/resolvers/profiles/IDNSRecordResolver.sol"; +import {IDNSZoneResolver} from "@ens/contracts/resolvers/profiles/IDNSZoneResolver.sol"; +import {IDataResolver} from "@ens/contracts/resolvers/profiles/IDataResolver.sol"; +import {IHasAddressResolver} from "@ens/contracts/resolvers/profiles/IHasAddressResolver.sol"; +import {IInterfaceResolver} from "@ens/contracts/resolvers/profiles/IInterfaceResolver.sol"; +import {INameResolver} from "@ens/contracts/resolvers/profiles/INameResolver.sol"; +import {IPubkeyResolver} from "@ens/contracts/resolvers/profiles/IPubkeyResolver.sol"; +import {ITextResolver} from "@ens/contracts/resolvers/profiles/ITextResolver.sol"; + +import {PublicResolverV2} from "~src/resolver/PublicResolverV2.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {V1Fixture} from "~test/fixtures/V1Fixture.sol"; +import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; + +contract PublicResolverV2Test is V1Fixture, V2Fixture { + PublicResolverV2 publicResolver; + + address actor = makeAddr("actor"); + address friend = makeAddr("friend"); + + function setUp() external { + deployV1Fixture(); + deployV2Fixture(); + publicResolver = new PublicResolverV2(nameWrapper, rootRegistry, contractNamer); + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IMulticallable).interfaceId + ), + "IMulticallable" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IContractNamer).interfaceId + ), + "IContractNamer" + ); + + // profiles + assertTrue( + ERC165Checker.supportsInterface(address(publicResolver), type(IABIResolver).interfaceId), + "IABIResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(publicResolver), type(IAddrResolver).interfaceId), + "IAddrResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IAddressResolver).interfaceId + ), + "IAddressResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IContentHashResolver).interfaceId + ), + "IContentHashResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(publicResolver), type(IDataResolver).interfaceId), + "IDataResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IDNSRecordResolver).interfaceId + ), + "IDNSRecordResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IDNSZoneResolver).interfaceId + ), + "IDNSZoneResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IHasAddressResolver).interfaceId + ), + "IHasAddressResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IInterfaceResolver).interfaceId + ), + "IInterfaceResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(publicResolver), type(INameResolver).interfaceId), + "INameResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(publicResolver), + type(IPubkeyResolver).interfaceId + ), + "IPubkeyResolver" + ); + assertTrue( + ERC165Checker.supportsInterface(address(publicResolver), type(ITextResolver).interfaceId), + "ITextResolver" + ); + } + + function test_canModifyName() external { + bytes32 node = _register("test"); + + // call a setter + vm.prank(testOwner); + publicResolver.setAddr(node, testOwner); + } + + function test_canModifyName_setApprovalForAll() external { + bytes32 node = _register("test"); + + vm.prank(testOwner); + publicResolver.setApprovalForAll(friend, true); + + assertTrue(publicResolver.canModifyName(node, friend)); + + // call a setter + vm.prank(friend); + publicResolver.setAddr(node, testOwner); + } + + function test_canModifyName_approve() external { + bytes32 node = _register("test"); + + vm.prank(testOwner); + publicResolver.approve(node, friend, true); + + assertTrue(publicResolver.canModifyName(node, friend)); + assertFalse(publicResolver.canModifyName(~node, friend)); + + // call a setter + vm.prank(friend); + publicResolver.setAddr(node, testOwner); + } + + function test_canModifyName_notAuthorized(bytes32 node) external { + assertFalse(publicResolver.canModifyName(node, testOwner)); + + // call a setter + vm.expectRevert(); + vm.prank(actor); + publicResolver.setAddr(node, testOwner); + } + + //////////////////////////////////////////////////////////////////////// + // Approval + //////////////////////////////////////////////////////////////////////// + + function test_isApprovedForAll() external { + assertFalse(publicResolver.isApprovedForAll(testOwner, friend)); + + vm.expectEmit(); + emit PublicResolverV2.ApprovalForAll(testOwner, friend, true); + vm.prank(testOwner); + publicResolver.setApprovalForAll(friend, true); + + assertTrue(publicResolver.isApprovedForAll(testOwner, friend), "friend"); + assertFalse(publicResolver.isApprovedForAll(testOwner, actor), "actor"); + } + + function test_isApprovedFor(bytes32 node) external { + assertFalse(publicResolver.isApprovedFor(testOwner, node, friend)); + + vm.expectEmit(); + emit PublicResolverV2.Approved(testOwner, node, friend, true); + vm.prank(testOwner); + publicResolver.approve(node, friend, true); + + assertTrue(publicResolver.isApprovedFor(testOwner, node, friend), "friend"); + assertFalse(publicResolver.isApprovedFor(testOwner, ~node, friend), "other node"); + assertFalse(publicResolver.isApprovedFor(testOwner, node, actor), "other actor"); + } + + //////////////////////////////////////////////////////////////////////// + // Helpers + //////////////////////////////////////////////////////////////////////// + + function _register(string memory label) internal returns (bytes32 node) { + // register wrapped name in v1 + bytes memory name = registerWrappedETH2LD(label, 0); + node = NameCoder.namehash(name, 0); + + assertFalse(publicResolver.canModifyName(node, testOwner), "before"); + + // register same name in v2 + ethRegistry.register( + label, + testOwner, + IRegistry(address(0)), + address(publicResolver), + 0, + uint64(block.timestamp + 1 days) + ); + + assertTrue(publicResolver.canModifyName(node, testOwner), "after"); + } +} diff --git a/contracts/test/unit/resolver/libraries/ResolverProfileRewriterLib.t.sol b/contracts/test/unit/resolver/libraries/ResolverProfileRewriterLib.t.sol index 335082a9d..62331fc6c 100755 --- a/contracts/test/unit/resolver/libraries/ResolverProfileRewriterLib.t.sol +++ b/contracts/test/unit/resolver/libraries/ResolverProfileRewriterLib.t.sol @@ -1,54 +1,132 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; -// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file - import {Test} from "forge-std/Test.sol"; import {IMulticallable} from "@ens/contracts/resolvers/IMulticallable.sol"; -import {IAddressResolver} from "@ens/contracts/resolvers/profiles/IAddressResolver.sol"; -import { - ResolverProfileRewriterLib -} from "~src/resolver/libraries/ResolverProfileRewriterLib.sol"; +import {ResolverProfileRewriterLib} from "~src/resolver/libraries/ResolverProfileRewriterLib.sol"; contract ResolverProfileRewriterLibTest is Test { - function replaceNode(bytes calldata call, bytes32 node) public pure returns (bytes memory) { + bytes vMin = abi.encodeCall(this.resolverProfile, bytes32(0)); // 36 bytes + bytes vBad = new bytes(vMin.length - 1); + + function resolverProfile(bytes32) external {} + + function replaceNode(bytes calldata call, bytes32 node) external pure returns (bytes memory) { return ResolverProfileRewriterLib.replaceNode(call, node); } - function drop4(bytes calldata v) public pure returns (bytes memory) { + function drop4(bytes calldata v) external pure returns (bytes memory) { return v[4:]; } - function testFuzz_replaceNode_call(bytes32 node, uint256 coinType) external view { - (bytes32 x, uint256 c) = abi.decode( - this.drop4( - this.replaceNode( - abi.encodeCall(IAddressResolver.addr, (keccak256("a"), coinType)), - node - ) + function testFuzz_replaceNode_call(bytes32 node) external view { + assertEq( + abi.decode( + this.drop4( + this.replaceNode(abi.encodeCall(this.resolverProfile, (keccak256("a"))), node) + ), + (bytes32) ), - (bytes32, uint256) + node ); - assertEq(x, node, "node"); - assertEq(c, coinType, "coinType"); + } + + function test_replaceNode_call_smallestWrite(bytes32 node) external view { + assertEq(bytes32(this.drop4(this.replaceNode(vMin, node))), node); + } + + function test_replaceNode_call_outOfBounds(bytes32 node) external view { + assertEq(this.replaceNode(vBad, node), vBad); // unchanged } function testFuzz_replaceNode_multicall(bytes32 node, uint8 calls) external view { bytes[] memory m = new bytes[](calls); for (uint256 i; i < calls; i++) { - m[i] = abi.encodeCall(IAddressResolver.addr, (keccak256("a"), i)); + m[i] = abi.encodeCall(this.resolverProfile, (keccak256("a"))); } m = abi.decode( this.drop4(this.replaceNode(abi.encodeCall(IMulticallable.multicall, (m)), node)), (bytes[]) ); - assertEq(m.length, calls, "count"); + assertEq(m.length, calls); for (uint256 i; i < calls; i++) { - (bytes32 x, uint256 c) = abi.decode(this.drop4(m[i]), (bytes32, uint256)); - assertEq(x, node, "node"); - assertEq(c, i, "coinType"); + assertEq(abi.decode(this.drop4(m[i]), (bytes32)), node); + } + } + + function test_replaceNode_multicall_smallestWrite(bytes32 node) external view { + bytes[] memory m = new bytes[](1); + m[0] = vMin; + m = abi.decode( + this.drop4(this.replaceNode(abi.encodeCall(IMulticallable.multicall, (m)), node)), + (bytes[]) + ); + assertEq(bytes32(this.drop4(m[0])), node); + } + + function test_replaceNode_multicall_outOfBounds(bytes32 node) external view { + bytes[] memory m = new bytes[](1); + m[0] = vBad; + bytes memory v0 = abi.encodeCall(IMulticallable.multicall, (m)); + bytes memory v = this.replaceNode(v0, node); + assertEq(v0, v); // unchanged + } + + function test_replaceNode_multicall_outOfBounds_arrayStart(bytes32 node) external view { + bytes[] memory m = new bytes[](1); + m[0] = vMin; + bytes memory v0 = abi.encodeCall(IMulticallable.multicall, (m)); + uint256 offset = 100; // offset of first element + uint256 save; + bytes memory v = abi.encodePacked(v0); + assembly { + save := mload(add(v, offset)) + mstore(add(v, offset), mload(v)) // mangle + } + v = this.replaceNode(v, node); + assembly { + mstore(add(v, offset), save) // unmangle + } + assertEq(v0, v); // unchanged + } + + function test_replaceNode_multicall_underflow(bytes32 node) external view { + bytes[] memory m = new bytes[](1); + m[0] = vMin; + bytes memory v0 = abi.encodeCall(IMulticallable.multicall, (m)); + assembly { + mstore(add(v0, 36), not(0)) // jump backwards + } + bytes memory v = this.replaceNode(v0, node); + assertEq(v0, v); // unchanged + } + + function test_replaceNode_multicall_underflow_arrayStart(bytes32 node) external view { + bytes[] memory m = new bytes[](1); + m[0] = vMin; + bytes memory v0 = abi.encodeCall(IMulticallable.multicall, (m)); + assembly { + mstore(add(v0, 100), not(0)) // jump backwards + } + bytes memory v = this.replaceNode(v0, node); + assertEq(v0, v); // unchanged + } + + function testFuzz_replaceNode_nestedMulticall(bytes32 node, uint8 depth) external view { + vm.assume(depth < 10); + bytes memory v = abi.encodeCall(this.resolverProfile, (keccak256("a"))); + bytes[] memory m = new bytes[](1); + for (uint256 i; i < depth; ++i) { + m[0] = v; + v = abi.encodeCall(IMulticallable.multicall, (m)); + } + v = this.replaceNode(v, node); + for (uint256 i; i < depth; ++i) { + m = abi.decode(this.drop4(v), (bytes[])); + v = m[0]; } + assertEq(abi.decode(this.drop4(v), (bytes32)), node); } } diff --git a/contracts/test/unit/reverse-registrar/DefaultReverseRegistrarAdapter.t.sol b/contracts/test/unit/reverse-registrar/DefaultReverseRegistrarAdapter.t.sol new file mode 100644 index 000000000..654ae5d65 --- /dev/null +++ b/contracts/test/unit/reverse-registrar/DefaultReverseRegistrarAdapter.t.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// solhint-disable private-vars-leading-underscore, state-visibility, func-name-mixedcase + +import {Test} from "forge-std/Test.sol"; + +import {DefaultReverseRegistrar} from "@ens/contracts/reverseRegistrar/DefaultReverseRegistrar.sol"; +import {MockOwnable} from "@ens/contracts/test/mocks/MockOwnable.sol"; + +import { + DefaultReverseRegistrarAdapter +} from "~src/reverse-registrar/DefaultReverseRegistrarAdapter.sol"; +import {MockContractNamer} from "~test/mocks/MockContractNamer.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; + +contract DefaultReverseRegistrarAdapterTest is Test { + DefaultReverseRegistrar defaultReverseRegistrar; + DefaultReverseRegistrarAdapter defaultAdapter; + + address owner = makeAddr("owner"); + string name = "primary.eth"; + + function setUp() external { + defaultReverseRegistrar = new DefaultReverseRegistrar(); + defaultAdapter = new DefaultReverseRegistrarAdapter( + defaultReverseRegistrar, + IContractNamer(address(0)) + ); + + defaultReverseRegistrar.setController(address(defaultAdapter), true); + } + + function test_constructor() external view { + assertEq( + address(defaultAdapter.DEFAULT_REVERSE_REGISTRAR()), + address(defaultReverseRegistrar), + "DEFAULT_REVERSE_REGISTRAR" + ); + } + + function test_setName_EOA() external { + vm.prank(owner); + defaultAdapter.setName(owner, name); + + assertEq(defaultReverseRegistrar.nameForAddr(owner), name); + } + + function test_setName_Ownable() external { + MockOwnable c = new MockOwnable(owner); + + vm.prank(owner); + defaultAdapter.setName(address(c), name); + + assertEq(defaultReverseRegistrar.nameForAddr(address(c)), name); + } + + function test_setName_IContractNamer() external { + MockContractNamer c = new MockContractNamer(owner); + + vm.prank(owner); + defaultAdapter.setName(address(c), name); + + assertEq(defaultReverseRegistrar.nameForAddr(address(c)), name); + } +} diff --git a/contracts/test/unit/reverse-registrar/L2ReverseRegistrar.t.sol b/contracts/test/unit/reverse-registrar/L2ReverseRegistrar.t.sol new file mode 100644 index 000000000..7f6579c01 --- /dev/null +++ b/contracts/test/unit/reverse-registrar/L2ReverseRegistrar.t.sol @@ -0,0 +1,1495 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, namechain/ordering, one-contract-per-file, namechain/import-order-separation, gas-small-strings, gas-strict-inequalities, gas-increment-by-one, gas-custom-errors + +import {Test} from "forge-std/Test.sol"; + +import {IExtendedResolver} from "@ens/contracts/resolvers/profiles/IExtendedResolver.sol"; +import {INameResolver} from "@ens/contracts/resolvers/profiles/INameResolver.sol"; +import {MockSmartContractWallet} from "@ens/contracts/test/mocks/MockSmartContractWallet.sol"; +import {MockOwnable} from "@ens/contracts/test/mocks/MockOwnable.sol"; +import {MockERC6492WalletFactory} from "@ens/contracts/test/mocks/MockERC6492WalletFactory.sol"; +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +import {LibString} from "~src/utils/LibString.sol"; +import {LibISO8601} from "~src/utils/LibISO8601.sol"; +import {L2ReverseRegistrar} from "~src/reverse-registrar/L2ReverseRegistrar.sol"; +import {IL2ReverseRegistrar} from "~src/reverse-registrar/interfaces/IL2ReverseRegistrar.sol"; +import {IContractName} from "~src/reverse-registrar/interfaces/IContractName.sol"; +import {AccountNamerLib} from "~src/reverse-registrar/libraries/AccountNamerLib.sol"; +import {ChainIdsBuilderLib} from "~src/reverse-registrar/libraries/ChainIdsBuilderLib.sol"; + +contract L2ReverseRegistrarTest is Test { + using MessageHashUtils for bytes; + using Strings for uint256; + using Strings for address; + + // Constants matching Optimism chain setup + uint256 constant OPTIMISM_CHAIN_ID = 10; + // Coin type format: 0x80000000 | chainId (see ENSIP-11) + uint256 constant COIN_TYPE = 0x80000000 | OPTIMISM_CHAIN_ID; + string constant COIN_TYPE_LABEL = "8000000a"; + string constant PARENT_NAMESPACE = "8000000a.reverse"; + + bytes32 constant REVERSE_NODE = + 0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34; + + L2ReverseRegistrar registrar; + MockSmartContractWallet mockSca; + MockERC6492WalletFactory mockErc6492Factory; + MockOwnable mockOwnableEoa; + MockOwnable mockOwnableSca; + + // Test accounts + uint256 user1Pk = 0x1; + uint256 user2Pk = 0x2; + address user1; + address user2; + address relayer; + + function setUp() public { + // Deploy Universal Signature Validator at the expected address + _deployUniversalSigValidator(); + + user1 = vm.addr(user1Pk); + user2 = vm.addr(user2Pk); + relayer = makeAddr("relayer"); + + // Deploy the L2ReverseRegistrar + registrar = new L2ReverseRegistrar(OPTIMISM_CHAIN_ID, COIN_TYPE_LABEL); + + // Deploy mock contracts + mockSca = new MockSmartContractWallet(user1); + mockErc6492Factory = new MockERC6492WalletFactory(); + mockOwnableEoa = new MockOwnable(user1); + mockOwnableSca = new MockOwnable(address(mockSca)); + } + + function _deployUniversalSigValidator() internal { + // Deploy the actual UniversalSigValidator at the expected address + // Bytecode from: contracts/test/integration/fixtures/deployUniversalSigValidator.ts + address expectedAddress = 0x164af34fAF9879394370C7f09064127C043A35E9; + + // Use vm.etch with the runtime bytecode of the UniversalSigValidator + // This bytecode is extracted from the deployment in the TypeScript fixture + bytes memory runtimeCode = + hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806316d43401146100465780638f0684301461006d57806398ef1ed814610080575b600080fd5b61005961005436600461085e565b610093565b604051901515815260200160405180910390f35b61005961007b3660046108d2565b6105f8565b61005961008e3660046108d2565b61068e565b600073ffffffffffffffffffffffffffffffffffffffff86163b6060826020861080159061010157507f649264926492649264926492649264926492649264926492649264926492649287876100ea60208261092e565b6100f6928a929061096e565b6100ff91610998565b145b90508015610200576000606088828961011b60208261092e565b926101289392919061096e565b8101906101359190610acf565b9550909250905060008590036101f9576000808373ffffffffffffffffffffffffffffffffffffffff168360405161016d9190610b6e565b6000604051808303816000865af19150503d80600081146101aa576040519150601f19603f3d011682016040523d82523d6000602084013e6101af565b606091505b5091509150816101f657806040517f9d0d6e2d0000000000000000000000000000000000000000000000000000000081526004016101ed9190610bd4565b60405180910390fd5b50505b505061023a565b86868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b80806102465750600083115b156103d3576040517f1626ba7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a1690631626ba7e9061029f908b908690600401610bee565b602060405180830381865afa9250505080156102f6575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526102f391810190610c07565b60015b61035e573d808015610324576040519150601f19603f3d011682016040523d82523d6000602084013e610329565b606091505b50806040517f6f2a95990000000000000000000000000000000000000000000000000000000081526004016101ed9190610bd4565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f1626ba7e0000000000000000000000000000000000000000000000000000000014841580156103ae5750825b80156103b8575086155b156103c757806000526001601ffd5b94506105ef9350505050565b60418614610463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5369676e617475726556616c696461746f72237265636f7665725369676e657260448201527f3a20696e76616c6964207369676e6174757265206c656e67746800000000000060648201526084016101ed565b6000610472602082898b61096e565b61047b91610998565b9050600061048d604060208a8c61096e565b61049691610998565b90506000898960408181106104ad576104ad610c49565b919091013560f81c915050601b81148015906104cd57508060ff16601c14155b1561055a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5369676e617475726556616c696461746f723a20696e76616c6964207369676e60448201527f617475726520762076616c75650000000000000000000000000000000000000060648201526084016101ed565b6040805160008152602081018083528d905260ff831691810191909152606081018490526080810183905273ffffffffffffffffffffffffffffffffffffffff8d169060019060a0016020604051602081039080840390855afa1580156105c5573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff161496505050505050505b95945050505050565b6040517f16d4340100000000000000000000000000000000000000000000000000000000815260009030906316d4340190610640908890889088908890600190600401610c78565b6020604051808303816000875af115801561065f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106839190610cf5565b90505b949350505050565b6040517f16d4340100000000000000000000000000000000000000000000000000000000815260009030906316d43401906106d59088908890889088908890600401610c78565b6020604051808303816000875af192505050801561072e575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261072b91810190610cf5565b60015b6107db573d80801561075c576040519150601f19603f3d011682016040523d82523d6000602084013e610761565b606091505b50805160018190036107d4578160008151811061078057610780610c49565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f0100000000000000000000000000000000000000000000000000000000000000149250610686915050565b8060208301fd5b9050610686565b73ffffffffffffffffffffffffffffffffffffffff8116811461080457600080fd5b50565b60008083601f84011261081957600080fd5b50813567ffffffffffffffff81111561083157600080fd5b60208301915083602082850101111561084957600080fd5b9250929050565b801515811461080457600080fd5b60008060008060006080868803121561087657600080fd5b8535610881816107e2565b945060208601359350604086013567ffffffffffffffff8111156108a457600080fd5b6108b088828901610807565b90945092505060608601356108c481610850565b809150509295509295909350565b600080600080606085870312156108e857600080fd5b84356108f3816107e2565b935060208501359250604085013567ffffffffffffffff81111561091657600080fd5b61092287828801610807565b95989497509550505050565b81810381811115610968577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b6000808585111561097e57600080fd5b8386111561098b57600080fd5b5050820193919092039150565b80356020831015610968577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610a1457600080fd5b813567ffffffffffffffff811115610a2e57610a2e6109d4565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff82111715610a9a57610a9a6109d4565b604052818152838201602001851015610ab257600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215610ae457600080fd5b8335610aef816107e2565b9250602084013567ffffffffffffffff811115610b0b57600080fd5b610b1786828701610a03565b925050604084013567ffffffffffffffff811115610b3457600080fd5b610b4086828701610a03565b9150509250925092565b60005b83811015610b65578181015183820152602001610b4d565b50506000910152565b60008251610b80818460208701610b4a565b9190910192915050565b60008151808452610ba2816020860160208601610b4a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610be76020830184610b8a565b9392505050565b8281526040602082015260006106866040830184610b8a565b600060208284031215610c1957600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114610be757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015260806040820152826080820152828460a0830137600060a08483010152600060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116830101905082151560608301529695505050505050565b600060208284031215610d0757600080fd5b8151610be78161085056fea2646970667358221220fa1669652244780c8dcf7823a819ca1aa2abb64af0cf4d7adedb2339d4e907d964736f6c634300081a0033"; + vm.etch(expectedAddress, runtimeCode); + } + + //////////////////////////////////////////////////////////////////////// + // Helper Functions + //////////////////////////////////////////////////////////////////////// + + function _getNode(address addr) internal view returns (bytes32) { + string memory label = LibString.toAddressString(addr); + return + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + } + + function _buildDnsEncodedName(address addr) internal pure returns (bytes memory) { + string memory addrString = LibString.toAddressString(addr); + bytes memory parent = + abi.encodePacked( + uint8(bytes(COIN_TYPE_LABEL).length), + COIN_TYPE_LABEL, + uint8(7), + "reverse", + uint8(0) + ); + return abi.encodePacked(uint8(40), addrString, parent); + } + + function _chainIdsToString(uint256[] memory chainIds) internal pure returns (string memory) { + string memory result = ""; + for (uint256 i = 0; i < chainIds.length; i++) { + result = string.concat(result, chainIds[i].toString()); + if (i < chainIds.length - 1) + result = string.concat(result, ", "); + } + return result; + } + + function _createNameForAddrMessage( + string memory name_, + address addr, + uint256[] memory chainIds, + uint256 signedAt + ) + internal + pure + returns (bytes32) + { + string memory addrString = addr.toChecksumHexString(); + string memory chainIdsString = _chainIdsToString(chainIds); + string memory signedAtString = LibISO8601.toISO8601(signedAt); + + return + abi.encodePacked( + "You are setting your ENS primary name to:\n", + name_, + "\n\nAddress: ", + addrString, + "\nChains: ", + chainIdsString, + "\nSigned At: ", + signedAtString + ).toEthSignedMessageHash(); + } + + function _createNameForOwnableMessage( + string memory name_, + address contractAddress, + address owner, + uint256[] memory chainIds, + uint256 signedAt + ) + internal + pure + returns (bytes32) + { + string memory addrString = contractAddress.toChecksumHexString(); + string memory ownerString = owner.toChecksumHexString(); + string memory chainIdsString = _chainIdsToString(chainIds); + string memory signedAtString = LibISO8601.toISO8601(signedAt); + + return + abi.encodePacked( + "You are setting the ENS primary name for a contract you own to:\n", + name_, + "\n\nContract Address: ", + addrString, + "\nOwner: ", + ownerString, + "\nChains: ", + chainIdsString, + "\nSigned At: ", + signedAtString + ).toEthSignedMessageHash(); + } + + function _singleChainIdArray() internal pure returns (uint256[] memory) { + uint256[] memory chainIds = new uint256[](1); + chainIds[0] = OPTIMISM_CHAIN_ID; + return chainIds; + } + + function _multipleChainIdArray() internal pure returns (uint256[] memory) { + uint256[] memory chainIds = new uint256[](4); + chainIds[0] = 1; // ETH + chainIds[1] = OPTIMISM_CHAIN_ID; // Optimism (10) + chainIds[2] = 8453; // Base + chainIds[3] = 42161; // Arbitrum + // Must be in ascending order: 1, 10, 8453, 42161 + return chainIds; + } + + function _unsortedChainIdArray() internal pure returns (uint256[] memory) { + uint256[] memory chainIds = new uint256[](4); + chainIds[0] = 1; // ETH + chainIds[1] = 42161; // Arbitrum + chainIds[2] = OPTIMISM_CHAIN_ID; // Optimism (10) - out of order + chainIds[3] = 8453; // Base + return chainIds; + } + + function _duplicateChainIdArray() internal pure returns (uint256[] memory) { + uint256[] memory chainIds = new uint256[](3); + chainIds[0] = 1; // ETH + chainIds[1] = OPTIMISM_CHAIN_ID; // Optimism + chainIds[2] = OPTIMISM_CHAIN_ID; // Duplicate + return chainIds; + } + + function _chainIdArrayWithoutOptimism() internal pure returns (uint256[] memory) { + uint256[] memory chainIds = new uint256[](3); + chainIds[0] = 1; // ETH + chainIds[1] = 8453; // Base + chainIds[2] = 42161; // Arbitrum + // Ascending order: 1, 8453, 42161 (does not include Optimism's chain ID 10) + return chainIds; + } + + function _emptyChainIdArray() internal pure returns (uint256[] memory) { + return new uint256[](0); + } + + function _largeChainIdArray(uint256 length) internal pure returns (uint256[] memory) { + uint256[] memory chainIds = new uint256[](length); + for (uint256 i = 1; i < length; i++) { + chainIds[i] = i; + } + return chainIds; + } + + //////////////////////////////////////////////////////////////////////// + // Constructor / Immutables Tests + //////////////////////////////////////////////////////////////////////// + + function test_constructor_setChainId() public view { + assertEq(registrar.CHAIN_ID(), OPTIMISM_CHAIN_ID, "CHAIN_ID should match"); + } + + function test_constructor_setParentNode() public view { + bytes32 expectedParentNode = + keccak256(abi.encodePacked(REVERSE_NODE, keccak256(abi.encodePacked(COIN_TYPE_LABEL)))); + assertEq(registrar.PARENT_NODE(), expectedParentNode, "PARENT_NODE should match"); + } + + //////////////////////////////////////////////////////////////////////// + // supportsInterface Tests + //////////////////////////////////////////////////////////////////////// + + function test_supportsInterface_erc165() public view { + assertTrue(ERC165Checker.supportsERC165(address(registrar)), "Should support ERC165"); + } + + function test_supportsInterface_extendedResolver() public view { + assertTrue( + registrar.supportsInterface(type(IExtendedResolver).interfaceId), + "Should support IExtendedResolver" + ); + } + + function test_supportsInterface_nameResolver() public view { + assertTrue( + registrar.supportsInterface(type(INameResolver).interfaceId), + "Should support INameResolver" + ); + } + + function test_supportsInterface_ierc165() public view { + assertTrue(registrar.supportsInterface(type(IERC165).interfaceId), "Should support IERC165"); + } + + function test_supportsInterface_il2ReverseRegistrar() public view { + assertTrue( + registrar.supportsInterface(type(IL2ReverseRegistrar).interfaceId), + "Should support IL2ReverseRegistrar" + ); + } + + function test_supportsInterface_invalidInterface() public view { + assertFalse( + registrar.supportsInterface(bytes4(0xdeadbeef)), + "Should not support random interface" + ); + } + + //////////////////////////////////////////////////////////////////////// + // setName Tests + //////////////////////////////////////////////////////////////////////// + + function test_setName_setsNameRecord() public { + string memory name_ = "myname.eth"; + + vm.prank(user1); + registrar.setName(name_); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set"); + } + + function test_setName_emitsNameChangedEvent() public { + string memory name_ = "myname.eth"; + bytes32 expectedNode = _getNode(user1); + + vm.prank(user1); + vm.expectEmit(true, false, false, true); + emit INameResolver.NameChanged(expectedNode, name_); + registrar.setName(name_); + } + + function test_setName_canUpdateNameRecord() public { + string memory firstName = "first.eth"; + string memory secondName = "second.eth"; + + vm.startPrank(user1); + registrar.setName(firstName); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), firstName, "First name should be set"); + + registrar.setName(secondName); + assertEq(registrar.name(node), secondName, "Name should be updated"); + vm.stopPrank(); + } + + function test_setName_updatesInception() public { + uint256 timestamp = 1_700_000_000; + vm.warp(timestamp); + + vm.prank(user1); + registrar.setName("myname.eth"); + + assertEq(registrar.inceptionOf(user1), timestamp, "Inception should track direct write"); + } + + function test_setName_invalidatesPriorUnusedSignature() public { + string memory signedName = "signed.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = _createNameForAddrMessage(signedName, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: signedName, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.warp(block.timestamp + 1); + uint256 directSetAt = block.timestamp; + + vm.prank(user1); + registrar.setName("direct.eth"); + + vm.expectRevert( + abi.encodeWithSelector(L2ReverseRegistrar.StaleSignature.selector, signedAt, directSetAt) + ); + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setName_canSetToEmptyString() public { + string memory name_ = "myname.eth"; + + vm.startPrank(user1); + registrar.setName(name_); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set"); + + registrar.setName(""); + assertEq(registrar.name(node), "", "Name should be empty"); + vm.stopPrank(); + } + + function testFuzz_setName(address addr, string memory name_) public { + vm.assume(addr != address(0)); + + vm.prank(addr); + registrar.setName(name_); + + bytes32 node = _getNode(addr); + assertEq(registrar.name(node), name_, "Name should be set"); + } + + //////////////////////////////////////////////////////////////////////// + // setNameForAddr Tests + //////////////////////////////////////////////////////////////////////// + + function test_setNameForAddr_setsNameForOwnedContract() public { + string memory name_ = "myname.eth"; + + vm.prank(user1); + registrar.setNameForAddr(address(mockOwnableEoa), name_); + + bytes32 node = _getNode(address(mockOwnableEoa)); + assertEq(registrar.name(node), name_, "Name should be set for contract"); + } + + function test_setNameForAddr_emitsNameChangedEvent() public { + string memory name_ = "myname.eth"; + bytes32 expectedNode = _getNode(address(mockOwnableEoa)); + + vm.prank(user1); + vm.expectEmit(true, false, false, true); + emit INameResolver.NameChanged(expectedNode, name_); + registrar.setNameForAddr(address(mockOwnableEoa), name_); + } + + function test_setNameForAddr_callerCanSetOwnName() public { + string memory name_ = "myname.eth"; + + vm.prank(user1); + registrar.setNameForAddr(user1, name_); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set for caller"); + } + + function test_setNameForAddr_updatesInceptionForTarget() public { + uint256 timestamp = 1_700_000_000; + vm.warp(timestamp); + + vm.prank(user1); + registrar.setNameForAddr(address(mockOwnableEoa), "myname.eth"); + + assertEq( + registrar.inceptionOf(address(mockOwnableEoa)), + timestamp, + "Inception should track target direct write" + ); + } + + function test_setNameForAddr_invalidatesPriorUnusedOwnableSignature() public { + string memory signedName = "signed.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = + _createNameForOwnableMessage( + signedName, + address(mockOwnableEoa), + user1, + chainIds, + signedAt + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: signedName, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.warp(block.timestamp + 1); + uint256 directSetAt = block.timestamp; + + vm.prank(user1); + registrar.setNameForAddr(address(mockOwnableEoa), "direct.eth"); + + vm.expectRevert( + abi.encodeWithSelector(L2ReverseRegistrar.StaleSignature.selector, signedAt, directSetAt) + ); + vm.prank(relayer); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForAddr_revert_callerNotOwnerOfTargetAddress() public { + string memory name_ = "myname.eth"; + + vm.prank(user2); + vm.expectRevert(abi.encodeWithSelector(AccountNamerLib.UnauthorizedNamer.selector, user2)); + registrar.setNameForAddr(address(mockOwnableEoa), name_); + } + + function test_setNameForAddr_revert_callerTriesToSetNameForAnotherEOA() public { + string memory name_ = "myname.eth"; + + vm.prank(user1); + vm.expectRevert(abi.encodeWithSelector(AccountNamerLib.UnauthorizedNamer.selector, user1)); + registrar.setNameForAddr(user2, name_); + } + + function test_setNameForAddr_revert_callerNotOwnerOfTargetContractViaOwnable() public { + string memory name_ = "myname.eth"; + + // mockOwnableSca is owned by mockSca, not user1 + vm.prank(user1); + vm.expectRevert(abi.encodeWithSelector(AccountNamerLib.UnauthorizedNamer.selector, user1)); + registrar.setNameForAddr(address(mockOwnableSca), name_); + } + + //////////////////////////////////////////////////////////////////////// + // setNameForAddrWithSignature Tests + //////////////////////////////////////////////////////////////////////// + + function test_setNameForAddrWithSignature_allowsRelayerToClaim() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set via signature"); + } + + function test_setNameForAddrWithSignature_emitsNameChangedEvent() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + bytes32 expectedNode = _getNode(user1); + + vm.prank(relayer); + vm.expectEmit(true, false, false, true); + emit INameResolver.NameChanged(expectedNode, name_); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setNameForAddrWithSignature_allowsScaSignaturesERC1271() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, address(mockSca), chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockSca), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + bytes32 node = _getNode(address(mockSca)); + assertEq(registrar.name(node), name_, "Name should be set for SCA"); + } + + function test_setNameForAddrWithSignature_allowsUndeployedScaSignaturesERC6492() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + + address predictedAddress = mockErc6492Factory.predictAddress(user1); + bytes memory wrappedSignature = _createErc6492Signature(name_, predictedAddress, signedAt); + + uint256[] memory chainIds = _singleChainIdArray(); + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: predictedAddress, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, wrappedSignature); + + bytes32 node = _getNode(predictedAddress); + assertEq(registrar.name(node), name_, "Name should be set for undeployed SCA"); + } + + function _createErc6492Signature(string memory name_, address predictedAddress, uint256 signedAt) + internal + view + returns (bytes memory) + { + uint256[] memory chainIds = _singleChainIdArray(); + bytes32 message = _createNameForAddrMessage(name_, predictedAddress, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory originalSignature = abi.encodePacked(r, s, v); + + bytes memory factoryCallData = abi.encodeCall(mockErc6492Factory.createWallet, (user1)); + bytes32 ERC6492_DETECTION_SUFFIX = + 0x6492649264926492649264926492649264926492649264926492649264926492; + + // ERC6492 format: abi.encode(factory, factoryCallData, originalSignature) ++ suffix + return + abi.encodePacked( + abi.encode(address(mockErc6492Factory), factoryCallData, originalSignature), + ERC6492_DETECTION_SUFFIX + ); + } + + function test_setNameForAddrWithSignature_revert_signatureParametersDoNotMatch() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // Sign with different name + bytes32 message = _createNameForAddrMessage("different.eth", user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(L2ReverseRegistrar.InvalidSignature.selector); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setNameForAddrWithSignature_revert_signedAtInFuture() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp + 1; // In the future + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + L2ReverseRegistrar.SignatureNotValidYet.selector, + signedAt, + block.timestamp + ) + ); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setNameForAddrWithSignature_revert_signedAtNotAfterInception() public { + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // First, set a name to establish an inception + { + bytes32 message = _createNameForAddrMessage("myname.eth", user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: "myname.eth", addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, abi.encodePacked(r, s, v)); + } + + // Now try to use a signature with signedAt equal to the inception (should fail) + { + bytes32 message = _createNameForAddrMessage("newname.eth", user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: "newname.eth", addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + L2ReverseRegistrar.StaleSignature.selector, + signedAt, + signedAt + ) + ); + registrar.setNameForAddrWithSignature(claim, abi.encodePacked(r, s, v)); + } + } + + function test_setNameForAddrWithSignature_allowsMultipleChainIds() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _multipleChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set with multiple chain IDs"); + } + + function test_setNameForAddrWithSignature_allowsLargeChainIdArray_25() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _largeChainIdArray(25); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set with large chain ID array"); + } + + function test_setNameForAddrWithSignature_allowsLargeChainIdArray_50() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _largeChainIdArray(50); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set with large chain ID array"); + } + + function test_setNameForAddrWithSignature_allowsLargeChainIdArray_100() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _largeChainIdArray(100); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set with large chain ID array"); + } + + function test_setNameForAddrWithSignature_allowsLargeChainIdArray_200() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _largeChainIdArray(200); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), name_, "Name should be set with large chain ID array"); + } + + function test_setNameForAddrWithSignature_revert_currentChainIdNotInArray() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _chainIdArrayWithoutOptimism(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + ChainIdsBuilderLib.CurrentChainNotFound.selector, + OPTIMISM_CHAIN_ID + ) + ); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setNameForAddrWithSignature_revert_emptyChainIdArray() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _emptyChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + ChainIdsBuilderLib.CurrentChainNotFound.selector, + OPTIMISM_CHAIN_ID + ) + ); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setNameForAddrWithSignature_revert_chainIdsNotAscending() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _unsortedChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setNameForAddrWithSignature_revert_duplicateChainIds() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _duplicateChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setNameForAddrWithSignature_revert_replayProtection() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + // First call should succeed + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + // Second call should fail (same signedAt is not after inception) + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector(L2ReverseRegistrar.StaleSignature.selector, signedAt, signedAt) + ); + registrar.setNameForAddrWithSignature(claim, signature); + } + + function test_setNameForAddrWithSignature_allowsNewerSignature() public { + uint256 signedAt1 = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // First signature + { + bytes32 message = _createNameForAddrMessage("first.eth", user1, chainIds, signedAt1); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: "first.eth", addr: user1, chainIds: chainIds, signedAt: signedAt1}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, abi.encodePacked(r, s, v)); + } + + // Advance time and use a newer signature + vm.warp(block.timestamp + 100); + uint256 signedAt2 = block.timestamp; + + { + bytes32 message = _createNameForAddrMessage("second.eth", user1, chainIds, signedAt2); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: "second.eth", addr: user1, chainIds: chainIds, signedAt: signedAt2}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, abi.encodePacked(r, s, v)); + } + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "second.eth", "Name should be updated to second"); + } + + function test_setNameForAddrWithSignature_revert_olderSignatureAfterNewerUsed() public { + uint256 signedAt1 = block.timestamp + 100; // Newer timestamp + uint256 signedAt2 = block.timestamp; // Older timestamp + uint256[] memory chainIds = _singleChainIdArray(); + + // Use the newer signature first + vm.warp(block.timestamp + 100); + { + bytes32 message = _createNameForAddrMessage("first.eth", user1, chainIds, signedAt1); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: "first.eth", addr: user1, chainIds: chainIds, signedAt: signedAt1}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, abi.encodePacked(r, s, v)); + } + + // Try to use the older signature (should fail) + { + bytes32 message = _createNameForAddrMessage("second.eth", user1, chainIds, signedAt2); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: "second.eth", addr: user1, chainIds: chainIds, signedAt: signedAt2}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + L2ReverseRegistrar.StaleSignature.selector, + signedAt2, + signedAt1 + ) + ); + registrar.setNameForAddrWithSignature(claim, abi.encodePacked(r, s, v)); + } + } + + function test_setNameForAddrWithSignature_updatesInception() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // Check initial inception is 0 + assertEq(registrar.inceptionOf(user1), 0, "Initial inception should be 0"); + + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForAddrWithSignature(claim, signature); + + // Check inception is updated + assertEq(registrar.inceptionOf(user1), signedAt, "Inception should be updated to signedAt"); + } + + function test_setNameForAddrWithSignature_revert_signedByWrongAccount() public { + string memory name_ = "myname.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // Sign with user2 but claim is for user1 + bytes32 message = _createNameForAddrMessage(name_, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user2Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user1, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(L2ReverseRegistrar.InvalidSignature.selector); + registrar.setNameForAddrWithSignature(claim, signature); + } + + //////////////////////////////////////////////////////////////////////// + // setNameForContractWithSignature Tests + //////////////////////////////////////////////////////////////////////// + + function test_setNameForContractWithSignature_allowsEoaOwner() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForContractWithSignature(claim, user1, signature); + + bytes32 node = _getNode(address(mockOwnableEoa)); + assertEq(registrar.name(node), name_, "Name should be set for ownable contract"); + } + + function test_setNameForContractWithSignature_allowsScaOwner() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // mockOwnableSca is owned by mockSca, which is owned by user1 + bytes32 message = + _createNameForOwnableMessage( + name_, + address(mockOwnableSca), + address(mockSca), + chainIds, + signedAt + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableSca), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForContractWithSignature(claim, address(mockSca), signature); + + bytes32 node = _getNode(address(mockOwnableSca)); + assertEq(registrar.name(node), name_, "Name should be set for ownable contract via SCA"); + } + + function test_setNameForContractWithSignature_revert_ownerAddressNotOwnerOfContract() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // Sign with user2 and claim they own mockOwnableEoa (which is owned by user1) + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user2, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user2Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(abi.encodeWithSelector(AccountNamerLib.UnauthorizedNamer.selector, user2)); + registrar.setNameForContractWithSignature(claim, user2, signature); + } + + function test_setNameForContractWithSignature_revert_targetAddressIsEOA() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // Try to claim for EOA user2 saying user1 owns it + bytes32 message = _createNameForOwnableMessage(name_, user2, user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: user2, chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(abi.encodeWithSelector(AccountNamerLib.UnauthorizedNamer.selector, user1)); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_revert_targetDoesNotImplementOwnable() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // L2ReverseRegistrar itself does not implement Ownable + bytes32 message = + _createNameForOwnableMessage(name_, address(registrar), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(registrar), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(abi.encodeWithSelector(AccountNamerLib.UnauthorizedNamer.selector, user1)); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_revert_invalidSignature() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // Sign with different name to create invalid signature + bytes32 message = + _createNameForOwnableMessage( + "different.eth", + address(mockOwnableEoa), + user1, + chainIds, + signedAt + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(L2ReverseRegistrar.InvalidSignature.selector); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_revert_signedAtInFuture() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp + 1; // In the future + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + L2ReverseRegistrar.SignatureNotValidYet.selector, + signedAt, + block.timestamp + ) + ); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_revert_signedAtNotAfterInception() public { + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // First, set a name to establish an inception + { + bytes32 message = + _createNameForOwnableMessage( + "ownable.eth", + address(mockOwnableEoa), + user1, + chainIds, + signedAt + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: "ownable.eth", addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForContractWithSignature(claim, user1, abi.encodePacked(r, s, v)); + } + + // Now try to use a signature with signedAt equal to the inception (should fail) + { + bytes32 message = + _createNameForOwnableMessage( + "newname.eth", + address(mockOwnableEoa), + user1, + chainIds, + signedAt + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: "newname.eth", addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + L2ReverseRegistrar.StaleSignature.selector, + signedAt, + signedAt + ) + ); + registrar.setNameForContractWithSignature(claim, user1, abi.encodePacked(r, s, v)); + } + } + + function test_setNameForContractWithSignature_allowsMultipleChainIds() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _multipleChainIdArray(); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForContractWithSignature(claim, user1, signature); + + bytes32 node = _getNode(address(mockOwnableEoa)); + assertEq(registrar.name(node), name_, "Name should be set with multiple chain IDs"); + } + + function test_setNameForContractWithSignature_allowsLargeChainIdArray() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _largeChainIdArray(50); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForContractWithSignature(claim, user1, signature); + + bytes32 node = _getNode(address(mockOwnableEoa)); + assertEq(registrar.name(node), name_, "Name should be set with large chain ID array"); + } + + function test_setNameForContractWithSignature_revert_currentChainIdNotInArray() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _chainIdArrayWithoutOptimism(); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + ChainIdsBuilderLib.CurrentChainNotFound.selector, + OPTIMISM_CHAIN_ID + ) + ); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_revert_emptyChainIdArray() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _emptyChainIdArray(); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector( + ChainIdsBuilderLib.CurrentChainNotFound.selector, + OPTIMISM_CHAIN_ID + ) + ); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_revert_chainIdsNotAscending() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _unsortedChainIdArray(); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_revert_duplicateChainIds() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _duplicateChainIdArray(); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_revert_replayProtection() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + // First call should succeed + vm.prank(relayer); + registrar.setNameForContractWithSignature(claim, user1, signature); + + // Second call should fail (same signedAt is not after inception) + vm.prank(relayer); + vm.expectRevert( + abi.encodeWithSelector(L2ReverseRegistrar.StaleSignature.selector, signedAt, signedAt) + ); + registrar.setNameForContractWithSignature(claim, user1, signature); + } + + function test_setNameForContractWithSignature_updatesInception() public { + string memory name_ = "ownable.eth"; + uint256 signedAt = block.timestamp; + uint256[] memory chainIds = _singleChainIdArray(); + + // Check initial inception is 0 + assertEq(registrar.inceptionOf(address(mockOwnableEoa)), 0, "Initial inception should be 0"); + + bytes32 message = + _createNameForOwnableMessage(name_, address(mockOwnableEoa), user1, chainIds, signedAt); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(user1Pk, message); + bytes memory signature = abi.encodePacked(r, s, v); + + IL2ReverseRegistrar.NameClaim memory claim = + IL2ReverseRegistrar.NameClaim({name: name_, addr: address(mockOwnableEoa), chainIds: chainIds, signedAt: signedAt}); + + vm.prank(relayer); + registrar.setNameForContractWithSignature(claim, user1, signature); + + // Check inception is updated + assertEq( + registrar.inceptionOf(address(mockOwnableEoa)), + signedAt, + "Inception should be updated to signedAt" + ); + } + + //////////////////////////////////////////////////////////////////////// + // syncName() Tests + //////////////////////////////////////////////////////////////////////// + + function test_syncName() external { + string memory name = "mycontract.eth"; + address addr = address(new MockContractName(name)); + assertEq(registrar.nameForAddr(addr), "", "before"); + vm.prank(makeAddr("anyone")); + registrar.syncName(addr); + assertEq(registrar.nameForAddr(addr), name, "after"); + } + + function test_syncName_empty() external { + string memory name = "mycontract.eth"; + address addr = address(new MockContractName("")); + vm.prank(addr); + registrar.setName(name); + assertEq(registrar.nameForAddr(addr), name, "before"); + registrar.syncName(addr); + assertEq(registrar.nameForAddr(addr), "", "after"); + } + + function test_syncName_notContract() external { + vm.expectRevert(); + registrar.syncName(makeAddr("dne")); + } + + function test_syncName_notImplemented() external { + vm.expectRevert(); + registrar.syncName(address(this)); + } + + //////////////////////////////////////////////////////////////////////// + // name() Tests (reading reverse records) + //////////////////////////////////////////////////////////////////////// + + function test_name_returnsEmptyForUnsetAddress() public view { + bytes32 node = _getNode(user2); + assertEq(registrar.name(node), "", "Should return empty for unset address"); + } + + function test_name_returnsSetName() public { + string memory expectedName = "vitalik.eth"; + + vm.prank(user1); + registrar.setName(expectedName); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), expectedName, "Should return set name"); + } + + //////////////////////////////////////////////////////////////////////// + // resolve() Tests + //////////////////////////////////////////////////////////////////////// + + function test_resolve_canResolveNameForAddress() public { + string memory expectedName = "test.eth"; + + vm.prank(user1); + registrar.setName(expectedName); + + bytes memory dnsEncodedName = _buildDnsEncodedName(user1); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + bytes memory result = registrar.resolve(dnsEncodedName, data); + + string memory decodedName = abi.decode(result, (string)); + assertEq(decodedName, expectedName, "Resolved name should match"); + } + + function test_resolve_returnsEmptyForUnsetAddress() public view { + bytes memory dnsEncodedName = _buildDnsEncodedName(user1); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + bytes memory result = registrar.resolve(dnsEncodedName, data); + + string memory decodedName = abi.decode(result, (string)); + assertEq(decodedName, "", "Should return empty for unset address"); + } + + function testFuzz_resolve_differentAddresses(address addr, string memory expectedName) public { + vm.assume(addr != address(0)); + + vm.prank(addr); + registrar.setName(expectedName); + + bytes memory dnsEncodedName = _buildDnsEncodedName(addr); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + bytes memory result = registrar.resolve(dnsEncodedName, data); + + string memory decodedName = abi.decode(result, (string)); + assertEq(decodedName, expectedName, "Should return correct name"); + } + + //////////////////////////////////////////////////////////////////////// + // Integration Tests + //////////////////////////////////////////////////////////////////////// + + function test_fullFlow_setAndResolve() public { + string memory expectedName = "integration.eth"; + + vm.prank(user1); + registrar.setName(expectedName); + + // Resolve via resolve() + bytes memory dnsEncodedName = _buildDnsEncodedName(user1); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + bytes memory result = registrar.resolve(dnsEncodedName, data); + + string memory resolvedName = abi.decode(result, (string)); + assertEq(resolvedName, expectedName, "Resolved name should match"); + + // Also verify via direct name() call + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), expectedName, "Direct name() should match"); + } + + function test_multipleUsers() public { + string memory name1 = "user1.eth"; + string memory name2 = "user2.eth"; + + vm.prank(user1); + registrar.setName(name1); + + vm.prank(user2); + registrar.setName(name2); + + bytes32 node1 = _getNode(user1); + bytes32 node2 = _getNode(user2); + + assertEq(registrar.name(node1), name1, "User1 name should match"); + assertEq(registrar.name(node2), name2, "User2 name should match"); + } +} + + +contract MockContractName is IContractName { + string public contractName; + constructor(string memory name) { + contractName = name; + } +} diff --git a/contracts/test/unit/reverse-registrar/L2ReverseRegistrarWithMigration.t.sol b/contracts/test/unit/reverse-registrar/L2ReverseRegistrarWithMigration.t.sol new file mode 100644 index 000000000..f3baae312 --- /dev/null +++ b/contracts/test/unit/reverse-registrar/L2ReverseRegistrarWithMigration.t.sol @@ -0,0 +1,567 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, namechain/ordering, one-contract-per-file, namechain/import-order-separation, gas-small-strings, gas-strict-inequalities, gas-increment-by-one, gas-custom-errors + +import {Test} from "forge-std/Test.sol"; + +import {INameResolver} from "@ens/contracts/resolvers/profiles/INameResolver.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +import { + L2ReverseRegistrarWithMigration, + IL2ReverseRegistrarV1 +} from "~src/reverse-registrar/L2ReverseRegistrarWithMigration.sol"; +import {LibString} from "~src/utils/LibString.sol"; + +/// @title Mock Old L2 Reverse Registrar +/// @notice A mock implementation of the V1 reverse registrar interface for testing migration. +contract MockOldL2ReverseRegistrar is IL2ReverseRegistrarV1 { + mapping(address addr => string name) private _names; + + function setMockName(address addr, string memory name) external { + _names[addr] = name; + } + + function nameForAddr(address addr) external view override returns (string memory) { + return _names[addr]; + } +} + + +contract L2ReverseRegistrarWithMigrationTest is Test { + // Constants matching Optimism chain setup + uint256 constant OPTIMISM_CHAIN_ID = 10; + string constant COIN_TYPE_LABEL = "8000000a"; + + bytes32 constant REVERSE_NODE = + 0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34; + + L2ReverseRegistrarWithMigration registrar; + MockOldL2ReverseRegistrar mockOldRegistrar; + + // Test accounts + address owner; + address user1; + address user2; + address user3; + address nonOwner; + + function setUp() public { + owner = makeAddr("owner"); + user1 = makeAddr("user1"); + user2 = makeAddr("user2"); + user3 = makeAddr("user3"); + nonOwner = makeAddr("nonOwner"); + + // Deploy mock old registrar + mockOldRegistrar = new MockOldL2ReverseRegistrar(); + + // Deploy the L2ReverseRegistrarWithMigration + registrar = new L2ReverseRegistrarWithMigration( + OPTIMISM_CHAIN_ID, + COIN_TYPE_LABEL, + owner, + IL2ReverseRegistrarV1(address(mockOldRegistrar)) + ); + } + + //////////////////////////////////////////////////////////////////////// + // Helper Functions + //////////////////////////////////////////////////////////////////////// + + function _getNode(address addr) internal view returns (bytes32) { + string memory label = LibString.toAddressString(addr); + return + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + } + + //////////////////////////////////////////////////////////////////////// + // Constructor Tests + //////////////////////////////////////////////////////////////////////// + + function test_constructor_setsOwner() public view { + assertEq(registrar.owner(), owner, "Owner should be set correctly"); + } + + function test_constructor_setsOldL2ReverseRegistrar() public view { + assertEq( + address(registrar.OLD_L2_REVERSE_REGISTRAR()), + address(mockOldRegistrar), + "OLD_L2_REVERSE_REGISTRAR should be set correctly" + ); + } + + function test_constructor_setsChainId() public view { + assertEq(registrar.CHAIN_ID(), OPTIMISM_CHAIN_ID, "CHAIN_ID should be set correctly"); + } + + function test_constructor_setsParentNode() public view { + bytes32 expectedParentNode = + keccak256(abi.encodePacked(REVERSE_NODE, keccak256(abi.encodePacked(COIN_TYPE_LABEL)))); + assertEq(registrar.PARENT_NODE(), expectedParentNode, "PARENT_NODE should be set correctly"); + } + + function test_constructor_differentOwner() public { + address differentOwner = makeAddr("differentOwner"); + L2ReverseRegistrarWithMigration newRegistrar = + new L2ReverseRegistrarWithMigration( + OPTIMISM_CHAIN_ID, + COIN_TYPE_LABEL, + differentOwner, + IL2ReverseRegistrarV1(address(mockOldRegistrar)) + ); + assertEq(newRegistrar.owner(), differentOwner, "Different owner should be set"); + } + + //////////////////////////////////////////////////////////////////////// + // batchSetName Tests - Access Control + //////////////////////////////////////////////////////////////////////// + + function test_batchSetName_revert_callerNotOwner() public { + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.expectRevert( + abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, nonOwner) + ); + vm.prank(nonOwner); + registrar.batchSetName(addresses); + } + + function test_batchSetName_onlyOwnerCanCall() public { + mockOldRegistrar.setMockName(user1, "user1.eth"); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "user1.eth", "Name should be migrated"); + } + + //////////////////////////////////////////////////////////////////////// + // batchSetName Tests - Single Address Migration + //////////////////////////////////////////////////////////////////////// + + function test_batchSetName_migratesSingleAddress() public { + string memory expectedName = "vitalik.eth"; + mockOldRegistrar.setMockName(user1, expectedName); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), expectedName, "Name should be migrated correctly"); + } + + function test_batchSetName_emitsNameChangedEvent() public { + string memory expectedName = "test.eth"; + mockOldRegistrar.setMockName(user1, expectedName); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + bytes32 expectedNode = _getNode(user1); + + vm.expectEmit(true, false, false, true); + emit INameResolver.NameChanged(expectedNode, expectedName); + + vm.prank(owner); + registrar.batchSetName(addresses); + } + + //////////////////////////////////////////////////////////////////////// + // batchSetName Tests - Multiple Address Migration + //////////////////////////////////////////////////////////////////////// + + function test_batchSetName_migratesMultipleAddresses() public { + mockOldRegistrar.setMockName(user1, "user1.eth"); + mockOldRegistrar.setMockName(user2, "user2.eth"); + mockOldRegistrar.setMockName(user3, "user3.eth"); + + address[] memory addresses = new address[](3); + addresses[0] = user1; + addresses[1] = user2; + addresses[2] = user3; + + vm.prank(owner); + registrar.batchSetName(addresses); + + assertEq(registrar.name(_getNode(user1)), "user1.eth", "User1 name should be migrated"); + assertEq(registrar.name(_getNode(user2)), "user2.eth", "User2 name should be migrated"); + assertEq(registrar.name(_getNode(user3)), "user3.eth", "User3 name should be migrated"); + } + + function test_batchSetName_emitsMultipleNameChangedEvents() public { + mockOldRegistrar.setMockName(user1, "user1.eth"); + mockOldRegistrar.setMockName(user2, "user2.eth"); + mockOldRegistrar.setMockName(user3, "user3.eth"); + + address[] memory addresses = new address[](3); + addresses[0] = user1; + addresses[1] = user2; + addresses[2] = user3; + + vm.expectEmit(true, false, false, true); + emit INameResolver.NameChanged(_getNode(user1), "user1.eth"); + vm.expectEmit(true, false, false, true); + emit INameResolver.NameChanged(_getNode(user2), "user2.eth"); + vm.expectEmit(true, false, false, true); + emit INameResolver.NameChanged(_getNode(user3), "user3.eth"); + + vm.prank(owner); + registrar.batchSetName(addresses); + } + + //////////////////////////////////////////////////////////////////////// + // batchSetName Tests - Edge Cases + //////////////////////////////////////////////////////////////////////// + + function test_batchSetName_emptyArray() public { + address[] memory addresses = new address[](0); + + vm.prank(owner); + registrar.batchSetName(addresses); + + // Should not revert, just do nothing + } + + function test_batchSetName_addressWithNoNameInOldRegistrar() public { + // user1 has no name set in old registrar (returns empty string by default) + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "", "Name should be empty for address with no name"); + } + + function test_batchSetName_mixedAddressesWithAndWithoutNames() public { + mockOldRegistrar.setMockName(user1, "user1.eth"); + // user2 has no name set + mockOldRegistrar.setMockName(user3, "user3.eth"); + + address[] memory addresses = new address[](3); + addresses[0] = user1; + addresses[1] = user2; + addresses[2] = user3; + + vm.prank(owner); + registrar.batchSetName(addresses); + + assertEq(registrar.name(_getNode(user1)), "user1.eth", "User1 name should be migrated"); + assertEq(registrar.name(_getNode(user2)), "", "User2 should have empty name"); + assertEq(registrar.name(_getNode(user3)), "user3.eth", "User3 name should be migrated"); + } + + function test_batchSetName_duplicateAddressesInArray() public { + mockOldRegistrar.setMockName(user1, "user1.eth"); + + address[] memory addresses = new address[](3); + addresses[0] = user1; + addresses[1] = user1; + addresses[2] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + // Should not revert, name should be set (same value written multiple times) + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "user1.eth", "Name should be set correctly"); + } + + function test_batchSetName_overwritesExistingName() public { + // First, set a name directly on the new registrar + vm.prank(user1); + registrar.setName("original.eth"); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "original.eth", "Original name should be set"); + + // Now migrate from old registrar (overwrites) + mockOldRegistrar.setMockName(user1, "migrated.eth"); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + assertEq(registrar.name(node), "migrated.eth", "Name should be overwritten by migration"); + } + + function test_batchSetName_handlesLongName() public { + string memory longName = "very-long-ens-name-used-in-production.eth"; + mockOldRegistrar.setMockName(user1, longName); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), longName, "Long name should be migrated correctly"); + } + + function test_batchSetName_handlesSpecialCharactersInName() public { + string memory specialName = unicode"emoji🔥.eth"; + mockOldRegistrar.setMockName(user1, specialName); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), specialName, "Special characters should be preserved"); + } + + //////////////////////////////////////////////////////////////////////// + // batchSetName Tests - Large Batch + //////////////////////////////////////////////////////////////////////// + + function test_batchSetName_largeBatch() public { + uint256 batchSize = 100; + address[] memory addresses = new address[](batchSize); + + for (uint256 i = 0; i < batchSize; i++) { + address addr = address(uint160(i + 1)); + string memory name = string(abi.encodePacked("user", vm.toString(i), ".eth")); + mockOldRegistrar.setMockName(addr, name); + addresses[i] = addr; + } + + vm.prank(owner); + registrar.batchSetName(addresses); + + // Verify a few addresses + assertEq( + registrar.name(_getNode(address(1))), + "user0.eth", + "First address name should be migrated" + ); + assertEq( + registrar.name(_getNode(address(50))), + "user49.eth", + "Middle address name should be migrated" + ); + assertEq( + registrar.name(_getNode(address(100))), + "user99.eth", + "Last address name should be migrated" + ); + } + + //////////////////////////////////////////////////////////////////////// + // batchSetName Tests - Sequential Calls + //////////////////////////////////////////////////////////////////////// + + function test_batchSetName_multipleBatchCalls() public { + // First batch + mockOldRegistrar.setMockName(user1, "user1.eth"); + address[] memory batch1 = new address[](1); + batch1[0] = user1; + + vm.prank(owner); + registrar.batchSetName(batch1); + + // Second batch + mockOldRegistrar.setMockName(user2, "user2.eth"); + address[] memory batch2 = new address[](1); + batch2[0] = user2; + + vm.prank(owner); + registrar.batchSetName(batch2); + + assertEq(registrar.name(_getNode(user1)), "user1.eth", "User1 name should persist"); + assertEq(registrar.name(_getNode(user2)), "user2.eth", "User2 name should be migrated"); + } + + //////////////////////////////////////////////////////////////////////// + // Inherited Functionality Tests + //////////////////////////////////////////////////////////////////////// + + function test_inheritedSetName_stillWorks() public { + vm.prank(user1); + registrar.setName("direct.eth"); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "direct.eth", "Direct setName should work"); + } + + function test_inheritedSetNameForAddr_stillWorks() public { + vm.prank(user1); + registrar.setNameForAddr(user1, "foraddr.eth"); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "foraddr.eth", "setNameForAddr should work"); + } + + //////////////////////////////////////////////////////////////////////// + // Ownership Tests + //////////////////////////////////////////////////////////////////////// + + function test_transferOwnership() public { + address newOwner = makeAddr("newOwner"); + + vm.prank(owner); + registrar.transferOwnership(newOwner); + + assertEq(registrar.owner(), newOwner, "Ownership should be transferred"); + } + + function test_newOwnerCanCallBatchSetName() public { + address newOwner = makeAddr("newOwner"); + + vm.prank(owner); + registrar.transferOwnership(newOwner); + + mockOldRegistrar.setMockName(user1, "user1.eth"); + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(newOwner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "user1.eth", "New owner should be able to migrate"); + } + + function test_oldOwnerCannotCallBatchSetNameAfterTransfer() public { + address newOwner = makeAddr("newOwner"); + + vm.prank(owner); + registrar.transferOwnership(newOwner); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, owner)); + registrar.batchSetName(addresses); + } + + function test_renounceOwnership() public { + vm.prank(owner); + registrar.renounceOwnership(); + + assertEq(registrar.owner(), address(0), "Owner should be zero address"); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, owner)); + registrar.batchSetName(addresses); + } + + //////////////////////////////////////////////////////////////////////// + // Fuzz Tests + //////////////////////////////////////////////////////////////////////// + + function testFuzz_batchSetName_singleAddress(address addr, string memory name) public { + vm.assume(addr != address(0)); // Avoid potential edge cases with zero address + + mockOldRegistrar.setMockName(addr, name); + + address[] memory addresses = new address[](1); + addresses[0] = addr; + + vm.prank(owner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(addr); + assertEq(registrar.name(node), name, "Fuzzed name should be migrated correctly"); + } + + function testFuzz_batchSetName_revertNonOwner(address caller) public { + vm.assume(caller != owner); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(caller); + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller)); + registrar.batchSetName(addresses); + } + + //////////////////////////////////////////////////////////////////////// + // Integration Tests + //////////////////////////////////////////////////////////////////////// + + function test_integration_migrateAndResolve() public { + string memory expectedName = "integration.eth"; + mockOldRegistrar.setMockName(user1, expectedName); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + // Verify via direct name() call + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), expectedName, "Direct name() should match"); + } + + function test_integration_migrateAndUpdateDirectly() public { + // Step 1: Migrate from old registrar + mockOldRegistrar.setMockName(user1, "migrated.eth"); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + vm.prank(owner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "migrated.eth", "Migration should succeed"); + + // Step 2: User updates their name directly + vm.prank(user1); + registrar.setName("updated.eth"); + + assertEq(registrar.name(node), "updated.eth", "Direct update should succeed"); + } + + function test_integration_oldRegistrarValueChangesAfterMigration() public { + // Set initial name in old registrar + mockOldRegistrar.setMockName(user1, "initial.eth"); + + address[] memory addresses = new address[](1); + addresses[0] = user1; + + // Migrate + vm.prank(owner); + registrar.batchSetName(addresses); + + bytes32 node = _getNode(user1); + assertEq(registrar.name(node), "initial.eth", "Initial migration should succeed"); + + // Change name in old registrar (simulating someone using old registrar) + mockOldRegistrar.setMockName(user1, "changed.eth"); + + // New registrar should still have original migrated name + assertEq( + registrar.name(node), + "initial.eth", + "New registrar should not reflect old registrar changes" + ); + + // Re-migrate to get updated name + vm.prank(owner); + registrar.batchSetName(addresses); + + assertEq(registrar.name(node), "changed.eth", "Re-migration should update name"); + } +} diff --git a/contracts/test/unit/reverse-registrar/ReverseRegistrarAdapter.t.sol b/contracts/test/unit/reverse-registrar/ReverseRegistrarAdapter.t.sol new file mode 100644 index 000000000..1652248c5 --- /dev/null +++ b/contracts/test/unit/reverse-registrar/ReverseRegistrarAdapter.t.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// solhint-disable private-vars-leading-underscore, state-visibility, func-name-mixedcase + +import {Test} from "forge-std/Test.sol"; + +import {ENSRegistry} from "@ens/contracts/registry/ENSRegistry.sol"; +import {ReverseRegistrar} from "@ens/contracts/reverseRegistrar/ReverseRegistrar.sol"; +import {MockOwnable} from "@ens/contracts/test/mocks/MockOwnable.sol"; + +import {MockContractNamer} from "~test/mocks/MockContractNamer.sol"; +import {ReverseRegistrarAdapter} from "~src/reverse-registrar/ReverseRegistrarAdapter.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; + +contract ReverseRegistrarAdapterTest is Test { + bytes32 constant REVERSE_LABELHASH = keccak256("reverse"); + bytes32 constant ADDR_LABELHASH = keccak256("addr"); + bytes32 constant REVERSE_NODE = keccak256(abi.encodePacked(bytes32(0), REVERSE_LABELHASH)); + + ENSRegistry registry; + ReverseRegistrar reverseRegistrar; + ReverseRegistrarAdapter reverseAdapter; + + address owner = makeAddr("owner"); + address resolver = makeAddr("resolver"); + + function setUp() external { + registry = new ENSRegistry(); + reverseRegistrar = new ReverseRegistrar(registry); + reverseAdapter = new ReverseRegistrarAdapter(reverseRegistrar, IContractNamer(address(0))); + + registry.setSubnodeOwner(bytes32(0), REVERSE_LABELHASH, address(this)); + registry.setSubnodeOwner(REVERSE_NODE, ADDR_LABELHASH, address(reverseRegistrar)); + + reverseRegistrar.setController(address(reverseAdapter), true); + } + + function test_reverse_constructor() external view { + assertEq( + address(reverseAdapter.REVERSE_REGISTRAR()), + address(reverseRegistrar), + "REVERSE_REGISTRAR" + ); + } + + function test_claimForAddr_EOA() external { + vm.prank(owner); + bytes32 node = reverseAdapter.claim(owner, resolver); + + assertEq(node, reverseRegistrar.node(owner), "node"); + assertEq(registry.owner(node), owner, "owner"); + assertEq(registry.resolver(node), resolver, "resolver"); + } + + function test_claim_Ownable() external { + MockOwnable c = new MockOwnable(owner); + + vm.prank(owner); + bytes32 node = reverseAdapter.claim(address(c), resolver); + + assertEq(node, reverseRegistrar.node(address(c)), "node"); + assertEq(registry.owner(node), owner, "owner"); + assertEq(registry.resolver(node), resolver, "resolver"); + } + + function test_claimForContract_IContractNamer() external { + MockContractNamer c = new MockContractNamer(owner); + + vm.prank(owner); + bytes32 node = reverseAdapter.claim(address(c), resolver); + + assertEq(node, reverseRegistrar.node(address(c)), "node"); + assertEq(registry.owner(node), owner, "owner"); + assertEq(registry.resolver(node), resolver, "resolver"); + } +} diff --git a/contracts/test/unit/reverse-registrar/StandaloneReverseRegistrar.t.sol b/contracts/test/unit/reverse-registrar/StandaloneReverseRegistrar.t.sol new file mode 100644 index 000000000..03550c57b --- /dev/null +++ b/contracts/test/unit/reverse-registrar/StandaloneReverseRegistrar.t.sol @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, namechain/ordering, one-contract-per-file, namechain/import-order-separation, gas-small-strings, gas-strict-inequalities, gas-increment-by-one, gas-custom-errors + +import {Test, Vm} from "forge-std/Test.sol"; + +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +import { + StandaloneReverseRegistrar, + IRegistryEvents, + IExtendedResolver, + INameResolver, + IStandaloneReverseRegistrar, + LibString +} from "~src/reverse-registrar/StandaloneReverseRegistrar.sol"; +import { + MockStandaloneReverseRegistrarImplementer +} from "~test/mocks/MockStandaloneReverseRegistrarImplementer.sol"; + +contract StandaloneReverseRegistrarTest is Test { + // Constants matching the contract + bytes32 constant REVERSE_NODE = + 0xa097f6721ce401e757d1223a763fef49b8b5f90bb18567ddb86fd205dff71d34; + + // Test parameters + uint256 constant ETH_COIN_TYPE = 60; + string constant ETH_LABEL = "default"; + + MockStandaloneReverseRegistrarImplementer registrar; + + address user1 = makeAddr("user1"); + address user2 = makeAddr("user2"); + + function setUp() public { + registrar = new MockStandaloneReverseRegistrarImplementer(ETH_LABEL); + } + + //////////////////////////////////////////////////////////////////////// + // Constructor / Immutables Tests + //////////////////////////////////////////////////////////////////////// + + function test_constructor_setParentNode() public view { + bytes32 expectedParentNode = + keccak256(abi.encodePacked(REVERSE_NODE, keccak256(abi.encodePacked(ETH_LABEL)))); + assertEq(registrar.PARENT_NODE(), expectedParentNode, "PARENT_NODE should match"); + } + + function test_constructor_setSimpleHashedParent() public view { + bytes memory parent = + abi.encodePacked( + uint8(bytes(ETH_LABEL).length), + ETH_LABEL, + uint8(7), + "reverse", + uint8(0) + ); + bytes32 expectedHash = keccak256(parent); + assertEq(registrar.SIMPLE_HASHED_PARENT(), expectedHash, "SIMPLE_HASHED_PARENT should match"); + } + + function test_constructor_setParentLength() public view { + bytes memory parent = + abi.encodePacked( + uint8(bytes(ETH_LABEL).length), + ETH_LABEL, + uint8(7), + "reverse", + uint8(0) + ); + assertEq(registrar.PARENT_LENGTH(), parent.length, "PARENT_LENGTH should match"); + } + + function testFuzz_constructor_differentLabels(string memory label) public { + vm.assume(bytes(label).length > 0 && bytes(label).length <= 255); + + MockStandaloneReverseRegistrarImplementer newRegistrar = + new MockStandaloneReverseRegistrarImplementer(label); + + bytes32 expectedParentNode = + keccak256(abi.encodePacked(REVERSE_NODE, keccak256(abi.encodePacked(label)))); + assertEq(newRegistrar.PARENT_NODE(), expectedParentNode, "PARENT_NODE should match"); + + bytes memory parent = + abi.encodePacked(uint8(bytes(label).length), label, uint8(7), "reverse", uint8(0)); + assertEq(newRegistrar.SIMPLE_HASHED_PARENT(), keccak256(parent), "SIMPLE_HASHED_PARENT"); + assertEq(newRegistrar.PARENT_LENGTH(), parent.length, "PARENT_LENGTH should match"); + } + + //////////////////////////////////////////////////////////////////////// + // supportsInterface Tests + //////////////////////////////////////////////////////////////////////// + + function test_supportsInterface_erc165() public view { + assertTrue(ERC165Checker.supportsERC165(address(registrar)), "Should support ERC165"); + } + + function test_supportsInterface_extendedResolver() public view { + assertTrue( + registrar.supportsInterface(type(IExtendedResolver).interfaceId), + "Should support IExtendedResolver" + ); + } + + function test_supportsInterface_nameResolver() public view { + assertTrue( + registrar.supportsInterface(type(INameResolver).interfaceId), + "Should support INameResolver" + ); + } + + function test_supportsInterface_istandloneReverseRegistrar() public view { + assertTrue( + registrar.supportsInterface(type(IStandaloneReverseRegistrar).interfaceId), + "Should support IStandaloneReverseRegistrar" + ); + } + + function test_supportsInterface_ierc165() public view { + assertTrue(registrar.supportsInterface(type(IERC165).interfaceId), "Should support IERC165"); + } + + function test_supportsInterface_invalidInterface() public view { + assertFalse( + registrar.supportsInterface(bytes4(0xdeadbeef)), + "Should not support random interface" + ); + } + + //////////////////////////////////////////////////////////////////////// + // name() Tests + //////////////////////////////////////////////////////////////////////// + + function test_name_returnsEmptyForUnsetNode(bytes32 node) public view { + assertEq(registrar.name(node), "", "Should return empty for unset node"); + } + + function test_name_returnsSetName() public { + string memory expectedName = "vitalik.eth"; + registrar.setName(user1, expectedName); + + string memory label = LibString.toAddressString(user1); + bytes32 node = + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + + assertEq(registrar.name(node), expectedName, "Should return set name"); + } + + function testFuzz_name_returnsSetName(address addr, string memory expectedName) public { + registrar.setName(addr, expectedName); + + string memory label = LibString.toAddressString(addr); + bytes32 node = + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + + assertEq(registrar.name(node), expectedName, "Should return set name"); + } + + //////////////////////////////////////////////////////////////////////// + // nameForAddr() Tests + //////////////////////////////////////////////////////////////////////// + + function test_nameForAddr(address addr, string memory name) public { + assertEq(registrar.nameForAddr(addr), "", "before"); + vm.prank(addr); + registrar.setName(addr, name); + assertEq(registrar.nameForAddr(addr), name, "after"); + } + + //////////////////////////////////////////////////////////////////////// + // resolve() Tests + //////////////////////////////////////////////////////////////////////// + + function test_resolve_returnsEncodedName() public { + string memory expectedName = "nick.eth"; + registrar.setName(user1, expectedName); + + // Build DNS-encoded name for user1 + bytes memory dnsEncodedName = _buildDnsEncodedName(user1); + + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + bytes memory result = registrar.resolve(dnsEncodedName, data); + + string memory decodedName = abi.decode(result, (string)); + assertEq(decodedName, expectedName, "Should return encoded name"); + } + + function test_resolve_returnsEmptyForUnsetAddress() public view { + bytes memory dnsEncodedName = _buildDnsEncodedName(user1); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + bytes memory result = registrar.resolve(dnsEncodedName, data); + + string memory decodedName = abi.decode(result, (string)); + assertEq(decodedName, "", "Should return empty for unset address"); + } + + function testFuzz_resolve_differentAddresses(address addr, string memory expectedName) public { + registrar.setName(addr, expectedName); + + bytes memory dnsEncodedName = _buildDnsEncodedName(addr); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + bytes memory result = registrar.resolve(dnsEncodedName, data); + + string memory decodedName = abi.decode(result, (string)); + assertEq(decodedName, expectedName, "Should return correct name"); + } + + function test_resolve_revert_unsupportedResolverProfile() public { + bytes memory dnsEncodedName = _buildDnsEncodedName(user1); + // Use a different selector (e.g., addr(bytes32)) + bytes memory data = abi.encodeWithSelector(bytes4(0x3b3b57de), bytes32(0)); + + vm.expectRevert( + abi.encodeWithSelector( + StandaloneReverseRegistrar.UnsupportedResolverProfile.selector, + bytes4(0x3b3b57de) + ) + ); + registrar.resolve(dnsEncodedName, data); + } + + function testFuzz_resolve_revert_unsupportedResolverProfile(bytes4 selector) public { + vm.assume(selector != INameResolver.name.selector); + + bytes memory dnsEncodedName = _buildDnsEncodedName(user1); + bytes memory data = abi.encodeWithSelector(selector, bytes32(0)); + + vm.expectRevert( + abi.encodeWithSelector( + StandaloneReverseRegistrar.UnsupportedResolverProfile.selector, + selector + ) + ); + registrar.resolve(dnsEncodedName, data); + } + + function test_resolve_revert_unreachableName_wrongLength() public { + // Create a name with wrong length (not PARENT_LENGTH + 41) + bytes memory shortName = abi.encodePacked(uint8(10), "0123456789"); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + + vm.expectRevert( + abi.encodeWithSelector(StandaloneReverseRegistrar.UnreachableName.selector, shortName) + ); + registrar.resolve(shortName, data); + } + + function test_resolve_revert_unreachableName_wrongParent() public { + // Build name with correct length but wrong parent + // 41 bytes for address part + wrong parent + bytes memory addressPart = + abi.encodePacked(uint8(40), "0000000000000000000000000000000000000001"); + bytes memory wrongParent = + abi.encodePacked(uint8(5), "wrong", uint8(7), "reverse", uint8(0)); + bytes memory dnsEncodedName = abi.encodePacked(addressPart, wrongParent); + + // Ensure length matches expected + uint256 expectedLength = registrar.PARENT_LENGTH() + 41; + if (dnsEncodedName.length != expectedLength) { + // Adjust to have correct length but wrong hash + bytes memory padded = new bytes(expectedLength); + for (uint256 i = 0; i < addressPart.length && i < expectedLength; i++) { + padded[i] = addressPart[i]; + } + dnsEncodedName = padded; + } + + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + + vm.expectRevert( + abi.encodeWithSelector( + StandaloneReverseRegistrar.UnreachableName.selector, + dnsEncodedName + ) + ); + registrar.resolve(dnsEncodedName, data); + } + + //////////////////////////////////////////////////////////////////////// + // _setName() Tests (via mock) + //////////////////////////////////////////////////////////////////////// + + function test_setName_updatesMapping() public { + string memory name_ = "test.eth"; + registrar.setName(user1, name_); + + string memory label = LibString.toAddressString(user1); + bytes32 node = + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + + assertEq(registrar.name(node), name_, "Name should be stored"); + } + + function test_setName_emitsLabelRegisteredEvent() public { + string memory name_ = "alice.eth"; + string memory expectedLabel = LibString.toAddressString(user1); + uint256 expectedTokenId = uint256(keccak256(abi.encodePacked(expectedLabel))); + + vm.expectEmit(true, false, false, true); + emit IRegistryEvents.LabelRegistered( + expectedTokenId, + bytes32(expectedTokenId), + expectedLabel, + user1, + type(uint64).max, + address(this) + ); + + registrar.setName(user1, name_); + } + + function test_setName_emitsResolverUpdatedEvent() public { + string memory name_ = "bob.eth"; + string memory expectedLabel = LibString.toAddressString(user1); + uint256 expectedTokenId = uint256(keccak256(abi.encodePacked(expectedLabel))); + + vm.expectEmit(true, false, false, true); + emit IRegistryEvents.ResolverUpdated(expectedTokenId, address(registrar), address(this)); + + registrar.setName(user1, name_); + } + + function test_setName_emitsNameChangedEvent() public { + string memory name_ = "carol.eth"; + string memory label = LibString.toAddressString(user1); + bytes32 expectedNode = + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + + vm.expectEmit(true, false, false, true); + emit INameResolver.NameChanged(expectedNode, name_); + + registrar.setName(user1, name_); + } + + function test_setName_allEvents() public { + string memory name_ = "dave.eth"; + + vm.recordLogs(); + registrar.setName(user1, name_); + Vm.Log[] memory logs = vm.getRecordedLogs(); + + // Should have 3 events: NameRegistered, ResolverUpdated, NameChanged + assertEq(logs.length, 3, "Should emit 3 events"); + + // Verify event topics + assertEq( + logs[0].topics[0], + keccak256("LabelRegistered(uint256,bytes32,string,address,uint64,address)"), + "First event should be LabelRegistered" + ); + assertEq( + logs[1].topics[0], + keccak256("ResolverUpdated(uint256,address,address)"), + "Second event should be ResolverUpdated" + ); + assertEq( + logs[2].topics[0], + keccak256("NameChanged(bytes32,string)"), + "Third event should be NameChanged" + ); + } + + function test_setName_canOverwrite() public { + string memory firstName = "first.eth"; + string memory secondName = "second.eth"; + + registrar.setName(user1, firstName); + + string memory label = LibString.toAddressString(user1); + bytes32 node = + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + + assertEq(registrar.name(node), firstName, "First name should be set"); + + registrar.setName(user1, secondName); + assertEq(registrar.name(node), secondName, "Name should be overwritten"); + } + + function test_setName_emptyName() public { + registrar.setName(user1, ""); + + string memory label = LibString.toAddressString(user1); + bytes32 node = + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + + assertEq(registrar.name(node), "", "Empty name should be stored"); + } + + function testFuzz_setName(address addr, string memory name_) public { + registrar.setName(addr, name_); + + string memory label = LibString.toAddressString(addr); + bytes32 node = + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + + assertEq(registrar.name(node), name_, "Name should be stored"); + } + + //////////////////////////////////////////////////////////////////////// + // Integration Tests + //////////////////////////////////////////////////////////////////////// + + function test_fullFlow_setAndResolve() public { + string memory expectedName = "integration.eth"; + + // Set name + registrar.setName(user1, expectedName); + + // Resolve via resolve() + bytes memory dnsEncodedName = _buildDnsEncodedName(user1); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + bytes memory result = registrar.resolve(dnsEncodedName, data); + + string memory resolvedName = abi.decode(result, (string)); + assertEq(resolvedName, expectedName, "Resolved name should match"); + + // Also verify via direct name() call + string memory label = LibString.toAddressString(user1); + bytes32 node = + keccak256(abi.encodePacked(registrar.PARENT_NODE(), keccak256(abi.encodePacked(label)))); + assertEq(registrar.name(node), expectedName, "Direct name() should match"); + } + + function test_multipleUsers() public { + string memory name1 = "user1.eth"; + string memory name2 = "user2.eth"; + + registrar.setName(user1, name1); + registrar.setName(user2, name2); + + bytes memory dnsEncodedName1 = _buildDnsEncodedName(user1); + bytes memory dnsEncodedName2 = _buildDnsEncodedName(user2); + bytes memory data = abi.encodeCall(INameResolver.name, (bytes32(0))); + + string memory resolved1 = abi.decode(registrar.resolve(dnsEncodedName1, data), (string)); + string memory resolved2 = abi.decode(registrar.resolve(dnsEncodedName2, data), (string)); + + assertEq(resolved1, name1, "User1 name should match"); + assertEq(resolved2, name2, "User2 name should match"); + } + + function test_differentLabels() public { + // Deploy registrars with different labels + MockStandaloneReverseRegistrarImplementer ethRegistrar = + new MockStandaloneReverseRegistrarImplementer("default"); + MockStandaloneReverseRegistrarImplementer opRegistrar = + new MockStandaloneReverseRegistrarImplementer("8000000a"); + + // Parent nodes should be different + assertTrue( + ethRegistrar.PARENT_NODE() != opRegistrar.PARENT_NODE(), + "Parent nodes should differ" + ); + } + + //////////////////////////////////////////////////////////////////////// + // Helper Functions + //////////////////////////////////////////////////////////////////////// + + function _buildDnsEncodedName(address addr) internal pure returns (bytes memory) { + string memory addrString = LibString.toAddressString(addr); + + bytes memory parent = + abi.encodePacked( + uint8(bytes(ETH_LABEL).length), + ETH_LABEL, + uint8(7), + "reverse", + uint8(0) + ); + + return abi.encodePacked(uint8(40), addrString, parent); + } + + function _parseAddress(string memory str) internal pure returns (address) { + bytes memory strBytes = bytes(str); + require(strBytes.length == 40, "Invalid address length"); + + uint160 result = 0; + for (uint256 i = 0; i < 40; i++) { + result = result * 16 + _hexCharToUint(strBytes[i]); + } + return address(result); + } + + function _hexCharToUint(bytes1 c) internal pure returns (uint160) { + if (c >= "0" && c <= "9") { + return uint160(uint8(c) - uint8(bytes1("0"))); + } + if (c >= "a" && c <= "f") { + return uint160(uint8(c) - uint8(bytes1("a")) + 10); + } + if (c >= "A" && c <= "F") { + return uint160(uint8(c) - uint8(bytes1("A")) + 10); + } + revert("Invalid hex char"); + } +} diff --git a/contracts/test/unit/reverse-registrar/libraries/ChainIdsBuilderLib.t.sol b/contracts/test/unit/reverse-registrar/libraries/ChainIdsBuilderLib.t.sol new file mode 100644 index 000000000..7686cc46d --- /dev/null +++ b/contracts/test/unit/reverse-registrar/libraries/ChainIdsBuilderLib.t.sol @@ -0,0 +1,506 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// solhint-disable private-vars-leading-underscore, state-visibility, func-name-mixedcase, namechain/ordering, one-contract-per-file, namechain/import-order-separation, gas-small-strings, gas-strict-inequalities, gas-increment-by-one, gas-custom-errors + +import {Test} from "forge-std/Test.sol"; + +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +import {ChainIdsBuilderLib} from "~src/reverse-registrar/libraries/ChainIdsBuilderLib.sol"; + +/// @dev Harness that exposes the internal library function via an external call. +/// Memory arrays in the test are ABI-encoded as calldata automatically. +contract ChainIdsBuilderLibHarness { + function validateAndBuild(uint256[] calldata chainIds, uint256 currentChainId) + external + pure + returns (string memory) + { + return ChainIdsBuilderLib.validateAndBuild(chainIds, currentChainId); + } +} + + +contract ChainIdsBuilderLibTest is Test { + using Strings for uint256; + + ChainIdsBuilderLibHarness harness; + + function setUp() public { + harness = new ChainIdsBuilderLibHarness(); + } + + /// @dev Naive O(n²) reference implementation using string.concat. + function _referenceImpl(uint256[] memory ids) internal pure returns (string memory) { + string memory result = ids[0].toString(); + for (uint256 i = 1; i < ids.length; i++) { + result = string.concat(result, ", ", ids[i].toString()); + } + return result; + } + + //////////////////////////////////////////////////////////////////////// + // Happy Path – Single Element + //////////////////////////////////////////////////////////////////////// + + function test_singleChainId() public view { + uint256[] memory ids = new uint256[](1); + ids[0] = 10; + assertEq(harness.validateAndBuild(ids, 10), "10"); + } + + function test_singleChainId_zero() public view { + uint256[] memory ids = new uint256[](1); + ids[0] = 0; + assertEq(harness.validateAndBuild(ids, 0), "0"); + } + + function test_singleChainId_one() public view { + uint256[] memory ids = new uint256[](1); + ids[0] = 1; + assertEq(harness.validateAndBuild(ids, 1), "1"); + } + + function test_singleChainId_maxUint256() public view { + uint256[] memory ids = new uint256[](1); + ids[0] = type(uint256).max; + assertEq(harness.validateAndBuild(ids, type(uint256).max), type(uint256).max.toString()); + } + + //////////////////////////////////////////////////////////////////////// + // Happy Path – Two Elements + //////////////////////////////////////////////////////////////////////// + + function test_twoChainIds() public view { + uint256[] memory ids = new uint256[](2); + ids[0] = 1; + ids[1] = 10; + assertEq(harness.validateAndBuild(ids, 10), "1, 10"); + } + + function test_twoChainIds_zeroAndOne() public view { + uint256[] memory ids = new uint256[](2); + ids[0] = 0; + ids[1] = 1; + assertEq(harness.validateAndBuild(ids, 0), "0, 1"); + } + + function test_twoChainIds_consecutiveLarge() public view { + uint256[] memory ids = new uint256[](2); + ids[0] = type(uint256).max - 1; + ids[1] = type(uint256).max; + string memory expected = + string.concat((type(uint256).max - 1).toString(), ", ", type(uint256).max.toString()); + assertEq(harness.validateAndBuild(ids, type(uint256).max), expected); + } + + //////////////////////////////////////////////////////////////////////// + // Happy Path – Multiple Elements + //////////////////////////////////////////////////////////////////////// + + function test_multipleChainIds_currentAtStart() public view { + uint256[] memory ids = new uint256[](4); + ids[0] = 1; + ids[1] = 10; + ids[2] = 8453; + ids[3] = 42161; + assertEq(harness.validateAndBuild(ids, 1), "1, 10, 8453, 42161"); + } + + function test_multipleChainIds_currentInMiddle() public view { + uint256[] memory ids = new uint256[](4); + ids[0] = 1; + ids[1] = 10; + ids[2] = 8453; + ids[3] = 42161; + assertEq(harness.validateAndBuild(ids, 10), "1, 10, 8453, 42161"); + } + + function test_multipleChainIds_currentAtEnd() public view { + uint256[] memory ids = new uint256[](4); + ids[0] = 1; + ids[1] = 10; + ids[2] = 8453; + ids[3] = 42161; + assertEq(harness.validateAndBuild(ids, 42161), "1, 10, 8453, 42161"); + } + + function test_consecutiveNumbers() public view { + uint256[] memory ids = new uint256[](5); + ids[0] = 1; + ids[1] = 2; + ids[2] = 3; + ids[3] = 4; + ids[4] = 5; + assertEq(harness.validateAndBuild(ids, 3), "1, 2, 3, 4, 5"); + } + + function test_chainIdZeroWithOthers() public view { + uint256[] memory ids = new uint256[](3); + ids[0] = 0; + ids[1] = 1; + ids[2] = 10; + assertEq(harness.validateAndBuild(ids, 0), "0, 1, 10"); + } + + function test_maxUint256WithOthers() public view { + uint256[] memory ids = new uint256[](3); + ids[0] = 1; + ids[1] = 42161; + ids[2] = type(uint256).max; + string memory expected = string.concat("1, 42161, ", type(uint256).max.toString()); + assertEq(harness.validateAndBuild(ids, 1), expected); + } + + //////////////////////////////////////////////////////////////////////// + // Happy Path – Large Array (matches reference implementation) + //////////////////////////////////////////////////////////////////////// + + function test_largeArray_matchesReference() public view { + uint256[] memory ids = new uint256[](20); + ids[0] = 1; + ids[1] = 5; + ids[2] = 10; + ids[3] = 25; + ids[4] = 56; + ids[5] = 100; + ids[6] = 137; + ids[7] = 250; + ids[8] = 324; + ids[9] = 1101; + ids[10] = 5000; + ids[11] = 8453; + ids[12] = 34443; + ids[13] = 42161; + ids[14] = 42170; + ids[15] = 43114; + ids[16] = 59144; + ids[17] = 81457; + ids[18] = 534352; + ids[19] = 7777777; + + string memory result = harness.validateAndBuild(ids, 10); + string memory expected = _referenceImpl(ids); + assertEq(result, expected); + } + + function test_largeArray_explicitString() public view { + uint256[] memory ids = new uint256[](6); + ids[0] = 1; + ids[1] = 10; + ids[2] = 137; + ids[3] = 8453; + ids[4] = 42161; + ids[5] = 534352; + assertEq(harness.validateAndBuild(ids, 10), "1, 10, 137, 8453, 42161, 534352"); + } + + //////////////////////////////////////////////////////////////////////// + // Happy Path – Typical Real-World Chain IDs + //////////////////////////////////////////////////////////////////////// + + function test_realWorldChainIds_ethereumAndL2s() public view { + uint256[] memory ids = new uint256[](5); + ids[0] = 1; // Ethereum + ids[1] = 10; // Optimism + ids[2] = 137; // Polygon + ids[3] = 8453; // Base + ids[4] = 42161; // Arbitrum + assertEq(harness.validateAndBuild(ids, 1), "1, 10, 137, 8453, 42161"); + } + + //////////////////////////////////////////////////////////////////////// + // Error Tests – Empty Array + //////////////////////////////////////////////////////////////////////// + + function test_revert_emptyArray() public { + uint256[] memory ids = new uint256[](0); + vm.expectRevert(abi.encodeWithSelector(ChainIdsBuilderLib.CurrentChainNotFound.selector, 10)); + harness.validateAndBuild(ids, 10); + } + + function test_revert_emptyArray_chainIdZero() public { + uint256[] memory ids = new uint256[](0); + vm.expectRevert(abi.encodeWithSelector(ChainIdsBuilderLib.CurrentChainNotFound.selector, 0)); + harness.validateAndBuild(ids, 0); + } + + //////////////////////////////////////////////////////////////////////// + // Error Tests – Current Chain Not Found + //////////////////////////////////////////////////////////////////////// + + function test_revert_currentChainNotFound_singleElement() public { + uint256[] memory ids = new uint256[](1); + ids[0] = 1; + vm.expectRevert(abi.encodeWithSelector(ChainIdsBuilderLib.CurrentChainNotFound.selector, 10)); + harness.validateAndBuild(ids, 10); + } + + function test_revert_currentChainNotFound_multipleElements() public { + uint256[] memory ids = new uint256[](3); + ids[0] = 1; + ids[1] = 8453; + ids[2] = 42161; + vm.expectRevert(abi.encodeWithSelector(ChainIdsBuilderLib.CurrentChainNotFound.selector, 10)); + harness.validateAndBuild(ids, 10); + } + + function test_revert_currentChainNotFound_neighbourValues() public { + uint256[] memory ids = new uint256[](2); + ids[0] = 9; + ids[1] = 11; + vm.expectRevert(abi.encodeWithSelector(ChainIdsBuilderLib.CurrentChainNotFound.selector, 10)); + harness.validateAndBuild(ids, 10); + } + + //////////////////////////////////////////////////////////////////////// + // Error Tests – Not Ascending + //////////////////////////////////////////////////////////////////////// + + function test_revert_notAscending_equalPair() public { + uint256[] memory ids = new uint256[](2); + ids[0] = 10; + ids[1] = 10; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, 10); + } + + function test_revert_notAscending_descendingPair() public { + uint256[] memory ids = new uint256[](2); + ids[0] = 42161; + ids[1] = 10; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, 10); + } + + function test_revert_notAscending_equalInMiddle() public { + uint256[] memory ids = new uint256[](3); + ids[0] = 1; + ids[1] = 10; + ids[2] = 10; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, 10); + } + + function test_revert_notAscending_descendingInMiddle() public { + uint256[] memory ids = new uint256[](3); + ids[0] = 1; + ids[1] = 42161; + ids[2] = 10; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, 10); + } + + function test_revert_notAscending_fullyDescending() public { + uint256[] memory ids = new uint256[](3); + ids[0] = 42161; + ids[1] = 10; + ids[2] = 1; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, 10); + } + + function test_revert_notAscending_duplicateAtStart() public { + uint256[] memory ids = new uint256[](3); + ids[0] = 1; + ids[1] = 1; + ids[2] = 10; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, 10); + } + + function test_revert_notAscending_duplicateZeros() public { + uint256[] memory ids = new uint256[](2); + ids[0] = 0; + ids[1] = 0; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, 0); + } + + //////////////////////////////////////////////////////////////////////// + // Error Tests – Ascending check fires before CurrentChainNotFound + //////////////////////////////////////////////////////////////////////// + + function test_revert_notAscending_firesBeforeCurrentNotFound() public { + // Array is not ascending AND doesn't contain current chain. + // ChainIdsNotAscending should fire first because the loop breaks early. + uint256[] memory ids = new uint256[](3); + ids[0] = 100; + ids[1] = 50; + ids[2] = 200; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, 999); + } + + //////////////////////////////////////////////////////////////////////// + // Fuzz Tests – Single Element + //////////////////////////////////////////////////////////////////////// + + function testFuzz_singleElement(uint256 chainId) public view { + uint256[] memory ids = new uint256[](1); + ids[0] = chainId; + assertEq(harness.validateAndBuild(ids, chainId), chainId.toString()); + } + + //////////////////////////////////////////////////////////////////////// + // Fuzz Tests – Two Elements (matches reference) + //////////////////////////////////////////////////////////////////////// + + function testFuzz_twoElements(uint256 a, uint256 gap) public view { + vm.assume(a < type(uint256).max); + gap = bound(gap, 1, type(uint256).max - a); + uint256 b = a + gap; + + uint256[] memory ids = new uint256[](2); + ids[0] = a; + ids[1] = b; + + string memory expected = _referenceImpl(ids); + assertEq(harness.validateAndBuild(ids, a), expected); + } + + //////////////////////////////////////////////////////////////////////// + // Fuzz Tests – Three Elements (matches reference) + //////////////////////////////////////////////////////////////////////// + + function testFuzz_threeElements(uint256 a, uint256 gap1, uint256 gap2) public view { + vm.assume(a < type(uint256).max - 1); + gap1 = bound(gap1, 1, (type(uint256).max - a) / 2); + uint256 b = a + gap1; + gap2 = bound(gap2, 1, type(uint256).max - b); + uint256 c = b + gap2; + + uint256[] memory ids = new uint256[](3); + ids[0] = a; + ids[1] = b; + ids[2] = c; + + string memory expected = _referenceImpl(ids); + // Use middle element as current chain ID + assertEq(harness.validateAndBuild(ids, b), expected); + } + + //////////////////////////////////////////////////////////////////////// + // Fuzz Tests – Not Ascending (always reverts) + //////////////////////////////////////////////////////////////////////// + + function testFuzz_revert_notAscending(uint256 a, uint256 b) public { + vm.assume(b <= a); + uint256[] memory ids = new uint256[](2); + ids[0] = a; + ids[1] = b; + vm.expectRevert(ChainIdsBuilderLib.ChainIdsNotAscending.selector); + harness.validateAndBuild(ids, a); + } + + //////////////////////////////////////////////////////////////////////// + // Fuzz Tests – Current Chain Not Found (always reverts) + //////////////////////////////////////////////////////////////////////// + + function testFuzz_revert_currentNotFound(uint256 current, uint256 chainId) public { + vm.assume(current != chainId); + uint256[] memory ids = new uint256[](1); + ids[0] = chainId; + vm.expectRevert( + abi.encodeWithSelector(ChainIdsBuilderLib.CurrentChainNotFound.selector, current) + ); + harness.validateAndBuild(ids, current); + } + + //////////////////////////////////////////////////////////////////////// + // Fuzz Test – Larger Array (matches reference, random ascending values) + //////////////////////////////////////////////////////////////////////// + + function testFuzz_fiveElements_matchesReference( + uint256 a, + uint256 g1, + uint256 g2, + uint256 g3, + uint256 g4 + ) + public + view + { + vm.assume(a < type(uint256).max / 5); + g1 = bound(g1, 1, type(uint256).max / 5); + g2 = bound(g2, 1, type(uint256).max / 5); + g3 = bound(g3, 1, type(uint256).max / 5); + g4 = bound(g4, 1, type(uint256).max / 5); + + uint256[] memory ids = new uint256[](5); + ids[0] = a; + ids[1] = a + g1; + ids[2] = a + g1 + g2; + ids[3] = a + g1 + g2 + g3; + ids[4] = a + g1 + g2 + g3 + g4; + + string memory expected = _referenceImpl(ids); + assertEq(harness.validateAndBuild(ids, ids[2]), expected); + } + + //////////////////////////////////////////////////////////////////////// + // Edge Case – Memory Safety (subsequent allocations are not corrupted) + //////////////////////////////////////////////////////////////////////// + + function test_memorySafety_subsequentAllocations() public view { + uint256[] memory ids = new uint256[](3); + ids[0] = 1; + ids[1] = 10; + ids[2] = 8453; + + string memory result = harness.validateAndBuild(ids, 10); + + // Perform another allocation after the library call and verify both are intact. + string memory other = "hello world"; + + assertEq(result, "1, 10, 8453"); + assertEq(other, "hello world"); + } + + //////////////////////////////////////////////////////////////////////// + // Edge Case – Digit Boundary Values (powers of 10) + //////////////////////////////////////////////////////////////////////// + + function test_powersOfTen() public view { + uint256[] memory ids = new uint256[](8); + ids[0] = 1; + ids[1] = 10; + ids[2] = 100; + ids[3] = 1000; + ids[4] = 10000; + ids[5] = 100000; + ids[6] = 1000000; + ids[7] = 10000000; + + string memory result = harness.validateAndBuild(ids, 1); + assertEq(result, "1, 10, 100, 1000, 10000, 100000, 1000000, 10000000"); + } + + function test_justBelowPowersOfTen() public view { + uint256[] memory ids = new uint256[](4); + ids[0] = 9; + ids[1] = 99; + ids[2] = 999; + ids[3] = 9999; + + string memory result = harness.validateAndBuild(ids, 9); + assertEq(result, "9, 99, 999, 9999"); + } + + //////////////////////////////////////////////////////////////////////// + // Edge Case – Wide Spread of Digit Lengths + //////////////////////////////////////////////////////////////////////// + + function test_wideSpreadDigitLengths() public view { + uint256[] memory ids = new uint256[](4); + ids[0] = 0; + ids[1] = 7; + ids[2] = 42161; + ids[3] = 100000000000000000; // 1e17 + + string memory result = harness.validateAndBuild(ids, 0); + string memory expected = _referenceImpl(ids); + assertEq(result, expected); + } +} diff --git a/contracts/test/unit/testnet/MockPremigrator.t.sol b/contracts/test/unit/testnet/MockPremigrator.t.sol new file mode 100644 index 000000000..3e44b4430 --- /dev/null +++ b/contracts/test/unit/testnet/MockPremigrator.t.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +// solhint-disable private-vars-leading-underscore, state-visibility, func-name-mixedcase + +import {LibLabel} from "~src/utils/LibLabel.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {MockPremigrator} from "~test/mocks/MockPremigrator.sol"; +import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; + +contract MockPremigratorTest is V2Fixture { + MockPremigrator premigrator; + + string testLabel = "test"; + IRegistry testSubregistry = IRegistry(makeAddr("subregistry")); + address testResolver = makeAddr("resolver"); + + function setUp() external { + deployV2Fixture(); + premigrator = new MockPremigrator(ethRegistry); + ethRegistry.grantRootRoles( + RegistryRolesLib.ROLE_REGISTRAR | RegistryRolesLib.ROLE_RENEW, + address(premigrator) + ); + } + + function test_constructor() external view { + assertEq(address(premigrator.ETH_REGISTRY()), address(ethRegistry), "ETH_REGISTRY"); + } + + function test_preMigrate_reservesAvailableName() external { + uint64 expiry = uint64(block.timestamp + 30 days); + premigrator.preMigrate(testLabel, expiry, testSubregistry, testResolver); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id(testLabel)); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.RESERVED), "status"); + assertEq(state.expiry, expiry, "expiry"); + assertEq(state.latestOwner, address(0), "latestOwner"); + assertEq( + address(ethRegistry.getSubregistry(testLabel)), + address(testSubregistry), + "subregistry" + ); + assertEq(ethRegistry.getResolver(testLabel), testResolver, "resolver"); + } + + function test_preMigrate_renewsExistingReservation() external { + uint64 expiry = uint64(block.timestamp + 30 days); + premigrator.preMigrate(testLabel, expiry, testSubregistry, testResolver); + uint256 tokenId = ethRegistry.getState(LibLabel.id(testLabel)).tokenId; + + uint64 newExpiry = expiry + 30 days; + premigrator.preMigrate(testLabel, newExpiry, IRegistry(address(0)), address(0)); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id(testLabel)); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.RESERVED), "status"); + assertEq(state.expiry, newExpiry, "expiry"); + assertEq(state.tokenId, tokenId, "tokenId"); + + // renewal keeps the original reservation's subregistry and resolver + assertEq( + address(ethRegistry.getSubregistry(testLabel)), + address(testSubregistry), + "subregistry" + ); + assertEq(ethRegistry.getResolver(testLabel), testResolver, "resolver"); + } + + function test_preMigrate_keepsLaterReservation() external { + uint64 expiry = uint64(block.timestamp + 60 days); + premigrator.preMigrate(testLabel, expiry, testSubregistry, testResolver); + + premigrator.preMigrate(testLabel, expiry - 30 days, IRegistry(address(0)), address(0)); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id(testLabel)); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.RESERVED), "status"); + assertEq(state.expiry, expiry, "expiry"); + } + + function test_preMigrate_skipsRegisteredName() external { + address owner = makeAddr("owner"); + uint64 expiry = uint64(block.timestamp + 30 days); + ethRegistry.register(testLabel, owner, IRegistry(address(0)), address(0), 0, expiry); + + premigrator.preMigrate(testLabel, expiry + 30 days, testSubregistry, testResolver); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id(testLabel)); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.REGISTERED), "status"); + assertEq(state.expiry, expiry, "expiry"); + assertEq(state.latestOwner, owner, "latestOwner"); + } +} diff --git a/contracts/test/unit/testnet/TestnetV1PremigrationRegistrar.t.sol b/contracts/test/unit/testnet/TestnetV1PremigrationRegistrar.t.sol new file mode 100644 index 000000000..3dd2d30d1 --- /dev/null +++ b/contracts/test/unit/testnet/TestnetV1PremigrationRegistrar.t.sol @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +// solhint-disable private-vars-leading-underscore, state-visibility, func-name-mixedcase, contracts-v2/ordering, one-contract-per-file + +import {IETHRegistrarController} from "@ens/contracts/ethregistrar/IETHRegistrarController.sol"; +import {DefaultReverseRegistrar} from "@ens/contracts/reverseRegistrar/DefaultReverseRegistrar.sol"; +import { + ReverseRegistrar, + ADDR_REVERSE_NODE +} from "@ens/contracts/reverseRegistrar/ReverseRegistrar.sol"; +import {PublicResolver} from "@ens/contracts/resolvers/PublicResolver.sol"; +import {INameWrapper} from "@ens/contracts/wrapper/INameWrapper.sol"; + +import {LibLabel} from "~src/utils/LibLabel.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {RegistryRolesLib} from "~src/registry/libraries/RegistryRolesLib.sol"; +import {TestnetV1PremigrationRegistrar} from "~src/testnet/TestnetV1PremigrationRegistrar.sol"; +import {V1Fixture} from "~test/fixtures/V1Fixture.sol"; +import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; + +contract TestnetV1PremigrationRegistrarTest is V1Fixture, V2Fixture { + TestnetV1PremigrationRegistrar registrar; + ReverseRegistrar reverseRegistrar; + DefaultReverseRegistrar defaultReverseRegistrar; + PublicResolver publicResolver; + + IRegistry premigrationRegistry = IRegistry(makeAddr("premigrationRegistry")); + address premigrationResolver = makeAddr("premigrationResolver"); + + string testLabel = "test"; + bytes32 testReferrer = keccak256("referrer"); + address user = makeAddr("user"); + + function setUp() external { + deployV1Fixture(); + deployV2Fixture(); + + reverseRegistrar = new ReverseRegistrar(registryV1); + registryV1.setOwner(ADDR_REVERSE_NODE, address(reverseRegistrar)); + defaultReverseRegistrar = new DefaultReverseRegistrar(); + + registrar = new TestnetV1PremigrationRegistrar( + baseRegistrar, + registryV1, + reverseRegistrar, + defaultReverseRegistrar, + ethRegistry, + premigrationRegistry, + premigrationResolver + ); + + publicResolver = new PublicResolver( + registryV1, + INameWrapper(address(nameWrapper)), + address(registrar), // trustedETHController + address(reverseRegistrar) // trustedReverseRegistrar + ); + + baseRegistrar.addController(address(registrar)); + ethRegistry.grantRootRoles( + RegistryRolesLib.ROLE_REGISTRAR | RegistryRolesLib.ROLE_RENEW, + address(registrar) + ); + reverseRegistrar.setController(address(registrar), true); + defaultReverseRegistrar.setController(address(registrar), true); + } + + function _defaultRegistration() + internal + view + returns (IETHRegistrarController.Registration memory) + { + return + IETHRegistrarController.Registration({label: testLabel, owner: user, duration: registrar.MIN_REGISTRATION_DURATION(), secret: bytes32( + 0 + ), resolver: address(0), data: new bytes[](0), reverseRecord: 0, referrer: testReferrer}); + } + + function _ethNode(bytes32 labelhash) internal view returns (bytes32) { + return keccak256(abi.encodePacked(registrar.ETH_NODE(), labelhash)); + } + + function test_constructor() external view { + assertEq(address(registrar.BASE()), address(baseRegistrar), "BASE"); + assertEq(address(registrar.ENS_REGISTRY()), address(registryV1), "ENS_REGISTRY"); + assertEq( + address(registrar.REVERSE_REGISTRAR()), + address(reverseRegistrar), + "REVERSE_REGISTRAR" + ); + assertEq( + address(registrar.DEFAULT_REVERSE_REGISTRAR()), + address(defaultReverseRegistrar), + "DEFAULT_REVERSE_REGISTRAR" + ); + assertEq(address(registrar.ETH_REGISTRY()), address(ethRegistry), "ETH_REGISTRY"); + assertEq( + address(registrar.PREMIGRATION_REGISTRY()), + address(premigrationRegistry), + "PREMIGRATION_REGISTRY" + ); + assertEq(registrar.PREMIGRATION_RESOLVER(), premigrationResolver, "PREMIGRATION_RESOLVER"); + } + + //////////////////////////////////////////////////////////////////////// + // available() + //////////////////////////////////////////////////////////////////////// + + function test_available() external view { + assertTrue(registrar.available(testLabel)); + } + + function test_available_labelTooShort() external view { + assertFalse(registrar.available("ab")); + } + + function test_available_registered() external { + registrar.register(_defaultRegistration()); + assertFalse(registrar.available(testLabel), "registered"); + + uint256 tokenId = LibLabel.id(testLabel); + vm.warp(baseRegistrar.nameExpires(tokenId) + baseRegistrar.GRACE_PERIOD() + 1); + assertTrue(registrar.available(testLabel), "after grace"); + } + + //////////////////////////////////////////////////////////////////////// + // register() + //////////////////////////////////////////////////////////////////////// + + function test_register() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + uint256 tokenId = LibLabel.id(testLabel); + uint256 expires = block.timestamp + registration.duration; + + vm.expectEmit(); + emit TestnetV1PremigrationRegistrar.NameRegistered( + testLabel, + bytes32(tokenId), + user, + 0, + 0, + expires, + testReferrer + ); + vm.prank(user); + registrar.register(registration); + + // v1 registration + assertEq(baseRegistrar.ownerOf(tokenId), user, "ownerOf"); + assertEq(baseRegistrar.nameExpires(tokenId), expires, "nameExpires"); + assertEq(registryV1.owner(_ethNode(bytes32(tokenId))), user, "node owner"); + + // v2 reservation + IPermissionedRegistry.State memory state = ethRegistry.getState(tokenId); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.RESERVED), "status"); + assertEq(state.expiry, uint64(expires + registrar.CONTINUITY_BONUS_PERIOD()), "expiry"); + assertEq(state.latestOwner, address(0), "latestOwner"); + assertEq( + address(ethRegistry.getSubregistry(testLabel)), + address(premigrationRegistry), + "subregistry" + ); + assertEq(ethRegistry.getResolver(testLabel), premigrationResolver, "resolver"); + } + + function test_register_refundsOverpayment() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + vm.deal(user, 1 ether); + vm.prank(user); + registrar.register{value: 0.5 ether}(registration); + + assertEq(user.balance, 1 ether, "user balance"); + assertEq(address(registrar).balance, 0, "registrar balance"); + } + + function test_register_refundFailed() external { + RegisterCaller caller = new RegisterCaller(registrar); + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + + vm.expectRevert( + abi.encodeWithSelector( + TestnetV1PremigrationRegistrar.RefundFailed.selector, + address(caller), + 0.5 ether + ) + ); + caller.callRegister{value: 0.5 ether}(registration); + } + + function test_register_durationTooShort() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registration.duration = registrar.MIN_REGISTRATION_DURATION() - 1; + + vm.expectRevert( + abi.encodeWithSelector( + TestnetV1PremigrationRegistrar.DurationTooShort.selector, + registration.duration + ) + ); + registrar.register(registration); + } + + function test_register_nameNotAvailable_registered() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registrar.register(registration); + + vm.expectRevert( + abi.encodeWithSelector( + TestnetV1PremigrationRegistrar.NameNotAvailable.selector, + testLabel + ) + ); + registrar.register(registration); + } + + function test_register_nameNotAvailable_labelTooShort() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registration.label = "ab"; + + vm.expectRevert( + abi.encodeWithSelector( + TestnetV1PremigrationRegistrar.NameNotAvailable.selector, + registration.label + ) + ); + registrar.register(registration); + } + + function test_register_resolverRequiredWhenDataSupplied() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registration.data = new bytes[](1); + registration.data[0] = ""; + + vm.expectRevert(TestnetV1PremigrationRegistrar.ResolverRequiredWhenDataSupplied.selector); + registrar.register(registration); + } + + function test_register_resolverRequiredForReverseRecord() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registration.reverseRecord = registrar.REVERSE_RECORD_ETHEREUM_BIT(); + + vm.expectRevert(TestnetV1PremigrationRegistrar.ResolverRequiredForReverseRecord.selector); + registrar.register(registration); + } + + function test_register_expiryTooLarge() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registration.duration = type(uint64).max; + uint256 expires = block.timestamp + registration.duration; + + vm.expectRevert( + abi.encodeWithSelector( + TestnetV1PremigrationRegistrar.ExpiryTooLarge.selector, + expires + registrar.CONTINUITY_BONUS_PERIOD() + ) + ); + registrar.register(registration); + } + + //////////////////////////////////////////////////////////////////////// + // register() with resolver / reverse records + //////////////////////////////////////////////////////////////////////// + + function test_register_withResolverAndData() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + uint256 tokenId = LibLabel.id(testLabel); + bytes32 node = _ethNode(bytes32(tokenId)); + registration.resolver = address(publicResolver); + registration.data = new bytes[](1); + registration.data[0] = abi.encodeCall( + publicResolver.setText, + (node, "url", "https://ens.domains") + ); + + vm.prank(user); + registrar.register(registration); + + assertEq(baseRegistrar.ownerOf(tokenId), user, "ownerOf"); + assertEq(registryV1.owner(node), user, "node owner"); + assertEq(registryV1.resolver(node), address(publicResolver), "node resolver"); + assertEq(publicResolver.text(node, "url"), "https://ens.domains", "text"); + + // no reverse record requested + assertEq(registryV1.owner(reverseRegistrar.node(user)), address(0), "reverse owner"); + assertEq(defaultReverseRegistrar.nameForAddr(user), "", "default reverse"); + } + + function test_register_reverseRecordEthereum() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registration.resolver = address(publicResolver); + registration.reverseRecord = registrar.REVERSE_RECORD_ETHEREUM_BIT(); + + vm.prank(user); + registrar.register(registration); + + bytes32 reverseNode = reverseRegistrar.node(user); + assertEq(registryV1.owner(reverseNode), user, "reverse owner"); + assertEq(registryV1.resolver(reverseNode), address(publicResolver), "reverse resolver"); + assertEq(publicResolver.name(reverseNode), "test.eth", "reverse name"); + assertEq(defaultReverseRegistrar.nameForAddr(user), "", "default reverse"); + } + + function test_register_reverseRecordDefault() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registration.resolver = address(publicResolver); + registration.reverseRecord = registrar.REVERSE_RECORD_DEFAULT_BIT(); + + vm.prank(user); + registrar.register(registration); + + assertEq(defaultReverseRegistrar.nameForAddr(user), "test.eth", "default reverse"); + assertEq(registryV1.owner(reverseRegistrar.node(user)), address(0), "reverse owner"); + } + + function test_register_reverseRecordBoth() external { + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + registration.resolver = address(publicResolver); + registration.reverseRecord = + registrar.REVERSE_RECORD_ETHEREUM_BIT() | registrar.REVERSE_RECORD_DEFAULT_BIT(); + + vm.prank(user); + registrar.register(registration); + + bytes32 reverseNode = reverseRegistrar.node(user); + assertEq(registryV1.owner(reverseNode), user, "reverse owner"); + assertEq(publicResolver.name(reverseNode), "test.eth", "reverse name"); + assertEq(defaultReverseRegistrar.nameForAddr(user), "test.eth", "default reverse"); + } + + //////////////////////////////////////////////////////////////////////// + // register() premigration branches + //////////////////////////////////////////////////////////////////////// + + function test_register_renewsExistingReservation() external { + address reservedResolver = makeAddr("reservedResolver"); + uint64 reservedExpiry = uint64(block.timestamp + 1 days); + ethRegistry.register( + testLabel, + address(0), // reserve + IRegistry(address(0)), + reservedResolver, + 0, + reservedExpiry + ); + uint256 tokenId = ethRegistry.getState(LibLabel.id(testLabel)).tokenId; + + IETHRegistrarController.Registration memory registration = _defaultRegistration(); + uint256 expires = block.timestamp + registration.duration; + registrar.register(registration); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id(testLabel)); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.RESERVED), "status"); + assertEq(state.expiry, uint64(expires + registrar.CONTINUITY_BONUS_PERIOD()), "expiry"); + assertEq(state.tokenId, tokenId, "tokenId"); + + // renewal keeps the original reservation's subregistry and resolver + assertEq(address(ethRegistry.getSubregistry(testLabel)), address(0), "subregistry"); + assertEq(ethRegistry.getResolver(testLabel), reservedResolver, "resolver"); + } + + function test_register_keepsLaterReservation() external { + uint64 reservedExpiry = uint64(block.timestamp + 365 days); + ethRegistry.register( + testLabel, + address(0), // reserve + IRegistry(address(0)), + address(0), + 0, + reservedExpiry + ); + + registrar.register(_defaultRegistration()); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id(testLabel)); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.RESERVED), "status"); + assertEq(state.expiry, reservedExpiry, "expiry"); + } + + function test_register_skipsRegisteredName() external { + address ownerV2 = makeAddr("ownerV2"); + uint64 registeredExpiry = uint64(block.timestamp + 1 days); + ethRegistry.register( + testLabel, + ownerV2, + IRegistry(address(0)), + address(0), + 0, + registeredExpiry + ); + + registrar.register(_defaultRegistration()); + + IPermissionedRegistry.State memory state = ethRegistry.getState(LibLabel.id(testLabel)); + assertEq(uint8(state.status), uint8(IPermissionedRegistry.Status.REGISTERED), "status"); + assertEq(state.expiry, registeredExpiry, "expiry"); + assertEq(state.latestOwner, ownerV2, "latestOwner"); + } +} + + +/// @dev Calls `register` with value but cannot receive the refund. +contract RegisterCaller { + TestnetV1PremigrationRegistrar internal immutable REGISTRAR; + + constructor(TestnetV1PremigrationRegistrar registrar) { + REGISTRAR = registrar; + } + + function callRegister(IETHRegistrarController.Registration memory registration) + external + payable + { + REGISTRAR.register{value: msg.value}(registration); + } +} diff --git a/contracts/test/unit/universalResolver/UniversalResolverV2.t.sol b/contracts/test/unit/universalResolver/UniversalResolverV2.t.sol new file mode 100755 index 000000000..aa1c72c9c --- /dev/null +++ b/contracts/test/unit/universalResolver/UniversalResolverV2.t.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {IUniversalResolver} from "@ens/contracts/universalResolver/IUniversalResolver.sol"; + +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {IUniversalResolverV2} from "~src/universalResolver/interfaces/IUniversalResolverV2.sol"; +import {V2Fixture} from "~test/fixtures/V2Fixture.sol"; + +// NOTE: most of these tests are covered by LibRegistry.t.sol + +contract UniversalResolverV2Test is V2Fixture { + function setUp() external { + deployV2Fixture(); + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface( + address(universalResolver), + type(IUniversalResolver).interfaceId + ), + "IUniversalResolver" + ); + assertTrue( + ERC165Checker.supportsInterface( + address(universalResolver), + type(IUniversalResolverV2).interfaceId + ), + "IUniversalResolverV2" + ); + } + + function test_findOwner() external { + assertEq(universalResolver.findOwner(NameCoder.encode("")), address(0)); + assertEq(universalResolver.findOwner(NameCoder.encode("eth")), address(this)); + + ethRegistry.register( + "test", + address(1), + IRegistry(address(0)), + address(0), + 0, + type(uint64).max + ); + assertEq(universalResolver.findOwner(NameCoder.encode("test.eth")), address(1)); + } + + function test_findCanonicalName() external view { + assertEq(universalResolver.findCanonicalName(rootRegistry), NameCoder.encode("")); + assertEq(universalResolver.findCanonicalName(ethRegistry), NameCoder.encode("eth")); + } + + function test_findCanonicalRegistry() external view { + assertEq( + address(universalResolver.findCanonicalRegistry(NameCoder.encode(""))), + address(rootRegistry) + ); + assertEq( + address(universalResolver.findCanonicalRegistry(NameCoder.encode("eth"))), + address(ethRegistry) + ); + } + + function test_findExactRegistry() external view { + assertEq( + address(universalResolver.findExactRegistry(NameCoder.encode(""))), + address(rootRegistry) + ); + assertEq( + address(universalResolver.findExactRegistry(NameCoder.encode("eth"))), + address(ethRegistry) + ); + } + + function test_findParentRegistry() external view { + assertEq(address(universalResolver.findParentRegistry(NameCoder.encode(""))), address(0)); + assertEq( + address(universalResolver.findParentRegistry(NameCoder.encode("eth"))), + address(rootRegistry) + ); + } + + function test_findRegistries() external view { + IRegistry[] memory v = universalResolver.findRegistries(NameCoder.encode("eth")); + assertEq(address(v[0]), address(ethRegistry)); + assertEq(address(v[1]), address(rootRegistry)); + } +} diff --git a/contracts/test/unit/universalResolver/UpgradableUniversalResolverProxy.t.sol b/contracts/test/unit/universalResolver/UpgradableUniversalResolverProxy.t.sol index 57d37470d..f5ac00cef 100644 --- a/contracts/test/unit/universalResolver/UpgradableUniversalResolverProxy.t.sol +++ b/contracts/test/unit/universalResolver/UpgradableUniversalResolverProxy.t.sol @@ -15,7 +15,8 @@ import { import {BytesUtils} from "@ens/contracts/utils/BytesUtils.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {IPermissionedRegistry} from "~src/registry/interfaces/IPermissionedRegistry.sol"; import {UniversalResolverV2} from "~src/universalResolver/UniversalResolverV2.sol"; import { UpgradableUniversalResolverProxy @@ -48,7 +49,11 @@ contract ProxyTest is Test { // Deploy the implementations urV1 = new UniversalResolverV1(address(0), ENS(address(this)), batchGatewayProvider); - urV2 = new UniversalResolverV2(IRegistry(address(0)), batchGatewayProvider); + urV2 = new UniversalResolverV2( + IPermissionedRegistry(address(0)), + batchGatewayProvider, + IContractNamer(address(0)) + ); // Deploy the proxy with V1 implementation proxy = new UpgradableUniversalResolverProxy(ADMIN, address(urV1)); @@ -126,17 +131,12 @@ contract ProxyTest is Test { // Create a new proxy with the mock implementation vm.prank(ADMIN); - UpgradableUniversalResolverProxy testProxy = new UpgradableUniversalResolverProxy( - ADMIN, - address(mockImpl) - ); + UpgradableUniversalResolverProxy testProxy = + new UpgradableUniversalResolverProxy(ADMIN, address(mockImpl)); // Create calldata for resolve method - bytes memory callData = abi.encodeWithSignature( - "resolve(bytes,bytes)", - dnsEncodedName, - mockData - ); + bytes memory callData = + abi.encodeWithSignature("resolve(bytes,bytes)", dnsEncodedName, mockData); // Make the call through the proxy (bool success, bytes memory result) = address(testProxy).call(callData); @@ -145,10 +145,8 @@ contract ProxyTest is Test { assertTrue(success); // Decode the result to verify it matches expectations - (bytes memory returnedData, address returnedResolver) = abi.decode( - result, - (bytes, address) - ); + (bytes memory returnedData, address returnedResolver) = + abi.decode(result, (bytes, address)); assertEq(returnedData, bytes.concat(dnsEncodedName, mockData)); assertEq(returnedResolver, mockResolver); } @@ -159,17 +157,12 @@ contract ProxyTest is Test { // Create a new proxy with the mock implementation vm.prank(ADMIN); - UpgradableUniversalResolverProxy testProxy = new UpgradableUniversalResolverProxy( - ADMIN, - address(mockImpl) - ); + UpgradableUniversalResolverProxy testProxy = + new UpgradableUniversalResolverProxy(ADMIN, address(mockImpl)); // Create calldata for reverse method - bytes memory callData = abi.encodeWithSignature( - "reverse(bytes,uint256)", - dnsEncodedName, - uint256(60) - ); + bytes memory callData = + abi.encodeWithSignature("reverse(bytes,uint256)", dnsEncodedName, uint256(60)); // Make the call through the proxy (bool success, bytes memory result) = address(testProxy).call(callData); @@ -178,10 +171,8 @@ contract ProxyTest is Test { assertTrue(success); // Decode the result to verify it matches expectations - (string memory name, address resolver, address reverseResolver) = abi.decode( - result, - (string, address, address) - ); + (string memory name, address resolver, address reverseResolver) = + abi.decode(result, (string, address, address)); assertEq(name, "test.eth"); assertEq(resolver, mockResolver); assertEq(reverseResolver, address(mockImpl)); @@ -195,17 +186,12 @@ contract ProxyTest is Test { // Create a new proxy using the mock implementation vm.prank(ADMIN); - UpgradableUniversalResolverProxy ccipProxy = new UpgradableUniversalResolverProxy( - ADMIN, - address(mockCCIPImpl) - ); + UpgradableUniversalResolverProxy ccipProxy = + new UpgradableUniversalResolverProxy(ADMIN, address(mockCCIPImpl)); // Create calldata for resolve method - bytes memory callData = abi.encodeWithSignature( - "resolve(bytes,bytes)", - dnsEncodedName, - mockData - ); + bytes memory callData = + abi.encodeWithSignature("resolve(bytes,bytes)", dnsEncodedName, mockData); // Make the call and catch the revert data (bool success, bytes memory returnData) = address(ccipProxy).call(callData); @@ -224,7 +210,8 @@ contract ProxyTest is Test { bytes memory ccipCallData, bytes4 callbackFunction, bytes memory extraData - ) = abi.decode(errorData, (address, string[], bytes, bytes4, bytes)); + ) = + abi.decode(errorData, (address, string[], bytes, bytes4, bytes)); // Third assertion: the sender should be the proxy address, not the implementation assertEq(sender, address(ccipProxy)); @@ -243,17 +230,12 @@ contract ProxyTest is Test { // Create a new proxy using the mock implementation vm.prank(ADMIN); - UpgradableUniversalResolverProxy senderProxy = new UpgradableUniversalResolverProxy( - ADMIN, - address(mockDiffSenderImpl) - ); + UpgradableUniversalResolverProxy senderProxy = + new UpgradableUniversalResolverProxy(ADMIN, address(mockDiffSenderImpl)); // Create calldata for resolve method - bytes memory callData = abi.encodeWithSignature( - "resolve(bytes,bytes)", - dnsEncodedName, - mockData - ); + bytes memory callData = + abi.encodeWithSignature("resolve(bytes,bytes)", dnsEncodedName, mockData); // Make the call (bool success, bytes memory result) = address(senderProxy).call(callData); @@ -280,17 +262,12 @@ contract ProxyTest is Test { // Create a new proxy using the mock implementation vm.prank(ADMIN); - UpgradableUniversalResolverProxy revertProxy = new UpgradableUniversalResolverProxy( - ADMIN, - address(mockRevertImpl) - ); + UpgradableUniversalResolverProxy revertProxy = + new UpgradableUniversalResolverProxy(ADMIN, address(mockRevertImpl)); // Create calldata for resolve method - bytes memory callData = abi.encodeWithSignature( - "resolve(bytes,bytes)", - dnsEncodedName, - mockData - ); + bytes memory callData = + abi.encodeWithSignature("resolve(bytes,bytes)", dnsEncodedName, mockData); // Make the call and capture the result (bool success, bytes memory result) = address(revertProxy).call(callData); @@ -310,17 +287,12 @@ contract ProxyTest is Test { // Create a new proxy with the mock implementation vm.prank(ADMIN); - UpgradableUniversalResolverProxy testProxy = new UpgradableUniversalResolverProxy( - ADMIN, - address(mockImpl) - ); + UpgradableUniversalResolverProxy testProxy = + new UpgradableUniversalResolverProxy(ADMIN, address(mockImpl)); // Create calldata for a method that is properly implemented in mock - bytes memory callData = abi.encodeWithSignature( - "resolve(bytes,bytes)", - dnsEncodedName, - mockData - ); + bytes memory callData = + abi.encodeWithSignature("resolve(bytes,bytes)", dnsEncodedName, mockData); // Make the call through the fallback (bool success, bytes memory result) = address(testProxy).call(callData); @@ -341,6 +313,7 @@ contract ProxyTest is Test { } } + // Base contract for mocks to implement common functionality abstract contract UniversalResolverMockBase is IUniversalResolver { function supportsInterface(bytes4 interfaceId) external pure virtual returns (bool) { @@ -350,27 +323,30 @@ abstract contract UniversalResolverMockBase is IUniversalResolver { } // Default implementation for all methods - function resolve( - bytes calldata, - bytes calldata - ) external view virtual returns (bytes memory, address) { + function resolve(bytes calldata, bytes calldata) + external + view + virtual + returns (bytes memory, address) + { return (bytes(""), address(0)); } - function findResolver( - bytes calldata - ) external view virtual returns (address, bytes32, uint256) { + function findResolver(bytes calldata) external view virtual returns (address, bytes32, uint256) { return (address(0), bytes32(0), 0); } - function reverse( - bytes calldata, - uint256 - ) external view virtual returns (string memory, address, address) { + function reverse(bytes calldata, uint256) + external + view + virtual + returns (string memory, address, address) + { return ("", address(0), address(0)); } } + // Mock with full implementation returning expected values contract MockCompleteImplementation is UniversalResolverMockBase { address public constant MOCK_RESOLVER = address(0xabc); @@ -378,34 +354,43 @@ contract MockCompleteImplementation is UniversalResolverMockBase { uint256 public constant MOCK_OFFSET = 0; // Add this method to handle the resolveCallback - function resolveCallback( - bytes calldata response, - bytes calldata extraData - ) external pure returns (bytes memory, address) { + function resolveCallback(bytes calldata response, bytes calldata extraData) + external + pure + returns (bytes memory, address) + { return (bytes.concat(response, extraData), MOCK_RESOLVER); } - function resolve( - bytes calldata name, - bytes calldata data - ) external pure override returns (bytes memory, address) { + function resolve(bytes calldata name, bytes calldata data) + external + pure + override + returns (bytes memory, address) + { return (bytes.concat(name, data), MOCK_RESOLVER); } - function findResolver( - bytes calldata - ) external pure override returns (address, bytes32, uint256) { + function findResolver(bytes calldata) + external + pure + override + returns (address, bytes32, uint256) + { return (MOCK_RESOLVER, MOCK_NAMEHASH, MOCK_OFFSET); } - function reverse( - bytes calldata, - uint256 - ) external view override returns (string memory, address, address) { + function reverse(bytes calldata, uint256) + external + view + override + returns (string memory, address, address) + { return ("test.eth", MOCK_RESOLVER, address(this)); } } + // Mock that reverts with CCIP-Read contract MockCCIPReadImplementation is UniversalResolverMockBase { string[] private urls = new string[](1); @@ -433,15 +418,18 @@ contract MockCCIPReadImplementation is UniversalResolverMockBase { return extraData; } - function resolve( - bytes calldata, - bytes calldata - ) external view override returns (bytes memory, address) { + function resolve(bytes calldata, bytes calldata) + external + view + override + returns (bytes memory, address) + { // Revert with OffchainLookup revert OffchainLookup(address(this), urls, callData, callbackFunction, extraData); } } + // Mock that reverts with CCIP-Read but uses a different sender contract MockCCIPReadWithDifferentSender is UniversalResolverMockBase { address private differentSender = address(0xbeef); @@ -470,23 +458,28 @@ contract MockCCIPReadWithDifferentSender is UniversalResolverMockBase { return extraData; } - function resolve( - bytes calldata, - bytes calldata - ) external view override returns (bytes memory, address) { + function resolve(bytes calldata, bytes calldata) + external + view + override + returns (bytes memory, address) + { // Revert with OffchainLookup using a different sender revert OffchainLookup(differentSender, urls, callData, callbackFunction, extraData); } } + // Mock that reverts with a custom error contract MockRevertingImplementation is UniversalResolverMockBase { error CustomError(); - function resolve( - bytes calldata, - bytes calldata - ) external pure override returns (bytes memory, address) { + function resolve(bytes calldata, bytes calldata) + external + pure + override + returns (bytes memory, address) + { revert CustomError(); } } diff --git a/contracts/test/unit/universalResolver/libraries/LibRegistry.t.sol b/contracts/test/unit/universalResolver/libraries/LibRegistry.t.sol index 3cae79e26..8c51172e4 100755 --- a/contracts/test/unit/universalResolver/libraries/LibRegistry.t.sol +++ b/contracts/test/unit/universalResolver/libraries/LibRegistry.t.sol @@ -7,52 +7,24 @@ import {Test} from "forge-std/Test.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; import {EACBaseRolesLib} from "~src/access-control/EnhancedAccessControl.sol"; -import {IHCAFactoryBasic} from "~src/hca/interfaces/IHCAFactoryBasic.sol"; -import { - PermissionedRegistry, - IStandardRegistry, - IRegistry, - IRegistryMetadata -} from "~src/registry/PermissionedRegistry.sol"; -import {LibRegistry, NameCoder} from "~src/universalResolver/libraries/LibRegistry.sol"; +import {IRegistry} from "~src/registry/interfaces/IRegistry.sol"; +import {IStandardRegistry} from "~src/registry/interfaces/IStandardRegistry.sol"; +import {PermissionedRegistry} from "~src/registry/PermissionedRegistry.sol"; +import {LibRegistry} from "~src/universalResolver/libraries/LibRegistry.sol"; +import {LabelStore} from "~src/utils/LabelStore.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; contract LibRegistryTest is Test, ERC1155Holder { PermissionedRegistry rootRegistry; - address resolverAddress = makeAddr("resolver"); + LabelStore labelStore; - function _createRegistry() internal returns (PermissionedRegistry) { - return - new PermissionedRegistry( - IHCAFactoryBasic(address(0)), - IRegistryMetadata(address(0)), - address(this), - EACBaseRolesLib.ALL_ROLES - ); - } - function _register( - PermissionedRegistry parentRegistry, - string memory label, - IRegistry registry, - address resolver - ) internal { - parentRegistry.register( - label, - address(this), - registry, - resolver, - EACBaseRolesLib.ALL_ROLES, - uint64(block.timestamp + 1000) - ); - if ( - ERC165Checker.supportsInterface(address(registry), type(IStandardRegistry).interfaceId) - ) { - IStandardRegistry(address(registry)).setParent(parentRegistry, label); - } - } + address resolverAddress = makeAddr("resolver"); function setUp() external { + labelStore = new LabelStore(IContractNamer(address(0))); rootRegistry = _createRegistry(); } @@ -62,9 +34,12 @@ contract LibRegistryTest is Test, ERC1155Holder { address parentRegistry, IRegistry[] memory registries, bytes memory canonicalName - ) internal view { - (IRegistry registry, address resolver, bytes32 node, uint256 resolverOffset_) = LibRegistry - .findResolver(rootRegistry, name, 0); + ) + internal + view + { + (IRegistry registry, address resolver, bytes32 node, uint256 resolverOffset_) = + LibRegistry.findResolver(rootRegistry, name, 0); assertEq( address(LibRegistry.findExactRegistry(rootRegistry, name, 0)), address(registry), @@ -99,15 +74,6 @@ contract LibRegistryTest is Test, ERC1155Holder { (, offset) = NameCoder.nextLabel(name, offset); } assertEq(offset, name.length, "length"); - (IRegistry registryFrom, address resolverFrom) = LibRegistry.findResolverFromParent( - name, - 0, - name.length - 1, - rootRegistry, - address(0) - ); - assertEq(address(registryFrom), address(registry), "registryFrom"); - assertEq(resolverFrom, resolver, "resolverFrom"); assertEq( LibRegistry.findCanonicalName(rootRegistry, registries[0]), canonicalName, @@ -276,11 +242,7 @@ contract LibRegistryTest is Test, ERC1155Holder { _register(rootRegistry, "eth", ethRegistry, address(0)); _register(ethRegistry, "test", testRegistry, address(0)); ethRegistry.setParent(IRegistry(address(0)), "eth"); // wrong - assertEq( - LibRegistry.findCanonicalName(rootRegistry, testRegistry), - "", - "findCanonicalName" - ); + assertEq(LibRegistry.findCanonicalName(rootRegistry, testRegistry), "", "findCanonicalName"); assertEq( address(LibRegistry.findCanonicalRegistry(rootRegistry, NameCoder.encode("test.eth"))), address(0), @@ -294,11 +256,21 @@ contract LibRegistryTest is Test, ERC1155Holder { _register(rootRegistry, "eth", ethRegistry, address(0)); _register(ethRegistry, "test", testRegistry, address(0)); ethRegistry.setParent(IRegistry(address(0)), "xyz"); // wrong + assertEq(LibRegistry.findCanonicalName(rootRegistry, testRegistry), "", "findCanonicalName"); assertEq( - LibRegistry.findCanonicalName(rootRegistry, testRegistry), - "", - "findCanonicalName" + address(LibRegistry.findCanonicalRegistry(rootRegistry, NameCoder.encode("test.eth"))), + address(0), + "findCanonicalRegistry" ); + } + + function test_findCanonical_wrongChild() external { + PermissionedRegistry ethRegistry = _createRegistry(); + PermissionedRegistry testRegistry = _createRegistry(); + _register(rootRegistry, "eth", ethRegistry, address(0)); + uint256 tokenId = _register(ethRegistry, "test", testRegistry, address(0)); + ethRegistry.setSubregistry(tokenId, IRegistry(address(0))); // wrong + assertEq(LibRegistry.findCanonicalName(rootRegistry, testRegistry), "", "findCanonicalName"); assertEq( address(LibRegistry.findCanonicalRegistry(rootRegistry, NameCoder.encode("test.eth"))), address(0), @@ -343,4 +315,45 @@ contract LibRegistryTest is Test, ERC1155Holder { "xyz:test.eth" ); } + + function test_findOwner() external { + PermissionedRegistry ethRegistry = _createRegistry(); + PermissionedRegistry testRegistry = _createRegistry(); + _register(rootRegistry, "eth", ethRegistry, address(0)); + _register(ethRegistry, "test", testRegistry, address(0)); + + assertEq(LibRegistry.findOwner(rootRegistry, NameCoder.encode(""), 0), address(0)); + assertEq(LibRegistry.findOwner(rootRegistry, NameCoder.encode("eth"), 0), address(this)); + assertEq(LibRegistry.findOwner(rootRegistry, NameCoder.encode("test.eth"), 0), address(this)); + } + + //////////////////////////////////////////////////////////////////////// + // Helpers + //////////////////////////////////////////////////////////////////////// + + function _createRegistry() internal returns (PermissionedRegistry) { + return new PermissionedRegistry(labelStore, address(this), EACBaseRolesLib.ALL_ROLES); + } + + function _register( + PermissionedRegistry parentRegistry, + string memory label, + IRegistry registry, + address resolver + ) + internal + returns (uint256 tokenId) + { + tokenId = parentRegistry.register( + label, + address(this), + registry, + resolver, + EACBaseRolesLib.ALL_ROLES, + uint64(block.timestamp + 1000) + ); + if (ERC165Checker.supportsInterface(address(registry), type(IStandardRegistry).interfaceId)) { + IStandardRegistry(address(registry)).setParent(parentRegistry, label); + } + } } diff --git a/contracts/test/unit/utils/ContactNamer.t.sol b/contracts/test/unit/utils/ContactNamer.t.sol new file mode 100755 index 000000000..910111afb --- /dev/null +++ b/contracts/test/unit/utils/ContactNamer.t.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {Test} from "forge-std/Test.sol"; + +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; + +import {ContractNamer} from "~src/utils/ContractNamer.sol"; +import {DelegatedContractNamer} from "~src/utils/DelegatedContractNamer.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; + +contract ContractNamerTest is Test { + ContractNamer contractNamer; + MockDelegated delegated; + + address owner = makeAddr("owner"); + + function setUp() external { + contractNamer = ContractNamer( + address( + new ERC1967Proxy( + address(new ContractNamer()), + abi.encodeCall(ContractNamer.initialize, (owner)) + ) + ) + ); + delegated = new MockDelegated(contractNamer); + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface(address(contractNamer), type(IContractNamer).interfaceId), + "IContractNamer" + ); + assertTrue( + ERC165Checker.supportsInterface(address(delegated), type(IContractNamer).interfaceId), + "IContractNamer" + ); + } + + function test_isContractNamer() external view { + assertFalse(contractNamer.isContractNamer(address(0))); + assertTrue(contractNamer.isContractNamer(owner)); + + assertFalse(delegated.isContractNamer(address(0))); + assertTrue(delegated.isContractNamer(owner)); + } + + function test_upgrade() external { + MockUpgrade c = new MockUpgrade(); + vm.prank(owner); + contractNamer.upgradeToAndCall(address(c), ""); + assertTrue(contractNamer.isContractNamer(address(1))); + } + + function test_upgrade_notAuthorized() external { + MockUpgrade c = new MockUpgrade(); + vm.expectRevert(); + contractNamer.upgradeToAndCall(address(c), ""); + } +} + + +contract MockUpgrade is UUPSUpgradeable, IContractNamer { + function isContractNamer(address namer) external pure returns (bool) { + return namer == address(1); + } + function _authorizeUpgrade(address) internal override {} +} + + +contract MockDelegated is DelegatedContractNamer { + constructor(IContractNamer namer) DelegatedContractNamer(namer) {} +} diff --git a/contracts/test/unit/utils/LabelStore.t.sol b/contracts/test/unit/utils/LabelStore.t.sol new file mode 100755 index 000000000..0e96d0f06 --- /dev/null +++ b/contracts/test/unit/utils/LabelStore.t.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {Test, Vm} from "forge-std/Test.sol"; + +import {NameCoder} from "@ens/contracts/utils/NameCoder.sol"; +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; + +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {ILabelStore} from "~src/utils/interfaces/ILabelStore.sol"; +import {LabelStore} from "~src/utils/LabelStore.sol"; +import {LibLabel} from "~src/utils/LibLabel.sol"; + +contract LabelStoreTest is Test { + LabelStore labelStore; + + function setUp() external { + labelStore = new LabelStore(IContractNamer(address(0))); + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface(address(labelStore), type(ILabelStore).interfaceId), + "ILabelStore" + ); + } + + function test_setLabel(string calldata label, uint32 version) external { + _assumeValidLabel(label); + + uint256 labelId = LibLabel.id(label); + + assertEq(labelStore.getLabel(LibLabel.withVersion(labelId, version)), "", "before"); + + vm.expectEmit(); + emit ILabelStore.Label(bytes32(labelId), label); + labelStore.setLabel(label); + + assertEq(labelStore.getLabel(LibLabel.withVersion(labelId, version)), label, "after"); + } + + function test_setLabel_again(string calldata label) external { + _assumeValidLabel(label); + + labelStore.setLabel(label); + + vm.recordLogs(); + labelStore.setLabel(label); + _expectNoEmit(vm.getRecordedLogs(), ILabelStore.Label.selector); + } + + function test_setLabel_empty() external { + vm.expectRevert(abi.encodeWithSelector(NameCoder.LabelIsEmpty.selector)); + labelStore.setLabel(""); + } + + function test_setLabel_tooLong() external { + string memory label = new string(256); + vm.expectRevert(abi.encodeWithSelector(NameCoder.LabelIsTooLong.selector, label)); + labelStore.setLabel(label); + } + + function _assumeValidLabel(string memory label) internal pure { + vm.assume(bytes(label).length > 0 && bytes(label).length < 256); + } + + function _expectNoEmit(Vm.Log[] memory logs, bytes32 topic0) internal pure { + for (uint256 i; i < logs.length; ++i) { + assertNotEq(logs[i].topics[0], topic0, "found unexpected event"); + } + } +} diff --git a/contracts/test/unit/utils/LibMem.t.sol b/contracts/test/unit/utils/LibMem.t.sol new file mode 100644 index 000000000..a7bc4ce36 --- /dev/null +++ b/contracts/test/unit/utils/LibMem.t.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {Test} from "forge-std/Test.sol"; + +import {LibMem} from "~src/utils/LibMem.sol"; + +contract LibMemTest is Test { + function test_ptr() external view { + for (uint256 i; i < 100; ++i) { + bytes memory v = new bytes(i); + uint256 ptr; + assembly { + ptr := add(v, 32) + } + assertEq(ptr, LibMem.ptr(v)); + } + } + + function test_load() external view { + for (uint256 i; i < 100; ++i) { + bytes memory v = new bytes(i); + uint256 value; + assembly { + value := mload(add(v, 32)) + } + assertEq(value, LibMem.load(LibMem.ptr(v))); + } + } + + function test_copy(bytes memory v0) external view { + bytes memory v = new bytes(v0.length); + LibMem.copy(LibMem.ptr(v), LibMem.ptr(v0), v0.length); + assertEq(v, v0); + } +} diff --git a/contracts/test/unit/utils/LibString.t.sol b/contracts/test/unit/utils/LibString.t.sol new file mode 100644 index 000000000..1c0fdfead --- /dev/null +++ b/contracts/test/unit/utils/LibString.t.sol @@ -0,0 +1,487 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// solhint-disable no-console, private-vars-leading-underscore, state-visibility, func-name-mixedcase, namechain/ordering, one-contract-per-file + +import {Test} from "forge-std/Test.sol"; + +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; + +import {LibString} from "~src/utils/LibString.sol"; + +contract LibStringTest is Test { + //////////////////////////////////////////////////////////////////////// + // toAddressString Tests + //////////////////////////////////////////////////////////////////////// + + function test_toAddressString_zeroAddress() external pure { + string memory result = LibString.toAddressString(address(0)); + assertEq(result, "0000000000000000000000000000000000000000"); + assertEq(bytes(result).length, 40); + } + + function test_toAddressString_maxAddress() external pure { + address maxAddr = address(type(uint160).max); + string memory result = LibString.toAddressString(maxAddr); + assertEq(result, "ffffffffffffffffffffffffffffffffffffffff"); + assertEq(bytes(result).length, 40); + } + + function test_toAddressString_knownAddress1() external pure { + // 0xdead...beef pattern + address addr = address(0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF); + string memory result = LibString.toAddressString(addr); + assertEq(result, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"); + } + + function test_toAddressString_knownAddress2() external pure { + // Common test address + address addr = address(0x1234567890AbcdEF1234567890aBcdef12345678); + string memory result = LibString.toAddressString(addr); + assertEq(result, "1234567890abcdef1234567890abcdef12345678"); + } + + function test_toAddressString_singleByteHigh() external pure { + // Address with only high byte set + address addr = address(uint160(0xff) << 152); + string memory result = LibString.toAddressString(addr); + assertEq(result, "ff00000000000000000000000000000000000000"); + } + + function test_toAddressString_singleByteLow() external pure { + // Address with only low byte set + address addr = address(uint160(0xff)); + string memory result = LibString.toAddressString(addr); + assertEq(result, "00000000000000000000000000000000000000ff"); + } + + function test_toAddressString_alternatingNibbles() external pure { + // 0x0a0a... pattern to test nibble extraction + address addr = address(0x0A0A0a0a0a0a0a0A0a0a0A0a0A0A0A0a0a0a0a0a); + string memory result = LibString.toAddressString(addr); + assertEq(result, "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a"); + } + + function test_toAddressString_allHexDigits() external pure { + // Address containing all hex digits 0-9 and a-f + address addr = address(0x0123456789AbCDEFAbCDef0123456789AbcDEf01); + string memory result = LibString.toAddressString(addr); + // Note: result is always lowercase + assertEq(result, "0123456789abcdefabcdef0123456789abcdef01"); + } + + function test_toAddressString_leadingZeros() external pure { + // Small number with many leading zeros + address addr = address(uint160(0x123)); + string memory result = LibString.toAddressString(addr); + assertEq(result, "0000000000000000000000000000000000000123"); + } + + function testFuzz_toAddressString_length(address addr) external pure { + string memory result = LibString.toAddressString(addr); + assertEq(bytes(result).length, 40, "Result should always be 40 characters"); + } + + function testFuzz_toAddressString_lowercase(address addr) external pure { + string memory result = LibString.toAddressString(addr); + bytes memory b = bytes(result); + for (uint256 i = 0; i < b.length; i++) { + bytes1 char = b[i]; + // Should only contain 0-9 (0x30-0x39) or a-f (0x61-0x66) + bool isDigit = char >= 0x30 && char <= 0x39; + bool isLowerHex = char >= 0x61 && char <= 0x66; + assertTrue(isDigit || isLowerHex, "Should only contain lowercase hex chars"); + } + } + + function testFuzz_toAddressString_roundtrip(address addr) external pure { + string memory result = LibString.toAddressString(addr); + // Parse the hex string back to address + address parsed = _parseHexAddress(result); + assertEq(parsed, addr, "Round-trip conversion should match"); + } + + //////////////////////////////////////////////////////////////////////// + // toChecksumHexString Tests + //////////////////////////////////////////////////////////////////////// + + function test_toChecksumHexString_zeroAddress() external pure { + string memory result = LibString.toChecksumHexString(address(0)); + assertEq(result, "0x0000000000000000000000000000000000000000"); + assertEq(bytes(result).length, 42); + } + + function test_toChecksumHexString_hasPrefix() external pure { + address addr = address(0x1234567890AbcdEF1234567890aBcdef12345678); + string memory result = LibString.toChecksumHexString(addr); + bytes memory b = bytes(result); + assertEq(b[0], bytes1("0"), "First char should be '0'"); + assertEq(b[1], bytes1("x"), "Second char should be 'x'"); + } + + function test_toChecksumHexString_knownChecksum1() external pure { + // Well-known checksummed address (Vitalik's address) + address addr = 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045; + string memory result = LibString.toChecksumHexString(addr); + assertEq(result, "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"); + } + + function test_toChecksumHexString_knownChecksum2() external pure { + // Another known checksummed address (WETH on mainnet) + address addr = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + string memory result = LibString.toChecksumHexString(addr); + assertEq(result, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); + } + + function test_toChecksumHexString_knownChecksum3() external pure { + // USDC on mainnet + address addr = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; + string memory result = LibString.toChecksumHexString(addr); + assertEq(result, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"); + } + + function test_toChecksumHexString_allLowercase() external pure { + // Address where checksum results in all lowercase (0x0000...0001) + address addr = address(1); + string memory result = LibString.toChecksumHexString(addr); + // This specific address should have specific checksum pattern + assertEq(bytes(result).length, 42); + // Verify it starts with 0x + assertEq(bytes(result)[0], bytes1("0")); + assertEq(bytes(result)[1], bytes1("x")); + } + + function test_toChecksumHexString_deadbeef() external pure { + address addr = 0x00000000000000000000000000000000DeaDBeef; + string memory result = LibString.toChecksumHexString(addr); + // Verify the checksum is applied correctly + assertEq(bytes(result).length, 42); + } + + function testFuzz_toChecksumHexString_length(address addr) external pure { + string memory result = LibString.toChecksumHexString(addr); + assertEq(bytes(result).length, 42, "Result should always be 42 characters"); + } + + function testFuzz_toChecksumHexString_prefix(address addr) external pure { + string memory result = LibString.toChecksumHexString(addr); + bytes memory b = bytes(result); + assertEq(b[0], bytes1("0"), "First char should be '0'"); + assertEq(b[1], bytes1("x"), "Second char should be 'x'"); + } + + function testFuzz_toChecksumHexString_validHexChars(address addr) external pure { + string memory result = LibString.toChecksumHexString(addr); + bytes memory b = bytes(result); + // Skip first two chars (0x prefix) + for (uint256 i = 2; i < b.length; i++) { + bytes1 char = b[i]; + // Should only contain 0-9 (0x30-0x39), a-f (0x61-0x66), or A-F (0x41-0x46) + bool isDigit = char >= 0x30 && char <= 0x39; + bool isLowerHex = char >= 0x61 && char <= 0x66; + bool isUpperHex = char >= 0x41 && char <= 0x46; + assertTrue(isDigit || isLowerHex || isUpperHex, "Should only contain valid hex chars"); + } + } + + function testFuzz_toChecksumHexString_matchesOpenZeppelin(address addr) external pure { + string memory ourResult = LibString.toChecksumHexString(addr); + string memory ozResult = Strings.toChecksumHexString(addr); + assertEq(ourResult, ozResult, "Should match OpenZeppelin implementation"); + } + + function testFuzz_toChecksumHexString_verifyEIP55(address addr) external pure { + string memory result = LibString.toChecksumHexString(addr); + assertTrue(_verifyEIP55Checksum(result), "Should pass EIP-55 checksum verification"); + } + + //////////////////////////////////////////////////////////////////////// + // toString (uint256) Tests + //////////////////////////////////////////////////////////////////////// + + function test_toString_zero() external pure { + string memory result = LibString.toString(0); + assertEq(result, "0"); + assertEq(bytes(result).length, 1); + } + + function test_toString_one() external pure { + string memory result = LibString.toString(1); + assertEq(result, "1"); + } + + function test_toString_nine() external pure { + string memory result = LibString.toString(9); + assertEq(result, "9"); + } + + function test_toString_ten() external pure { + string memory result = LibString.toString(10); + assertEq(result, "10"); + } + + function test_toString_hundred() external pure { + string memory result = LibString.toString(100); + assertEq(result, "100"); + } + + function test_toString_thousand() external pure { + string memory result = LibString.toString(1000); + assertEq(result, "1000"); + } + + function test_toString_largeNumber() external pure { + string memory result = LibString.toString(123456789); + assertEq(result, "123456789"); + } + + function test_toString_maxUint8() external pure { + string memory result = LibString.toString(type(uint8).max); + assertEq(result, "255"); + } + + function test_toString_maxUint16() external pure { + string memory result = LibString.toString(type(uint16).max); + assertEq(result, "65535"); + } + + function test_toString_maxUint32() external pure { + string memory result = LibString.toString(type(uint32).max); + assertEq(result, "4294967295"); + } + + function test_toString_maxUint64() external pure { + string memory result = LibString.toString(type(uint64).max); + assertEq(result, "18446744073709551615"); + } + + function test_toString_maxUint128() external pure { + string memory result = LibString.toString(type(uint128).max); + assertEq(result, "340282366920938463463374607431768211455"); + } + + function test_toString_maxUint256() external pure { + string memory result = LibString.toString(type(uint256).max); + assertEq( + result, + "115792089237316195423570985008687907853269984665640564039457584007913129639935" + ); + } + + function test_toString_powersOfTen() external pure { + assertEq(LibString.toString(1), "1"); + assertEq(LibString.toString(10), "10"); + assertEq(LibString.toString(100), "100"); + assertEq(LibString.toString(1000), "1000"); + assertEq(LibString.toString(10000), "10000"); + assertEq(LibString.toString(100000), "100000"); + assertEq(LibString.toString(1000000), "1000000"); + assertEq(LibString.toString(10000000), "10000000"); + assertEq(LibString.toString(100000000), "100000000"); + assertEq(LibString.toString(1000000000), "1000000000"); + } + + function test_toString_allSingleDigits() external pure { + assertEq(LibString.toString(0), "0"); + assertEq(LibString.toString(1), "1"); + assertEq(LibString.toString(2), "2"); + assertEq(LibString.toString(3), "3"); + assertEq(LibString.toString(4), "4"); + assertEq(LibString.toString(5), "5"); + assertEq(LibString.toString(6), "6"); + assertEq(LibString.toString(7), "7"); + assertEq(LibString.toString(8), "8"); + assertEq(LibString.toString(9), "9"); + } + + function test_toString_repeatingDigits() external pure { + assertEq(LibString.toString(11111), "11111"); + assertEq(LibString.toString(22222), "22222"); + assertEq(LibString.toString(99999), "99999"); + assertEq(LibString.toString(1111111111), "1111111111"); + } + + function test_toString_specificPatterns() external pure { + assertEq(LibString.toString(12345678901234567890), "12345678901234567890"); + assertEq(LibString.toString(98765432109876543210), "98765432109876543210"); + } + + function test_toString_ethereumValues() external pure { + // 1 ETH in wei + assertEq(LibString.toString(1 ether), "1000000000000000000"); + // 1 gwei + assertEq(LibString.toString(1 gwei), "1000000000"); + } + + function test_toString_chainIds() external pure { + // Ethereum mainnet + assertEq(LibString.toString(1), "1"); + // Optimism + assertEq(LibString.toString(10), "10"); + // Arbitrum + assertEq(LibString.toString(42161), "42161"); + // Polygon + assertEq(LibString.toString(137), "137"); + // Base + assertEq(LibString.toString(8453), "8453"); + } + + function testFuzz_toString_noLeadingZeros(uint256 value) external pure { + string memory result = LibString.toString(value); + bytes memory b = bytes(result); + + // If the value is not zero, first char should not be '0' + if (value != 0) { + assertTrue(b[0] != bytes1("0"), "Should not have leading zeros"); + } + } + + function testFuzz_toString_onlyDigits(uint256 value) external pure { + string memory result = LibString.toString(value); + bytes memory b = bytes(result); + + for (uint256 i = 0; i < b.length; i++) { + bytes1 char = b[i]; + // Should only contain 0-9 (0x30-0x39) + assertTrue(char >= 0x30 && char <= 0x39, "Should only contain digits"); + } + } + + function testFuzz_toString_matchesOpenZeppelin(uint256 value) external pure { + string memory ourResult = LibString.toString(value); + string memory ozResult = Strings.toString(value); + assertEq(ourResult, ozResult, "Should match OpenZeppelin implementation"); + } + + function testFuzz_toString_roundtrip(uint256 value) external pure { + string memory result = LibString.toString(value); + uint256 parsed = _parseUint(result); + assertEq(parsed, value, "Round-trip conversion should match"); + } + + function testFuzz_toString_length(uint256 value) external pure { + string memory result = LibString.toString(value); + uint256 expectedLength = _countDigits(value); + assertEq(bytes(result).length, expectedLength, "Length should match digit count"); + } + + //////////////////////////////////////////////////////////////////////// + // Gas Benchmarks + //////////////////////////////////////////////////////////////////////// + + function test_gas_toAddressString() external pure { + LibString.toAddressString(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045); + } + + function test_gas_toChecksumHexString() external pure { + LibString.toChecksumHexString(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045); + } + + function test_gas_toString_small() external pure { + LibString.toString(123); + } + + function test_gas_toString_medium() external pure { + LibString.toString(123456789); + } + + function test_gas_toString_large() external pure { + LibString.toString(type(uint256).max); + } + + //////////////////////////////////////////////////////////////////////// + // Helper Functions + //////////////////////////////////////////////////////////////////////// + + /// @dev Parses a 40-character lowercase hex string to an address + function _parseHexAddress(string memory s) internal pure returns (address) { + bytes memory b = bytes(s); + require(b.length == 40, "Invalid length"); + + uint160 result = 0; + for (uint256 i = 0; i < 40; i++) { + result = result * 16 + _hexCharToUint(b[i]); + } + return address(result); + } + + /// @dev Converts a hex character to its uint256 value + function _hexCharToUint(bytes1 c) internal pure returns (uint8) { + if (c >= 0x30 && c <= 0x39) { + return uint8(c) - 0x30; // 0-9 + } else if (c >= 0x61 && c <= 0x66) { + return uint8(c) - 0x61 + 10; // a-f + } else if (c >= 0x41 && c <= 0x46) { + return uint8(c) - 0x41 + 10; // A-F + } + revert("Invalid hex char"); + } + + /// @dev Parses a decimal string to uint256 + function _parseUint(string memory s) internal pure returns (uint256) { + bytes memory b = bytes(s); + uint256 result = 0; + for (uint256 i = 0; i < b.length; i++) { + require(b[i] >= 0x30 && b[i] <= 0x39, "Invalid digit"); + result = result * 10 + (uint8(b[i]) - 0x30); + } + return result; + } + + /// @dev Counts the number of decimal digits in a value + function _countDigits(uint256 value) internal pure returns (uint256) { + if (value == 0) + return 1; + uint256 digits = 0; + while (value > 0) { + digits++; + value /= 10; + } + return digits; + } + + /// @dev Verifies an EIP-55 checksummed address string + function _verifyEIP55Checksum(string memory addr) internal pure returns (bool) { + bytes memory b = bytes(addr); + if (b.length != 42) + return false; + if (b[0] != 0x30 || b[1] != 0x78) + return false; // "0x" + + // Extract lowercase hex (without 0x prefix) + bytes memory lowercase = new bytes(40); + for (uint256 i = 0; i < 40; i++) { + bytes1 c = b[i + 2]; + if (c >= 0x41 && c <= 0x46) { + // Uppercase A-F -> lowercase a-f + lowercase[i] = bytes1(uint8(c) + 32); + } else { + lowercase[i] = c; + } + } + + // Hash the lowercase hex + bytes32 hash = keccak256(lowercase); + + // Verify checksum + for (uint256 i = 0; i < 40; i++) { + bytes1 c = b[i + 2]; + uint8 hashNibble = uint8(hash[i / 2]); + if (i % 2 == 0) { + hashNibble = hashNibble >> 4; + } else { + hashNibble = hashNibble & 0x0f; + } + + // If it's a letter (a-f or A-F) + if ((c >= 0x61 && c <= 0x66) || (c >= 0x41 && c <= 0x46)) { + bool shouldBeUpper = hashNibble >= 8; + bool isUpper = c >= 0x41 && c <= 0x46; + if (shouldBeUpper != isUpper) + return false; + } + } + + return true; + } +} diff --git a/contracts/test/unit/utils/PermissionedAddressSet.t.sol b/contracts/test/unit/utils/PermissionedAddressSet.t.sol new file mode 100755 index 000000000..c39b37d93 --- /dev/null +++ b/contracts/test/unit/utils/PermissionedAddressSet.t.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {Test} from "forge-std/Test.sol"; + +import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; + +import {IEnhancedAccessControl} from "~src/access-control/interfaces/IEnhancedAccessControl.sol"; +import {IContractNamer} from "~src/reverse-registrar/interfaces/IContractNamer.sol"; +import {IAddressSet} from "~src/utils/interfaces/IAddressSet.sol"; +import { + PermissionedAddressSet, + ROLE_APPROVE, + ROLE_CAN_NAME +} from "~src/utils/PermissionedAddressSet.sol"; + +contract PermissionedAddressSetTest is Test { + PermissionedAddressSet set; + + address testAddr = makeAddr("something"); + address friend = makeAddr("anotherAdmin"); + + function setUp() external { + set = new PermissionedAddressSet(address(this)); + } + + function test_supportsInterface() external view { + assertTrue( + ERC165Checker.supportsInterface(address(set), type(IAddressSet).interfaceId), + "IAddressSet" + ); + assertTrue( + ERC165Checker.supportsInterface(address(set), type(IContractNamer).interfaceId), + "IContractNamer" + ); + } + + function test_approve_notAuthorized() external { + vm.expectRevert( + abi.encodeWithSelector( + IEnhancedAccessControl.EACUnauthorizedAccountRoles.selector, + set.ROOT_RESOURCE(), + ROLE_APPROVE, + friend + ) + ); + vm.prank(friend); + set.approve(testAddr, true); + } + + function test_approve_unchanged() external { + vm.expectRevert(); + set.approve(testAddr, false); + } + + function test_approve() external { + assertFalse(set.includes(testAddr)); + + vm.expectEmit(); + emit PermissionedAddressSet.ApprovalChanged(testAddr, true, address(this)); + set.approve(testAddr, true); + + assertTrue(set.includes(testAddr)); + + vm.expectEmit(); + emit PermissionedAddressSet.ApprovalChanged(testAddr, false, address(this)); + set.approve(testAddr, false); + + assertFalse(set.includes(testAddr)); + } + + function test_approve_multiple(bool[] calldata approved) external { + for (uint160 i; i < approved.length; ++i) { + if (approved[i]) { + set.approve(address(i), true); + } + } + for (uint160 i; i < approved.length; ++i) { + assertEq(set.includes(address(i)), approved[i]); + } + } + + function test_approve_granted() external { + vm.expectRevert(); + vm.prank(friend); + set.approve(testAddr, true); + + set.grantRootRoles(ROLE_APPROVE, friend); + + vm.prank(friend); + set.approve(testAddr, true); + } + + function test_isContractNamer() external { + assertTrue(set.isContractNamer(address(this))); + + assertFalse(set.isContractNamer(friend), "before"); + + set.grantRootRoles(ROLE_CAN_NAME, friend); + assertTrue(set.isContractNamer(friend), "granted"); + + set.revokeRootRoles(ROLE_CAN_NAME, friend); + assertFalse(set.isContractNamer(friend), "revoked"); + } +} diff --git a/contracts/test/unit/utils/StorageTester.sol b/contracts/test/unit/utils/StorageTester.sol deleted file mode 100755 index 046327952..000000000 --- a/contracts/test/unit/utils/StorageTester.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import {Test} from "forge-std/Test.sol"; - -contract StorageTester is Test { - /// @dev Read storage `bytes` from `addr` @ `slot`. - function readBytes(address addr, uint256 slot) public view returns (bytes memory v) { - uint256 first = uint256(vm.load(addr, bytes32(slot))); - if ((first & 1) == 0) { - uint256 size = (first & 255) >> 1; - vm.assertLt(size, 32, "small too big"); - v = abi.encodePacked(first); - assembly { - mstore(v, size) // truncate - } - } else { - uint256 size = first >> 1; - vm.assertGe(size, 32, "big too small"); - v = new bytes(size); - size = (size + 31) >> 5; // words - slot = uint256(keccak256(abi.encode(slot))); - for (uint256 i; i < size; ++i) { - bytes32 word = vm.load(addr, bytes32(slot + i)); - assembly { - mstore(add(v, shl(5, add(i, 1))), word) - } - } - } - } - - /// @dev Compute slot for `mapping[key]` where `slot = mapping.slot`. - function follow(uint256 slot, bytes memory key) public pure returns (uint256) { - return uint256(keccak256(abi.encodePacked(key, slot))); - } -} diff --git a/contracts/test/unit/utils/StorageTester.t.sol b/contracts/test/unit/utils/StorageTester.t.sol deleted file mode 100755 index e79da56c9..000000000 --- a/contracts/test/unit/utils/StorageTester.t.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.13; - -import {Test} from "forge-std/Test.sol"; - -import {StorageTester} from "./StorageTester.sol"; - -contract StorageTesterTest is StorageTester { - bytes smallData; - bytes bigData; - mapping(bytes => bytes) mappedData; - - function setUp() external { - smallData = vm.randomBytes(31); - bigData = vm.randomBytes(99); - mappedData["small"] = smallData; - mappedData["big"] = bigData; - } - - function test_readBytes_smallData() external view { - uint256 slot; - assembly { - slot := smallData.slot - } - assertEq(readBytes(address(this), slot), smallData); - } - - function test_readBytes_bigData() external view { - uint256 slot; - assembly { - slot := bigData.slot - } - assertEq(readBytes(address(this), slot), bigData); - } - - function test_mapped_readBytes_smallData() external view { - uint256 slot; - assembly { - slot := mappedData.slot - } - assertEq(readBytes(address(this), follow(slot, "small")), smallData); - } - - function test_mapped_readBytes_bigData() external view { - uint256 slot; - assembly { - slot := mappedData.slot - } - assertEq(readBytes(address(this), follow(slot, "big")), bigData); - } -} diff --git a/contracts/test/utils/expectVar.ts b/contracts/test/utils/expectVar.ts index 3ee5857cc..86b5a7164 100644 --- a/contracts/test/utils/expectVar.ts +++ b/contracts/test/utils/expectVar.ts @@ -1,7 +1,9 @@ import { expect } from "vitest"; +export { expect }; + // expectVar({ x }) <==> expect(x, 'x') -export function expectVar(obj: Record) { +export function expectVar(obj: Record, tag?: string) { const [[k, v]] = Object.entries(obj); - return expect(v, k); + return expect(v, tag ? `k: ${tag}` : k); } diff --git a/contracts/test/utils/hardhat-coverage.ts b/contracts/test/utils/hardhat-coverage.ts index cdbfd562f..1256b1132 100644 --- a/contracts/test/utils/hardhat-coverage.ts +++ b/contracts/test/utils/hardhat-coverage.ts @@ -1,6 +1,6 @@ import { addStatementCoverageInstrumentation } from "@nomicfoundation/edr"; import hre from "hardhat"; -import { mkdir, readFile, writeFile } from "node:fs/promises"; +import { mkdir, readdir, readFile, writeFile } from "node:fs/promises"; import { toHex } from "viem"; // https://github.com/NomicFoundation/hardhat/blob/main/v-next/hardhat/src/internal/builtin-plugins/coverage/hook-handlers/hre.ts @@ -37,32 +37,47 @@ export function recordCoverage(testName: string) { if (!tags.length) return; const rootDir = new URL("../../", import.meta.url); - const artifactStr = await readFile( - new URL("generated/artifacts.ts", rootDir), - { encoding: "utf8" }, - ); - - const hardhatLibrary = artifactStr.match( - /__hardhat_coverage_library_[a-f0-9-]+\.sol/, - )?.[0]; - if (!hardhatLibrary) { + // each instrumented build is recorded in artifacts/build-info/ + // .json, whose input lists every source plus the injected + // __hardhat_coverage_library_*.sol; re-instrumenting the local sources + // with that library reproduces the statement tags + const buildInfoDir = new URL("artifacts/build-info/", rootDir); + type SourceBuild = { + sourceName: string; + inputSourceName: string; + solcVersion: string; + coverageLibrary: string; + }; + const sourceBuilds = new Map(); + for (const file of await readdir(buildInfoDir)) { + if (!file.endsWith(".json") || file.endsWith(".output.json")) continue; + const buildInfo = JSON.parse( + await readFile(new URL(file, buildInfoDir), { encoding: "utf8" }), + ) as { + solcVersion: string; + input: { sources: Record }; + }; + const inputSourceNames = Object.keys(buildInfo.input.sources); + const coverageLibrary = inputSourceNames.find((x) => + /^__hardhat_coverage_library_[a-f0-9-]+\.sol$/.test(x), + ); + if (!coverageLibrary) continue; // not an instrumented build + const prefix = "project/"; + for (const inputSourceName of inputSourceNames) { + if (!inputSourceName.startsWith(prefix)) continue; + if (sourceBuilds.has(inputSourceName)) continue; + sourceBuilds.set(inputSourceName, { + sourceName: inputSourceName.slice(prefix.length), + inputSourceName, + solcVersion: buildInfo.solcVersion, + coverageLibrary, + }); + } + } + if (!sourceBuilds.size) { throw new Error("expected hardhat coverage library"); } - const rawArtifacts = JSON.parse( - artifactStr.slice( - artifactStr.indexOf("{"), - artifactStr.lastIndexOf("}") + 1, - ), - ) as Record< - string, - { - sourceName: string; - inputSourceName: string; - metadata: string; - } - >; - type CodeUnit = { line: number; kind: string; name: string }; type CodeBlock = CodeUnit & { unit: CodeUnit; id: string }; type Location = { @@ -75,18 +90,15 @@ export function recordCoverage(testName: string) { }; const tagMap = new Map(); const fileMap = new Map(); - for (const rawArtifact of Object.values(rawArtifacts)) { + for (const rawArtifact of sourceBuilds.values()) { const code = await readFile(new URL(rawArtifact.sourceName, rootDir), { encoding: "utf8", }); - const rawMetadata = JSON.parse(rawArtifact.metadata) as { - compiler: { version: string }; - }; - const { metadata, source } = addStatementCoverageInstrumentation( + const { metadata } = addStatementCoverageInstrumentation( code, rawArtifact.inputSourceName, // "project/..." - rawMetadata.compiler.version.replace(/\+.*$/, ""), // "0.8.25"+commit.b61c2a9 => "0.8.25" - hardhatLibrary, + rawArtifact.solcVersion, // "0.8.25" + rawArtifact.coverageLibrary, ); // generate line numbers diff --git a/contracts/test/utils/mockPreMigration.ts b/contracts/test/utils/mockPreMigration.ts new file mode 100644 index 000000000..996de83c4 --- /dev/null +++ b/contracts/test/utils/mockPreMigration.ts @@ -0,0 +1,123 @@ +import { writeFileSync } from "node:fs"; +import type { Address } from "viem"; +import type { DevnetEnvironment } from "../../script/setup.js"; +import { idFromLabel } from "./utils.js"; + +const DEPLOYER_PRIVATE_KEY = + "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" as const; + +export async function setupBaseRegistrarController(env: DevnetEnvironment) { + const { deployer, owner } = env.namedAccounts; + // v1.7.0: BaseRegistrar is now owned by RegistrarSecurityController + await env.v1.RegistrarSecurityController.write.addRegistrarController( + [deployer.address], + { account: owner }, + ); +} + +export async function registerV1Name( + env: DevnetEnvironment, + label: string, + ownerAddress: Address, + durationSeconds: number, +) { + const tokenId = idFromLabel(label); + await env.v1.BaseRegistrar.write.register([ + tokenId, + ownerAddress, + BigInt(durationSeconds), + ]); + const expiry = await env.v1.BaseRegistrar.read.nameExpires([tokenId]); + return expiry; +} + +export async function renewV1Name( + env: DevnetEnvironment, + label: string, + additionalDuration: number, +) { + const tokenId = idFromLabel(label); + await env.v1.BaseRegistrar.write.renew([tokenId, BigInt(additionalDuration)]); + const expiry = await env.v1.BaseRegistrar.read.nameExpires([tokenId]); + return expiry; +} + +const CSV_HEADER = + "node,name,labelHash,owner,parentName,parentLabelHash,labelName,registrationDate,expiryDate"; + +export function createCSVFile(filePath: string, labels: string[]) { + const rows = labels.map((label) => `,,,,,,${label},,`); + const content = [CSV_HEADER, ...rows].join("\n"); + writeFileSync(filePath, content); +} + +export function buildMainArgs( + env: DevnetEnvironment, + csvFilePath: string, + overrides: { + dryRun?: boolean; + limit?: number; + continue?: boolean; + bonusPeriodDays?: number; + batchSize?: number; + useEnvVarForPrivateKey?: boolean; + omitPrivateKey?: boolean; + } = {}, +): string[] { + const rpcUrl = `http://${env.hostPort}`; + const registryAddress = env.v2.ETHRegistry.address; + + const args = [ + "node", + "script", + "--rpc-url", + rpcUrl, + "--registry", + registryAddress, + "--batch-registrar", + env.rocketh.get("BatchRegistrar").address, + "--csv-file", + csvFilePath, + "--v1-resolver", + env.v2.ENSV1Resolver.address, + "--mainnet-rpc-url", + rpcUrl, + "--bonus-period-days", + String(overrides.bonusPeriodDays ?? 0), + "--v1-base-registrar", + env.v1.BaseRegistrar.address, + ]; + + if (overrides.useEnvVarForPrivateKey) { + process.env.PREMIGRATION_PRIVATE_KEY = DEPLOYER_PRIVATE_KEY; + } else if (!overrides.omitPrivateKey) { + args.push("--private-key", DEPLOYER_PRIVATE_KEY); + } + + if (overrides.dryRun) { + args.push("--dry-run"); + } + if (overrides.limit !== undefined) { + args.push("--limit", String(overrides.limit)); + } + if (overrides.continue) { + args.push("--continue"); + } + if (overrides.batchSize !== undefined) { + args.push("--batch-size", String(overrides.batchSize)); + } + + return args; +} + + +export async function verifyV2State( + env: DevnetEnvironment, + label: string, +): Promise<{ + status: number; + expiry: bigint; + latestOwner: Address; +}> { + return env.v2.ETHRegistry.read.getState([idFromLabel(label)]); +} diff --git a/contracts/test/utils/mockPrepareMigration.ts b/contracts/test/utils/mockPrepareMigration.ts new file mode 100644 index 000000000..400ba6db9 --- /dev/null +++ b/contracts/test/utils/mockPrepareMigration.ts @@ -0,0 +1,32 @@ +import { ROLES } from "../../script/deploy-constants.js"; +import type { DevnetEnvironment } from "../../script/setup.js"; + +/// Revoke the roles that `deploy/03_ETHRegistrar.ts`, +/// `deploy/02_UnlockedMigrationController.ts`, and +/// `deploy/04_LockedMigrationController.ts` pre-grant on the .eth registry. +/// +/// The devnet's deploy scripts grant the three registrars/controllers the same +/// roles that `prepareMigration` is meant to grant later in the migration +/// sequence. Calling this from a test `initialize()` puts the devnet into the +/// true pre-`prepareMigration` state so the grant path can be exercised +/// end-to-end. +export async function revertPrePrepareMigrationRoles( + env: DevnetEnvironment, +): Promise { + const registry = env.v2.ETHRegistry; + + await registry.write.revokeRootRoles([ + ROLES.REGISTRY.REGISTRAR | ROLES.REGISTRY.RENEW, + env.v2.ETHRegistrar.address, + ]); + + await registry.write.revokeRootRoles([ + ROLES.REGISTRY.REGISTER_RESERVED, + env.v2.UnlockedMigrationController.address, + ]); + + await registry.write.revokeRootRoles([ + ROLES.REGISTRY.REGISTER_RESERVED, + env.v2.LockedMigrationController.address, + ]); +} diff --git a/contracts/test/utils/preMigrationTestUtils.ts b/contracts/test/utils/preMigrationTestUtils.ts new file mode 100644 index 000000000..8a90a97f1 --- /dev/null +++ b/contracts/test/utils/preMigrationTestUtils.ts @@ -0,0 +1,38 @@ +import { existsSync, unlinkSync, writeFileSync, readFileSync } from "node:fs"; +import { + createFreshCheckpoint, + type Checkpoint, +} from "../../script/preMigration.js"; + +const DEFAULT_CHECKPOINT_FILE = "preMigration-checkpoint.json"; + +export function createTestCheckpoint( + overrides: Partial = {}, +): Checkpoint { + return { + ...createFreshCheckpoint(), + ...overrides, + }; +} + +export function writeTestCheckpoint( + checkpoint: Checkpoint, + filename: string = DEFAULT_CHECKPOINT_FILE, +) { + writeFileSync(filename, JSON.stringify(checkpoint, null, 2)); +} + +export function readTestCheckpoint( + filename: string = DEFAULT_CHECKPOINT_FILE, +): Checkpoint | null { + if (!existsSync(filename)) return null; + return JSON.parse(readFileSync(filename, "utf-8")); +} + +export function deleteTestCheckpoint( + filename: string = DEFAULT_CHECKPOINT_FILE, +) { + if (existsSync(filename)) { + unlinkSync(filename); + } +} diff --git a/contracts/test/utils/resolutions.ts b/contracts/test/utils/resolutions.ts index bced6c813..e0e588334 100755 --- a/contracts/test/utils/resolutions.ts +++ b/contracts/test/utils/resolutions.ts @@ -9,12 +9,7 @@ import { } from "viem"; import { expect } from "vitest"; -import { - COIN_TYPE_ETH, - shortCoin, -} from "../../lib/ens-contracts/test/fixtures/ensip19.js"; - -export * from "../../lib/ens-contracts/test/fixtures/ensip19.js"; +import { shortCoin, COIN_TYPE_ETH } from "./utils.js"; export const MULTICALL_ABI = parseAbi([ "function multicall(bytes[] calls) external view returns (bytes[])", @@ -26,28 +21,26 @@ export const ADDR_ABI = parseAbi([ ]); export const PROFILE_ABI = parseAbi([ - "function hasAddr(bytes32, uint256 coinType) external view returns (bool)", - + "function ABI(bytes32, uint256 contentTypes) external view returns (uint256, bytes memory)", "function addr(bytes32, uint256 coinType) external view returns (bytes)", - "function setAddr(bytes32, uint256 coinType, bytes value) external", - - "function text(bytes32, string key) external view returns (string)", - "function setText(bytes32, string key, string value) external", - "function contenthash(bytes32) external view returns (bytes)", - "function setContenthash(bytes32, bytes value) external", - - "function pubkey(bytes32) external view returns (bytes32, bytes32)", - "function setPubkey(bytes32, bytes32 x, bytes32 y) external", - + "function data(bytes32, string key) external view returns (bytes)", + "function hasAddr(bytes32, uint256 coinType) external view returns (bool)", + "function interfaceImplementer(bytes32, bytes4 interfaceID) external view returns (address)", "function name(bytes32) external view returns (string)", - "function setName(bytes32, string name) external", + "function pubkey(bytes32) external view returns (bytes32, bytes32)", + "function text(bytes32, string key) external view returns (string)", +]); - "function ABI(bytes32, uint256 contentTypes) external view returns (uint256, bytes memory)", +export const V1_SETTER_ABI = parseAbi([ "function setABI(bytes32, uint256 contentType, bytes data) external", - - "function interfaceImplementer(bytes32, bytes4 interfaceID) external view returns (address)", + "function setAddr(bytes32, uint256 coinType, bytes value) external", + "function setContenthash(bytes32, bytes value) external", + "function setData(bytes32, string key, bytes value) external", "function setInterface(bytes32, bytes4 interfaceID, address implementer) external", + "function setName(bytes32, string name) external", + "function setPubkey(bytes32, bytes32 x, bytes32 y) external", + "function setText(bytes32, string key, string value) external", ]); type StringRecord = { value: string }; @@ -56,6 +49,7 @@ export type HasAddressRecord = { coinType: bigint; exists: boolean }; export type PubkeyRecord = { x: Hex; y: Hex }; export type ErrorRecord = { call: Hex; answer: Hex }; export type TextRecord = StringRecord & { key: string }; +export type DataRecord = BytesRecord & { key: string }; export type AddressRecord = BytesRecord & { coinType: bigint }; export type ABIRecord = BytesRecord & { contentType: bigint }; export type InterfaceRecord = BytesRecord & { selector: Hex }; @@ -67,6 +61,7 @@ export type KnownProfile = { addresses?: AddressRecord[]; hasAddresses?: HasAddressRecord[]; texts?: TextRecord[]; + datas?: DataRecord[]; contenthash?: BytesRecord; primary?: StringRecord; pubkey?: PubkeyRecord; @@ -100,7 +95,7 @@ export type KnownBundle = Expected & { }; export function bundleCalls(resolutions: KnownResolution[]): KnownBundle { - if (resolutions.length == 1) { + if (resolutions.length === 1) { return { ...resolutions[0], resolutions, @@ -125,7 +120,9 @@ export function bundleCalls(resolutions: KnownResolution[]): KnownBundle { expect(answer) { const answers = this.unbundleAnswers(answer); expect(answers).toHaveLength(resolutions.length); - resolutions.forEach((x, i) => x.expect(answers[i])); + resolutions.forEach((x, i) => { + x.expect(answers[i]); + }); }, write: encodeFunctionData({ abi: MULTICALL_ABI, @@ -171,7 +168,7 @@ export function makeResolutions(p: KnownProfile): KnownResolution[] { expect(actual, this.desc).toStrictEqual(value.toLowerCase()); }, write: encodeFunctionData({ - abi, + abi: V1_SETTER_ABI, functionName: "setAddr", args: [node, coinType, value], }), @@ -212,13 +209,45 @@ export function makeResolutions(p: KnownProfile): KnownResolution[] { expect(actual, this.desc).toStrictEqual(value); }, write: encodeFunctionData({ - abi, + abi: V1_SETTER_ABI, functionName: "setText", args: [node, key, value], }), }); } } + if (p.datas) { + const abi = PROFILE_ABI; + const functionName = "data"; + for (const { key, value } of p.datas) { + resolutions.push({ + desc: `${functionName}(${key})`, + call: encodeFunctionData({ + abi, + functionName, + args: [node, key], + }), + answer: encodeFunctionResult({ + abi, + functionName, + result: value, + }), + expect(data) { + const actual = decodeFunctionResult({ + abi, + functionName, + data, + }); + expect(actual, this.desc).toStrictEqual(value); + }, + write: encodeFunctionData({ + abi: V1_SETTER_ABI, + functionName: "setData", + args: [node, key, value], + }), + }); + } + } if (p.contenthash) { const abi = PROFILE_ABI; const functionName = "contenthash"; @@ -232,7 +261,7 @@ export function makeResolutions(p: KnownProfile): KnownResolution[] { expect(actual, this.desc).toStrictEqual(value); }, write: encodeFunctionData({ - abi, + abi: V1_SETTER_ABI, functionName: "setContenthash", args: [node, value], }), @@ -251,7 +280,7 @@ export function makeResolutions(p: KnownProfile): KnownResolution[] { expect(actual, this.desc).toStrictEqual([x, y]); }, write: encodeFunctionData({ - abi, + abi: V1_SETTER_ABI, functionName: "setPubkey", args: [node, x, y], }), @@ -270,7 +299,7 @@ export function makeResolutions(p: KnownProfile): KnownResolution[] { expect(actual, this.desc).toStrictEqual(value); }, write: encodeFunctionData({ - abi, + abi: V1_SETTER_ABI, functionName: "setName", args: [node, value], }), @@ -297,7 +326,7 @@ export function makeResolutions(p: KnownProfile): KnownResolution[] { expect(actual, this.desc).toStrictEqual([contentType, value]); }, write: encodeFunctionData({ - abi, + abi: V1_SETTER_ABI, functionName: "setABI", args: [node, contentType, value], }), @@ -317,7 +346,7 @@ export function makeResolutions(p: KnownProfile): KnownResolution[] { expect(actual, this.desc).toStrictEqual(value); }, write: encodeFunctionData({ - abi, + abi: V1_SETTER_ABI, functionName: "setInterface", args: [node, selector, value], }), diff --git a/contracts/test/utils/utils.ts b/contracts/test/utils/utils.ts index ec0c7893f..b929de31e 100644 --- a/contracts/test/utils/utils.ts +++ b/contracts/test/utils/utils.ts @@ -1,12 +1,14 @@ -import { labelhash } from "viem"; // note: viem's labelhash() has long-label support, which ENSv2 is not using // we should eventually replace all labelhash(*) usage with keccak256(toBytes(*)). +import { keccak256, stringToBytes } from "viem"; export { dnsEncodeName } from "../../lib/ens-contracts/test/fixtures/dnsEncodeName.js"; +export { dnsDecodeName } from "../../lib/ens-contracts/test/fixtures/dnsDecodeName.js"; +export * from "../../lib/ens-contracts/test/fixtures/ensip19.js"; // LibLabel.id() export function idFromLabel(label: string): bigint { - return BigInt(labelhash(label)); + return BigInt(keccak256(stringToBytes(label))); } // LibLabel.withVersion() @@ -24,7 +26,7 @@ export function splitName(name: string): string[] { // "a.b.c" => "b.c" export function getParentName(name: string) { const i = name.indexOf("."); - return i == -1 ? "" : name.slice(i + 1); + return i === -1 ? "" : name.slice(i + 1); } // "a.b.c" 0 => "a" aka firstLabel() diff --git a/contracts/tsconfig.json b/contracts/tsconfig.json index 676d05f83..fc3a68750 100644 --- a/contracts/tsconfig.json +++ b/contracts/tsconfig.json @@ -11,7 +11,9 @@ "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "paths": { - "@rocketh": ["./rocketh.ts"] + "@rocketh": ["./rocketh/deploy.ts"], + "generated/*": ["./generated/*"], + "tsx": ["./script/tsx.ts"] }, "noEmit": true, "allowImportingTsExtensions": true @@ -28,6 +30,6 @@ "experimentalSpecifierResolution": "node", "files": true }, - "files": ["hardhat.config.ts", "rocketh.ts", "vitest.config.ts"], + "files": ["hardhat.config.ts", "vitest.config.ts"], "exclude": ["lib"] } diff --git a/doc/AUDIT_README.md b/doc/AUDIT_README.md new file mode 100644 index 000000000..b72323420 --- /dev/null +++ b/doc/AUDIT_README.md @@ -0,0 +1,174 @@ +# ENSv2 Audit Scope + +## 0. Changelog + +- Audit fix commit (6th May 2026): [ffe4a731c5489a2cc032639b205f36341d7ac660](https://github.com/ensdomains/contracts-v2/commit/ffe4a731c5489a2cc032639b205f36341d7ac660). 14 files touched in `contracts/src/**.sol` (1 added, 13 modified) and +370 LoC additions/modifications (`cloc --diff`, code-only). [diff](https://github.com/ensdomains/contracts-v2/compare/41b67f10d8a62151e67649d98b92bc2317fa56a8...ffe4a731c5489a2cc032639b205f36341d7ac660) +- Initial audit commit (16th March 2026): [41b67f10d8a62151e67649d98b92bc2317fa56a8](https://github.com/ensdomains/contracts-v2/commit/41b67f10d8a62151e67649d98b92bc2317fa56a8) + + +## 1. Project Overview + +ENSv2 is the next-generation Ethereum Name Service, transitioning from a flat registry to a hierarchical system with cross-chain support. + +- **Design doc**: [go.ens.xyz/ensv2](http://go.ens.xyz/ensv2) +- **Docs**:[v2 docs (WIP)](https://github.com/ensdomains/docs/tree/master/src/pages/contracts/ensv2) +- **Repository**: [github.com/ensdomains/contracts-v2](https://github.com/ensdomains/contracts-v2) +- **Contracts README**: [contracts/README.md](../contracts/README.md) (architecture, access control, usage examples) +- **Audit commit**: [41b67f10d8a62151e67649d98b92bc2317fa56a8](https://github.com/ensdomains/contracts-v2/commit/41b67f10d8a62151e67649d98b92bc2317fa56a8) + +## 2. Architecture + +See the [contracts README](../contracts/README.md) for detailed architecture documentation covering: + +- Hierarchical registry system and resolution process +- Mutable token ID system (canonical IDs) +- Enhanced Access Control (EAC) with bitmap-based roles +- Migration framework (ENSv1 -> ENSv2) + +### External Dependencies + +| Dependency | Usage | +|------------|-------| +| [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) | ERC1155, ERC165, UUPS, access control base | +| [OpenZeppelin Contracts v4](https://github.com/OpenZeppelin/openzeppelin-contracts) | Used by vendored ENSv1 contracts | +| [ENSv1 contracts](https://github.com/ensdomains/ens-contracts) | V1 registry, NameWrapper, BaseRegistrar (for migration) | +| [ENS metadata service](https://github.com/ensdomains/ens-metadata-service) | ENS metadata service | +| [Rhinestone ENS Modules](https://github.com/rhinestone-external/ens-modules) | Custom HCA (Hierarchical Context Authority) module and cross-chain intent for registration/renewal (**separate audit scope**) | +| [Verifiable Factory](https://github.com/ensdomains/verifiable-factory) | Deterministic deployment with verification (**in scope**, see below) | +| [Unruggable Gateways](https://github.com/unruggable-eth/unruggable-gateways) | CCIP-Read gateway support | + +## 3. Contracts in Scope + +### Primary repository: `ensdomains/contracts-v2` + +All Solidity source files under `contracts/src/`. To generate the current file listing, run from the `contracts/` directory: + +```sh +tree src -P '*.sol' --prune -I '*.t.sol' +``` + +At current `main` (`ffe4a73`): **61 files, 4,410 code lines** (8,057 raw lines incl. comments + blanks; subject to change until scope is frozen). + +LoC differences between each audit interval are measured using `cloc --diff` on `contracts/src/**.sol` (code-only; comments and blanks excluded). `+code` is the canonical sizing metric: `added.code + modified.code`. + +### Secondary repository: `ensdomains/verifiable-factory` + +- **Repository**: [github.com/ensdomains/verifiable-factory](https://github.com/ensdomains/verifiable-factory) +- **Audit commit**: `c47c0e61ce03b3ab5891a3b743287b54aee9f021` +- **3 files, ~150 lines** (excluding mocks): `VerifiableFactory.sol`, `UUPSProxy.sol`, `IUUPSProxy.sol` + +### Out of Scope + +- Test files (`contracts/test/`) +- Deployment scripts (`contracts/deploy/`, `contracts/script/`) +- Vendored ENSv1 contracts (`contracts/lib/ens-contracts/`) +- Rhinestone ENS Modules ([separate audit](https://github.com/rhinestone-external/ens-modules)) + +## 4. Open PRs Pending Merge + + +## 5. Key Areas of Concern + +Areas where the team particularly welcomes auditor scrutiny, listed in recommended reading order: + +1. **Enhanced Access Control (EAC)** (`src/access-control/`): Bitmap-based role system underpinning all permission logic. Admin role restrictions, role grant/revoke semantics, resource-scoped vs root-scoped permissions. +2. **PermissionedRegistry** (`src/registry/PermissionedRegistry.sol`): Primary use-case of EAC. Token ownership, admin restrictions, role inheritance on transfer, token ID regeneration on permission changes. +3. **Name transfer safety**: Ensuring ownership state is fully reset on transfer/re-registration, preventing previous owners from retaining access (cf. [CVE-2020-5232](https://github.com/ensdomains/ens/security/advisories/GHSA-8f9f-pc5v-9r5h) in ENSv1). +4. **ETHRegistrar** (`src/registrar/ETHRegistrar.sol`): Use-case of both EAC and PermissionedRegistry. Registration, renewal, commit-reveal, and ERC20 payment flow. Price oracle rounding and minimum payment enforcement. +5. **Migration logic** (`src/migration/`): Locked vs unlocked migration paths from ENSv1, wrapper receiver contracts, edge cases around expired/burned V1 names. +6. **Upgradeability**: UUPS proxy patterns (UserRegistry, PermissionedResolver, UniversalResolverV2). +7. **Universal resolution** (`src/universalResolver/`): Recursive registry traversal, wildcard handling, CCIP-Read integration. +8. **DNS/DNSSEC integration** (`src/dns/`): `DNSTLDResolver` trusts the DNSSEC oracle for proof verification and TXT record parsing; previous ENSv1 DNSSEC padding vulnerability (cf. [GHSA-c6rr-7pmc-73wc](https://github.com/ensdomains/ens-contracts/security/advisories/GHSA-c6rr-7pmc-73wc)). +9. **HCA proxy resolution** (`src/hca/`): `_msgSender()` override via HCA context, equivalence checking across contracts. + +## 6. Key Invariants + +The following invariants have been verified in the source code: + +**Ownership & Access Control:** +- Each ERC1155 token ID has at most one owner (`ERC1155Singleton`) +- Each token resource has at most one admin (the token owner). Admin roles can never be directly granted via external EAC methods — only revoked from oneself, or swapped to a new owner through transfer. +- This grant restriction also applies to the root resource, which means that as long as root permissions do not overlap with token-level permissions, the token owner is the sole controller of their name. See the [Static Deployment Permissions](../contracts/README.md#static-deployment-permissions) table in the contracts README for the exact role assignments per contract, which demonstrates the orthogonal separation between root-level and token-level roles (the ENSv2 equivalent of NameWrapper's `PARENT_CANNOT_CONTROL`). +- Token ID regeneration fully invalidates previous roles via `tokenVersionId` increment (`PermissionedRegistry.sol`) +- On transfer, the new owner receives all admin roles; the previous owner retains none + +**Registration & Expiry:** +- A name cannot be registered while it is not expired — reverts with `NameAlreadyRegistered` (`PermissionedRegistry.sol`) +- Renewal cannot shorten a name's expiry — reverts with `CannotReduceExpiration` (`PermissionedRegistry.sol`) +- Commit-reveal: registration requires a commitment aged between `MIN_COMMITMENT_AGE` and `MAX_COMMITMENT_AGE` (`ETHRegistrar.sol`) +- Payment amount cannot round to zero — enforced via ceiling rounding and zero-unit checks (`StandardRentPriceOracle.sol`) + +**Migration:** +- A name cannot be migrated twice — `register()` reverts with `NameAlreadyRegistered` on the second attempt + +**UUPS Proxies:** +- Only accounts with `ROLE_UPGRADE` on the root resource can upgrade proxy implementations (`UserRegistry.sol`) +- Implementation contracts have initializers disabled via `_disableInitializers()` + +### Known Design Decisions + +- **Circular subregistries are permitted**: The contracts do not prevent circular parent/subregistry references. Cycle detection is intentionally deferred to the indexer/off-chain layer rather than enforced on-chain. On-chain resolution (`LibRegistry.findCanonicalName`) relies on gas limits as a natural bound rather than explicit depth checks. +- **Migration allows V1 owner to specify a different V2 owner**: The `LibMigration.Data` struct includes an `owner` field chosen by the caller. The contracts do not verify that `md.owner` matches the V1 token owner. This is safe because only the V1 owner (or approved operator) can initiate the transfer via `safeTransferFrom`, and specifying a different V2 address is a valid use case (e.g., migrating to a different wallet). + +## 7. Trust Assumptions & Privileged Roles + +See the [Access Control section](../contracts/README.md#access-control) of the contracts README for full details. + +### EAC (Enhanced Access Control) Roles + +Bitmap-based roles managed by the EAC system, scoped to specific name resources (token IDs) or the root resource (contract-wide). See the [Access Control section](../contracts/README.md#access-control) of the contracts README for the full role listing and semantics. + +Contracts using EAC: `PermissionedRegistry`, `ETHRegistrar`, `BaseUriRegistryMetadata`, `SimpleRegistryMetadata`, `PermissionedResolver`. + +### User-Owned Contracts + +These contracts are deployed per user and controlled by individual name owners: + +- **UserRegistry**: UUPS-upgradeable registry deployed via `VerifiableFactory` for user-owned subdomain management. +- **PermissionedResolver**: Resolver where name owners set their own resolution records. Permissions can be delegated via EAC roles. + +### Non-EAC Privileged Roles + +These use OpenZeppelin `Ownable` or are implicit trust assumptions outside the EAC system. + +- **StandardRentPriceOracle owner** (`Ownable`): Can update base pricing rates, discount points, payment token configurations, and halving parameters. +- **Deployer roles**: The deployer receives specific admin roles per contract during deployment (not all roles). See the [Static Deployment Permissions](../contracts/README.md#static-deployment-permissions) table in the contracts README for the exact role matrix. +- **ETHRegistrar BENEFICIARY** (`immutable`): All registration and renewal payments (ERC20 via `safeTransferFrom`) are sent to this address. Set at construction and cannot be changed. + +### Trusted External Contracts + +These are external dependencies the system trusts without on-chain verification: + +- **ENSv1 contracts**: ENS Registry, NameWrapper, BaseRegistrar -- trusted as data sources during migration. CCIP-Read functionality is provided via ENSv1's `CCIPReader`/`CCIPBatcher`, which transitively depends on [Unruggable Gateways](https://github.com/unruggable-eth/unruggable-gateways). +- **DNSSEC oracle**: `DNSTLDResolver` trusts the ENSv1 DNSSEC oracle (`DNSSEC.verifyRRSet`) for cryptographic proof verification of DNS records. Set as an immutable constructor parameter. +- **HCA Factory** (Rhinestone module): Trusted to correctly resolve proxy accounts to their real owners via `_msgSender()`. Under separate audit at [rhinestone-external/ens-modules](https://github.com/rhinestone-external/ens-modules). + +## 8. Build & Test Instructions + +See the [Getting Started section](../contracts/README.md#getting-started) of the contracts README. + +**Quick start:** + +```sh +bun i && cd contracts && forge i +forge build # Build contracts +bun run test # Run all tests (Forge + Hardhat) +bun run test:forge # Forge tests only +bun run test:hardhat # Hardhat tests only +``` + +**Requirements:** Node.js v24+, Foundry v1.3.2+, Bun v1.2+ + +## 9. Prior Audits & Security Reviews + +ENSv2 (this repository) has not been previously audited. The vendored ENSv1 contracts ([ens-contracts](https://github.com/ensdomains/ens-contracts)) have undergone multiple audits: + +- [ConsenSys Diligence -- ENS Permanent Registrar (2019)](https://github.com/ConsenSys/ens-audit-report-2019-02) +- [ChainSecurity -- ENS NameWrapper](https://www.chainsecurity.com/security-audit/ethereum-name-service-ens-namewrapper) + +Previously disclosed vulnerabilities on ENSv1: + +- [GHSA-8f9f-pc5v-9r5h](https://github.com/ensdomains/ens/security/advisories/GHSA-8f9f-pc5v-9r5h) (Jan 2020, Critical): Malicious takeover of previously owned ENS names (CVE-2020-5232) +- [GHSA-rrxv-q8m4-wch3](https://github.com/ensdomains/ens-contracts/security/advisories/GHSA-rrxv-q8m4-wch3) (Aug 2023, Medium): .eth registrar controller can shorten the duration of registered names +- [GHSA-c6rr-7pmc-73wc](https://github.com/ensdomains/ens-contracts/security/advisories/GHSA-c6rr-7pmc-73wc) (Feb 2025, Low): RSA Signature Forgery via Missing PKCS#1 v1.5 Padding Validation in ENS DNSSEC Oracle + diff --git a/docs/indexing-ensv2-events.md b/docs/indexing-ensv2-events.md new file mode 100644 index 000000000..90d6291d6 --- /dev/null +++ b/docs/indexing-ensv2-events.md @@ -0,0 +1,570 @@ +# Indexing ENSv2: Contracts, Functions, and Events + +This document describes the ENSv2 contract events and functions relevant to building an indexer. It covers the full lifecycle of names — registration, transfer, renewal, subname creation, resolver record changes, role management, and aliasing. + +## Contract Hierarchy + +ENSv2 uses a hierarchical registry model. There is no single registry contract that holds all names. Instead: + +``` +RootRegistry (PermissionedRegistry) + └── ETHRegistry (PermissionedRegistry) — manages *.eth + ├── name.eth (token in ETHRegistry) + │ └── UserRegistry — manages *.name.eth + │ ├── sub.name.eth (token in UserRegistry) + │ │ └── UserRegistry — manages *.sub.name.eth + │ │ └── ... + │ └── ... + └── ... +``` + +Each registry is a `PermissionedRegistry` (or `UserRegistry` for subnames), implementing `IRegistry`, `IStandardRegistry`, `IPermissionedRegistry`, and `IEnhancedAccessControl`. Tokens are ERC1155 (one token per name, via `ERC1155Singleton`). + +Resolvers are separate contracts (`PermissionedResolver`) deployed per-owner, not per-name. Multiple names can share the same resolver, and aliases (`setAlias`) allow one name to reuse another's resolver records by rewriting the name suffix during resolution (e.g., `sub.alias.eth` → `sub.test.eth`). + +--- + +## Registry Events + +These events are emitted by any registry contract (`PermissionedRegistry` / `UserRegistry`). + +### NameRegistered + +```solidity +event NameRegistered( + uint256 indexed tokenId, + bytes32 indexed labelHash, + string label, + address owner, + uint64 expiry, + address indexed sender +); +``` + +**Emitted by**: `IRegistry` (on `PermissionedRegistry`, `UserRegistry`) + +**When**: A new name is registered via `register()`. The full name is constructed by appending the parent name (e.g., label `"test"` under ETHRegistry = `"test.eth"`). The registry contract address that emitted this event identifies which level of the hierarchy this name belongs to. + +--- + +### NameReserved + +```solidity +event NameReserved( + uint256 indexed tokenId, + bytes32 indexed labelHash, + string label, + uint64 expiry, + address indexed sender +); +``` + +**Emitted by**: `IRegistry` (on `PermissionedRegistry`) + +**When**: A name is reserved via `register()` with `owner = address(0)` and `roleBitmap = 0`. No token is minted and no owner is set. A reserved name can be promoted to REGISTERED by calling `register()` again with a real owner, which requires `ROLE_REGISTER_RESERVED`. + +--- + +### NameUnregistered + +```solidity +event NameUnregistered(uint256 indexed tokenId, address indexed sender); +``` + +**Emitted by**: `IRegistry` (on `PermissionedRegistry`, `UserRegistry`) + +**When**: A name is explicitly deleted via `unregister()`. The ERC1155 token is burned and the expiry is set to `block.timestamp`. + +--- + +### ExpiryUpdated + +```solidity +event ExpiryUpdated(uint256 indexed tokenId, uint64 newExpiry, address indexed sender); +``` + +**Emitted by**: `IRegistry` (on `PermissionedRegistry`, `UserRegistry`) + +**When**: A name's expiry is extended via `renew()` on the registry. + +--- + +### SubregistryUpdated + +```solidity +event SubregistryUpdated( + uint256 indexed tokenId, + IRegistry subregistry, + address indexed sender +); +``` + +**Emitted by**: `IRegistry` (on `PermissionedRegistry`, `UserRegistry`) + +**When**: A name's child registry is set or changed via `setSubregistry()`. This also fires during `register()` if a subregistry is provided. New subregistry addresses indicate dynamically deployed `UserRegistry` contracts for subnames. + +--- + +### ResolverUpdated + +```solidity +event ResolverUpdated(uint256 indexed tokenId, address resolver, address indexed sender); +``` + +**Emitted by**: `IRegistry` (on `PermissionedRegistry`, `UserRegistry`) + +**When**: A name's resolver is set or changed via `setResolver()`. Also fires during `register()`. New resolver addresses indicate dynamically deployed `PermissionedResolver` contracts. + +--- + +### TokenRegenerated + +```solidity +event TokenRegenerated(uint256 indexed oldTokenId, uint256 indexed newTokenId); +``` + +**Emitted by**: `IRegistry` (on `PermissionedRegistry`, `UserRegistry`) + +**When**: A name's EAC roles are modified via `grantRoles()` or `revokeRoles()`. The ERC1155 token ID changes to encode the new role configuration, while the underlying name (canonical ID / resource) remains the same. Always accompanied by ERC1155 `TransferSingle` events (burn old + mint new). + +--- + +### ParentUpdated + +```solidity +event ParentUpdated(IRegistry indexed parent, string label, address indexed sender); +``` + +**Emitted by**: `IRegistry` (on `PermissionedRegistry`, `UserRegistry`) + +**When**: A registry's parent reference is set via `setParent()`. This establishes the upward link in the registry hierarchy, complementing `SubregistryUpdated` (which links parent→child) by establishing the child→parent direction. + +--- + +### TokenResource + +```solidity +event TokenResource(uint256 indexed tokenId, uint256 indexed resource); +``` + +**Emitted by**: `IPermissionedRegistry` + +**When**: A token is created or regenerated. Maps a `tokenId` to its stable `resource` (canonical ID). The `resource` is derived from the `labelHash` and remains constant across token regenerations, making it the stable identifier for a name within a registry. + +--- + +## ERC1155 Transfer Events + +These standard ERC1155 events are emitted by all registries (which extend `ERC1155Singleton`). + +### TransferSingle + +```solidity +event TransferSingle( + address indexed operator, + address indexed from, + address indexed to, + uint256 id, + uint256 value +); +``` + +**When**: +- **Registration (mint)**: `from = address(0)`, `to = owner` — a new name token is minted +- **Transfer**: `from = previousOwner`, `to = newOwner` — ownership changes via `safeTransferFrom()` +- **Unregistration (burn)**: `from = owner`, `to = address(0)` — name token is burned +- **Token regeneration**: Two events fire — burn old tokenId + mint new tokenId. Correlate with `TokenRegenerated` to avoid treating it as a separate domain. + +### TransferBatch + +```solidity +event TransferBatch( + address indexed operator, + address indexed from, + address indexed to, + uint256[] ids, + uint256[] values +); +``` + +**When**: Batch transfers of multiple name tokens. Same semantics as `TransferSingle` but for multiple tokens at once. + +--- + +## Registrar Events + +These events are emitted by the `ETHRegistrar` contract, which is the user-facing entry point for `.eth` name registration (with commit-reveal and pricing). + +### CommitmentMade + +```solidity +event CommitmentMade(bytes32 commitment); +``` + +**Emitted by**: `IETHRegistrar` + +**When**: Step 1 of the commit-reveal registration via `commit()`. The commitment hash can be matched to the subsequent registration. + +--- + +### NameRegistered (Registrar) + +```solidity +event NameRegistered( + uint256 indexed tokenId, + string label, + address owner, + IRegistry subregistry, + address resolver, + uint64 duration, + IERC20 paymentToken, + bytes32 referrer, + uint256 base, + uint256 premium +); +``` + +**Emitted by**: `IETHRegistrar` + +**When**: Step 2 of the commit-reveal registration via `register()`. This is distinct from the `IRegistry.NameRegistered` event — the registrar emits its own event with pricing information, and the underlying `ETHRegistry` also emits `IRegistry.NameRegistered`. + +> **Note**: Both events fire for the same registration. The registrar event has pricing data; the registry event has the canonical registration data. + +--- + +### NameRenewed + +```solidity +event NameRenewed( + uint256 indexed tokenId, + string label, + uint64 duration, + uint64 newExpiry, + IERC20 paymentToken, + bytes32 referrer, + uint256 base +); +``` + +**Emitted by**: `IETHRegistrar` + +**When**: A `.eth` name is renewed via `renew()`. The registrar also calls `renew()` on the ETHRegistry, which emits `ExpiryUpdated`. + +--- + +## Resolver Events + +These events are emitted by resolver contracts (`PermissionedResolver`) and any contract implementing the standard resolver profile interfaces. Resolvers are keyed by `node` (namehash of the full name). + +### AddressChanged + +```solidity +event AddressChanged(bytes32 indexed node, uint256 coinType, bytes newAddress); +``` + +**Emitted by**: `IAddressResolver` (on `PermissionedResolver`) + +**When**: An address record is set via `setAddr(node, coinType, address)`. `coinType = 60` is ETH. Other coin types follow [SLIP-44](https://github.com/AdrianSimionov/slip-0044/blob/main/slip-0044.md) (e.g., 0 = BTC, 501 = SOL). The `node` maps to a domain via namehash. + +--- + +### TextChanged + +```solidity +event TextChanged( + bytes32 indexed node, + string indexed indexedKey, + string key, + string value +); +``` + +**Emitted by**: `ITextResolver` (on `PermissionedResolver`) + +**When**: A text record is set via `setText(node, key, value)`. Common keys: `avatar`, `url`, `description`, `com.twitter`, `com.github`, `email`, etc. + +--- + +### ContenthashChanged + +```solidity +event ContenthashChanged(bytes32 indexed node, bytes hash); +``` + +**Emitted by**: `IContentHashResolver` (on `PermissionedResolver`) + +**When**: A content hash is set via `setContenthash(node, hash)`. Supports IPFS, Arweave, Swarm, etc. + +--- + +### ABIChanged + +```solidity +event ABIChanged(bytes32 indexed node, uint256 indexed contentType); +``` + +**Emitted by**: `IABIResolver` (on `PermissionedResolver`) + +**When**: An ABI record is set. + +--- + +### PubkeyChanged + +```solidity +event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y); +``` + +**Emitted by**: `IPubkeyResolver` (on `PermissionedResolver`) + +**When**: A public key record is set (secp256k1 x,y coordinates). + +--- + +### NameChanged + +```solidity +event NameChanged(bytes32 indexed node, string name); +``` + +**Emitted by**: `INameResolver` (on `PermissionedResolver`) + +**When**: A reverse name record is set. + +--- + +### InterfaceChanged + +```solidity +event InterfaceChanged( + bytes32 indexed node, + bytes4 indexed interfaceID, + address implementer +); +``` + +**Emitted by**: `IInterfaceResolver` (on `PermissionedResolver`) + +**When**: An EIP-165 interface implementer is set. + +--- + +### VersionChanged + +```solidity +event VersionChanged(bytes32 indexed node, uint64 newVersion); +``` + +**Emitted by**: `IVersionableResolver` (on `PermissionedResolver`) + +**When**: All records for a node are cleared via `clearRecords(node)`. The version counter is incremented, invalidating all previously stored records for that node. + +--- + +### AliasChanged + +```solidity +event AliasChanged( + bytes indexed indexedFromName, + bytes indexed indexedToName, + bytes fromName, + bytes toName +); +``` + +**Emitted by**: `PermissionedResolver` + +**When**: An alias is set via `setAlias(fromName, toName)`. Names are DNS-encoded. Setting `toName` to empty bytes removes the alias. The resolver rewrites the suffix during resolution (e.g., if `alias.eth -> test.eth`, then `sub.alias.eth` resolves records for `sub.test.eth`). Aliases are resolver-level constructs — the registry does not know about them. + +--- + +### NamedResource + +```solidity +event NamedResource(uint256 indexed resource, bytes name); +``` + +**Emitted by**: `PermissionedResolver` + +**When**: An EAC resource is associated with a name for fine-grained permission control on the resolver. + +--- + +### NamedTextResource + +```solidity +event NamedTextResource(uint256 indexed resource, bytes name, bytes32 indexed keyHash, string key); +``` + +**Emitted by**: `PermissionedResolver` + +**When**: An EAC resource is associated with a specific text record key for a name, allowing fine-grained permission to modify only a specific text record (e.g., only the `avatar` key). + +--- + +### NamedAddrResource + +```solidity +event NamedAddrResource(uint256 indexed resource, bytes name, uint256 indexed coinType); +``` + +**Emitted by**: `PermissionedResolver` + +**When**: An EAC resource is associated with a specific address coin type for a name, allowing fine-grained permission to modify only a specific address record (e.g., only the ETH address). + +--- + +## Access Control Events + +ENSv2 uses Enhanced Access Control (EAC) with bitmap-based roles. Role changes emit `EACRolesChanged` and trigger `TokenRegenerated` (documented above). For full details on the role system, see [Access Control](https://github.com/ensdomains/contracts-v2/tree/main/contracts#access-control). + +--- + +## Key Concepts for Indexers + +### Dynamic Contract Discovery + +An indexer cannot know all contract addresses at startup. The core pattern is: + +1. Start by watching the **RootRegistry** and **ETHRegistry** (known addresses from deployment). +2. When a `SubregistryUpdated` event fires with a new subregistry address, add that address to the watch list. +3. When a `ResolverUpdated` event fires with a new resolver address, add that address to the watch list for resolver events. + +This creates a self-expanding set of monitored contracts. + +### TokenId vs Resource (Canonical ID) + +- **tokenId**: The ERC1155 token ID. Changes when roles are modified (`TokenRegenerated`). Encodes role configuration. +- **resource**: The stable canonical identifier for a name within a registry. Derived from the `labelHash`. Does not change across role modifications or re-registrations. + +Use the `TokenResource` event to maintain the mapping. The `resource` should be the primary key for domain lookups. + +### Name Construction + +The indexer must track the registry hierarchy to construct full names: + +1. **ETHRegistry** emits `NameRegistered` with `label = "test"` -> full name is `"test.eth"` +2. A `SubregistryUpdated` on `test.eth` points to `UserRegistry` at address `0xABC` +3. That `UserRegistry` emits `NameRegistered` with `label = "sub"` -> full name is `"sub.test.eth"` + +The indexer must map each registry address to its parent name to build the complete DNS name. + +### Shared Subregistries (Linked Names) + +Multiple parent names can point to the same subregistry via `setSubregistry()`. For example: + +- `sub1.sub2.parent.eth` has subregistry at `0xABC` +- `linked.parent.eth` also has subregistry at `0xABC` + +Children registered in `0xABC` appear under both parents. The token `wallet` in registry `0xABC` is simultaneously `wallet.sub1.sub2.parent.eth` and `wallet.linked.parent.eth` — they share the same tokenId. + +### Alias Resolution + +Aliases are a resolver-level concept, not a registry-level one: + +- `alias.eth` and `test.eth` may share the same resolver +- The resolver stores: `alias.eth -> test.eth` alias mapping +- When resolving `sub.alias.eth`, the resolver rewrites it to `sub.test.eth` and returns those records +- The registry hierarchy knows nothing about aliases — they exist only in the resolver's storage + +### Registration Status + +Names can be in one of three states (from `IPermissionedRegistry.Status`): + +| Status | Value | Description | +|--------|-------|-------------| +| `AVAILABLE` | 0 | Name can be registered | +| `RESERVED` | 1 | Name is reserved (cannot be registered until expiry, unless caller has `ROLE_REGISTER_RESERVED`) | +| `REGISTERED` | 2 | Name is actively registered with an owner | + +After expiry, names return to `AVAILABLE`. Re-registration creates a new `tokenId` but keeps the same `resource`. + +### Event Processing Order + +For a single registration via `ETHRegistrar.register()`, events fire in this order: + +1. `IETHRegistrar.NameRegistered` — registrar-level event with pricing +2. `IRegistry.NameRegistered` — registry-level event with registration details +3. `TokenResource` — tokenId-to-resource mapping +4. `TransferSingle` (mint) — ERC1155 token creation +5. `SubregistryUpdated` — if a subregistry was provided +6. `ResolverUpdated` — if a resolver was provided + +For a direct `IStandardRegistry.register()` call (e.g., on a UserRegistry): + +1. `IRegistry.NameRegistered` +2. `TokenResource` +3. `TransferSingle` (mint) +4. `SubregistryUpdated` — if a subregistry was provided +5. `ResolverUpdated` — if a resolver was provided + +--- + +## Contract Address Summary + +| Contract | Role | Events to Watch | +|----------|------|----------------| +| `PermissionedRegistry` (ETHRegistry) | Manages `.eth` names | All `IRegistry` events (incl. `ParentUpdated`), `TokenResource`, ERC1155 transfers | +| `PermissionedRegistry` (RootRegistry) | Manages TLDs | Same as above | +| `UserRegistry` | Manages subnames (dynamically deployed) | Same as above | +| `ETHRegistrar` | User-facing `.eth` registration | `CommitmentMade`, `NameRegistered`, `NameRenewed` | +| `PermissionedResolver` | Stores resolver records (dynamically deployed) | `AddressChanged`, `TextChanged`, `ContenthashChanged`, `ABIChanged`, `PubkeyChanged`, `NameChanged`, `InterfaceChanged`, `VersionChanged`, `AliasChanged`, `NamedResource`, `NamedTextResource`, `NamedAddrResource` | + +--- + +## Read Functions for State Verification + +These view functions are useful for verifying indexed state or backfilling data: + +### Registry State + +```solidity +// Get full state of a name (status, expiry, owner, tokenId, resource) +function getState(uint256 anyId) external view returns (State memory); + +// Get the subregistry for a label +function getSubregistry(string calldata label) external view returns (IRegistry); + +// Get the resolver for a label +function getResolver(string calldata label) external view returns (address); + +// Get the owner of a token +function ownerOf(uint256 tokenId) external view returns (address); + +// Get the stable resource ID +function getResource(uint256 anyId) external view returns (uint256); + +// Get the current tokenId (may change after role modifications) +function getTokenId(uint256 anyId) external view returns (uint256); + +// Get the expiry +function getExpiry(uint256 anyId) external view returns (uint64); +``` + +### Registrar State + +```solidity +// Check if a name is available for registration +function isAvailable(string memory label) external view returns (bool); + +// Get rental price +function rentPrice(string memory label, address buyer, uint64 duration, IERC20 paymentToken) + external view returns (uint256 base, uint256 premium); +``` + +### Resolver State + +```solidity +// Get address record +function addr(bytes32 node, uint256 coinType) external view returns (bytes memory); + +// Get text record +function text(bytes32 node, string calldata key) external view returns (string memory); + +// Get content hash +function contenthash(bytes32 node) external view returns (bytes memory); + +// Get alias +function getAlias(bytes calldata name) external view returns (bytes memory); +``` + diff --git a/docs/indexing-test-names.md b/docs/indexing-test-names.md new file mode 100644 index 000000000..f632c4bb3 --- /dev/null +++ b/docs/indexing-test-names.md @@ -0,0 +1,192 @@ +# Indexing ENSv2 Test Names + +This document explains the test data created by `contracts/script/testNames.ts` and how an indexer (such as [v2-mini-indexer](https://github.com/ensdomains/ensv2-indexer)) would index each name by listening to on-chain events. + +## Overview + +The `testNames()` function sets up a devnet with various ENS names in different states. Each operation emits specific contract events that an indexer must process to build a complete picture of the namespace. + +## Test Data Summary + +| Name | Operation | Expected Indexed State | +|------|-----------|----------------------| +| `test.eth` | Register | Domain with owner, resolver (addr + text records) | +| `example.eth` | Register | Domain with owner, resolver | +| `demo.eth` | Register | Domain with owner, resolver | +| `newowner.eth` | Register + Transfer | Domain owned by `user` account (not `owner`) | +| `renew.eth` | Register + Renew (365 days) | Domain with extended expiry | +| `reregister.eth` | Register + Expire + Re-register | Domain with new expiry and new tokenId | +| `parent.eth` | Register | Domain with owner, resolver | +| `changerole.eth` | Register + Role change | Domain with modified EAC roles, new tokenId | +| `alias.eth` | Register + Set alias to `test.eth` | Domain sharing resolver with `test.eth`; alias record set | +| `sub.alias.eth` | Records set on `test.eth` resolver | Resolves via alias chain (no direct registry entry) | +| `sub2.parent.eth` | Create subname (UserRegistry) | Subname with dedicated UserRegistry and resolver | +| `sub1.sub2.parent.eth` | Create subname (UserRegistry) | Nested subname | +| `wallet.sub1.sub2.parent.eth` | Create subname (UserRegistry) | Deeply nested subname | +| `linked.parent.eth` | Link to `sub1.sub2.parent.eth` subregistry | Shares subregistry with `sub1.sub2.parent.eth` | +| `wallet.linked.parent.eth` | Shared token via linked subregistry | Same token as `wallet.sub1.sub2.parent.eth` | +| `reserved.eth` | Reserve (no owner) | Domain with RESERVED status, no token minted | +| `unregistered.eth` | Register + Unregister | Domain returned to AVAILABLE status, token burned | + +## Setup: Parent Registry Links + +Before registering names, `testNames()` calls `ETHRegistry.setParent(RootRegistry, "eth")` to establish the child→parent link. This emits: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `ParentUpdated(parent, label, sender)` | `IRegistry` (ETHRegistry) | Parent registry address, label in parent | + +**Indexer action**: Record the parent registry and label for the ETHRegistry. This enables reconstructing full domain names by traversing the parent chain (e.g., ETHRegistry → "eth" in RootRegistry → root). + +## Events Emitted Per Operation + +### 1. Name Registration (`registerTestNames`) + +Each name registration triggers events on the **ETHRegistry** (a `PermissionedRegistry`): + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `NameRegistered(tokenId, labelHash, label, owner, expiry, ...)` | `IRegistry` | tokenId, label, owner, expiry | +| `TransferSingle(operator, from=0x0, to, id, value)` | `ERC1155Singleton` | Mint event: `from=address(0)` | +| `TokenResource(tokenId, resource)` | `IPermissionedRegistry` | Links tokenId to its resource/canonical ID | + +Each registration also deploys a **PermissionedResolver** and sets records: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `AddressChanged(node, coinType=60, address)` | Resolver | ETH address record | +| `TextChanged(node, key="description", value)` | Resolver | Text record | + +**Indexer action**: Create a `Domain` entry with name, namehash, owner, expiry, resolver address. Create `Registration` entry. Index resolver records. + +### 2. Transfer (`transferName`) + +Transferring `newowner.eth` to the `user` account: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `TransferSingle(operator, from=owner, to=user, id=tokenId, value=1)` | `ERC1155Singleton` | Ownership change | + +**Indexer action**: Update domain `owner` field. The `registrant` (original registerer) remains unchanged. + +### 3. Renewal (`renewName`) + +Renewing `renew.eth` for 365 days via the ETHRegistrar: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `NameRenewed(label, newExpiry)` | `IETHRegistrar` | Updated expiry | +| `ExpiryUpdated(tokenId, newExpiry, sender)` | `IRegistry` | Updated expiry on registry | + +**Indexer action**: Update domain `expiryDate`. + +### 4. Re-registration (`reregisterName`) + +Time-warps past expiry, then re-registers with a new expiry: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `NameRegistered(tokenId, labelHash, label, owner, expiry, ...)` | `IRegistry` | New tokenId (different from original) | +| `TransferSingle(operator, from=0x0, to, id, value)` | `ERC1155Singleton` | New mint | +| `TokenResource(tokenId, resource)` | `IPermissionedRegistry` | New tokenId-to-resource mapping | + +**Indexer action**: The domain gets a new tokenId. Update the domain entry, reset expiry. The canonical ID (resource) stays the same but the tokenId changes. + +### 5. Subname Creation (`createSubname`) + +Creating `wallet.sub1.sub2.parent.eth` involves multiple levels: + +For each level (sub2, sub1, wallet): + +1. **Deploy UserRegistry** (UUPS proxy): + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| (Proxy deployment events) | `VerifiableFactory` | New registry address | + +2. **Set subregistry on parent**: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `SubregistryUpdated(tokenId, subregistry, sender)` | `IRegistry` | Parent tokenId linked to child registry | + +3. **Set parent on new UserRegistry**: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `ParentUpdated(parent, label, sender)` | `IRegistry` (UserRegistry) | Links child registry back to its parent | + +4. **Register subname in UserRegistry**: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `NameRegistered(tokenId, labelHash, label, owner, expiry, ...)` | `IRegistry` (UserRegistry) | Subname registration | +| `TransferSingle(operator, from=0x0, to, id, value)` | `ERC1155Singleton` | Mint in UserRegistry | +| `ResolverUpdated(tokenId, resolver, sender)` | `IRegistry` | Resolver set on subname | + +**Indexer action**: The indexer must **dynamically discover** new UserRegistry contracts by watching `SubregistryUpdated` events. Once discovered, the indexer adds the new registry address to its watch list and starts indexing events from it. The `ParentUpdated` events allow the indexer to reconstruct the full name hierarchy by traversing child→parent links. This is the key "hierarchical registry tracking" feature. + +### 6. Name Linking (`linkName`) + +Creating `linked.parent.eth` that shares the subregistry of `sub1.sub2.parent.eth`: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `NameRegistered(tokenId, labelHash, "linked", owner, expiry, ...)` | Parent UserRegistry | New name in registry | +| `TransferSingle(...)` | `ERC1155Singleton` | Mint | + +The key detail: `linked.parent.eth` points to the **same subregistry** as `sub1.sub2.parent.eth`. This means `wallet.linked.parent.eth` and `wallet.sub1.sub2.parent.eth` resolve to the same token in the same UserRegistry. + +An alias is also set on the wallet resolver so that resolver records work correctly: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `AliasChanged(name, alias)` | `PermissionedResolver` | Resolver alias mapping | + +**Indexer action**: Register `linked.parent.eth` as a normal domain. Its `SubregistryUpdated` points to the already-known UserRegistry. Children resolve through shared subregistry. + +### 7. Alias Creation + +`alias.eth` is registered with `test.eth`'s resolver, then an alias is set: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `NameRegistered(...)` | `IRegistry` | alias.eth registration | +| `AliasChanged(dnsEncode("alias.eth"), dnsEncode("test.eth"))` | `PermissionedResolver` | Alias mapping | + +`sub.alias.eth` has no direct registry entry. Records for `sub.test.eth` are set on test.eth's resolver, and the `UniversalResolverV2` follows the alias chain to resolve `sub.alias.eth` to `sub.test.eth`'s records. + +**Indexer action**: Index alias records. Resolution of `sub.alias.eth` happens at query time through the UniversalResolver, not via direct registry lookups. + +### 8. Role Changes (`changeRole`) + +Granting `SET_RESOLVER` and revoking `SET_SUBREGISTRY` on `changerole.eth`: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `TokenRegenerated(oldTokenId, newTokenId)` | `IRegistry` | TokenId changes when roles change | +| `TransferSingle(operator, from, to=0x0, oldTokenId, 1)` | `ERC1155Singleton` | Burn old token | +| `TransferSingle(operator, from=0x0, to, newTokenId, 1)` | `ERC1155Singleton` | Mint new token | + +**Indexer action**: Update domain tokenId. The canonical ID / resource remains stable. For details on the access control system, see [Access Control](https://github.com/ensdomains/contracts-v2/tree/main/contracts#access-control). + +### 9. Reservation (`reserveName`) + +Reserving `reserved.eth` with no owner: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `NameReserved(tokenId, labelHash, label, expiry, sender)` | `IRegistry` | tokenId, label, expiry | + +**Indexer action**: Create a domain entry with `RESERVED` status. No owner is set and no ERC1155 token is minted. + +### 10. Unregistration (`unregisterName`) + +Registering then unregistering `unregistered.eth`: + +| Event | Source | Indexed Fields | +|-------|--------|---------------| +| `NameUnregistered(tokenId, sender)` | `IRegistry` | tokenId | +| `TransferSingle(operator, from=owner, to=0x0, id=tokenId, value=1)` | `ERC1155Singleton` | Burn event | + +**Indexer action**: Mark the domain as `AVAILABLE`. The ERC1155 token is burned. diff --git a/package.json b/package.json index 7af899494..81d96cffa 100644 --- a/package.json +++ b/package.json @@ -6,15 +6,19 @@ "bun": "^1.2.15" }, "workspaces": [ - "contracts", - "solhint-plugins" + "contracts" ], "devDependencies": { + "@biomejs/biome": "^2.4.11", "husky": "^9.1.7", "typescript": "^5.8.3" }, "resolutions": { "esbuild": "0.25.11" }, - "engineStrict": true + "engineStrict": true, + "patchedDependencies": { + "@rocketh/node@0.19.3": "patches/@rocketh-node@0.19.3.patch", + "rocketh@0.19.3": "patches/rocketh@0.19.3.patch" + } } diff --git a/patches/@rocketh-node@0.19.3.patch b/patches/@rocketh-node@0.19.3.patch new file mode 100644 index 000000000..46382f85a --- /dev/null +++ b/patches/@rocketh-node@0.19.3.patch @@ -0,0 +1,12 @@ +diff --git a/dist/executor/index.js b/dist/executor/index.js +index 00db18f8f807c3f47828e4c46aa963c525ddc2f2..6c389ef9247c35d0d006b5dc3fdd2552bf46f263 100644 +--- a/dist/executor/index.js ++++ b/dist/executor/index.js +@@ -1,4 +1,6 @@ +-import 'tsx'; ++if (!globalThis.Bun) { ++ await import('tsx'); ++} + import fs from 'node:fs'; + import path from 'node:path'; + import prompts from 'prompts'; diff --git a/patches/rocketh@0.19.3.patch b/patches/rocketh@0.19.3.patch new file mode 100644 index 000000000..b566cccfb --- /dev/null +++ b/patches/rocketh@0.19.3.patch @@ -0,0 +1,63 @@ +diff --git a/dist/index.d.ts b/dist/index.d.ts +index 48eba2596a81afaa45cfbe2f3f655fdf150abdbc..2a909de3149d01735df331b3990c0f121ad5a2c6 100644 +--- a/dist/index.d.ts ++++ b/dist/index.d.ts +@@ -2,4 +2,6 @@ export { setupDeployScripts, loadEnvironment, resolveConfig, resolveExecutionPar + export { createEnvironment, loadDeployments } from './environment/index.js'; + export { enhanceEnvIfNeeded } from '@rocketh/core/environment'; + export { getChainConfigFromUserConfig } from './environment/chains.js'; ++export declare const setup: typeof setupDeployScripts; ++export type * from './types.js'; + //# sourceMappingURL=index.d.ts.map +diff --git a/dist/index.js b/dist/index.js +index 018a31ca31616c50679b1b566c1092b67857c47d..b21ab3736f81172de7ab5402e97f1390f807ca37 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -3,4 +3,47 @@ export { createEnvironment, loadDeployments } from './environment/index.js'; + // used by hardhat-deploy and instead of having hardhat-deploy depends on @rocketh/core we export it here as well + export { enhanceEnvIfNeeded } from '@rocketh/core/environment'; + export { getChainConfigFromUserConfig } from './environment/chains.js'; ++import { setupDeployScripts } from './executor/index.js'; ++ ++export function setup(extensions) { ++ const legacyExtensions = { ...extensions }; ++ legacyExtensions.savePendingDeployment ??= (env) => async (pendingDeployment) => { ++ const receipt = await waitForReceipt(env, pendingDeployment.transaction.hash); ++ const contractAddress = pendingDeployment.expectedAddress ?? receipt.contractAddress; ++ if (!contractAddress) { ++ throw new Error(`no contract address found for ${pendingDeployment.name}`); ++ } ++ const { abi, ...artifactObjectWithoutABI } = pendingDeployment.partialDeployment; ++ return env.save(pendingDeployment.name, { ++ address: contractAddress, ++ abi, ++ ...artifactObjectWithoutABI, ++ transaction: pendingDeployment.transaction, ++ receipt: { ++ blockHash: receipt.blockHash, ++ blockNumber: receipt.blockNumber, ++ transactionIndex: receipt.transactionIndex, ++ }, ++ }); ++ }; ++ return setupDeployScripts(legacyExtensions); ++} ++ ++async function waitForReceipt(env, hash) { ++ for (;;) { ++ let receipt; ++ try { ++ receipt = await env.network.provider.request({ ++ method: 'eth_getTransactionReceipt', ++ params: [hash], ++ }); ++ } ++ catch { ++ } ++ if (receipt?.blockHash) { ++ return receipt; ++ } ++ await new Promise((resolve) => setTimeout(resolve, 50)); ++ } ++} + //# sourceMappingURL=index.js.map diff --git a/solhint-plugins/import-order-separation.js b/solhint-plugins/import-order-separation.js deleted file mode 100644 index dedbcaf46..000000000 --- a/solhint-plugins/import-order-separation.js +++ /dev/null @@ -1,326 +0,0 @@ -// Solhint plugin: import-order-separation -// Recreates the idea of `importOrderSeparation` from prettier-plugin-sort-imports -// for Solidity imports using Solhint's class-based rules API. - -/** - * @typedef {Object} ImportDirectiveNode - * @property {string} type - * @property {Object} loc - * @property {Object} path - * @property {Array} range - * @property {Array} symbolAliases - */ - -// Grouping helper: first matching regex wins -/** - * @description Selects the group index for a given import path - * @param {string} importPath - * @param {string[] | undefined} patterns - * @returns {number} - */ -function selectGroupIndex(importPath, patterns) { - if (Array.isArray(patterns) && patterns.length > 0) { - for (let i = 0; i < patterns.length; i++) { - const raw = patterns[i]; - if (typeof raw !== "string") continue; - try { - const re = new RegExp(raw); - if (re.test(importPath)) return i; - } catch { - // Ignore invalid regex; continue - } - } - // Non-matching imports go last - return patterns.length; - } - // Default grouping similar to JS: external vs relative - return importPath.startsWith(".") ? 1 : 0; -} - -/** - * @description Gets the source path for a given import directive node - * @param {ImportDirectiveNode} node - * @returns {string | undefined} - */ -function sourcePath(node) { - const anyNode = node; - const p = anyNode.path; - if (typeof p === "string") return p; - if (p && typeof p.value === "string") return p.value; - if (p && typeof p.name === "string") return p.name; - return undefined; -} - -// Rule implemented as a class per Solhint's plugin guide -class ImportOrderSeparationRule { - ruleId = "import-order-separation"; - meta = { fixable: true }; - /** - * @type {Object} - * // Solhint's reporter accepts an optional fixer function; use any for broad compatibility - * @property {(node: any, ruleId: string, message: string, fix?: (fixer: any) => any) => void} error - */ - reporter; - /** - * @type {string[] | undefined} - */ - importOrder; - /** - * @type {ImportDirectiveNode[]} - */ - imports = []; - /** - * @type {Array<{ node: any; insertPos: number }>} - */ - violations = []; - /** - * @type {Array<{ range: [number, number]; path: string; fullSentence: string }>} - */ - fromContractImports = []; - /** - * @type {Array<{ range: [number, number]; path: string; fullSentence: string }>} - */ - orderedImports = []; - - /** - * @param {any} reporter - * @param {any} config - */ - constructor(reporter, config) { - this.reporter = reporter; - this.importOrder = - config && config.getObject(`contracts-v2/${this.ruleId}`, {}).importOrder; - } - - /** - * Visitor: collect imports - * @param {ImportDirectiveNode} node - */ - ImportDirective(node) { - if (node && node.type === "ImportDirective") { - this.imports.push(node); - } - } - - // Visitor exit: analyze spacing between groups - ["SourceUnit:exit"]() { - if (this.imports.length < 2) { - this.imports = []; - return; - } - - this.imports.sort( - (a, b) => (a.loc?.start.line ?? 0) - (b.loc?.start.line ?? 0), - ); - - // Build import entries with ranges and normalized paths - this.fromContractImports = this.imports - .filter((n) => n && n.type === "ImportDirective") - .map((n) => { - const p = sourcePath(n) ?? ""; - const normalized = this.normalizePath(p); - const fullSentence = n.symbolAliases - ? `${this.getFullSentence(n.symbolAliases)}'${normalized}';` - : `import '${normalized}';`; - /** - * @type {[number, number]} - */ - const range = Array.isArray(n.range) ? n.range : [0, 0]; - return { range, path: normalized, fullSentence }; - }); - - // Prepare ordered copy - this.orderedImports = JSON.parse(JSON.stringify(this.fromContractImports)); - this.orderedImports = this.sortImports(this.orderedImports); - - // If order differs, rewrite the import block with correct order and separation - if (!this.arePathsEqual(this.fromContractImports, this.orderedImports)) { - // Determine separation between groups based on configured importOrder - const groupFor = (/** @type {string} */ p) => - selectGroupIndex(p, this.importOrder); - const groups = this.orderedImports.map((imp) => groupFor(imp.path)); - - let currentStart = Math.min( - ...this.fromContractImports.map((imp) => imp.range[0]), - ); - const replacements = this.orderedImports.map((orderedImport, i) => { - const newText = orderedImport.fullSentence.replace(/'/g, '"'); - const sep = - i < this.orderedImports.length - 1 - ? groups[i] !== groups[i + 1] - ? "\n\n" - : "\n" - : ""; - const rangeEnd = currentStart + newText.length + sep.length; // account for sep when slicing ranges - const replacement = { - range: [currentStart, rangeEnd], - newText, - sep, - }; - currentStart = rangeEnd; - return replacement; - }); - - const lastRangeEnd = - this.fromContractImports[this.fromContractImports.length - 1].range[1]; - // Apply fixes from bottom to top - for (let i = replacements.length - 1; i >= 0; i--) { - const rep = replacements[i]; - if (!rep) continue; - const node = this.imports[i]; - const isLast = i === replacements.length - 1; - if (isLast) { - this.reporter.error( - node, - this.ruleId, - "Wrong import order", - (fixer) => - fixer.replaceTextRange([rep.range[0], lastRangeEnd], rep.newText), - ); - } else { - this.reporter.error( - node, - this.ruleId, - "Wrong import order", - (fixer) => fixer.replaceTextRange(rep.range, rep.newText + rep.sep), - ); - } - } - - // Reset state and stop (spacing handled by our constructed separators) - this.imports = []; - this.violations = []; - this.fromContractImports = []; - this.orderedImports = []; - return; - } - - /** - * @type {number | undefined} - */ - let prevGroup; - /** - * @type {number | undefined} - */ - let prevEndLine; - - // Track violations to report bottom-to-top for safe fixing - this.violations = []; - - for (let i = 0; i < this.imports.length; i++) { - const node = this.imports[i]; - const p = sourcePath(node); - if (!p || !node.loc) continue; - const group = selectGroupIndex(p, this.importOrder); - - if ( - prevGroup !== undefined && - group !== prevGroup && - prevEndLine !== undefined - ) { - const currentStart = node.loc.start.line; - if (currentStart < prevEndLine + 2) { - // Prefer inserting a newline before the current import start. - const range = Array.isArray(node.range) ? node.range : undefined; - if (range) { - this.violations.push({ node, insertPos: range[0] }); - } else { - // Fallback: report without fix if range is unavailable - this.reporter.error( - node, - this.ruleId, - "Expected a blank line between import groups", - ); - } - } - } - - prevGroup = group; - prevEndLine = node.loc.end.line; - } - - // Report fixes from bottom to top to avoid range shifting issues - for (let i = this.violations.length - 1; i >= 0; i--) { - const v = this.violations[i]; - if (!v) continue; - this.reporter.error( - v.node, - this.ruleId, - "Expected a blank line between import groups", - (fixer) => fixer.replaceTextRange([v.insertPos, v.insertPos], "\n"), - ); - } - - // Reset for next file - this.imports = []; - this.violations = []; - this.fromContractImports = []; - this.orderedImports = []; - } - - // ----- Helpers borrowed and adapted from Solhint's imports-order ----- - /** - * @param {Array<{ range: [number, number]; path: string; fullSentence: string }>} unorderedImports - * @returns {Array<{ range: [number, number]; path: string; fullSentence: string }>} - */ - sortImports(unorderedImports) { - /** - * @param {string} path - * @returns {number} - */ - const regexOrder = this.importOrder.map((regex, i, arr) => [ - new RegExp(regex), - (arr.length - i) * -10000, - ]); - function getHierarchyLevel(path) { - for (const [regex, order] of regexOrder) { - if (regex.test(path)) { - return order; - } - } - return Infinity; - } - const orderedImports = unorderedImports.sort((a, b) => { - const levelA = getHierarchyLevel(a.path); - const levelB = getHierarchyLevel(b.path); - if (levelA !== levelB) return levelA - levelB; - return a.path.localeCompare(b.path, undefined, { sensitivity: "base" }); - }); - return orderedImports; - } - - /** - * @param {Array<[string, string?]>} elements - * @returns {string} - */ - getFullSentence(elements) { - const importParts = elements.map(([name, alias]) => - alias ? `${name} as ${alias}` : name, - ); - return `import {${importParts.join(", ")}} from `; - } - - /** - * @param {string} path - * @returns {string} - */ - normalizePath(path) { - return path; - } - - /** - * @param {Array<{ path: string }>} arr1 - * @param {Array<{ path: string }>} arr2 - * @returns {boolean} - */ - arePathsEqual(arr1, arr2) { - if (arr1.length !== arr2.length) return false; - for (let i = 0; i < arr1.length; i++) { - if (!arr1[i] || !arr2[i]) return false; - if (arr1[i].path !== arr2[i].path) return false; - } - return true; - } -} - -module.exports = ImportOrderSeparationRule; diff --git a/solhint-plugins/index.js b/solhint-plugins/index.js deleted file mode 100644 index 3437b5675..000000000 --- a/solhint-plugins/index.js +++ /dev/null @@ -1,6 +0,0 @@ -const ordering = require("./ordering"); -const importOrderSeparation = require("./import-order-separation"); -const selectorTags = require("./selector-tags"); -const natspecTripleSlash = require("./natspec-triple-slash"); - -module.exports = [ordering, importOrderSeparation, selectorTags, natspecTripleSlash]; diff --git a/solhint-plugins/natspec-triple-slash.js b/solhint-plugins/natspec-triple-slash.js deleted file mode 100644 index b903679c9..000000000 --- a/solhint-plugins/natspec-triple-slash.js +++ /dev/null @@ -1,154 +0,0 @@ -const ruleId = "natspec-triple-slash"; - -class NatspecTripleSlashChecker { - ruleId = ruleId; - meta = { fixable: true }; - - constructor(reporter, config, inputSrc) { - this.reporter = reporter; - this.inputSrc = inputSrc; - this._lines = null; - this._reported = new Set(); - } - - _initLines() { - if (this._lines) return; - this._lines = []; - const src = this.inputSrc; - let start = 0; - for (let i = 0; i <= src.length; i++) { - if (i === src.length || src[i] === "\n") { - this._lines.push({ - start, - end: i, - content: src.slice(start, i), - }); - start = i + 1; - } - } - } - - _getLineIndex(offset) { - let lo = 0; - let hi = this._lines.length - 1; - while (lo < hi) { - const mid = (lo + hi + 1) >> 1; - if (this._lines[mid].start <= offset) lo = mid; - else hi = mid - 1; - } - return lo; - } - - _findNatspecBlockComment(rangeStart) { - this._initLines(); - const defLineIdx = this._getLineIndex(rangeStart); - - for (let i = defLineIdx - 1; i >= 0; i--) { - const trimmed = this._lines[i].content.trimStart(); - - if (trimmed === "") continue; - if (/^\/\/\//.test(trimmed)) continue; - - if (/\*\/\s*$/.test(trimmed)) { - for (let j = i; j >= 0; j--) { - const jTrimmed = this._lines[j].content.trimStart(); - if (/^\/\*\*/.test(jTrimmed)) { - return { startLineIdx: j, endLineIdx: i }; - } - if (/^\/\*/.test(jTrimmed)) { - return null; - } - } - return null; - } - - break; - } - - return null; - } - - _convertBlockToTripleSlash(startLineIdx, endLineIdx) { - const lines = []; - const indent = this._lines[startLineIdx].content.match(/^(\s*)/)[1]; - - for (let i = startLineIdx; i <= endLineIdx; i++) { - let text = this._lines[i].content.trimStart(); - - if (i === endLineIdx) { - text = text.replace(/\s*\*\/$/, ""); - } - - if (i === startLineIdx) { - text = text.replace(/^\/\*\*\s?/, ""); - } else { - text = text.replace(/^\*\s?/, ""); - } - - text = text.trimEnd(); - - if ((i === startLineIdx || i === endLineIdx) && text === "") continue; - - if (text === "") { - lines.push(`${indent}///`); - } else { - lines.push(`${indent}/// ${text}`); - } - } - - return lines.join("\n"); - } - - _checkNode(node) { - if (!node || !node.range) return; - this._initLines(); - - const block = this._findNatspecBlockComment(node.range[0]); - if (!block) return; - - const key = `${block.startLineIdx}:${block.endLineIdx}`; - if (this._reported.has(key)) return; - this._reported.add(key); - - const replacement = this._convertBlockToTripleSlash( - block.startLineIdx, - block.endLineIdx, - ); - const startOffset = this._lines[block.startLineIdx].start; - const endOffset = this._lines[block.endLineIdx].end - 1; - - this.reporter.error( - node, - this.ruleId, - "NatSpec comments should use triple-slash (///) format instead of block (/** */) format", - (fixer) => fixer.replaceTextRange([startOffset, endOffset], replacement), - ); - } - - ContractDefinition(node) { - this._checkNode(node); - } - FunctionDefinition(node) { - this._checkNode(node); - } - EventDefinition(node) { - this._checkNode(node); - } - CustomErrorDefinition(node) { - this._checkNode(node); - } - StateVariableDeclaration(node) { - this._checkNode(node); - } - ModifierDefinition(node) { - this._checkNode(node); - } - StructDefinition(node) { - this._checkNode(node); - } - EnumDefinition(node) { - this._checkNode(node); - } -} - -module.exports = NatspecTripleSlashChecker; diff --git a/solhint-plugins/ordering.js b/solhint-plugins/ordering.js deleted file mode 100644 index edbcae764..000000000 --- a/solhint-plugins/ordering.js +++ /dev/null @@ -1,236 +0,0 @@ -const BaseChecker = require("solhint/lib/rules/base-checker"); -const { - isFallbackFunction, - isReceiveFunction, -} = require("solhint/lib/common/ast-types"); - -const ruleId = "ordering"; - -class OrderingChecker extends BaseChecker { - constructor(reporter) { - super(reporter, ruleId, {}); - } - - SourceUnit(node) { - const children = node.children; - this.checkOrder(children, sourceUnitPartOrder); - } - - ContractDefinition(node) { - const children = node.subNodes; - - this.checkOrder(children, contractPartOrder); - } - - checkOrder(children, orderFunction) { - if (children.length === 0) { - return; - } - - let maxChild = children[0]; - let [maxComparisonValue, maxLabel] = orderFunction(children[0]); - - for (let i = 1; i < children.length; i++) { - const [comparisonValue, label] = orderFunction(children[i]); - if (comparisonValue < maxComparisonValue) { - this.report(children[i], maxChild, label, maxLabel); - return; - } - - maxChild = children[i]; - maxComparisonValue = comparisonValue; - maxLabel = label; - } - } - - report(node, nodeBefore, label, labelBefore) { - const message = `Function order is incorrect, ${label} can not go after ${labelBefore} (line ${nodeBefore.loc.start.line})`; - this.reporter.error(node, this.ruleId, message); - } -} - -function getMutabilityWeight({ baseWeight, stateMutability }) { - switch (stateMutability) { - case "constant": - case "view": - return baseWeight + 2; - case "pure": - return baseWeight + 4; - default: - return baseWeight; - } -} - -function isInitializeFunction(node) { - return ( - node.name === "initialize" && - node.visibility === "public" && - node.modifiers.find( - (modifier) => - modifier.type === "ModifierInvocation" && - modifier.name === "initializer", - ) - ); -} - -function isContractSupportFunction(node) { - if (node.name !== "supportsInterface" && node.name !== "supportsFeature") - return false; - if (node.visibility !== "public" && node.visibility !== "external") - return false; - if (node.stateMutability !== "view" && node.stateMutability !== "pure") - return false; - if (node.parameters.length !== 1) return false; - if (node.parameters[0].type !== "VariableDeclaration") return false; - if (node.parameters[0].typeName.name !== "bytes4") return false; - if (node.returnParameters.length !== 1) return false; - if (node.returnParameters[0].type !== "VariableDeclaration") return false; - if (node.returnParameters[0].typeName.name !== "bool") return false; - return true; -} - -function sourceUnitPartOrder(node) { - if (node.type === "PragmaDirective") { - return [0, "pragma directive"]; - } - - if (node.type === "ImportDirective") { - return [10, "import directive"]; - } - - if (node.type === "FileLevelConstant") { - return [20, "file level constant"]; - } - - if (node.type === "EnumDefinition") { - return [30, "enum definition"]; - } - - if (node.type === "StructDefinition") { - return [35, "struct definition"]; - } - - if (node.type === "CustomErrorDefinition") { - return [40, "custom error definition"]; - } - - if (node.type === "FunctionDefinition") { - return [50, "free function definition"]; - } - - if (node.type === "ContractDefinition") { - if (node.kind === "interface") { - return [60, "interface"]; - } - - if (node.kind === "library") { - return [70, "library definition"]; - } - - if (node.kind === "contract") { - return [80, "contract definition"]; - } - } - - throw new Error("Unrecognized source unit part, please report this issue"); -} - -function contractPartOrder(node) { - if (node.type === "UsingForDeclaration") { - return [0, "using for declaration"]; - } - - if (node.type === "EnumDefinition") { - return [10, "enum definition"]; - } - - if (node.type === "StructDefinition") { - return [15, "struct definition"]; - } - - if (node.type === "StateVariableDeclaration") { - // the grammar: https://docs.soliditylang.org/en/latest/grammar.html - // forbids declaration of multiple state variables in the same - // StateVariableDeclaration, however in the AST they show up in an array, - // similar to regular VariableDeclarationStatements, which allow - // VariableDefinitionTuples inside them and therefore can declare many - // variables at once - if (node.variables.length !== 1) { - throw new Error( - "state variable definition with more than one variable. Please report this issue", - ); - } - const variable = node.variables[0]; - if (variable.isDeclaredConst) { - return [20, "contract constant declaration"]; - } else if (variable.isImmutable) { - return [22, "contract immutable declaration"]; - } else { - return [25, "state variable declaration"]; - } - } - - if (node.type === "EventDefinition") { - return [30, "event definition"]; - } - - if (node.type === "CustomErrorDefinition") { - return [35, "custom error definition"]; - } - - if (node.type === "ModifierDefinition") { - return [40, "modifier definition"]; - } - - if (node.isConstructor) { - return [50, "constructor"]; - } - - if (isReceiveFunction(node)) { - return [60, "receive function"]; - } - - if (isFallbackFunction(node)) { - return [70, "fallback function"]; - } - - if (node.type === "FunctionDefinition") { - const { stateMutability, visibility } = node; - - if (isInitializeFunction(node) || isContractSupportFunction(node)) { - return [50, "initialization function"]; - } - - if (visibility === "external") { - const weight = getMutabilityWeight({ baseWeight: 80, stateMutability }); - const label = [visibility, stateMutability, "function"].join(" "); - - return [weight, label]; - } - - if (visibility === "public") { - const weight = getMutabilityWeight({ baseWeight: 90, stateMutability }); - const label = [visibility, stateMutability, "function"].join(" "); - - return [weight, label]; - } - - if (visibility === "internal") { - const weight = getMutabilityWeight({ baseWeight: 100, stateMutability }); - const label = [visibility, stateMutability, "function"].join(" "); - return [weight, label]; - } - - if (visibility === "private") { - const weight = getMutabilityWeight({ baseWeight: 110, stateMutability }); - const label = [visibility, stateMutability, "function"].join(" "); - return [weight, label]; - } - - throw new Error("Unknown order for function, please report this issue"); - } - - throw new Error("Unrecognized contract part, please report this issue"); -} - -module.exports = OrderingChecker; diff --git a/solhint-plugins/package.json b/solhint-plugins/package.json deleted file mode 100644 index a2999c145..000000000 --- a/solhint-plugins/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "solhint-plugin-contracts-v2", - "type": "commonjs", - "main": "index.js" -} diff --git a/solhint-plugins/selector-tags.js b/solhint-plugins/selector-tags.js deleted file mode 100644 index 0b0ea1b74..000000000 --- a/solhint-plugins/selector-tags.js +++ /dev/null @@ -1,261 +0,0 @@ -const { keccak256, toUtf8Bytes } = require("ethers"); - -const ruleId = "selector-tags"; - -const SELECTOR_TAG_RE = - /@dev\s+(Error|Interface)\s+selector:\s*`(0x[0-9a-fA-F]+)`/; -const SELECTOR_CONTINUATION_RE = - /(Error|Interface)\s+selector:\s*`(0x[0-9a-fA-F]+)`/; - -class SelectorTagsChecker { - ruleId = ruleId; - meta = { fixable: true }; - - constructor(reporter, config, inputSrc) { - this.reporter = reporter; - this.inputSrc = inputSrc; - this.typeMap = new Map(); - this._lines = null; - } - - _initLines() { - if (this._lines) return; - this._lines = []; - const src = this.inputSrc; - let start = 0; - for (let i = 0; i <= src.length; i++) { - if (i === src.length || src[i] === "\n") { - this._lines.push({ - start, - end: i, - content: src.slice(start, i), - }); - start = i + 1; - } - } - } - - _getLineIndex(offset) { - let lo = 0; - let hi = this._lines.length - 1; - while (lo < hi) { - const mid = (lo + hi + 1) >> 1; - if (this._lines[mid].start <= offset) lo = mid; - else hi = mid - 1; - } - return lo; - } - - SourceUnit(node) { - for (const child of node.children || []) { - this._collectTypes(child); - } - } - - _collectTypes(node) { - if (node.type === "ContractDefinition") { - this.typeMap.set(node.name, { kind: node.kind }); - for (const sub of node.subNodes || []) { - this._collectTypes(sub); - } - } else if (node.type === "EnumDefinition") { - this.typeMap.set(node.name, { kind: "enum" }); - } else if (node.type === "StructDefinition") { - this.typeMap.set(node.name, { - kind: "struct", - members: node.members, - }); - } - } - - _resolveType(typeName) { - if (!typeName) return ""; - - switch (typeName.type) { - case "ElementaryTypeName": - return typeName.name; - - case "UserDefinedTypeName": { - const name = typeName.namePath; - const info = this.typeMap.get(name); - if (info) { - if (info.kind === "enum") return "uint8"; - if (info.kind === "struct") { - const memberTypes = info.members.map((m) => - this._resolveType(m.typeName), - ); - return `(${memberTypes.join(",")})`; - } - return "address"; - } - return "address"; - } - - case "ArrayTypeName": { - const baseType = this._resolveType(typeName.baseTypeName); - if (typeName.length != null) { - const len = - typeName.length.number ?? typeName.length.value ?? typeName.length; - return `${baseType}[${len}]`; - } - return `${baseType}[]`; - } - - default: - return "unknown"; - } - } - - _functionSignature(funcNode) { - const paramTypes = (funcNode.parameters || []).map((p) => - this._resolveType(p.typeName), - ); - return `${funcNode.name}(${paramTypes.join(",")})`; - } - - _errorSignature(errorNode) { - const paramTypes = (errorNode.parameters || []).map((p) => - this._resolveType(p.typeName), - ); - return `${errorNode.name}(${paramTypes.join(",")})`; - } - - _computeSelector(signature) { - return keccak256(toUtf8Bytes(signature)).slice(0, 10); - } - - _computeInterfaceId(functions) { - let id = 0n; - for (const func of functions) { - const sig = this._functionSignature(func); - const sel = BigInt(this._computeSelector(sig)); - id ^= sel; - } - return "0x" + id.toString(16).padStart(8, "0"); - } - - _findNatspecBlock(rangeStart) { - this._initLines(); - const defLineIdx = this._getLineIndex(rangeStart); - const block = []; - - for (let i = defLineIdx - 1; i >= 0; i--) { - const line = this._lines[i]; - const trimmed = line.content.trimStart(); - if (/^\/\/\/(\s|$)/.test(trimmed)) { - block.unshift({ ...line, lineIdx: i, trimmed }); - } else { - break; - } - } - - return block; - } - - _checkSelectorTag(node, kind, expectedSelector) { - this._initLines(); - const block = this._findNatspecBlock(node.range[0]); - - let existingLine = null; - let existingSelector = null; - let isCanonicalFormat = false; - - for (const line of block) { - const canonical = line.content.match(SELECTOR_TAG_RE); - if (canonical && canonical[1] === kind) { - existingLine = line; - existingSelector = canonical[2]; - isCanonicalFormat = true; - break; - } - const continuation = line.content.match(SELECTOR_CONTINUATION_RE); - if (continuation && continuation[1] === kind) { - existingLine = line; - existingSelector = continuation[2]; - break; - } - } - - if (existingLine) { - if (existingSelector === expectedSelector && isCanonicalFormat) return; - - if (isCanonicalFormat) { - const message = `Incorrect ${kind.toLowerCase()} selector: expected \`${expectedSelector}\`, found \`${existingSelector}\``; - this.reporter.error(node, this.ruleId, message, (fixer) => { - const hexIdx = existingLine.content.indexOf(existingSelector); - const hexStart = existingLine.start + hexIdx; - const hexEnd = hexStart + existingSelector.length - 1; - return fixer.replaceTextRange([hexStart, hexEnd], expectedSelector); - }); - } else { - const defLineIdx = this._getLineIndex(node.range[0]); - const defLine = this._lines[defLineIdx]; - const indent = defLine.content.match(/^(\s*)/)[1]; - const canonical = `${indent}/// @dev ${kind} selector: \`${expectedSelector}\``; - const message = - existingSelector === expectedSelector - ? `Non-canonical @dev ${kind.toLowerCase()} selector format` - : `Incorrect ${kind.toLowerCase()} selector: expected \`${expectedSelector}\`, found \`${existingSelector}\``; - this.reporter.error(node, this.ruleId, message, (fixer) => - fixer.replaceTextRange( - [existingLine.start, existingLine.end - 1], - canonical, - ), - ); - } - } else { - const message = `Missing @dev ${kind.toLowerCase()} selector tag (expected \`${expectedSelector}\`)`; - - const defLineIdx = this._getLineIndex(node.range[0]); - const defLine = this._lines[defLineIdx]; - const indent = defLine.content.match(/^(\s*)/)[1]; - const newDevLine = `${indent}/// @dev ${kind} selector: \`${expectedSelector}\``; - - if (block.length > 0) { - const nlPos = block[block.length - 1].end; - if (nlPos < this.inputSrc.length) { - this.reporter.error(node, this.ruleId, message, (fixer) => - fixer.replaceTextRange([nlPos, nlPos], `\n${newDevLine}\n`), - ); - } - } else { - const prevNlPos = defLine.start - 1; - if (prevNlPos >= 0) { - this.reporter.error(node, this.ruleId, message, (fixer) => - fixer.replaceTextRange( - [prevNlPos, prevNlPos], - `\n${newDevLine}\n`, - ), - ); - } else { - this.reporter.error(node, this.ruleId, message, (fixer) => - fixer.replaceTextRange( - [0, 0], - `${newDevLine}\n${this.inputSrc[0]}`, - ), - ); - } - } - } - } - - ContractDefinition(node) { - if (node.kind !== "interface") return; - - const functions = (node.subNodes || []).filter( - (n) => n.type === "FunctionDefinition", - ); - if (functions.length === 0) return; - - const expectedId = this._computeInterfaceId(functions); - this._checkSelectorTag(node, "Interface", expectedId); - } - - CustomErrorDefinition(node) { - const sig = this._errorSignature(node); - const expectedSelector = this._computeSelector(sig); - this._checkSelectorTag(node, "Error", expectedSelector); - } -} - -module.exports = SelectorTagsChecker;